Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
jio_mebibou
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
Alexandra Rogova
jio_mebibou
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