Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
jio
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Aurélien Vermylen
jio
Commits
c74c465d
Commit
c74c465d
authored
Sep 21, 2014
by
Xiaowu Zhang
Browse files
Options
Browse Files
Download
Plain Diff
merge indexedDB branch
parents
86eaa055
4ed7981c
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
1873 additions
and
299 deletions
+1873
-299
jio.js
jio.js
+24
-1
src/jio.storage/davstorage.js
src/jio.storage/davstorage.js
+49
-8
src/jio.storage/indexeddbstorage.js
src/jio.storage/indexeddbstorage.js
+681
-285
src/jio/features/restParamChecker.js
src/jio/features/restParamChecker.js
+21
-1
test/jio.storage/davstorage.tests.js
test/jio.storage/davstorage.tests.js
+288
-4
test/jio.storage/indexeddbstorage.tests.js
test/jio.storage/indexeddbstorage.tests.js
+802
-0
test/tests.html
test/tests.html
+8
-0
No files found.
jio.js
View file @
c74c465d
...
...
@@ -2427,6 +2427,9 @@ function restCommandRejecter(param, args) {
if
(
arg
.
columnNumber
!==
undefined
&&
arg
.
columnNumber
!==
null
)
{
current_priority
.
columnNumber
=
arg
.
columnNumber
;
}
if
(
arg
.
fileName
!==
undefined
&&
arg
.
fileName
!==
null
)
{
current_priority
.
fileName
=
arg
.
fileName
;
}
if
(
arg
.
filename
!==
undefined
&&
arg
.
filename
!==
null
)
{
current_priority
.
filename
=
arg
.
filename
;
}
...
...
@@ -3659,8 +3662,28 @@ function enableRestParamChecker(jio, shared) {
}
});
[
"
getAttachment
"
,
"
removeAttachment
"
].
forEach
(
function
(
method
)
{
[
"
removeAttachment
"
].
forEach
(
function
(
method
)
{
shared
.
on
(
method
,
function
(
param
)
{
if
(
!
checkId
(
param
))
{
checkAttachmentId
(
param
);
}
});
});
[
"
getAttachment
"
].
forEach
(
function
(
method
)
{
shared
.
on
(
method
,
function
(
param
)
{
if
(
param
.
storage_spec
.
type
!==
"
indexeddb
"
&&
param
.
storage_spec
.
type
!==
"
dav
"
&&
(
param
.
kwargs
.
_start
!==
undefined
||
param
.
kwargs
.
_end
!==
undefined
))
{
restCommandRejecter
(
param
,
[
'
bad_request
'
,
'
unsupport
'
,
'
_start, _end not support
'
]);
return
false
;
}
if
(
!
checkId
(
param
))
{
checkAttachmentId
(
param
);
}
...
...
src/jio.storage/davstorage.js
View file @
c74c465d
...
...
@@ -184,8 +184,15 @@
* An ajax object to do the good request according to the auth type
*/
var
ajax
=
{
"
none
"
:
function
(
method
,
type
,
url
,
data
)
{
"
none
"
:
function
(
method
,
type
,
url
,
data
,
start
,
end
)
{
var
headers
=
{};
if
(
start
!==
undefined
)
{
if
(
end
!==
undefined
)
{
headers
=
{
"
Range
"
:
"
bytes=
"
+
start
+
"
-
"
+
end
};
}
else
{
headers
=
{
"
Range
"
:
"
bytes=
"
+
start
+
"
-
"
};
}
}
if
(
method
===
"
PROPFIND
"
)
{
headers
.
Depth
=
"
1
"
;
}
...
...
@@ -197,8 +204,15 @@
"
headers
"
:
headers
});
},
"
basic
"
:
function
(
method
,
type
,
url
,
data
,
login
)
{
"
basic
"
:
function
(
method
,
type
,
url
,
data
,
start
,
end
,
login
)
{
var
headers
=
{
"
Authorization
"
:
"
Basic
"
+
login
};
if
(
start
!==
undefined
)
{
if
(
end
!==
undefined
)
{
headers
.
Range
=
"
bytes=
"
+
start
+
"
-
"
+
end
;
}
else
{
headers
.
Range
=
"
bytes=
"
+
start
+
"
-
"
;
}
}
if
(
method
===
"
PROPFIND
"
)
{
headers
.
Depth
=
"
1
"
;
}
...
...
@@ -253,6 +267,8 @@
this
.
_url
+
'
/
'
+
idsToFileName
(
param
.
_id
,
param
.
_attachment
)
+
"
?_=
"
+
Date
.
now
(),
param
.
_blob
,
undefined
,
undefined
,
this
.
_login
);
};
...
...
@@ -263,6 +279,8 @@
"
text
"
,
this
.
_url
+
'
/
'
+
idsToFileName
(
param
.
_id
),
null
,
undefined
,
undefined
,
this
.
_login
).
then
(
function
(
e
)
{
try
{
...
...
@@ -286,6 +304,8 @@
"
blob
"
,
this
.
_url
+
'
/
'
+
idsToFileName
(
param
.
_id
,
param
.
_attachment
),
null
,
param
.
_start
,
param
.
_end
-
1
,
this
.
_login
);
};
...
...
@@ -296,6 +316,8 @@
null
,
this
.
_url
+
'
/
'
+
idsToFileName
(
param
.
_id
)
+
"
?_=
"
+
Date
.
now
(),
null
,
undefined
,
undefined
,
this
.
_login
);
};
...
...
@@ -307,6 +329,8 @@
this
.
_url
+
'
/
'
+
idsToFileName
(
param
.
_id
,
param
.
_attachment
)
+
"
?_=
"
+
Date
.
now
(),
null
,
undefined
,
undefined
,
this
.
_login
);
};
...
...
@@ -317,6 +341,8 @@
"
text
"
,
this
.
_url
+
'
/
'
,
null
,
undefined
,
undefined
,
this
.
_login
).
then
(
function
(
e
)
{
var
i
,
rows
=
[],
row
,
responses
=
new
DOMParser
().
parseFromString
(
...
...
@@ -346,9 +372,11 @@
row
.
id
=
row
.
id
[
0
];
}
if
(
row
!==
undefined
)
{
if
(
row
.
id
!==
""
)
{
rows
[
rows
.
length
]
=
row
;
}
}
}
return
{
"
target
"
:
{
"
response
"
:
{
"
total_rows
"
:
rows
.
length
,
"
rows
"
:
rows
...
...
@@ -631,7 +659,18 @@
);
}
};
if
(
param
.
_start
<
0
||
param
.
_end
<
0
)
{
command
.
reject
(
405
,
"
invalide _start,_end
"
,
"
_start and _end must be positive
"
);
return
;
}
if
(
param
.
_start
>
param
.
_end
)
{
command
.
reject
(
405
,
"
invalide _start,_end
"
,
"
start is great then end
"
);
return
;
}
this
.
_get
(
param
).
then
(
o
.
getAttachment
).
then
(
o
.
success
,
o
.
reject
,
o
.
notifyProgress
);
...
...
@@ -833,10 +872,12 @@
}
e
.
target
.
response
.
rows
.
forEach
(
function
(
row
)
{
if
(
row
.
id
!==
""
)
{
requests
[
requests
.
length
]
=
that
.
_get
({
"
_id
"
:
row
.
id
}).
then
(
function
(
e
)
{
row
.
doc
=
e
.
target
.
response
;
});
}
});
o
.
count
=
0
;
...
...
src/jio.storage/indexeddbstorage.js
View file @
c74c465d
...
...
@@ -13,7 +13,8 @@
*
* {
* "type": "indexeddb",
* "database": <string>
* "database": <string>,
* "unite": <integer> //byte
* }
*
* The database name will be prefixed by "jio:", so if the database property is
...
...
@@ -28,7 +29,7 @@
*/
/*jslint indent: 2, maxlen: 80, nomen: true */
/*global define, module, require, indexedDB, jIO, RSVP
*/
/*global define, module, require, indexedDB, jIO, RSVP
, Blob, Math
*/
(
function
(
dependencies
,
factory
)
{
"
use strict
"
;
...
...
@@ -47,7 +48,6 @@
var
Promise
=
RSVP
.
Promise
,
generateUuid
=
jIO
.
util
.
generateUuid
;
// XXX doc string
function
metadataObjectToString
(
value
)
{
var
i
,
l
;
if
(
Array
.
isArray
(
value
))
{
...
...
@@ -77,308 +77,445 @@
throw
new
TypeError
(
"
IndexedDBStorage 'database' description property
"
+
"
must be a non-empty string
"
);
}
if
(
description
.
unite
!==
undefined
)
{
if
(
description
.
unite
!==
parseInt
(
description
.
unite
,
10
))
{
throw
new
TypeError
(
"
IndexedDBStorage 'unite' description property
"
+
"
must be a integer
"
);
}
}
else
{
description
.
unite
=
2000000
;
}
this
.
_database_name
=
"
jio:
"
+
description
.
database
;
this
.
_unite
=
description
.
unite
;
}
// XXX doc string
function
openRequestOnUpgradeNeeded
(
shared
,
event
)
{
if
(
shared
.
aborted
)
{
return
;
}
shared
.
db
=
event
.
target
.
result
;
try
{
shared
.
store
=
shared
.
db
.
createObjectStore
(
"
metadata
"
,
{
/**
* creat 3 objectStores
* @param {string} the name of the database
*/
function
openIndexedDB
(
db_name
)
{
var
request
;
function
resolver
(
resolve
,
reject
)
{
// Open DB //
request
=
indexedDB
.
open
(
db_name
);
request
.
onerror
=
reject
;
// Create DB if necessary //
request
.
onupgradeneeded
=
function
(
evt
)
{
var
db
=
evt
.
target
.
result
,
store
;
store
=
db
.
createObjectStore
(
"
metadata
"
,
{
"
keyPath
"
:
"
_id
"
//"autoIncrement": true
});
store
.
createIndex
(
"
_id
"
,
"
_id
"
);
store
=
db
.
createObjectStore
(
"
attachment
"
,
{
"
keyPath
"
:
"
_id
"
//"autoIncrement": true
});
// `createObjectStore` can throw InvalidStateError - open_req.onerror
// and db.onerror won't be called.
shared
.
store
.
createIndex
(
"
_id
"
,
"
_id
"
);
// `store.createIndex` can throw an error
shared
.
db_created
=
true
;
shared
.
store
.
transaction
.
oncomplete
=
function
()
{
delete
shared
.
store
;
store
.
createIndex
(
"
_id
"
,
"
_id
"
);
store
=
db
.
createObjectStore
(
"
blob
"
,
{
"
keyPath
"
:
[
"
_id
"
,
"
_attachment
"
,
"
_part
"
]
//"autoIncrement": true
});
store
.
createIndex
(
"
_id_attachment_part
"
,
[
"
_id
"
,
"
_attachment
"
,
"
_part
"
]);
};
request
.
onsuccess
=
function
()
{
resolve
(
request
.
result
);
};
}
catch
(
e
)
{
shared
.
reject
(
e
);
shared
.
db
.
close
();
shared
.
aborted
=
true
;
}
return
new
RSVP
.
Promise
(
resolver
);
}
IndexedDBStorage
.
prototype
.
createDBIfNecessary
=
function
()
{
var
shared
=
{},
open_req
=
indexedDB
.
open
(
this
.
_database_name
);
// No request.abort() is provided so we cannot cancel database creation
return
new
Promise
(
function
(
resolve
,
reject
)
{
shared
.
reject
=
reject
;
open_req
.
onupgradeneeded
=
openRequestOnUpgradeNeeded
.
bind
(
open_req
,
shared
);
open_req
.
onerror
=
function
()
{
if
(
open_req
.
result
)
{
open_req
.
result
.
close
();
}
reject
(
open_req
.
error
);
return
openIndexedDB
(
this
.
_database_name
);
};
open_req
.
onsuccess
=
function
()
{
// *Called at t + 3*
open_req
.
result
.
close
();
resolve
(
shared
.
db_created
?
"
created
"
:
"
no_content
"
);
/**
*put a data into a store object
*@param {ObjectStore} store The objectstore
*@param {Object} metadata The data to put in
*@return a new promise
*/
function
putIndexedDBArrayBuffer
(
store
,
metadata
)
{
var
request
,
resolver
;
request
=
store
.
put
(
metadata
);
resolver
=
function
(
resolve
,
reject
)
{
request
.
onerror
=
function
(
e
)
{
reject
(
e
);
};
});
request
.
onsuccess
=
function
()
{
resolve
(
metadata
);
};
// XXX doc string
IndexedDBStorage
.
prototype
.
get
=
function
(
command
,
param
)
{
var
shared
=
{
"
connector
"
:
this
};
new
Promise
(
function
(
resolve
,
reject
)
{
shared
.
reject
=
reject
;
// Open DB //
var
open_req
=
indexedDB
.
open
(
shared
.
connector
.
_database_name
);
open_req
.
onerror
=
function
(
event
)
{
reject
(
event
.
target
.
errorCode
);
};
return
new
RSVP
.
Promise
(
resolver
);
}
// Create DB if necessary //
open_req
.
onupgradeneeded
=
openRequestOnUpgradeNeeded
.
bind
(
open_req
,
shared
);
open_req
.
onsuccess
=
function
(
event
)
{
if
(
shared
.
aborted
)
{
return
;
}
function
putIndexedDB
(
store
,
metadata
,
readData
)
{
var
request
,
resolver
;
try
{
shared
.
db
=
event
.
target
.
result
;
// Open transaction //
shared
.
tx
=
shared
.
db
.
transaction
(
"
metadata
"
,
"
readonly
"
);
shared
.
tx
.
onerror
=
function
()
{
reject
(
shared
.
tx
.
error
);
shared
.
db
.
close
();
};
shared
.
onCancel
=
function
()
{
shared
.
tx
.
abort
();
shared
.
db
.
close
();
};
// Get index //
shared
.
store
=
shared
.
tx
.
objectStore
(
"
metadata
"
);
shared
.
index_request
=
shared
.
store
.
index
(
"
_id
"
);
// Get metadata //
shared
.
index_request
.
get
(
param
.
_id
).
onsuccess
=
function
(
event
)
{
if
(
shared
.
aborted
)
{
return
;
}
if
(
event
.
target
.
result
===
undefined
)
{
reject
({
"
status
"
:
404
});
return
;
}
shared
.
final_result
=
{
"
data
"
:
event
.
target
.
result
};
request
=
store
.
put
(
metadata
);
resolver
=
function
(
resolve
,
reject
)
{
request
.
onerror
=
function
(
e
)
{
reject
(
e
);
};
request
.
onsuccess
=
function
()
{
resolve
(
metadata
);
};
// Respond to jIO //
shared
.
tx
.
oncomplete
=
function
()
{
resolve
(
shared
.
final_result
);
shared
.
db
.
close
();
};
}
catch
(
e1
)
{
reject
(
e1
);
shared
.
db
.
close
();
return
new
RSVP
.
Promise
(
resolver
);
}
catch
(
e
)
{
return
putIndexedDBArrayBuffer
(
store
,
{
"
_id
"
:
metadata
.
_id
,
"
_attachment
"
:
metadata
.
_attachment
,
"
_part
"
:
metadata
.
_part
,
"
blob
"
:
readData
});
}
}
function
transactionEnd
(
transaction
)
{
var
resolver
;
resolver
=
function
(
resolve
,
reject
)
{
transaction
.
onabort
=
reject
;
transaction
.
oncomplete
=
function
()
{
resolve
(
"
end
"
);
};
};
}).
then
(
command
.
success
,
command
.
error
,
command
.
notify
);
return
new
RSVP
.
Promise
(
resolver
);
}
/**
* get a data from a store object
* @param {ObjectStore} store The objectstore
* @param {String} id The data id
* return a new promise
*/
function
getIndexedDB
(
store
,
id
)
{
function
resolver
(
resolve
,
reject
)
{
var
request
=
store
.
get
(
id
);
request
.
onerror
=
reject
;
request
.
onsuccess
=
function
()
{
resolve
(
request
.
result
);
};
}
return
new
RSVP
.
Promise
(
resolver
);
}
// XXX doc string
IndexedDBStorage
.
prototype
.
post
=
function
(
command
,
metadata
)
{
var
shared
=
{
"
connector
"
:
this
};
if
(
!
metadata
.
_id
)
{
metadata
.
_id
=
generateUuid
();
/**
* delete a data of a store object
* @param {ObjectStore} store The objectstore
* @param {String} id The data id
* @return a new promise
*
*/
function
removeIndexedDB
(
store
,
id
)
{
function
resolver
(
resolve
,
reject
)
{
var
request
=
store
[
"
delete
"
](
id
);
request
.
onerror
=
function
(
e
)
{
reject
(
e
);
};
request
.
onsuccess
=
function
()
{
resolve
(
request
.
result
);
};
}
return
new
RSVP
.
Promise
(
resolver
);
}
new
Promise
(
function
(
resolve
,
reject
)
{
shared
.
reject
=
reject
;
// Open DB //
var
open_req
=
indexedDB
.
open
(
shared
.
connector
.
_database_name
);
open_req
.
onerror
=
function
(
event
)
{
reject
(
event
.
target
.
errorCode
);
/**
* research an id in a store
* @param {ObjectStore} store The objectstore
* @param {String} id The index id
* @param {var} researchID The data id
* return a new promise
*/
function
researchIndexedDB
(
store
,
id
,
researchID
)
{
function
resolver
(
resolve
)
{
var
index
=
store
.
index
(
researchID
);
index
.
get
(
id
).
onsuccess
=
function
(
evt
)
{
resolve
({
"
result
"
:
evt
.
target
.
result
,
"
store
"
:
store
});
};
}
return
new
RSVP
.
Promise
(
resolver
);
}
// Create DB if necessary //
open_req
.
onupgradeneeded
=
openRequestOnUpgradeNeeded
.
bind
(
open_req
,
shared
);
open_req
.
onsuccess
=
function
(
event
)
{
if
(
shared
.
aborted
)
{
return
;
}
try
{
shared
.
db
=
event
.
target
.
result
;
// Open transaction //
shared
.
tx
=
shared
.
db
.
transaction
(
"
metadata
"
,
"
readwrite
"
);
shared
.
tx
.
onerror
=
function
()
{
reject
(
shared
.
tx
.
error
);
shared
.
db
.
close
();
};
shared
.
onCancel
=
function
()
{
shared
.
tx
.
abort
();
shared
.
db
.
close
();
};
// Get index //
shared
.
store
=
shared
.
tx
.
objectStore
(
"
metadata
"
);
shared
.
index_request
=
shared
.
store
.
index
(
"
_id
"
);
// Get metadata //
shared
.
index_request
.
get
(
metadata
.
_id
).
onsuccess
=
function
(
event
)
{
if
(
shared
.
aborted
)
{
return
;
}
if
(
event
.
target
.
result
!==
undefined
)
{
shared
.
db
.
close
();
reject
({
"
status
"
:
409
,
"
reason
"
:
"
document already exist
"
});
return
;
function
promiseResearch
(
transaction
,
id
,
table
,
researchID
)
{
var
store
=
transaction
.
objectStore
(
table
);
return
researchIndexedDB
(
store
,
id
,
researchID
);
}
delete
metadata
.
_attachments
;
// Push metadata //
shared
.
store
.
put
(
metadata
);
};
shared
.
tx
.
oncomplete
=
function
()
{
// Respond to jIO //
shared
.
db
.
close
();
resolve
({
"
id
"
:
metadata
.
_id
});
};
}
catch
(
e1
)
{
reject
(
e1
);
shared
.
db
.
close
();
}
};
}).
then
(
command
.
success
,
command
.
error
,
command
.
notify
);
/**
* put or post a metadata into objectstore:metadata,attachment
* @param {function} open The function to open a basedata
* @param {function} research The function to reserach
* @param {function} ongoing The function to process
* @param {function} end The completed function
* @param {Object} command The JIO command
* @param {Object} metadata The data to put
*/
IndexedDBStorage
.
prototype
.
_putOrPost
=
function
(
open
,
research
,
ongoing
,
end
,
command
,
metadata
)
{
var
jio_storage
=
this
,
transaction
,
global_db
,
result
;
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
//open a database
return
open
(
jio_storage
.
_database_name
);
})
.
push
(
function
(
db
)
{
global_db
=
db
;
transaction
=
db
.
transaction
([
"
metadata
"
,
"
attachment
"
],
"
readwrite
"
);
//research in metadata
return
research
(
transaction
,
metadata
.
_id
,
"
metadata
"
,
"
_id
"
);
})
.
push
(
function
(
researchResult
)
{
return
ongoing
(
researchResult
);
})
.
push
(
function
(
ongoingResult
)
{
//research in attachment
result
=
ongoingResult
;
return
research
(
transaction
,
metadata
.
_id
,
"
attachment
"
,
"
_id
"
);
})
.
push
(
function
(
researchResult
)
{
//create an id in attachment si necessary
if
(
researchResult
.
result
===
undefined
)
{
return
putIndexedDB
(
researchResult
.
store
,
{
"
_id
"
:
metadata
.
_id
});
}
})
.
push
(
function
()
{
return
transactionEnd
(
transaction
);
})
.
push
(
function
()
{
return
end
(
result
);
})
.
push
(
undefined
,
function
(
error
)
{
if
(
global_db
!==
undefined
)
{
global_db
.
close
();
}
throw
error
;
})
.
push
(
command
.
success
,
command
.
error
,
command
.
notify
);
};
// XXX doc string
IndexedDBStorage
.
prototype
.
put
=
function
(
command
,
metadata
)
{
var
shared
=
{
"
connector
"
:
this
};
new
Promise
(
function
(
resolve
,
reject
)
{
shared
.
reject
=
reject
;
// Open DB //
var
open_req
=
indexedDB
.
open
(
shared
.
connector
.
_database_name
);
open_req
.
onerror
=
function
(
event
)
{
reject
(
event
.
target
.
errorCode
);
/**
* Retrieve data
*
*@param {Object} command The JIO command
*@param {Object} param The command parameters
*/
IndexedDBStorage
.
prototype
.
get
=
function
(
command
,
param
)
{
var
jio_storage
=
this
,
transaction
,
global_db
,
meta
;
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
return
openIndexedDB
(
jio_storage
.
_database_name
);
})
.
push
(
function
(
db
)
{
global_db
=
db
;
transaction
=
db
.
transaction
([
"
metadata
"
,
"
attachment
"
],
"
readwrite
"
);
var
store
=
transaction
.
objectStore
(
"
metadata
"
);
return
getIndexedDB
(
store
,
param
.
_id
);
})
.
push
(
function
(
result
)
{
if
(
result
)
{
//get a part data from metadata
meta
=
result
;
var
store
=
transaction
.
objectStore
(
"
attachment
"
);
return
getIndexedDB
(
store
,
param
.
_id
);
}
throw
({
"
status
"
:
404
,
"
reason
"
:
"
Not Found
"
,
"
message
"
:
"
IndexeddbStorage, unable to get document.
"
});
})
.
push
(
function
(
result
)
{
//get the reste data from attachment
if
(
result
.
_attachment
)
{
meta
.
_attachment
=
result
.
_attachment
;
}
return
transactionEnd
(
transaction
);
})
.
push
(
function
()
{
return
({
"
data
"
:
meta
});
})
.
push
(
undefined
,
function
(
error
)
{
if
(
global_db
!==
undefined
)
{
global_db
.
close
();
}
throw
error
;
})
.
push
(
command
.
success
,
command
.
error
,
command
.
notify
);
};
// Create DB if necessary //
open_req
.
onupgradeneeded
=
openRequestOnUpgradeNeeded
.
bind
(
open_req
,
shared
);
open_req
.
onsuccess
=
function
(
event
)
{
if
(
shared
.
aborted
)
{
return
;
}
try
{
shared
.
db
=
event
.
target
.
result
;
// Open transaction //
shared
.
tx
=
shared
.
db
.
transaction
(
"
metadata
"
,
"
readwrite
"
);
shared
.
tx
.
onerror
=
function
()
{
reject
(
shared
.
tx
.
error
);
shared
.
db
.
close
();
};
shared
.
onCancel
=
function
()
{
shared
.
tx
.
abort
();
shared
.
db
.
close
();
};
// Get index //
shared
.
store
=
shared
.
tx
.
objectStore
(
"
metadata
"
);
shared
.
index
=
shared
.
store
.
index
(
"
_id
"
);
// Get metadata //
shared
.
index
.
get
(
metadata
.
_id
).
onsuccess
=
function
(
event
)
{
if
(
shared
.
aborted
)
{
return
;
}
var
i
,
l
,
key
,
array
,
data
;
if
(
event
.
target
.
result
!==
undefined
)
{
shared
.
found
=
true
;
data
=
event
.
target
.
result
;
// Update metadata //
array
=
Object
.
keys
(
metadata
);
for
(
i
=
0
,
l
=
array
.
length
;
i
<
l
;
i
+=
1
)
{
key
=
array
[
i
];
metadata
[
key
]
=
metadataObjectToString
(
metadata
[
key
]);
/**
* Remove a document
*
* @param {Object} command The JIO command
* @param {Object} param The command parameters
*/
IndexedDBStorage
.
prototype
.
remove
=
function
(
command
,
param
)
{
var
jio_storage
=
this
,
transaction
,
global_db
,
queue
=
new
RSVP
.
Queue
();
function
removeAllPart
(
store
,
attachment
,
part
,
totalLength
)
{
if
(
part
*
jio_storage
.
_unite
>=
totalLength
)
{
return
;
}
if
(
data
.
_attachments
)
{
metadata
.
_attachments
=
data
.
_attachments
;
return
removeIndexedDB
(
store
,
[
param
.
_id
,
attachment
,
part
])
.
then
(
function
()
{
return
removeAllPart
(
store
,
attachment
,
part
+
1
,
totalLength
);
});
}
}
else
{
delete
metadata
.
_attachments
;
function
removeAll
(
store
,
array
,
index
,
allAttachment
)
{
var
totalLength
=
allAttachment
[
array
[
index
]].
length
;
return
removeAllPart
(
store
,
array
[
index
],
0
,
totalLength
)
.
then
(
function
()
{
if
(
index
<
array
.
length
-
1
)
{
return
removeAll
(
store
,
array
,
index
+
1
,
allAttachment
);
}
// Push metadata //
shared
.
store
.
put
(
metadata
);
};
shared
.
tx
.
oncomplete
=
function
()
{
// Respond to jIO //
shared
.
db
.
close
();
resolve
({
"
status
"
:
shared
.
found
?
204
:
201
});
};
}
catch
(
e1
)
{
reject
(
e1
);
shared
.
db
.
close
();
});
}
};
}).
then
(
command
.
success
,
command
.
error
,
command
.
notify
);
return
queue
.
push
(
function
()
{
return
openIndexedDB
(
jio_storage
.
_database_name
);
})
.
push
(
function
(
db
)
{
global_db
=
db
;
transaction
=
db
.
transaction
([
"
metadata
"
,
"
attachment
"
,
"
blob
"
],
"
readwrite
"
);
return
promiseResearch
(
transaction
,
param
.
_id
,
"
metadata
"
,
"
_id
"
);
})
.
push
(
function
(
resultResearch
)
{
if
(
resultResearch
.
result
===
undefined
)
{
throw
({
"
status
"
:
404
,
"
reason
"
:
"
Not Found
"
,
"
message
"
:
"
IndexeddbStorage, unable to get metadata.
"
});
}
//delete metadata
return
removeIndexedDB
(
resultResearch
.
store
,
param
.
_id
);
})
.
push
(
function
()
{
var
store
=
transaction
.
objectStore
(
"
attachment
"
);
return
getIndexedDB
(
store
,
param
.
_id
);
})
.
push
(
function
(
result
)
{
if
(
result
.
_attachment
)
{
var
array
,
store
;
array
=
Object
.
keys
(
result
.
_attachment
);
store
=
transaction
.
objectStore
(
"
blob
"
);
return
removeAll
(
store
,
array
,
0
,
result
.
_attachment
);
}
})
.
push
(
function
()
{
var
store
=
transaction
.
objectStore
(
"
attachment
"
);
//delete attachment
return
removeIndexedDB
(
store
,
param
.
_id
);
})
.
push
(
function
()
{
return
transactionEnd
(
transaction
);
})
.
push
(
function
()
{
return
({
"
status
"
:
204
});
})
.
push
(
undefined
,
function
(
error
)
{
if
(
global_db
!==
undefined
)
{
global_db
.
close
();
}
throw
error
;
})
.
push
(
command
.
success
,
command
.
error
,
command
.
notify
);
};
// XXX doc string
IndexedDBStorage
.
prototype
.
remove
=
function
(
command
,
param
)
{
var
shared
=
{
"
connector
"
:
this
};
new
Promise
(
function
(
resolve
,
reject
)
{
shared
.
reject
=
reject
;
// Open DB //
var
open_req
=
indexedDB
.
open
(
shared
.
connector
.
_database_name
);
open_req
.
onerror
=
function
(
event
)
{
reject
(
event
.
target
.
errorCode
);
};
// Create DB if necessary //
open_req
.
onupgradeneeded
=
openRequestOnUpgradeNeeded
.
bind
(
open_req
,
shared
);
/**
* Creates a new document if not already existes
* @param {Object} command The JIO command
* @param {Object} metadata The metadata to put
*/
IndexedDBStorage
.
prototype
.
post
=
function
(
command
,
metadata
)
{
var
that
=
this
;
if
(
!
metadata
.
_id
)
{
metadata
.
_id
=
generateUuid
();
}
function
promiseOngoingPost
(
researchResult
)
{
if
(
researchResult
.
result
===
undefined
)
{
delete
metadata
.
_attachment
;
return
putIndexedDB
(
researchResult
.
store
,
metadata
);
}
throw
({
"
status
"
:
409
,
"
reason
"
:
"
Document exists
"
});
}
open_req
.
onsuccess
=
function
(
event
)
{
if
(
shared
.
aborted
)
{
return
;
}
try
{
shared
.
db
=
event
.
target
.
result
;
// Open transaction //
shared
.
tx
=
shared
.
db
.
transaction
(
"
metadata
"
,
"
readwrite
"
);
shared
.
tx
.
onerror
=
function
()
{
reject
(
shared
.
tx
.
error
);
shared
.
db
.
close
();
};
shared
.
onCancel
=
function
()
{
shared
.
tx
.
abort
();
shared
.
db
.
close
();
};
// Get index //
shared
.
store
=
shared
.
tx
.
objectStore
(
"
metadata
"
);
shared
.
index
=
shared
.
store
.
index
(
"
_id
"
);
// Get metadata //
shared
.
index
.
get
(
param
.
_id
).
onsuccess
=
function
(
event
)
{
if
(
shared
.
aborted
)
{
return
;
}
if
(
event
.
target
.
result
===
undefined
)
{
shared
.
db
.
close
();
reject
({
"
status
"
:
404
});
return
;
function
promiseEndPost
(
metadata
)
{
return
({
"
id
"
:
metadata
.
_id
});
}
// Delete metadata //
shared
.
store
[
"
delete
"
](
param
.
_id
);
// XXX Delete attachments //
};
shared
.
tx
.
oncomplete
=
function
()
{
// Respond to jIO //
shared
.
db
.
close
(
);
resolve
();
return
that
.
_putOrPost
(
openIndexedDB
,
promiseResearch
,
promiseOngoingPost
,
promiseEndPost
,
command
,
metadata
);
};
}
catch
(
e1
)
{
reject
(
e1
);
shared
.
db
.
close
();
/**
* Creates or updates a document
* @param {Object} command The JIO command
* @param {Object} metadata The metadata to post
*/
IndexedDBStorage
.
prototype
.
put
=
function
(
command
,
metadata
)
{
var
that
=
this
,
found
;
function
promiseOngoingPut
(
researchResult
)
{
var
key
;
for
(
key
in
metadata
)
{
if
(
metadata
.
hasOwnProperty
(
key
))
{
metadata
[
key
]
=
metadataObjectToString
(
metadata
[
key
]);
}
}
delete
metadata
.
_attachment
;
if
(
researchResult
.
result
!==
undefined
)
{
found
=
true
;
}
return
putIndexedDB
(
researchResult
.
store
,
metadata
);
}
function
promiseEndPut
()
{
return
{
"
status
"
:
(
found
?
204
:
201
)
};
}
return
that
.
_putOrPost
(
openIndexedDB
,
promiseResearch
,
promiseOngoingPut
,
promiseEndPut
,
command
,
metadata
);
};
}).
then
(
command
.
success
,
command
.
error
,
command
.
notify
);
};
// XXX doc string
IndexedDBStorage
.
prototype
.
getList
=
function
(
option
)
{
/**
* Retrieve a list of present document
*
* @method allDocs
* @param {Object} command The JIO command
* @param {Object} param The command parameters
* @param {Object} options The command options
* @param {Boolean} [options.include_docs=false]
* Also retrieve the actual document content.
*/
IndexedDBStorage
.
prototype
.
getListMetadata
=
function
(
option
)
{
var
rows
=
[],
onCancel
,
open_req
=
indexedDB
.
open
(
this
.
_database_name
);
return
new
Promise
(
function
(
resolve
,
reject
,
notify
)
{
open_req
.
onerror
=
function
()
{
...
...
@@ -386,30 +523,25 @@
reject
(
open_req
.
error
);
};
open_req
.
onsuccess
=
function
()
{
var
tx
,
store
,
index
,
date
,
index_req
,
db
=
open_req
.
result
;
var
tx
,
date
,
j
=
0
,
index_req
,
db
=
open_req
.
result
;
try
{
tx
=
db
.
transaction
(
"
metadata
"
,
"
readonly
"
);
tx
=
db
.
transaction
(
[
"
metadata
"
,
"
attachment
"
]
,
"
readonly
"
);
onCancel
=
function
()
{
tx
.
abort
();
db
.
close
();
};
store
=
tx
.
objectStore
(
"
metadata
"
);
index
=
store
.
index
(
"
_id
"
);
index_req
=
index
.
openCursor
();
index_req
=
tx
.
objectStore
(
"
metadata
"
).
index
(
"
_id
"
).
openCursor
();
date
=
Date
.
now
();
index_req
.
onsuccess
=
function
(
event
)
{
var
cursor
=
event
.
target
.
result
,
now
,
value
,
i
,
key
;
if
(
cursor
)
{
// Called for each matching record.
// Called for each matching record
// notification management
now
=
Date
.
now
();
if
(
date
<=
now
-
1000
)
{
notify
({
"
loaded
"
:
rows
.
length
});
date
=
now
;
}
// option.limit management
if
(
Array
.
isArray
(
option
.
limit
))
{
if
(
option
.
limit
.
length
>
1
)
{
...
...
@@ -433,7 +565,6 @@
option
.
limit
[
0
]
-=
1
;
}
}
value
=
{};
// option.select_list management
if
(
option
.
select_list
)
{
...
...
@@ -442,7 +573,6 @@
value
[
key
]
=
cursor
.
value
[
key
];
}
}
// option.include_docs management
if
(
option
.
include_docs
)
{
rows
.
push
({
...
...
@@ -456,16 +586,39 @@
"
value
"
:
value
});
}
// continue to next iteration
cursor
[
"
continue
"
]();
}
else
{
index_req
=
tx
.
objectStore
(
"
attachment
"
).
index
(
"
_id
"
).
openCursor
();
index_req
.
onsuccess
=
function
(
event
)
{
//second table
cursor
=
event
.
target
.
result
;
if
(
cursor
)
{
value
=
{};
if
(
cursor
.
value
.
_attachment
)
{
if
(
option
.
select_list
)
{
for
(
i
=
0
;
i
<
option
.
select_list
.
length
;
i
+=
1
)
{
key
=
option
.
select_list
[
i
];
value
[
key
]
=
cursor
.
value
.
_attachment
[
key
];
}
}
//add info of attachment into metadata
rows
[
j
].
value
.
_attachment
=
value
;
if
(
option
.
include_docs
)
{
rows
[
j
].
doc
.
_attachment
=
cursor
.
value
.
_attachment
;
}
}
j
+=
1
;
cursor
[
"
continue
"
]();
}
else
{
notify
({
"
loaded
"
:
rows
.
length
});
// No more matching records.
resolve
({
"
data
"
:
{
"
rows
"
:
rows
,
"
total_rows
"
:
rows
.
length
}});
db
.
close
();
}
};
}
};
}
catch
(
e
)
{
reject
(
e
);
db
.
close
();
...
...
@@ -478,10 +631,254 @@
});
};
/**
* Add an attachment to a document
*
* @param {Object} command The JIO command
* @param {Object} metadata The data
*
*/
IndexedDBStorage
.
prototype
.
putAttachment
=
function
(
command
,
metadata
)
{
var
jio_storage
=
this
,
transaction
,
global_db
,
BlobInfo
,
readResult
;
function
putAllPart
(
store
,
metadata
,
readResult
,
count
,
part
)
{
var
blob
,
readPart
,
end
;
if
(
count
>=
metadata
.
_blob
.
size
)
{
return
;
}
end
=
count
+
jio_storage
.
_unite
;
blob
=
metadata
.
_blob
.
slice
(
count
,
end
);
readPart
=
readResult
.
slice
(
count
,
end
);
return
putIndexedDB
(
store
,
{
"
_id
"
:
metadata
.
_id
,
"
_attachment
"
:
metadata
.
_attachment
,
"
_part
"
:
part
,
"
blob
"
:
blob
},
readPart
)
.
then
(
function
()
{
return
putAllPart
(
store
,
metadata
,
readResult
,
end
,
part
+
1
);
});
}
return
jIO
.
util
.
readBlobAsArrayBuffer
(
metadata
.
_blob
)
.
then
(
function
(
event
)
{
readResult
=
event
.
target
.
result
;
BlobInfo
=
{
"
content_type
"
:
metadata
.
_blob
.
type
,
"
length
"
:
metadata
.
_blob
.
size
};
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
return
openIndexedDB
(
jio_storage
.
_database_name
);
})
.
push
(
function
(
db
)
{
global_db
=
db
;
transaction
=
db
.
transaction
([
"
attachment
"
,
"
blob
"
],
"
readwrite
"
);
return
promiseResearch
(
transaction
,
metadata
.
_id
,
"
attachment
"
,
"
_id
"
);
})
.
push
(
function
(
researchResult
)
{
if
(
researchResult
.
result
===
undefined
)
{
throw
({
"
status
"
:
404
,
"
reason
"
:
"
Not Found
"
,
"
message
"
:
"
indexeddbStorage unable to put attachment
"
});
}
//update attachment
researchResult
.
result
.
_attachment
=
researchResult
.
result
.
_attachment
||
{};
researchResult
.
result
.
_attachment
[
metadata
.
_attachment
]
=
(
BlobInfo
===
undefined
)
?
"
BlobInfo
"
:
BlobInfo
;
return
putIndexedDB
(
researchResult
.
store
,
researchResult
.
result
);
})
.
push
(
function
()
{
//put in blob
var
store
=
transaction
.
objectStore
(
"
blob
"
);
return
putAllPart
(
store
,
metadata
,
readResult
,
0
,
0
);
})
.
push
(
function
()
{
return
transactionEnd
(
transaction
);
})
.
push
(
function
()
{
return
{
"
status
"
:
204
};
})
.
push
(
undefined
,
function
(
error
)
{
if
(
global_db
!==
undefined
)
{
global_db
.
close
();
}
throw
error
;
})
.
push
(
command
.
success
,
command
.
error
,
command
.
notify
);
});
};
/**
* Retriev a document attachment
*
* @param {Object} command The JIO command
* @param {Object} param The command parameter
*/
IndexedDBStorage
.
prototype
.
getAttachment
=
function
(
command
,
param
)
{
var
jio_storage
=
this
,
transaction
,
global_db
,
blob
,
totalLength
;
function
getDesirePart
(
store
,
start
,
end
)
{
if
(
start
>
end
)
{
return
;
}
return
getIndexedDB
(
store
,
[
param
.
_id
,
param
.
_attachment
,
start
])
.
then
(
function
(
result
)
{
var
blobPart
=
result
.
blob
;
if
(
result
.
blob
.
byteLength
!==
undefined
)
{
blobPart
=
new
Blob
([
result
.
blob
]);
}
if
(
blob
)
{
blob
=
new
Blob
([
blob
,
blobPart
]);
}
else
{
blob
=
blobPart
;
}
return
getDesirePart
(
store
,
start
+
1
,
end
);
});
}
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
return
openIndexedDB
(
jio_storage
.
_database_name
);
})
.
push
(
function
(
db
)
{
global_db
=
db
;
transaction
=
db
.
transaction
([
"
attachment
"
,
"
blob
"
],
"
readwrite
"
);
//check if the attachment exists
return
promiseResearch
(
transaction
,
param
.
_id
,
"
attachment
"
,
"
_id
"
);
})
.
push
(
function
(
researchResult
)
{
var
result
=
researchResult
.
result
,
start
,
end
;
if
(
result
===
undefined
||
result
.
_attachment
[
param
.
_attachment
]
===
undefined
)
{
throw
({
"
status
"
:
404
,
"
reason
"
:
"
missing attachment
"
,
"
message
"
:
"
IndexeddbStorage, unable to get attachment.
"
});
}
totalLength
=
result
.
_attachment
[
param
.
_attachment
].
length
;
param
.
_start
=
param
.
_start
===
undefined
?
0
:
param
.
_start
;
param
.
_end
=
param
.
_end
===
undefined
?
totalLength
:
param
.
_end
;
if
(
param
.
_end
>
totalLength
)
{
param
.
_end
=
totalLength
;
}
if
(
param
.
_start
<
0
||
param
.
_end
<
0
)
{
throw
({
"
status
"
:
404
,
"
reason
"
:
"
invalide _start, _end
"
,
"
message
"
:
"
_start and _end must be positive
"
});
}
if
(
param
.
_start
>
param
.
_end
)
{
throw
({
"
status
"
:
404
,
"
reason
"
:
"
invalide offset
"
,
"
message
"
:
"
start is great then end
"
});
}
start
=
Math
.
floor
(
param
.
_start
/
jio_storage
.
_unite
);
end
=
Math
.
floor
(
param
.
_end
/
jio_storage
.
_unite
);
if
(
param
.
_end
%
jio_storage
.
_unite
===
0
)
{
end
-=
1
;
}
return
getDesirePart
(
transaction
.
objectStore
(
"
blob
"
),
start
,
end
);
})
.
push
(
function
()
{
var
start
=
param
.
_start
%
jio_storage
.
_unite
,
end
=
start
+
param
.
_end
-
param
.
_start
;
blob
=
blob
.
slice
(
start
,
end
);
return
({
"
data
"
:
new
Blob
([
blob
],
{
type
:
"
text/plain
"
})});
})
.
push
(
undefined
,
function
(
error
)
{
// Check if transaction is ongoing, if so, abort it
if
(
transaction
!==
undefined
)
{
transaction
.
abort
();
}
if
(
global_db
!==
undefined
)
{
global_db
.
close
();
}
throw
error
;
})
.
push
(
command
.
success
,
command
.
error
,
command
.
notify
);
};
/**
* Remove an attachment
*
* @method removeAttachment
* @param {Object} command The JIO command
* @param {Object} param The command parameters
*/
IndexedDBStorage
.
prototype
.
removeAttachment
=
function
(
command
,
param
)
{
var
jio_storage
=
this
,
transaction
,
global_db
,
totalLength
;
function
removePart
(
store
,
part
)
{
if
(
part
*
jio_storage
.
_unite
>=
totalLength
)
{
return
;
}
return
removeIndexedDB
(
store
,
[
param
.
_id
,
param
.
_attachment
,
part
])
.
then
(
function
()
{
return
removePart
(
store
,
part
+
1
);
});
}
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
return
openIndexedDB
(
jio_storage
.
_database_name
);
})
.
push
(
function
(
db
)
{
global_db
=
db
;
transaction
=
db
.
transaction
([
"
attachment
"
,
"
blob
"
],
"
readwrite
"
);
//check if the attachment exists
return
promiseResearch
(
transaction
,
param
.
_id
,
"
attachment
"
,
"
_id
"
);
})
.
push
(
function
(
researchResult
)
{
var
result
=
researchResult
.
result
;
if
(
result
===
undefined
||
result
.
_attachment
[
param
.
_attachment
]
===
undefined
)
{
throw
({
"
status
"
:
404
,
"
reason
"
:
"
missing attachment
"
,
"
message
"
:
"
IndexeddbStorage, document attachment not found.
"
});
}
totalLength
=
result
.
_attachment
[
param
.
_attachment
].
length
;
//updata attachment
delete
result
.
_attachment
[
param
.
_attachment
];
return
putIndexedDB
(
researchResult
.
store
,
result
);
})
.
push
(
function
()
{
var
store
=
transaction
.
objectStore
(
"
blob
"
);
return
removePart
(
store
,
0
);
})
.
push
(
function
()
{
return
transactionEnd
(
transaction
);
})
.
push
(
function
()
{
return
({
"
status
"
:
204
});
})
.
push
(
undefined
,
function
(
error
)
{
if
(
global_db
!==
undefined
)
{
global_db
.
close
();
}
throw
error
;
})
.
push
(
command
.
success
,
command
.
error
,
command
.
notify
);
};
IndexedDBStorage
.
prototype
.
allDocs
=
function
(
command
,
param
,
option
)
{
/*jslint unparam: true */
this
.
createDBIfNecessary
().
then
(
this
.
getList
.
bind
(
this
,
option
)).
then
(
this
.
getList
Metadata
.
bind
(
this
,
option
)).
then
(
command
.
success
,
command
.
error
,
command
.
notify
);
};
...
...
@@ -494,5 +891,4 @@
};
jIO
.
addStorage
(
"
indexeddb
"
,
IndexedDBStorage
);
}));
src/jio/features/restParamChecker.js
View file @
c74c465d
...
...
@@ -96,7 +96,7 @@ function enableRestParamChecker(jio, shared) {
}
});
[
"
getAttachment
"
,
"
removeAttachment
"
].
forEach
(
function
(
method
)
{
[
"
removeAttachment
"
].
forEach
(
function
(
method
)
{
shared
.
on
(
method
,
function
(
param
)
{
if
(
!
checkId
(
param
))
{
checkAttachmentId
(
param
);
...
...
@@ -104,6 +104,26 @@ function enableRestParamChecker(jio, shared) {
});
});
[
"
getAttachment
"
].
forEach
(
function
(
method
)
{
shared
.
on
(
method
,
function
(
param
)
{
if
(
param
.
storage_spec
.
type
!==
"
indexeddb
"
&&
param
.
storage_spec
.
type
!==
"
dav
"
&&
(
param
.
kwargs
.
_start
!==
undefined
||
param
.
kwargs
.
_end
!==
undefined
))
{
restCommandRejecter
(
param
,
[
'
bad_request
'
,
'
unsupport
'
,
'
_start, _end not support
'
]);
return
false
;
}
if
(
!
checkId
(
param
))
{
checkAttachmentId
(
param
);
}
});
});
[
"
check
"
,
"
repair
"
].
forEach
(
function
(
method
)
{
shared
.
on
(
method
,
function
(
param
)
{
if
(
param
.
kwargs
.
_id
!==
undefined
)
{
...
...
test/jio.storage/davstorage.tests.js
View file @
c74c465d
/*jslint indent: 2, maxlen: 80, nomen: true */
/*global module, test, stop, start, expect, ok, deepEqual, location, sinon,
davstorage_spec, RSVP, jIO, test_util, dav_storage, btoa, define,
setTimeout, clearTimeout */
setTimeout, clearTimeout
, parseInt
*/
// define([module_name], [dependencies], module);
(
function
(
dependencies
,
module
)
{
...
...
@@ -62,7 +62,7 @@
* X-Requested-With, X-HTTP-Method-Override, Accept, Authorization,
* Depth"
*/
test
(
"
Scenario
"
,
34
,
function
()
{
test
(
"
Scenario
"
,
48
,
function
()
{
var
server
,
responses
=
[],
shared
=
{},
jio
=
jIO
.
createJIO
(
spec
,
{
"
workspace
"
:
{},
...
...
@@ -94,7 +94,7 @@
jIO
.
util
.
ajax
=
function
(
param
)
{
var
timeout
,
xhr
=
{},
response
=
responses
.
shift
(),
statusTexts
=
{
"
404
"
:
"
Not Found
"
};
}
,
start
,
end
,
str
;
if
(
!
Array
.
isArray
(
response
))
{
setTimeout
(
function
()
{
throw
new
ReferenceError
(
"
Fake server, no response set for
"
+
...
...
@@ -116,6 +116,17 @@
timeout
=
setTimeout
(
function
()
{
/*global Blob*/
if
(
xhr
.
responseType
===
'
blob
'
)
{
if
(
param
.
headers
.
Range
!==
undefined
)
{
str
=
param
.
headers
.
Range
;
start
=
parseInt
(
str
.
substring
(
str
.
indexOf
(
"
=
"
)
+
1
,
str
.
indexOf
(
"
-
"
)),
10
);
if
(
str
.
indexOf
(
"
NaN
"
)
!==
-
1
)
{
response
[
2
]
=
response
[
2
].
substring
(
start
);
}
else
{
end
=
parseInt
(
str
.
substring
(
str
.
indexOf
(
"
-
"
)
+
1
),
10
);
response
[
2
]
=
response
[
2
].
substring
(
start
,
end
+
1
);
}
}
xhr
.
response
=
new
Blob
([
response
[
2
]],
{
"
type
"
:
response
[
1
][
"
Content-Type
"
]
||
response
[
1
][
"
Content-type
"
]
||
...
...
@@ -969,6 +980,179 @@
});
}
function
getFirstAttachmentRange1
()
{
responses
.
push
([
200
,
{
"
Content-Type
"
:
"
application/octet-stream
"
},
JSON
.
stringify
({
"
_id
"
:
"
a
"
,
"
title
"
:
"
Hoo
"
,
"
_attachments
"
:
{
"
aa
"
:
{
"
content_type
"
:
"
text/plain
"
,
"
digest
"
:
"
sha256-38760eabb666e8e61ee628a17c4090cc5
"
+
"
0728e095ff24218119d51bd22475363
"
,
"
length
"
:
3
},
"
ab
"
:
{
"
content_type
"
:
"
text/plain
"
,
"
digest
"
:
"
sha256-e124adcce1fb2f88e1ea799c3d0820845
"
+
"
ed343e6c739e54131fcb3a56e4bc1bd
"
,
"
length
"
:
3
}
}
})]);
// GET
responses
.
push
([
200
,
{
"
Content-Type
"
:
"
application/octet-stream
"
},
"
aab
"
]);
// GET
return
jio
.
getAttachment
({
"
_id
"
:
"
a
"
,
"
_attachment
"
:
"
aa
"
,
"
_start
"
:
0
});
}
function
getFirstAttachmentRangeTest1
(
answer
)
{
var
blob
=
answer
.
data
;
answer
.
data
=
"
<blob>
"
;
deepEqual
(
answer
,
{
"
attachment
"
:
"
aa
"
,
"
data
"
:
"
<blob>
"
,
"
id
"
:
"
a
"
,
"
digest
"
:
"
sha256-38760eabb666e8e61ee628a17c4090cc5
"
+
"
0728e095ff24218119d51bd22475363
"
,
"
method
"
:
"
getAttachment
"
,
"
result
"
:
"
success
"
,
"
status
"
:
200
,
"
statusText
"
:
"
Ok
"
},
"
Get first attachment with range:_start: 0, _end: undefined
"
);
return
jIO
.
util
.
readBlobAsText
(
blob
).
then
(
function
(
e
)
{
deepEqual
(
blob
.
type
,
"
text/plain
"
,
"
Check blob type
"
);
deepEqual
(
e
.
target
.
result
,
"
aab
"
,
"
Check blob text content
"
);
},
function
(
err
)
{
deepEqual
(
err
,
"
no error
"
,
"
Check blob text content
"
);
});
}
function
getFirstAttachmentRange2
()
{
responses
.
push
([
200
,
{
"
Content-Type
"
:
"
application/octet-stream
"
},
JSON
.
stringify
({
"
_id
"
:
"
a
"
,
"
title
"
:
"
Hoo
"
,
"
_attachments
"
:
{
"
aa
"
:
{
"
content_type
"
:
"
text/plain
"
,
"
digest
"
:
"
sha256-38760eabb666e8e61ee628a17c4090cc5
"
+
"
0728e095ff24218119d51bd22475363
"
,
"
length
"
:
3
},
"
ab
"
:
{
"
content_type
"
:
"
text/plain
"
,
"
digest
"
:
"
sha256-e124adcce1fb2f88e1ea799c3d0820845
"
+
"
ed343e6c739e54131fcb3a56e4bc1bd
"
,
"
length
"
:
3
}
}
})]);
// GET
responses
.
push
([
200
,
{
"
Content-Type
"
:
"
application/octet-stream
"
},
"
aab
"
]);
// GET
return
jio
.
getAttachment
({
"
_id
"
:
"
a
"
,
"
_attachment
"
:
"
aa
"
,
"
_start
"
:
0
,
"
_end
"
:
1
});
}
function
getFirstAttachmentRangeTest2
(
answer
)
{
var
blob
=
answer
.
data
;
answer
.
data
=
"
<blob>
"
;
deepEqual
(
answer
,
{
"
attachment
"
:
"
aa
"
,
"
data
"
:
"
<blob>
"
,
"
id
"
:
"
a
"
,
"
digest
"
:
"
sha256-38760eabb666e8e61ee628a17c4090cc5
"
+
"
0728e095ff24218119d51bd22475363
"
,
"
method
"
:
"
getAttachment
"
,
"
result
"
:
"
success
"
,
"
status
"
:
200
,
"
statusText
"
:
"
Ok
"
},
"
Get first attachment with range: _start:0, _end:1
"
);
return
jIO
.
util
.
readBlobAsText
(
blob
).
then
(
function
(
e
)
{
deepEqual
(
blob
.
type
,
"
text/plain
"
,
"
Check blob type
"
);
deepEqual
(
e
.
target
.
result
,
"
a
"
,
"
Check blob text content
"
);
},
function
(
err
)
{
deepEqual
(
err
,
"
no error
"
,
"
Check blob text content
"
);
});
}
function
getFirstAttachmentRange3
()
{
responses
.
push
([
200
,
{
"
Content-Type
"
:
"
application/octet-stream
"
},
JSON
.
stringify
({
"
_id
"
:
"
a
"
,
"
title
"
:
"
Hoo
"
,
"
_attachments
"
:
{
"
aa
"
:
{
"
content_type
"
:
"
text/plain
"
,
"
digest
"
:
"
sha256-38760eabb666e8e61ee628a17c4090cc5
"
+
"
0728e095ff24218119d51bd22475363
"
,
"
length
"
:
3
},
"
ab
"
:
{
"
content_type
"
:
"
text/plain
"
,
"
digest
"
:
"
sha256-e124adcce1fb2f88e1ea799c3d0820845
"
+
"
ed343e6c739e54131fcb3a56e4bc1bd
"
,
"
length
"
:
3
}
}
})]);
// GET
responses
.
push
([
200
,
{
"
Content-Type
"
:
"
application/octet-stream
"
},
"
aab
"
]);
// GET
return
jio
.
getAttachment
({
"
_id
"
:
"
a
"
,
"
_attachment
"
:
"
aa
"
,
"
_start
"
:
1
,
"
_end
"
:
3
});
}
function
getFirstAttachmentRangeTest3
(
answer
)
{
var
blob
=
answer
.
data
;
answer
.
data
=
"
<blob>
"
;
deepEqual
(
answer
,
{
"
attachment
"
:
"
aa
"
,
"
data
"
:
"
<blob>
"
,
"
id
"
:
"
a
"
,
"
digest
"
:
"
sha256-38760eabb666e8e61ee628a17c4090cc5
"
+
"
0728e095ff24218119d51bd22475363
"
,
"
method
"
:
"
getAttachment
"
,
"
result
"
:
"
success
"
,
"
status
"
:
200
,
"
statusText
"
:
"
Ok
"
},
"
Get first attachment with range:_start:1, _end:3
"
);
return
jIO
.
util
.
readBlobAsText
(
blob
).
then
(
function
(
e
)
{
deepEqual
(
blob
.
type
,
"
text/plain
"
,
"
Check blob type
"
);
deepEqual
(
e
.
target
.
result
,
"
ab
"
,
"
Check blob text content
"
);
},
function
(
err
)
{
deepEqual
(
err
,
"
no error
"
,
"
Check blob text content
"
);
});
}
function
getSecondAttachment
()
{
responses
.
push
([
200
,
{
"
Content-Type
"
:
"
application/octet-stream
"
...
...
@@ -1009,7 +1193,7 @@
"
result
"
:
"
success
"
,
"
status
"
:
200
,
"
statusText
"
:
"
Ok
"
},
"
Get
first
attachment
"
);
},
"
Get
second
attachment
"
);
return
jIO
.
util
.
readBlobAsText
(
blob
).
then
(
function
(
e
)
{
deepEqual
(
blob
.
type
,
"
text/plain
"
,
"
Check blob type
"
);
deepEqual
(
e
.
target
.
result
,
"
aba
"
,
"
Check blob text content
"
);
...
...
@@ -1018,6 +1202,100 @@
});
}
function
getSecondAttachmentRange1
()
{
return
success
(
jio
.
getAttachment
({
"
_id
"
:
"
a
"
,
"
_attachment
"
:
"
ab
"
,
"
_start
"
:
-
1
}));
}
function
getSecondAttachmentRangeTest1
(
answer
)
{
deepEqual
(
answer
,
{
"
attachment
"
:
"
ab
"
,
"
error
"
:
"
method_not_allowed
"
,
"
id
"
:
"
a
"
,
"
message
"
:
"
_start and _end must be positive
"
,
"
method
"
:
"
getAttachment
"
,
"
reason
"
:
"
invalide _start,_end
"
,
"
result
"
:
"
error
"
,
"
status
"
:
405
,
"
statusText
"
:
"
Method Not Allowed
"
},
"
Get second attachment with range: _start: -1
"
);
}
function
getSecondAttachmentRange2
()
{
return
success
(
jio
.
getAttachment
({
"
_id
"
:
"
a
"
,
"
_attachment
"
:
"
ab
"
,
"
_start
"
:
1
,
"
_end
"
:
0
}));
}
function
getSecondAttachmentRangeTest2
(
answer
)
{
deepEqual
(
answer
,
{
"
attachment
"
:
"
ab
"
,
"
error
"
:
"
method_not_allowed
"
,
"
id
"
:
"
a
"
,
"
message
"
:
"
start is great then end
"
,
"
method
"
:
"
getAttachment
"
,
"
reason
"
:
"
invalide _start,_end
"
,
"
result
"
:
"
error
"
,
"
status
"
:
405
,
"
statusText
"
:
"
Method Not Allowed
"
},
"
Get second attachment with range: _start: -1
"
);
}
function
getSecondAttachmentRange3
()
{
responses
.
push
([
200
,
{
"
Content-Type
"
:
"
application/octet-stream
"
},
JSON
.
stringify
({
"
_id
"
:
"
a
"
,
"
title
"
:
"
Hoo
"
,
"
_attachments
"
:
{
"
aa
"
:
{
"
content_type
"
:
"
text/plain
"
,
"
digest
"
:
"
sha256-38760eabb666e8e61ee628a17c4090cc5
"
+
"
0728e095ff24218119d51bd22475363
"
,
"
length
"
:
3
},
"
ab
"
:
{
"
content_type
"
:
"
text/plain
"
,
"
digest
"
:
"
sha256-e124adcce1fb2f88e1ea799c3d0820845
"
+
"
ed343e6c739e54131fcb3a56e4bc1bd
"
,
"
length
"
:
3
}
}
})]);
// GET
responses
.
push
([
200
,
{
"
Content-Type
"
:
"
application/octet-stream
"
},
"
aab
"
]);
// GET
return
jio
.
getAttachment
({
"
_id
"
:
"
a
"
,
"
_attachment
"
:
"
ab
"
,
"
_start
"
:
1
,
"
_end
"
:
2
});
}
function
getSecondAttachmentRangeTest3
(
answer
)
{
var
blob
=
answer
.
data
;
answer
.
data
=
"
<blob>
"
;
deepEqual
(
answer
,
{
"
attachment
"
:
"
ab
"
,
"
data
"
:
"
<blob>
"
,
"
id
"
:
"
a
"
,
"
digest
"
:
"
sha256-e124adcce1fb2f88e1ea799c3d0820845
"
+
"
ed343e6c739e54131fcb3a56e4bc1bd
"
,
"
method
"
:
"
getAttachment
"
,
"
result
"
:
"
success
"
,
"
status
"
:
200
,
"
statusText
"
:
"
Ok
"
},
"
Get second attachment with range:_start:1, _end:2
"
);
return
jIO
.
util
.
readBlobAsText
(
blob
).
then
(
function
(
e
)
{
deepEqual
(
blob
.
type
,
"
text/plain
"
,
"
Check blob type
"
);
deepEqual
(
e
.
target
.
result
,
"
a
"
,
"
Check blob text content
"
);
},
function
(
err
)
{
deepEqual
(
err
,
"
no error
"
,
"
Check blob text content
"
);
});
}
function
getLastDocument
()
{
responses
.
push
([
200
,
{
"
Content-Type
"
:
"
application/octet-stream
"
...
...
@@ -1348,8 +1626,14 @@
then
(
updateLastDocument
).
then
(
updateLastDocumentTest
).
// getA a 200
then
(
getFirstAttachment
).
then
(
getFirstAttachmentTest
).
then
(
getFirstAttachmentRange1
).
then
(
getFirstAttachmentRangeTest1
).
then
(
getFirstAttachmentRange2
).
then
(
getFirstAttachmentRangeTest2
).
then
(
getFirstAttachmentRange3
).
then
(
getFirstAttachmentRangeTest3
).
// getA b 200
then
(
getSecondAttachment
).
then
(
getSecondAttachmentTest
).
then
(
getSecondAttachmentRange1
).
then
(
getSecondAttachmentRangeTest1
).
then
(
getSecondAttachmentRange2
).
then
(
getSecondAttachmentRangeTest2
).
then
(
getSecondAttachmentRange3
).
then
(
getSecondAttachmentRangeTest3
).
// get 200
then
(
getLastDocument
).
then
(
getLastDocumentTest
).
// removeA b 204
...
...
test/jio.storage/indexeddbstorage.tests.js
0 → 100644
View file @
c74c465d
/*jslint indent: 2, maxlen: 80, nomen: true */
/*global module, test, stop, start, expect, ok, deepEqual, location, sinon,
davstorage_spec, RSVP, jIO, test_util, dav_storage, btoa, define,
setTimeout, clearTimeout, indexedDB */
// define([module_name], [dependencies], module);
(
function
(
dependencies
,
module
)
{
"
use strict
"
;
if
(
typeof
define
===
'
function
'
&&
define
.
amd
)
{
return
define
(
dependencies
,
module
);
}
module
(
test_util
,
RSVP
,
jIO
);
}([
'
test_util
'
,
'
rsvp
'
,
'
jio
'
,
'
indexeddbstorage
'
,
'
qunit
'
],
function
(
util
,
RSVP
,
jIO
)
{
"
use strict
"
;
module
(
"
indexeddbStorage
"
);
function
success
(
promise
)
{
return
new
RSVP
.
Promise
(
function
(
resolve
,
notify
)
{
promise
.
then
(
resolve
,
resolve
,
notify
);
},
function
()
{
promise
.
cancel
();
});
}
test
(
"
Scenario
"
,
46
,
function
()
{
indexedDB
.
deleteDatabase
(
"
jio:test
"
);
var
server
,
shared
=
{},
jio
=
jIO
.
createJIO
(
{
"
type
"
:
"
indexeddb
"
,
"
database
"
:
"
test
"
},
{
"
workspace
"
:
{}}
);
stop
();
server
=
{
restore
:
function
()
{
return
;
}};
function
postNewDocument
()
{
return
jio
.
post
({
"
title
"
:
"
Unique ID
"
});
}
function
postNewDocumentTest
(
answer
)
{
var
uuid
=
answer
.
id
;
answer
.
id
=
"
<uuid>
"
;
deepEqual
(
answer
,
{
"
id
"
:
"
<uuid>
"
,
"
method
"
:
"
post
"
,
"
result
"
:
"
success
"
,
"
status
"
:
201
,
"
statusText
"
:
"
Created
"
},
"
Post a new document
"
);
ok
(
util
.
isUuid
(
uuid
),
"
New document id should look like
"
+
"
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx :
"
+
uuid
);
shared
.
created_document_id
=
uuid
;
}
function
getCreatedDocument
()
{
return
jio
.
get
({
"
_id
"
:
shared
.
created_document_id
});
}
function
getCreatedDocumentTest
(
answer
)
{
deepEqual
(
answer
,
{
"
data
"
:
{
"
_id
"
:
shared
.
created_document_id
,
"
title
"
:
"
Unique ID
"
},
"
id
"
:
shared
.
created_document_id
,
"
method
"
:
"
get
"
,
"
result
"
:
"
success
"
,
"
status
"
:
200
,
"
statusText
"
:
"
Ok
"
},
"
Get new document
"
);
}
function
postSpecificDocument
()
{
return
jio
.
post
({
"
_id
"
:
"
b
"
,
"
title
"
:
"
Bee
"
});
}
function
postSpecificDocumentTest
(
answer
)
{
deepEqual
(
answer
,
{
"
id
"
:
"
b
"
,
"
method
"
:
"
post
"
,
"
result
"
:
"
success
"
,
"
status
"
:
201
,
"
statusText
"
:
"
Created
"
},
"
Post specific document
"
);
}
function
listDocument
()
{
return
jio
.
allDocs
();
}
function
list2DocumentsTest
(
answer
)
{
if
(
answer
&&
answer
.
data
&&
Array
.
isArray
(
answer
.
data
.
rows
))
{
answer
.
data
.
rows
.
sort
(
function
(
a
)
{
return
a
.
id
===
"
b
"
?
1
:
0
;
});
}
deepEqual
(
answer
,
{
"
data
"
:
{
"
total_rows
"
:
2
,
"
rows
"
:
[{
"
id
"
:
shared
.
created_document_id
,
"
value
"
:
{}
},
{
"
id
"
:
"
b
"
,
"
value
"
:
{}
}]
},
"
method
"
:
"
allDocs
"
,
"
result
"
:
"
success
"
,
"
status
"
:
200
,
"
statusText
"
:
"
Ok
"
},
"
List 2 documents
"
);
}
function
listDocumentsWithMetadata
()
{
return
jio
.
allDocs
({
"
include_docs
"
:
true
});
}
function
list2DocumentsWithMetadataTest
(
answer
)
{
if
(
answer
&&
answer
.
data
&&
Array
.
isArray
(
answer
.
data
.
rows
))
{
answer
.
data
.
rows
.
sort
(
function
(
a
)
{
return
a
.
id
===
"
b
"
?
1
:
0
;
});
}
deepEqual
(
answer
,
{
"
data
"
:
{
"
total_rows
"
:
2
,
"
rows
"
:
[{
"
id
"
:
shared
.
created_document_id
,
"
value
"
:
{},
"
doc
"
:
{
"
_id
"
:
shared
.
created_document_id
,
"
title
"
:
"
Unique ID
"
}
},
{
"
id
"
:
"
b
"
,
"
value
"
:
{},
"
doc
"
:
{
"
_id
"
:
"
b
"
,
"
title
"
:
"
Bee
"
}
}]
},
"
method
"
:
"
allDocs
"
,
"
result
"
:
"
success
"
,
"
status
"
:
200
,
"
statusText
"
:
"
Ok
"
},
"
List 2 documents with their metadata
"
);
}
function
removeCreatedDocument
()
{
return
jio
.
remove
({
"
_id
"
:
shared
.
created_document_id
});
}
function
removeCreatedDocumentTest
(
answer
)
{
deepEqual
(
answer
,
{
"
id
"
:
shared
.
created_document_id
,
"
method
"
:
"
remove
"
,
"
result
"
:
"
success
"
,
"
status
"
:
204
,
"
statusText
"
:
"
No Content
"
},
"
Remove first document.
"
);
}
function
removeSpecificDocument
()
{
return
jio
.
remove
({
"
_id
"
:
"
b
"
});
}
function
removeSpecificDocumentTest
(
answer
)
{
deepEqual
(
answer
,
{
"
id
"
:
"
b
"
,
"
method
"
:
"
remove
"
,
"
result
"
:
"
success
"
,
"
status
"
:
204
,
"
statusText
"
:
"
No Content
"
},
"
Remove second document.
"
);
}
function
listEmptyStorage
()
{
return
jio
.
allDocs
();
}
function
listEmptyStorageTest
(
answer
)
{
deepEqual
(
answer
,
{
"
data
"
:
{
"
total_rows
"
:
0
,
"
rows
"
:
[]
},
"
method
"
:
"
allDocs
"
,
"
result
"
:
"
success
"
,
"
status
"
:
200
,
"
statusText
"
:
"
Ok
"
},
"
List empty storage
"
);
}
function
putNewDocument
()
{
return
jio
.
put
({
"
_id
"
:
"
a
"
,
"
title
"
:
"
Hey
"
});
}
function
putNewDocumentTest
(
answer
)
{
deepEqual
(
answer
,
{
"
id
"
:
"
a
"
,
"
method
"
:
"
put
"
,
"
result
"
:
"
success
"
,
"
status
"
:
201
,
"
statusText
"
:
"
Created
"
},
"
Put new document
"
);
}
function
getCreatedDocument2
()
{
return
jio
.
get
({
"
_id
"
:
"
a
"
});
}
function
getCreatedDocument2Test
(
answer
)
{
deepEqual
(
answer
,
{
"
data
"
:
{
"
_id
"
:
"
a
"
,
"
title
"
:
"
Hey
"
},
"
id
"
:
"
a
"
,
"
method
"
:
"
get
"
,
"
result
"
:
"
success
"
,
"
status
"
:
200
,
"
statusText
"
:
"
Ok
"
},
"
Get new document
"
);
}
function
postSameDocument
()
{
return
success
(
jio
.
post
({
"
_id
"
:
"
a
"
,
"
title
"
:
"
Hoo
"
}));
}
function
postSameDocumentTest
(
answer
)
{
deepEqual
(
answer
,
{
"
error
"
:
"
conflict
"
,
"
id
"
:
"
a
"
,
"
message
"
:
"
Command failed
"
,
"
method
"
:
"
post
"
,
"
reason
"
:
"
Document exists
"
,
"
result
"
:
"
error
"
,
"
status
"
:
409
,
"
statusText
"
:
"
Conflict
"
},
"
Unable to post the same document (conflict)
"
);
}
function
putAttachmentToNonExistentDocument
()
{
return
success
(
jio
.
putAttachment
({
"
_id
"
:
"
ahaha
"
,
"
_attachment
"
:
"
aa
"
,
"
_data
"
:
"
aaa
"
,
"
_content_type
"
:
"
text/plain
"
}));
}
function
putAttachmentToNonExistentDocumentTest
(
answer
)
{
deepEqual
(
answer
,
{
"
attachment
"
:
"
aa
"
,
"
error
"
:
"
not_found
"
,
"
id
"
:
"
ahaha
"
,
"
message
"
:
"
indexeddbStorage unable to put attachment
"
,
"
method
"
:
"
putAttachment
"
,
"
reason
"
:
"
Not Found
"
,
"
result
"
:
"
error
"
,
"
status
"
:
404
,
"
statusText
"
:
"
Not Found
"
},
"
Put attachment to a non existent document -> 404 Not Found
"
);
}
function
createAttachment
()
{
return
jio
.
putAttachment
({
"
_id
"
:
"
a
"
,
"
_attachment
"
:
"
aa
"
,
"
_data
"
:
"
aaa
"
,
"
_content_type
"
:
"
text/plain
"
});
}
function
createAttachmentTest
(
answer
)
{
deepEqual
(
answer
,
{
"
attachment
"
:
"
aa
"
,
"
id
"
:
"
a
"
,
"
method
"
:
"
putAttachment
"
,
"
result
"
:
"
success
"
,
"
status
"
:
204
,
"
statusText
"
:
"
No Content
"
},
"
Create new attachment
"
);
}
function
updateAttachment
()
{
return
jio
.
putAttachment
({
"
_id
"
:
"
a
"
,
"
_attachment
"
:
"
aa
"
,
"
_data
"
:
"
aab
"
,
"
_content_type
"
:
"
text/plain
"
});
}
function
updateAttachmentTest
(
answer
)
{
deepEqual
(
answer
,
{
"
attachment
"
:
"
aa
"
,
"
id
"
:
"
a
"
,
"
method
"
:
"
putAttachment
"
,
"
result
"
:
"
success
"
,
"
status
"
:
204
,
"
statusText
"
:
"
No Content
"
},
"
Update last attachment
"
);
}
function
createAnotherAttachment
()
{
return
jio
.
putAttachment
({
"
_id
"
:
"
a
"
,
"
_attachment
"
:
"
ab
"
,
"
_data
"
:
"
aba
"
,
"
_content_type
"
:
"
text/plain
"
});
}
function
createAnotherAttachmentTest
(
answer
)
{
deepEqual
(
answer
,
{
"
attachment
"
:
"
ab
"
,
"
id
"
:
"
a
"
,
"
method
"
:
"
putAttachment
"
,
"
result
"
:
"
success
"
,
"
status
"
:
204
,
"
statusText
"
:
"
No Content
"
},
"
Create another attachment
"
);
}
function
updateLastDocument
()
{
return
jio
.
put
({
"
_id
"
:
"
a
"
,
"
title
"
:
"
Hoo
"
});
}
function
updateLastDocumentTest
(
answer
)
{
deepEqual
(
answer
,
{
"
id
"
:
"
a
"
,
"
method
"
:
"
put
"
,
"
result
"
:
"
success
"
,
"
status
"
:
204
,
"
statusText
"
:
"
No Content
"
},
"
Update document metadata
"
);
}
function
getFirstAttachment
()
{
return
jio
.
getAttachment
({
"
_id
"
:
"
a
"
,
"
_attachment
"
:
"
aa
"
});
}
function
getFirstAttachmentTest
(
answer
)
{
var
blob
=
answer
.
data
;
answer
.
data
=
"
<blob>
"
;
return
jIO
.
util
.
readBlobAsText
(
blob
).
then
(
function
(
e
)
{
deepEqual
(
blob
.
type
,
"
text/plain
"
,
"
Check blob type
"
);
deepEqual
(
e
.
target
.
result
,
"
aab
"
,
"
Check blob text content
"
);
deepEqual
(
answer
,
{
"
attachment
"
:
"
aa
"
,
"
data
"
:
"
<blob>
"
,
"
id
"
:
"
a
"
,
"
method
"
:
"
getAttachment
"
,
"
result
"
:
"
success
"
,
"
status
"
:
200
,
"
statusText
"
:
"
Ok
"
},
"
Get first attachment
"
);
},
function
(
err
)
{
deepEqual
(
err
,
"
no error
"
,
"
Check blob text content
"
);
});
}
function
getFirstAttachmentRange1
()
{
return
jio
.
getAttachment
({
"
_id
"
:
"
a
"
,
"
_attachment
"
:
"
aa
"
,
"
_start
"
:
0
});
}
function
getFirstAttachmentRangeTest1
(
answer
)
{
var
blob
=
answer
.
data
;
answer
.
data
=
"
<blob>
"
;
return
jIO
.
util
.
readBlobAsText
(
blob
).
then
(
function
(
e
)
{
deepEqual
(
blob
.
type
,
"
text/plain
"
,
"
Check blob type
"
);
deepEqual
(
e
.
target
.
result
,
"
aab
"
,
"
Check blob text content
"
);
deepEqual
(
answer
,
{
"
attachment
"
:
"
aa
"
,
"
data
"
:
"
<blob>
"
,
"
id
"
:
"
a
"
,
"
method
"
:
"
getAttachment
"
,
"
result
"
:
"
success
"
,
"
status
"
:
200
,
"
statusText
"
:
"
Ok
"
},
"
Get first attachment with range :_start:0, _end:undefined
"
);
},
function
(
err
)
{
deepEqual
(
err
,
"
no error
"
,
"
Check blob text content
"
);
});
}
function
getFirstAttachmentRange2
()
{
return
jio
.
getAttachment
({
"
_id
"
:
"
a
"
,
"
_attachment
"
:
"
aa
"
,
"
_start
"
:
0
,
"
_end
"
:
1
});
}
function
getFirstAttachmentRangeTest2
(
answer
)
{
var
blob
=
answer
.
data
;
answer
.
data
=
"
<blob>
"
;
return
jIO
.
util
.
readBlobAsText
(
blob
).
then
(
function
(
e
)
{
deepEqual
(
blob
.
type
,
"
text/plain
"
,
"
Check blob type
"
);
deepEqual
(
e
.
target
.
result
,
"
a
"
,
"
Check blob text content
"
);
deepEqual
(
answer
,
{
"
attachment
"
:
"
aa
"
,
"
data
"
:
"
<blob>
"
,
"
id
"
:
"
a
"
,
"
method
"
:
"
getAttachment
"
,
"
result
"
:
"
success
"
,
"
status
"
:
200
,
"
statusText
"
:
"
Ok
"
},
"
Get first attachment with range :_start:0, _end:1
"
);
},
function
(
err
)
{
deepEqual
(
err
,
"
no error
"
,
"
Check blob text content
"
);
});
}
function
getFirstAttachmentRange3
()
{
return
jio
.
getAttachment
({
"
_id
"
:
"
a
"
,
"
_attachment
"
:
"
aa
"
,
"
_start
"
:
1
,
"
_end
"
:
3
});
}
function
getFirstAttachmentRangeTest3
(
answer
)
{
var
blob
=
answer
.
data
;
answer
.
data
=
"
<blob>
"
;
return
jIO
.
util
.
readBlobAsText
(
blob
).
then
(
function
(
e
)
{
deepEqual
(
blob
.
type
,
"
text/plain
"
,
"
Check blob type
"
);
deepEqual
(
e
.
target
.
result
,
"
ab
"
,
"
Check blob text content
"
);
deepEqual
(
answer
,
{
"
attachment
"
:
"
aa
"
,
"
data
"
:
"
<blob>
"
,
"
id
"
:
"
a
"
,
"
method
"
:
"
getAttachment
"
,
"
result
"
:
"
success
"
,
"
status
"
:
200
,
"
statusText
"
:
"
Ok
"
},
"
Get first attachment with range :_start:1, _end:3
"
);
},
function
(
err
)
{
deepEqual
(
err
,
"
no error
"
,
"
Check blob text content
"
);
});
}
function
getSecondAttachment
()
{
return
jio
.
getAttachment
({
"
_id
"
:
"
a
"
,
"
_attachment
"
:
"
ab
"
});
}
function
getSecondAttachmentTest
(
answer
)
{
var
blob
=
answer
.
data
;
answer
.
data
=
"
<blob>
"
;
return
jIO
.
util
.
readBlobAsText
(
blob
).
then
(
function
(
e
)
{
deepEqual
(
blob
.
type
,
"
text/plain
"
,
"
Check blob type
"
);
deepEqual
(
e
.
target
.
result
,
"
aba
"
,
"
Check blob text content
"
);
deepEqual
(
answer
,
{
"
attachment
"
:
"
ab
"
,
"
data
"
:
"
<blob>
"
,
"
id
"
:
"
a
"
,
"
method
"
:
"
getAttachment
"
,
"
result
"
:
"
success
"
,
"
status
"
:
200
,
"
statusText
"
:
"
Ok
"
},
"
Get second attachment
"
);
},
function
(
err
)
{
deepEqual
(
err
,
"
no error
"
,
"
Check blob text content
"
);
});
}
function
getSecondAttachmentRange1
()
{
return
success
(
jio
.
getAttachment
({
"
_id
"
:
"
a
"
,
"
_attachment
"
:
"
ab
"
,
"
_start
"
:
-
1
}));
}
function
getSecondAttachmentRangeTest1
(
answer
)
{
deepEqual
(
answer
,
{
"
attachment
"
:
"
ab
"
,
"
error
"
:
"
not_found
"
,
"
id
"
:
"
a
"
,
"
message
"
:
"
_start and _end must be positive
"
,
"
method
"
:
"
getAttachment
"
,
"
reason
"
:
"
invalide _start, _end
"
,
"
result
"
:
"
error
"
,
"
status
"
:
404
,
"
statusText
"
:
"
Not Found
"
},
"
get attachment with _start or _end negative -> 404 Not Found
"
);
}
function
getSecondAttachmentRange2
()
{
return
success
(
jio
.
getAttachment
({
"
_id
"
:
"
a
"
,
"
_attachment
"
:
"
ab
"
,
"
_start
"
:
1
,
"
_end
"
:
0
}));
}
function
getSecondAttachmentRangeTest2
(
answer
)
{
deepEqual
(
answer
,
{
"
attachment
"
:
"
ab
"
,
"
error
"
:
"
not_found
"
,
"
id
"
:
"
a
"
,
"
message
"
:
"
start is great then end
"
,
"
method
"
:
"
getAttachment
"
,
"
reason
"
:
"
invalide offset
"
,
"
result
"
:
"
error
"
,
"
status
"
:
404
,
"
statusText
"
:
"
Not Found
"
},
"
get attachment with _start > _end -> 404 Not Found
"
);
}
function
getSecondAttachmentRange3
()
{
return
jio
.
getAttachment
({
"
_id
"
:
"
a
"
,
"
_attachment
"
:
"
ab
"
,
"
_start
"
:
1
,
"
_end
"
:
2
});
}
function
getSecondAttachmentRangeTest3
(
answer
)
{
var
blob
=
answer
.
data
;
answer
.
data
=
"
<blob>
"
;
return
jIO
.
util
.
readBlobAsText
(
blob
).
then
(
function
(
e
)
{
deepEqual
(
blob
.
type
,
"
text/plain
"
,
"
Check blob type
"
);
deepEqual
(
e
.
target
.
result
,
"
b
"
,
"
Check blob text content
"
);
deepEqual
(
answer
,
{
"
attachment
"
:
"
ab
"
,
"
data
"
:
"
<blob>
"
,
"
id
"
:
"
a
"
,
"
method
"
:
"
getAttachment
"
,
"
result
"
:
"
success
"
,
"
status
"
:
200
,
"
statusText
"
:
"
Ok
"
},
"
Get second attachment with range :_start:1, _end:3
"
);
},
function
(
err
)
{
deepEqual
(
err
,
"
no error
"
,
"
Check blob text content
"
);
});
}
function
getLastDocument
()
{
return
jio
.
get
({
"
_id
"
:
"
a
"
});
}
function
getLastDocumentTest
(
answer
)
{
deepEqual
(
answer
,
{
"
data
"
:
{
"
_id
"
:
"
a
"
,
"
title
"
:
"
Hoo
"
,
"
_attachment
"
:
{
"
aa
"
:
{
"
content_type
"
:
"
text/plain
"
,
"
length
"
:
3
},
"
ab
"
:
{
"
content_type
"
:
"
text/plain
"
,
"
length
"
:
3
}
}
},
"
id
"
:
"
a
"
,
"
method
"
:
"
get
"
,
"
result
"
:
"
success
"
,
"
status
"
:
200
,
"
statusText
"
:
"
Ok
"
},
"
Get last document metadata
"
);
}
function
removeSecondAttachment
()
{
return
jio
.
removeAttachment
({
"
_id
"
:
"
a
"
,
"
_attachment
"
:
"
ab
"
});
}
function
removeSecondAttachmentTest
(
answer
)
{
deepEqual
(
answer
,
{
"
attachment
"
:
"
ab
"
,
"
id
"
:
"
a
"
,
"
method
"
:
"
removeAttachment
"
,
"
result
"
:
"
success
"
,
"
status
"
:
204
,
"
statusText
"
:
"
No Content
"
},
"
Remove second document
"
);
}
function
getInexistentSecondAttachment
()
{
return
success
(
jio
.
getAttachment
({
"
_id
"
:
"
a
"
,
"
_attachment
"
:
"
ab
"
}));
}
function
getInexistentSecondAttachmentTest
(
answer
)
{
deepEqual
(
answer
,
{
"
attachment
"
:
"
ab
"
,
"
error
"
:
"
not_found
"
,
"
id
"
:
"
a
"
,
"
message
"
:
"
IndexeddbStorage, unable to get attachment.
"
,
"
method
"
:
"
getAttachment
"
,
"
reason
"
:
"
missing attachment
"
,
"
result
"
:
"
error
"
,
"
status
"
:
404
,
"
statusText
"
:
"
Not Found
"
},
"
Get inexistent second attachment
"
);
}
function
getOneAttachmentDocument
()
{
return
jio
.
get
({
"
_id
"
:
"
a
"
});
}
function
getOneAttachmentDocumentTest
(
answer
)
{
deepEqual
(
answer
,
{
"
data
"
:
{
"
_attachment
"
:
{
"
aa
"
:
{
"
content_type
"
:
"
text/plain
"
,
"
length
"
:
3
}
},
"
_id
"
:
"
a
"
,
"
title
"
:
"
Hoo
"
},
"
id
"
:
"
a
"
,
"
method
"
:
"
get
"
,
"
result
"
:
"
success
"
,
"
status
"
:
200
,
"
statusText
"
:
"
Ok
"
},
"
Get document metadata
"
);
}
function
removeSecondAttachmentAgain
()
{
return
success
(
jio
.
removeAttachment
({
"
_id
"
:
"
a
"
,
"
_attachment
"
:
"
ab
"
}));
}
function
removeSecondAttachmentAgainTest
(
answer
)
{
deepEqual
(
answer
,
{
"
attachment
"
:
"
ab
"
,
"
error
"
:
"
not_found
"
,
"
id
"
:
"
a
"
,
"
message
"
:
"
IndexeddbStorage, document attachment not found.
"
,
"
method
"
:
"
removeAttachment
"
,
"
reason
"
:
"
missing attachment
"
,
"
result
"
:
"
error
"
,
"
status
"
:
404
,
"
statusText
"
:
"
Not Found
"
},
"
Remove inexistent attachment
"
);
}
function
removeDocument
()
{
return
jio
.
remove
({
"
_id
"
:
"
a
"
});
}
function
removeDocumentTest
(
answer
)
{
deepEqual
(
answer
,
{
"
id
"
:
"
a
"
,
"
method
"
:
"
remove
"
,
"
result
"
:
"
success
"
,
"
status
"
:
204
,
"
statusText
"
:
"
No Content
"
},
"
Remove document and its attachments
"
);
}
function
getInexistentFirstAttachment
()
{
return
success
(
jio
.
getAttachment
({
"
_id
"
:
"
a
"
,
"
_attachment
"
:
"
aa
"
}));
}
function
getInexistentFirstAttachmentTest
(
answer
)
{
deepEqual
(
answer
,
{
"
attachment
"
:
"
aa
"
,
"
error
"
:
"
not_found
"
,
"
id
"
:
"
a
"
,
"
message
"
:
"
IndexeddbStorage, unable to get attachment.
"
,
"
method
"
:
"
getAttachment
"
,
"
reason
"
:
"
missing attachment
"
,
"
result
"
:
"
error
"
,
"
status
"
:
404
,
"
statusText
"
:
"
Not Found
"
},
"
Get inexistent first attachment
"
);
}
function
getInexistentDocument
()
{
return
success
(
jio
.
get
({
"
_id
"
:
"
a
"
}));
}
function
getInexistentDocumentTest
(
answer
)
{
deepEqual
(
answer
,
{
"
error
"
:
"
not_found
"
,
"
id
"
:
"
a
"
,
"
message
"
:
"
IndexeddbStorage, unable to get document.
"
,
"
method
"
:
"
get
"
,
"
reason
"
:
"
Not Found
"
,
"
result
"
:
"
error
"
,
"
status
"
:
404
,
"
statusText
"
:
"
Not Found
"
},
"
Get inexistent document
"
);
}
function
removeInexistentDocument
()
{
return
success
(
jio
.
remove
({
"
_id
"
:
"
a
"
}));
}
function
removeInexistentDocumentTest
(
answer
)
{
deepEqual
(
answer
,
{
"
error
"
:
"
not_found
"
,
"
id
"
:
"
a
"
,
"
message
"
:
"
IndexeddbStorage, unable to get metadata.
"
,
"
method
"
:
"
remove
"
,
"
reason
"
:
"
Not Found
"
,
"
result
"
:
"
error
"
,
"
status
"
:
404
,
"
statusText
"
:
"
Not Found
"
},
"
Remove already removed document
"
);
}
function
unexpectedError
(
error
)
{
if
(
error
instanceof
Error
)
{
deepEqual
([
error
.
name
+
"
:
"
+
error
.
message
,
error
],
"
UNEXPECTED ERROR
"
,
"
Unexpected error
"
);
}
else
{
deepEqual
(
error
,
"
UNEXPECTED ERROR
"
,
"
Unexpected error
"
);
}
}
// # Post new documents, list them and remove them
// post a 201
postNewDocument
().
then
(
postNewDocumentTest
).
// get 200
then
(
getCreatedDocument
).
then
(
getCreatedDocumentTest
).
// post b 201
then
(
postSpecificDocument
).
then
(
postSpecificDocumentTest
).
// allD 200 2 documents
then
(
listDocument
).
then
(
list2DocumentsTest
).
// allD+include_docs 200 2 documents
then
(
listDocumentsWithMetadata
).
then
(
list2DocumentsWithMetadataTest
).
// remove a 204
then
(
removeCreatedDocument
).
then
(
removeCreatedDocumentTest
).
// remove b 204
then
(
removeSpecificDocument
).
then
(
removeSpecificDocumentTest
).
// allD 200 empty storage
then
(
listEmptyStorage
).
then
(
listEmptyStorageTest
).
// # Create and update documents, and some attachment and remove them
// put 201
then
(
putNewDocument
).
then
(
putNewDocumentTest
).
// get 200
then
(
getCreatedDocument2
).
then
(
getCreatedDocument2Test
).
// post 409
then
(
postSameDocument
).
then
(
postSameDocumentTest
).
// putA 404
then
(
putAttachmentToNonExistentDocument
).
then
(
putAttachmentToNonExistentDocumentTest
).
// putA a 204
then
(
createAttachment
).
then
(
createAttachmentTest
).
// putA a 204
then
(
updateAttachment
).
then
(
updateAttachmentTest
).
// putA b 204
then
(
createAnotherAttachment
).
then
(
createAnotherAttachmentTest
).
// put 204
then
(
updateLastDocument
).
then
(
updateLastDocumentTest
).
// getA a 200
then
(
getFirstAttachment
).
then
(
getFirstAttachmentTest
).
then
(
getFirstAttachmentRange1
).
then
(
getFirstAttachmentRangeTest1
).
then
(
getFirstAttachmentRange2
).
then
(
getFirstAttachmentRangeTest2
).
then
(
getFirstAttachmentRange3
).
then
(
getFirstAttachmentRangeTest3
).
// getA b 200
then
(
getSecondAttachment
).
then
(
getSecondAttachmentTest
).
then
(
getSecondAttachmentRange1
).
then
(
getSecondAttachmentRangeTest1
).
then
(
getSecondAttachmentRange2
).
then
(
getSecondAttachmentRangeTest2
).
then
(
getSecondAttachmentRange3
).
then
(
getSecondAttachmentRangeTest3
).
// get 200
then
(
getLastDocument
).
then
(
getLastDocumentTest
).
// removeA b 204
then
(
removeSecondAttachment
).
then
(
removeSecondAttachmentTest
).
// getA b 404
then
(
getInexistentSecondAttachment
).
then
(
getInexistentSecondAttachmentTest
).
// get 200
then
(
getOneAttachmentDocument
).
then
(
getOneAttachmentDocumentTest
).
// removeA b 404
then
(
removeSecondAttachmentAgain
).
then
(
removeSecondAttachmentAgainTest
).
// remove 204
then
(
removeDocument
).
then
(
removeDocumentTest
).
// getA a 404
then
(
getInexistentFirstAttachment
).
then
(
getInexistentFirstAttachmentTest
).
// get 404
then
(
getInexistentDocument
).
then
(
getInexistentDocumentTest
).
// remove 404
then
(
removeInexistentDocument
).
then
(
removeInexistentDocumentTest
).
// end
fail
(
unexpectedError
).
always
(
start
).
always
(
function
()
{
server
.
restore
();
});
});
}));
test/tests.html
View file @
c74c465d
...
...
@@ -57,7 +57,15 @@
<script
src=
"../src/jio.storage/querystorage.js"
></script>
<script
src=
"../test/jio.storage/querystorage.tests.js"
></script>
<script
src=
"../src/jio.storage/replicatestorage.js"
></script>
<script
src=
"../test/jio.storage/replicatestorage.tests.js"
></script>
<!--
<script src="../src/jio.storage/indexeddbstorage.js"></script>
<script src="../test/jio.storage/indexeddbstorage.tests.js"></script>
-->
</body>
</html>
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment