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
2ae42bb4
Commit
2ae42bb4
authored
Apr 05, 2013
by
Tristan Cavelier
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
dav: post, put, putAttachment and get updated + test
parent
6e6a56d0
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
695 additions
and
466 deletions
+695
-466
src/jio.storage/davstorage.js
src/jio.storage/davstorage.js
+450
-346
test/jiotests.js
test/jiotests.js
+245
-120
No files found.
src/jio.storage/davstorage.js
View file @
2ae42bb4
...
...
@@ -3,147 +3,259 @@
* Released under the LGPL license.
* http://www.gnu.org/licenses/lgpl.html
*/
/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */
/*global jIO: true, $: true, btoa: true */
jIO
.
addStorageType
(
'
dav
'
,
function
(
spec
,
my
)
{
spec
=
spec
||
{};
var
that
,
priv
,
super_serialized
;
that
=
my
.
basicStorage
(
spec
,
my
);
priv
=
{};
super_serialized
=
that
.
serialized
;
priv
.
secureDocId
=
function
(
string
)
{
var
split
=
string
.
split
(
'
/
'
),
i
;
if
(
split
[
0
]
===
''
)
{
split
=
split
.
slice
(
1
);
}
for
(
i
=
0
;
i
<
split
.
length
;
i
+=
1
)
{
if
(
split
[
i
]
===
''
)
{
return
''
;
// JIO Dav Storage Description :
// {
// type: "dav",
// url: {string}
// }
// {
// type: "dav",
// url: {string},
// auth_type: {string}, (optional)
// - "auto" (default) (not implemented)
// - "basic"
// - "digest" (not implemented)
// realm: {string}, (optional)
// - undefined (default) (not implemented)
// - "<string>" realm name (not implemented)
// username: {string},
// password: {string} (optional)
// }
// {
// type: "dav",
// url: {string},
// encoded_login: {string}
// }
// {
// type: "dav",
// url: {string},
// secured_login: {string} (not implemented)
// }
// NOTE: to get the authentication type ->
// curl --verbose -X OPTION http://domain/
// In the headers: "WWW-Authenticate: Basic realm="DAV-upload"
// URL Characters convertion:
// If I want to retrieve the file which id is -> http://100%.json
// http://domain/collection/http://100%.json cannot be applied
// - '/' is col separator,
// - '%' is special char
// - '.' document and attachment separator
// http://100%.json will become
// - http:%2F%2F100%25.json to avoid bad request ('/', '%' -> '%2F', '%25')
// - http:%2F%2F100%25_.json to avoid ids conflicts ('.' -> '_.')
// - http:%252F%252F100%2525_.json to avoid request bad interpretation
// ('%', '%25')
// The file will be saved as http:%2F%2F100%25_.json
jIO
.
addStorageType
(
"
dav
"
,
function
(
spec
,
my
)
{
var
priv
=
{},
that
=
my
.
basicStorage
(
spec
,
my
),
dav
=
{};
// ATTRIBUTES //
priv
.
url
=
null
;
priv
.
username
=
null
;
priv
.
password
=
null
;
priv
.
encoded_login
=
null
;
// CONSTRUCTOR //
/**
* Init the dav storage connector thanks to the description
* @method __init__
* @param {object} description The description object
*/
priv
.
__init__
=
function
(
description
)
{
priv
.
url
=
description
.
url
||
""
;
priv
.
url
=
priv
.
removeSlashIfLast
(
priv
.
url
);
// if (description.secured_login) {
// not implemented
// } else
if
(
description
.
encoded_login
)
{
priv
.
encoded_login
=
description
.
encoded_login
;
}
else
if
(
description
.
auth_type
)
{
if
(
description
.
auth_type
===
"
basic
"
)
{
priv
.
encoded_login
=
"
Basic
"
+
btoa
((
description
.
username
||
""
)
+
"
:
"
+
(
description
.
password
||
""
));
}
}
else
{
priv
.
encoded_login
=
""
;
}
return
split
.
join
(
'
%2F
'
);
};
priv
.
convertSlashes
=
function
(
string
)
{
return
string
.
split
(
'
/
'
).
join
(
'
%2F
'
);
// OVERRIDES //
that
.
specToStore
=
function
()
{
// TODO: secured password
// The encoded_login can be seen by anyone, we must find a way to secure it!
// secured_login = encrypt(encoded_login)
// encoded_login = decrypt(secured_login)
return
{
"
url
"
:
priv
.
url
,
"
encoded_login
"
:
priv
.
encoded_login
};
};
priv
.
restoreSlashes
=
function
(
string
)
{
return
string
.
split
(
'
%2F
'
).
join
(
'
/
'
);
that
.
validateState
=
function
()
{
if
(
typeof
priv
.
url
!==
"
string
"
||
priv
.
url
===
""
)
{
return
"
The webDav server URL is not provided
"
;
}
if
(
priv
.
encoded_login
===
null
)
{
return
"
Impossible to create the authorization
"
;
}
return
""
;
};
// TOOLS //
/**
* Generate a new uuid
* @method generateUuid
* @return {string} The new uuid
*/
priv
.
generateUuid
=
function
()
{
var
S4
=
function
()
{
/* 65536 */
var
i
,
string
=
Math
.
floor
(
Math
.
random
()
*
0x10000
).
toString
(
16
);
for
(
i
=
string
.
length
;
i
<
4
;
i
+=
1
)
{
string
=
"
0
"
+
string
;
}
return
string
;
};
return
S4
()
+
S4
()
+
"
-
"
+
S4
()
+
"
-
"
+
S4
()
+
"
-
"
+
S4
()
+
"
-
"
+
S4
()
+
S4
()
+
S4
();
};
// /**
// * Clones an object in deep
// * @method clone
// * @param {object} object The object to clone
// * @return {object} The cloned object
// */
// priv.clone = function (object) {
// var tmp = JSON.stringify(object);
// if (tmp === undefined) {
// return undefined;
// }
// return JSON.parse(tmp);
// };
/**
* Checks if an object has no enumerable keys
* @method objectIsEmpty
* @param {object} obj The object
* @return {boolean} true if empty, else false
* Replace substrings to another strings
* @method recursiveReplace
* @param {string} string The string to do replacement
* @param {array} list_of_replacement An array of couple
* ["substring to select", "selected substring replaced by this string"].
* @return {string} The replaced string
*/
priv
.
objectIsEmpty
=
function
(
obj
)
{
var
k
;
for
(
k
in
obj
)
{
if
(
obj
.
hasOwnProperty
(
k
))
{
return
false
;
priv
.
recursiveReplace
=
function
(
string
,
list_of_replacement
)
{
var
i
,
split_string
=
string
.
split
(
list_of_replacement
[
0
][
0
]);
if
(
list_of_replacement
[
1
])
{
for
(
i
=
0
;
i
<
split_string
.
length
;
i
+=
1
)
{
split_string
[
i
]
=
priv
.
recursiveReplace
(
split_string
[
i
],
list_of_replacement
.
slice
(
1
)
);
}
}
return
true
;
return
split_string
.
join
(
list_of_replacement
[
0
][
1
])
;
};
priv
.
username
=
spec
.
username
||
''
;
priv
.
secured_username
=
priv
.
convertSlashes
(
priv
.
username
);
priv
.
password
=
spec
.
password
||
''
;
priv
.
url
=
spec
.
url
||
''
;
that
.
serialized
=
function
()
{
var
o
=
super_serialized
();
o
.
username
=
priv
.
username
;
o
.
url
=
priv
.
url
;
o
.
password
=
priv
.
password
;
return
o
;
/**
* Changes / to %2F, % to %25 and . to _.
* @method secureName
* @param {string} name The name to secure
* @return {string} The secured name
*/
priv
.
secureName
=
function
(
name
)
{
return
priv
.
recursiveReplace
(
name
,
[[
"
/
"
,
"
%2F
"
],
[
"
%
"
,
"
%25
"
]]);
};
priv
.
newAsyncModule
=
function
()
{
var
async
=
{};
async
.
call
=
function
(
obj
,
function_name
,
arglist
)
{
obj
.
_wait
=
obj
.
_wait
||
{};
if
(
obj
.
_wait
[
function_name
])
{
obj
.
_wait
[
function_name
]
-=
1
;
return
function
()
{};
}
// ok if undef or 0
arglist
=
arglist
||
[];
return
obj
[
function_name
].
apply
(
obj
[
function_name
],
arglist
);
};
async
.
neverCall
=
function
(
obj
,
function_name
)
{
obj
.
_wait
=
obj
.
_wait
||
{};
obj
.
_wait
[
function_name
]
=
-
1
;
};
async
.
wait
=
function
(
obj
,
function_name
,
times
)
{
obj
.
_wait
=
obj
.
_wait
||
{};
obj
.
_wait
[
function_name
]
=
times
;
};
async
.
end
=
function
()
{
async
.
call
=
function
()
{};
};
return
async
;
/**
* Restores the original name from a secured name
* @method restoreName
* @param {string} secured_name The secured name to restore
* @return {string} The original name
*/
priv
.
restoreName
=
function
(
secured_name
)
{
return
priv
.
recursiveReplace
(
secured_name
,
[[
"
%2F
"
,
"
/
"
],
[
"
%25
"
,
"
%
"
]]);
};
/**
* Checks if a browser supports cors (cross domain ajax requests)
* @method checkCors
* @return {boolean} true if supported, else false
* Convert document id and attachment id to a file name
* @method idsToFileName
* @param {string} doc_id The document id
* @param {string} attachment_id The attachment id (optional)
* @return {string} The file name
*/
priv
.
checkCors
=
function
()
{
return
$
.
support
.
cors
;
priv
.
idsToFileName
=
function
(
doc_id
,
attachment_id
)
{
doc_id
=
priv
.
secureName
(
doc_id
).
split
(
"
.
"
).
join
(
"
_.
"
);
if
(
typeof
attachment_id
===
"
string
"
)
{
attachment_id
=
priv
.
secureName
(
attachment_id
).
split
(
"
.
"
).
join
(
"
_.
"
);
return
doc_id
+
"
.
"
+
attachment_id
;
}
return
doc_id
;
};
/**
* Re
places last "." with "_." in document filenames
* @method
underscoreFileExtenisons
* @param
{string} url url to clean up
* @return {string}
clean_url cleaned up URL
* Re
moves the last character if it is a "/". "/a/b/c/" become "/a/b/c"
* @method
removeSlashIfLast
* @param
{string} string The string to modify
* @return {string}
The modified string
*/
priv
.
underscoreFileExtenisons
=
function
(
url
)
{
var
clean_url
=
url
.
replace
(
/,
\s(\w
+
)
$/
,
"
_.$1
"
);
return
clean_url
;
priv
.
removeSlashIfLast
=
function
(
string
)
{
if
(
string
[
string
.
length
-
1
]
===
"
/
"
)
{
return
string
.
slice
(
0
,
-
1
);
}
return
string
;
};
/**
* Replaces "_." with "." in document filenames
* @method restoreDots
* @param {string} url url to clean up
* @return {string} clean_url cleaned up URL
* Modify an ajax object to add default values
* @method makeAjaxObject
* @param {string} file_name The file name to add to the url
* @param {object} ajax_object The ajax object to override
* @return {object} A new ajax object with default values
*/
priv
.
restoreDots
=
function
(
url
)
{
var
clean_url
=
url
.
replace
(
/_
\.
/g
,
'
.
'
);
return
clean_url
;
priv
.
makeAjaxObject
=
function
(
file_name
,
method
,
ajax_object
)
{
ajax_object
.
type
=
method
||
ajax_object
.
type
||
"
GET
"
;
ajax_object
.
url
=
priv
.
url
+
"
/
"
+
priv
.
secureName
(
file_name
)
+
"
?_=
"
+
Date
.
now
();
ajax_object
.
async
=
ajax_object
.
async
===
false
?
false
:
true
;
ajax_object
.
crossdomain
=
ajax_object
.
crossdomain
===
false
?
false
:
true
;
ajax_object
.
headers
=
ajax_object
.
headers
||
{};
ajax_object
.
headers
.
Authorization
=
ajax_object
.
headers
.
Authorization
||
priv
.
encoded_login
;
return
ajax_object
;
};
/**
* Runs all ajax requests for davStorage
* @method ajax
* @param {object} ajax_object The request parameters
* @param {string} doc_id The document id
* @param {string} attachment_id The attachment id, can be undefined
* @param {string} method The request method
* @param {object} ajax_object The request parameters (optional)
*/
priv
.
ajax
=
function
(
ajax_object
)
{
$
.
ajax
({
url
:
ajax_object
.
url
,
type
:
ajax_object
.
type
,
async
:
true
,
dataType
:
ajax_object
.
dataType
||
null
,
data
:
ajax_object
.
data
||
null
,
crossdomain
:
true
,
headers
:
{
Authorization
:
'
Basic
'
+
btoa
(
priv
.
username
+
'
:
'
+
priv
.
password
),
Depth
:
ajax_object
.
headers
===
undefined
?
null
:
ajax_object
.
headers
.
depth
},
// xhrFields: {withCredentials: 'true'},
success
:
ajax_object
.
success
,
error
:
ajax_object
.
error
});
priv
.
ajax
=
function
(
doc_id
,
attachment_id
,
method
,
ajax_object
)
{
var
new_ajax_object
=
JSON
.
parse
(
JSON
.
stringify
(
ajax_object
)
||
"
{}
"
);
console
.
log
(
priv
.
makeAjaxObject
(
priv
.
idsToFileName
(
doc_id
,
attachment_id
),
method
,
new_ajax_object
));
return
$
.
ajax
(
priv
.
makeAjaxObject
(
priv
.
idsToFileName
(
doc_id
,
attachment_id
),
method
,
new_ajax_object
));
//.always(then || function () {});
};
/**
...
...
@@ -153,57 +265,123 @@ jIO.addStorageType('dav', function (spec, my) {
* @return {object} error The error object
*/
priv
.
createError
=
function
(
status
,
message
,
reason
)
{
var
error
=
{};
var
error
=
{
"
status
"
:
status
,
"
message
"
:
message
,
"
reason
"
:
reason
};
switch
(
status
)
{
case
404
:
error
.
status
=
status
;
error
.
statusText
=
"
Not found
"
;
error
.
error
=
"
not_found
"
;
error
.
message
=
message
;
error
.
reason
=
reason
;
break
;
case
405
:
error
.
status
=
status
;
error
.
statusText
=
"
Method Not Allowed
"
;
error
.
error
=
"
method_not_allowed
"
;
error
.
message
=
message
;
error
.
reason
=
reason
;
break
;
case
409
:
error
.
status
=
status
;
error
.
statusText
=
"
Conflicts
"
;
error
.
error
=
"
conflicts
"
;
error
.
message
=
message
;
error
.
reason
=
reason
;
break
;
case
24
:
error
.
statusText
=
"
Broken Document
"
;
break
;
}
error
.
error
=
error
.
statusText
.
toLowerCase
().
split
(
"
"
).
join
(
"
_
"
);
return
error
;
};
/**
* Check if method can be run on browser
* @method support
* Converts ajax error object to a JIO error object
* @method ajaxErrorToJioError
* @param {object} ajax_error_object The ajax error object
* @param {string} message The error message
* @param {string} reason The error reason
* @return {object} The JIO error object
*/
priv
.
support
=
function
(
docid
)
{
// no docId
if
(
!
(
typeof
docid
===
"
string
"
&&
docid
!==
""
))
{
that
.
error
(
priv
.
createError
(
405
,
"
Can't create document without id
"
,
"
Document id is undefined
"
));
return
true
;
priv
.
ajaxErrorToJioError
=
function
(
ajax_error_object
,
message
,
reason
)
{
var
jio_error_object
=
{};
jio_error_object
.
status
=
ajax_error_object
.
status
;
jio_error_object
.
statusText
=
ajax_error_object
.
statusText
;
jio_error_object
.
error
=
ajax_error_object
.
statusText
.
toLowerCase
().
split
(
"
"
).
join
(
"
_
"
);
jio_error_object
.
message
=
message
;
jio_error_object
.
reason
=
reason
;
return
jio_error_object
;
};
/**
* Function that create an object containing jQuery like callbacks
* @method makeJQLikeCallback
* @return {object} jQuery like callback methods
*/
priv
.
makeJQLikeCallback
=
function
()
{
var
result
=
null
,
emptyFun
=
function
()
{},
jql
=
{
"
respond
"
:
function
()
{
result
=
arguments
;
},
"
to_return
"
:
{
"
always
"
:
function
(
func
)
{
if
(
result
)
{
func
.
apply
(
func
,
result
);
jql
.
to_return
.
always
=
emptyFun
;
}
else
{
jql
.
respond
=
func
;
}
// no cross domain ajax
if
(
priv
.
checkCors
===
false
)
{
that
.
error
(
priv
.
createError
(
405
,
"
Browser does not support cross domain ajax
"
,
"
CORS is undefined
"
));
return
true
;
return
jql
.
to_return
;
},
"
then
"
:
function
(
func
)
{
if
(
result
)
{
func
(
result
[
1
]);
jql
.
to_return
.
then
=
emptyFun
;
}
else
{
jql
.
respond
=
function
(
err
,
response
)
{
func
(
response
);
};
}
return
jql
.
to_return
;
}
}
};
return
jql
;
};
// DAV REQUESTS //
/**
* Retrieve a document
* @method dav.getDocument
* @param {string} doc_id The document id
* @param {function} then The callback(err, response)
*/
dav
.
getDocument
=
function
(
doc_id
)
{
var
doc
,
jql
=
priv
.
makeJQLikeCallback
();
priv
.
ajax
(
doc_id
,
undefined
,
"
GET
"
).
always
(
function
(
one
,
state
,
three
)
{
if
(
state
!==
"
success
"
)
{
jql
.
respond
(
priv
.
ajaxErrorToJioError
(
one
,
"
Cannot retrieve document
"
,
"
Unknown error
"
),
undefined
);
}
else
{
try
{
doc
=
JSON
.
parse
(
one
);
}
catch
(
e
)
{
return
jql
.
respond
(
priv
.
createError
(
24
,
"
Cannot parse document
"
,
"
Document is broken
"
),
undefined
);
}
// document health is good
jql
.
respond
(
undefined
,
doc
);
}
});
return
jql
.
to_return
;
};
dav
.
putDocument
=
function
(
doc
)
{
// TODO
};
// JIO COMMANDS //
// wedDav methods rfc4918 (short summary)
// COPY Reproduces single resources (files) and collections (directory
// trees). Will overwrite files (if specified by request) but will
...
...
@@ -229,89 +407,54 @@ jIO.addStorageType('dav', function (spec, my) {
// adding custom headers triggers preflight OPTIONS request!
// http://remysharp.com/2011/04/21/getting-cors-working/
priv
.
putOrPost
=
function
(
command
,
type
)
{
var
docid
=
command
.
getDocId
(),
secured_docid
,
url
,
ajax_object
;
if
(
priv
.
support
(
docid
))
{
return
;
}
secured_docid
=
priv
.
secureDocId
(
command
.
getDocId
());
url
=
priv
.
url
+
'
/
'
+
priv
.
underscoreFileExtenisons
(
secured_docid
);
ajax_object
=
{
url
:
url
+
'
?_=
'
+
Date
.
now
(),
type
:
"
GET
"
,
dataType
:
"
text
"
,
success
:
function
()
{
if
(
type
===
'
POST
'
)
{
// POST the document already exists
that
.
error
(
priv
.
createError
(
409
,
"
Cannot create a new document
"
,
"
Document already exists
"
/**
* Creates a new document
* @method post
* @param {object} command The JIO command
*/
that
.
post
=
function
(
command
)
{
var
doc_id
=
command
.
getDocId
()
||
priv
.
generateUuid
();
priv
.
ajax
(
doc_id
,
undefined
,
"
GET
"
).
always
(
function
(
one
,
state
,
three
)
{
if
(
state
!==
"
success
"
)
{
if
(
one
.
status
===
404
)
{
// the document does not already exist
// updating document
priv
.
ajax
(
doc_id
,
undefined
,
"
PUT
"
,
{
"
dataType
"
:
"
text
"
,
"
data
"
:
JSON
.
stringify
(
command
.
cloneDoc
())
}).
always
(
function
(
one
,
state
,
three
)
{
if
(
state
!==
"
success
"
)
{
// an error occured
that
.
retry
(
priv
.
ajaxErrorToJioError
(
one
,
"
An error occured when trying to PUT data
"
,
"
Unknown
"
));
return
;
}
ajax_object
=
{
url
:
url
,
type
:
type
,
data
:
JSON
.
stringify
(
command
.
getDoc
()),
success
:
function
()
{
}
else
{
// document updated
that
.
success
({
ok
:
true
,
id
:
command
.
getDocId
()
"
ok
"
:
true
,
"
id
"
:
doc_id
});
},
error
:
function
()
{
that
.
error
(
priv
.
createError
(
409
,
"
Cannot modify document
"
,
"
Error writing to remote storage
"
));
}
};
priv
.
ajax
(
ajax_object
);
},
error
:
function
(
err
)
{
// Firefox returns 0 instead of 404 on CORS?
if
(
err
.
status
===
404
||
err
.
status
===
0
)
{
ajax_object
=
{
url
:
url
,
type
:
"
PUT
"
,
data
:
JSON
.
stringify
(
command
.
getDoc
()),
success
:
function
()
{
that
.
success
({
ok
:
true
,
id
:
command
.
getDocId
()
});
},
error
:
function
()
{
that
.
error
(
priv
.
createError
(
409
,
"
Cannot modify document
"
,
"
Error writing to remote storage
"
}
else
{
// an error occured
that
.
retry
(
priv
.
ajaxErrorToJioError
(
one
,
"
An error occured when trying to GET data
"
,
"
Unknown
"
));
}
};
priv
.
ajax
(
ajax_object
);
}
else
{
// error accessing remote storage
that
.
error
({
"
status
"
:
err
.
status
,
"
statusText
"
:
err
.
statusText
,
"
error
"
:
"
error
"
,
"
message
"
:
err
.
message
,
"
reason
"
:
"
Failed to access remote storage
"
});
}
// the document already exists
that
.
error
(
priv
.
createError
(
405
,
"
Cannot create document
"
,
"
Document already exists
"
));
}
};
priv
.
ajax
(
ajax_object
);
};
/**
* Creates a new document
* @method post
* @param {object} command The JIO command
*/
that
.
post
=
function
(
command
)
{
priv
.
putOrPost
(
command
,
'
POST
'
);
});
};
/**
...
...
@@ -320,7 +463,26 @@ jIO.addStorageType('dav', function (spec, my) {
* @param {object} command The JIO command
*/
that
.
put
=
function
(
command
)
{
priv
.
putOrPost
(
command
,
'
PUT
'
);
var
doc_id
=
command
.
getDocId
();
priv
.
ajax
(
doc_id
,
undefined
,
"
PUT
"
,
{
"
dataType
"
:
"
text
"
,
"
data
"
:
JSON
.
stringify
(
command
.
cloneDoc
())
}).
always
(
function
(
one
,
state
,
three
)
{
if
(
state
!==
"
success
"
)
{
// an error occured
that
.
retry
(
priv
.
ajaxErrorToJioError
(
one
,
"
Cannot update document
"
,
"
Unknown error
"
));
}
else
{
// document updated
that
.
success
({
"
ok
"
:
true
,
"
id
"
:
doc_id
});
}
});
};
/**
...
...
@@ -329,149 +491,90 @@ jIO.addStorageType('dav', function (spec, my) {
* @param {object} command The JIO command
*/
that
.
putAttachment
=
function
(
command
)
{
var
docid
=
command
.
getDocId
(),
doc
,
url
,
secured_docid
,
secured_attachmentid
,
attachment_url
,
ajax_object
;
priv
.
support
(
docid
);
secured_docid
=
priv
.
secureDocId
(
docid
);
url
=
priv
.
url
+
'
/
'
+
priv
.
underscoreFileExtenisons
(
secured_docid
);
ajax_object
=
{
url
:
url
+
'
?_=
'
+
Date
.
now
(),
type
:
'
GET
'
,
dataType
:
'
text
'
,
success
:
function
(
response
)
{
doc
=
JSON
.
parse
(
response
);
// the document exists - update document
var
doc
=
null
,
doc_id
=
command
.
getDocId
(),
attachment_id
,
tmp
;
attachment_id
=
command
.
getAttachmentId
();
priv
.
ajax
(
doc_id
,
undefined
,
"
GET
"
).
always
(
function
(
one
,
state
,
three
)
{
if
(
state
!==
"
success
"
)
{
// document not found or error
tmp
=
that
.
retry
;
if
(
one
.
status
===
404
)
{
tmp
=
that
.
error
;
}
tmp
(
priv
.
ajaxErrorToJioError
(
one
,
"
Cannot update document
"
,
"
Unknown error
"
));
}
else
{
try
{
doc
=
JSON
.
parse
(
one
);
}
catch
(
e
)
{
return
that
.
error
(
priv
.
createError
(
24
,
"
Cannot upload attachment
"
,
"
Document is broken
"
));
}
// document health is good
doc
.
_attachments
=
doc
.
_attachments
||
{};
doc
.
_attachments
[
command
.
getAttachmentId
()
]
=
{
"
content_type
"
:
command
.
getAttachmentMimeType
(),
doc
.
_attachments
[
attachment_id
]
=
{
"
length
"
:
command
.
getAttachmentLength
(),
"
digest
"
:
"
md5-
"
+
command
.
md5SumAttachmentData
(),
"
length
"
:
command
.
getAttachmentLength
()
};
// put updated document data
ajax_object
=
{
url
:
url
+
'
?_=
'
+
Date
.
now
(),
type
:
'
PUT
'
,
data
:
JSON
.
stringify
(
doc
),
success
:
function
()
{
secured_attachmentid
=
priv
.
secureDocId
(
command
.
getAttachmentId
());
attachment_url
=
url
+
'
.
'
+
priv
.
underscoreFileExtenisons
(
secured_attachmentid
);
ajax_object
=
{
url
:
attachment_url
+
'
?_=
'
+
Date
.
now
(),
type
:
'
PUT
'
,
data
:
JSON
.
stringify
(
command
.
getDoc
()),
success
:
function
()
{
"
content_type
"
:
command
.
getAttachmentMimeType
()
};
// put the attachment
priv
.
ajax
(
doc_id
,
attachment_id
,
"
PUT
"
,
{
"
dataType
"
:
"
text
"
,
"
data
"
:
command
.
getAttachmentData
()
}).
always
(
function
(
one
,
state
,
three
)
{
if
(
state
!==
"
success
"
)
{
// an error occured
that
.
retry
(
priv
.
ajaxErrorToJioError
(
one
,
"
An error occured when trying to PUT data
"
,
"
Unknown
"
));
}
else
{
// update the document
priv
.
ajax
(
doc_id
,
undefined
,
"
PUT
"
,
{
"
dataType
"
:
"
text
"
,
"
data
"
:
JSON
.
stringify
(
doc
)
}).
always
(
function
(
one
,
state
,
three
)
{
if
(
state
!==
"
success
"
)
{
that
.
retry
(
priv
.
ajaxErrorToJioError
(
one
,
"
An error occured when trying to PUT data
"
,
"
Unknown
"
));
}
else
{
that
.
success
({
ok
:
true
,
id
:
command
.
getDocId
()
+
'
/
'
+
command
.
getAttachmentId
()
"
ok
"
:
true
,
"
id
"
:
doc_id
,
"
attachment
"
:
attachment_id
});
},
error
:
function
()
{
that
.
error
(
priv
.
createError
(
409
,
"
Cannot modify document
"
,
"
Error when saving attachment
"
));
return
;
}
};
priv
.
ajax
(
ajax_object
);
},
error
:
function
()
{
that
.
error
(
priv
.
createError
(
409
,
"
Cannot modify document
"
,
"
Error writing to remote storage
"
));
return
;
});
}
};
priv
.
ajax
(
ajax_object
);
},
error
:
function
()
{
// the document does not exist
that
.
error
(
priv
.
createError
(
404
,
"
Impossible to add attachment
"
,
"
Document not found
"
));
return
;
});
}
};
// see if the underlying document exists
priv
.
ajax
(
ajax_object
);
});
};
/**
* Get a document or attachment from distant storage
* Options:
* - {boolean} revs Add simple revision history (false by default).
* - {boolean} revs_info Add revs info (false by default).
* - {boolean} conflicts Add conflict object (false by default).
* Get a document
* @method get
* @param {object} command The JIO command
*/
that
.
get
=
function
(
command
)
{
var
docid
=
command
.
getDocId
(),
doc
,
url
,
secured_docid
,
secured_attachmentid
,
attachment_url
,
ajax_object
;
if
(
priv
.
support
(
docid
))
{
return
;
dav
.
getDocument
(
command
.
getDocId
()).
always
(
function
(
err
,
response
)
{
if
(
err
)
{
if
(
err
.
status
===
404
)
{
return
that
.
error
(
err
);
}
secured_docid
=
priv
.
secureDocId
(
command
.
getDocId
());
url
=
priv
.
url
+
'
/
'
+
priv
.
underscoreFileExtenisons
(
secured_docid
);
if
(
typeof
command
.
getAttachmentId
()
===
"
string
"
)
{
secured_attachmentid
=
priv
.
secureDocId
(
command
.
getAttachmentId
());
attachment_url
=
url
+
'
.
'
+
priv
.
underscoreFileExtenisons
(
secured_attachmentid
);
// get attachment
ajax_object
=
{
url
:
attachment_url
+
'
?_=
'
+
Date
.
now
(),
type
:
"
GET
"
,
dataType
:
"
text
"
,
success
:
function
(
response
)
{
doc
=
JSON
.
parse
(
response
);
that
.
success
(
doc
);
},
error
:
function
()
{
that
.
error
(
priv
.
createError
(
404
,
"
Cannot find the attachment
"
,
"
Attachment does not exist
"
));
}
};
priv
.
ajax
(
ajax_object
);
}
else
{
// get document
ajax_object
=
{
url
:
url
+
'
?_=
'
+
Date
.
now
(),
type
:
"
GET
"
,
dataType
:
"
text
"
,
success
:
function
(
response
)
{
// metadata_only should not be handled by jIO, as it is a
// webDav only option, shouldn't it?
// ditto for content_only
doc
=
JSON
.
parse
(
response
);
that
.
success
(
doc
);
},
error
:
function
()
{
that
.
error
(
priv
.
createError
(
404
,
"
Cannot find the document
"
,
"
Document does not exist
"
));
}
};
priv
.
ajax
(
ajax_object
);
return
that
.
retry
(
err
);
}
return
that
.
success
(
response
);
});
};
/**
...
...
@@ -479,7 +582,7 @@ jIO.addStorageType('dav', function (spec, my) {
* @method remove
* @param {object} command The JIO command
*/
that
.
remove
=
function
(
command
)
{
that
.
_
remove
=
function
(
command
)
{
var
docid
=
command
.
getDocId
(),
doc
,
url
,
secured_docid
,
secured_attachmentid
,
attachment_url
,
attachment_list
=
[],
i
,
j
,
k
=
1
,
deleteAttachment
,
ajax_object
;
...
...
@@ -666,7 +769,7 @@ jIO.addStorageType('dav', function (spec, my) {
// },{...}
// ]
//}
that
.
allDocs
=
function
(
command
)
{
that
.
_
allDocs
=
function
(
command
)
{
var
rows
=
[],
url
,
am
=
priv
.
newAsyncModule
(),
o
=
{},
...
...
@@ -762,5 +865,6 @@ jIO.addStorageType('dav', function (spec, my) {
am
.
call
(
o
,
'
getDocumentList
'
);
};
priv
.
__init__
(
spec
);
return
that
;
});
test/jiotests.js
View file @
2ae42bb4
...
...
@@ -164,7 +164,6 @@ generateTools = function (test_namespace) {
var
o
=
{};
o
.
t
=
test_namespace
;
o
.
server
=
o
.
t
.
sandbox
.
useFakeServer
();
o
.
clock
=
sinon
.
useFakeTimers
();
o
.
clock
.
tick
(
base_tick
);
o
.
spy
=
basicSpyFunction
;
...
...
@@ -3471,7 +3470,7 @@ module ("JIO Replicate Revision Storage");
}]
},
"
2
"
);
});
/*
module
(
"
Jio DAVStorage
"
);
test
(
"
Post
"
,
function
()
{
...
...
@@ -3480,31 +3479,96 @@ test ("Post", function () {
o
.
jio
=
JIO
.
newJio
({
"
type
"
:
"
dav
"
,
"username": "davpost",
"password": "checkpwd",
"url": "https://ca-davstorage:8080"
"
url
"
:
"
https://ca-davstorage:8080
"
,
"
auth_type
"
:
"
basic
"
,
"
username
"
:
"
admin
"
,
"
password
"
:
"
pwd
"
});
// post without id
o.spy (o, "status", 405, "Post without id");
o.jio.post({}, o.f);
o.clock.tick(5000);
o
.
server
=
sinon
.
fakeServer
.
create
();
o
.
server
.
respondWith
(
"
GET
"
,
/https:
\/\/
ca-davstorage:8080
\/[
0-9a-fA-F
]{4}
/
,
[
404
,
{
"
Content-Type
"
:
"
text/html
"
},
"
<h1>Document not found</h1>
"
]
);
o
.
server
.
respondWith
(
"
PUT
"
,
/https:
\/\/
ca-davstorage:8080
\/[
0-9a-fA-F
]{4}
/
,
[
200
,
{
"
Content-Type
"
:
"
text/html
"
},
"
<h1>Document updated!</h1>
"
]
);
o
.
spy
(
o
,
"
jobstatus
"
,
"
done
"
,
"
Post without id
"
);
o
.
jio
.
post
({},
{
"
max_retry
"
:
1
},
function
(
err
,
response
)
{
o
.
f
.
apply
(
arguments
);
if
(
response
)
{
ok
(
isUuid
(
response
.
id
),
"
Uuid should look like
"
+
"
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx :
"
+
response
.
id
);
}
});
o
.
clock
.
tick
(
1000
);
o
.
server
.
respond
();
o
.
tick
(
o
);
o
.
server
.
restore
();
// post non empty document
o.addFakeServerResponse("dav", "PUT", "myFile", 201, "HTML RESPONSE");
o.spy(o, "value", {"id": "myFile", "ok": true},
"Create = POST non empty document");
o.jio.post({"_id": "myFile", "title": "hello there"}, o.f);
o.clock.tick(5000);
// post document with id
o
.
server
=
sinon
.
fakeServer
.
create
();
o
.
server
.
respondWith
(
"
GET
"
,
/https:
\/\/
ca-davstorage:8080
\/
http:%252F%252F100%2525_
\.
json/
,
[
404
,
{
"
Content-Type
"
:
"
text/html
"
},
"
<h1>Document not found</h1>
"
]
);
o
.
server
.
respondWith
(
"
PUT
"
,
/https:
\/\/
ca-davstorage:8080
\/
http:%252F%252F100%2525_
\.
json/
,
[
200
,
{
"
Content-Type
"
:
"
text/html
"
},
"
<h1>Document updated!</h1>
"
]
);
o
.
spy
(
o
,
"
value
"
,
{
"
id
"
:
"
http://100%.json
"
,
"
ok
"
:
true
},
"
Create document with an id
"
);
o
.
jio
.
post
({
"
_id
"
:
"
http://100%.json
"
,
"
title
"
:
"
Hello There
"
},
{
"
max_retry
"
:
1
},
o
.
f
);
o
.
clock
.
tick
(
1000
);
o
.
server
.
respond
();
o
.
tick
(
o
);
o
.
server
.
restore
();
// post but document already exists (post = error!, put = ok)
o.answer = JSON.stringify({"_id": "myFile", "title": "hello there"});
o.addFakeServerResponse("dav", "GET", "myFile", 200, o.answer);
o.spy (o, "status", 409, "Post but document already exists");
o.jio.post({"_id": "myFile", "title": "hello again"}, o.f);
o.clock.tick(5000);
// post already existant file
o
.
server
=
sinon
.
fakeServer
.
create
();
o
.
server
.
respondWith
(
"
GET
"
,
/https:
\/\/
ca-davstorage:8080
\/
http:%252F%252F100%2525_
\.
json/
,
[
200
,
{
"
Content-Type
"
:
"
text/plain
"
},
'
{"_id":"doc1","title":"Hello There"}
'
]
);
o
.
spy
(
o
,
"
status
"
,
405
,
"
Update document previous -> 405
"
);
o
.
jio
.
post
({
"
_id
"
:
"
http://100%.json
"
,
"
title
"
:
"
Hello There Again
"
},
{
"
max_retry
"
:
1
},
o
.
f
);
o
.
clock
.
tick
(
1000
);
o
.
server
.
respond
();
o
.
tick
(
o
);
o
.
server
.
restore
();
o
.
jio
.
stop
();
});
...
...
@@ -3515,35 +3579,60 @@ test ("Put", function(){
o
.
jio
=
JIO
.
newJio
({
"
type
"
:
"
dav
"
,
"username": "davput",
"password": "checkpwd",
"url": "https://ca-davstorage:8080"
"
url
"
:
"
https://ca-davstorage:8080
"
,
"
auth_type
"
:
"
basic
"
,
"
username
"
:
"
admin
"
,
"
password
"
:
"
pwd
"
});
// put without id =>
id r
equired
o.spy (o, "status", 20, "Put without id");
// put without id =>
20 Id R
equired
o
.
spy
(
o
,
"
status
"
,
20
,
"
Put without id
-> 20
"
);
o
.
jio
.
put
({},
o
.
f
);
o.
clock.tick(5000
);
o
.
tick
(
o
);
// put non empty document
o.addFakeServerResponse("dav", "PUT", "put1", 201, "HTML RESPONSE");
o.spy (o, "value", {"ok": true, "id": "put1"},
"Create = PUT non empty document");
o.jio.put({"_id": "put1", "title": "myPut1"}, o.f);
o.clock.tick(5000);
o
.
server
=
sinon
.
fakeServer
.
create
();
o
.
server
.
respondWith
(
"
PUT
"
,
/https:
\/\/
ca-davstorage:8080
\/
http:%252F%252F100%2525_
\.
json/
,
[
200
,
{
"
Content-Type
"
:
"
text/html
"
},
"
<h1>OK1</h1>
"
]
);
o
.
spy
(
o
,
"
value
"
,
{
"
ok
"
:
true
,
"
id
"
:
"
http://100%.json
"
},
"
Create document
"
);
o
.
jio
.
put
({
"
_id
"
:
"
http://100%.json
"
,
"
title
"
:
"
Hi There
"
},
{
"
max_retry
"
:
1
},
o
.
f
);
o
.
clock
.
tick
(
1000
);
o
.
server
.
respond
();
//console.log( o.server );
//console.log( o.server.requests[0].requestHeaders );
//console.log( o.server.requests[0].responseHeaders );
// put but document already exists = update
o.answer = JSON.stringify({"_id": "put1", "title": "myPut1"});
o.addFakeServerResponse("dav", "GET", "put1", 200, o.answer);
o.addFakeServerResponse("dav", "PUT", "put1", 201, "HTML RESPONSE");
o.spy (o, "value", {"ok": true, "id": "put1"}, "Updated the document");
o.jio.put({"_id": "put1", "title": "myPut2abcdedg"}, o.f);
o.clock.tick(5000);
o
.
tick
(
o
);
o
.
server
.
restore
();
// update document
o
.
server
=
sinon
.
fakeServer
.
create
();
o
.
server
.
respondWith
(
"
PUT
"
,
/https:
\/\/
ca-davstorage:8080
\/
http:%252F%252F100%2525_
\.
json/
,
[
200
,
{
"
Content-Type
"
:
"
text/html
"
},
"
<h1>OK!</h1>
"
]
);
o
.
spy
(
o
,
"
value
"
,
{
"
ok
"
:
true
,
"
id
"
:
"
http://100%.json
"
},
"
Update document
"
);
o
.
jio
.
put
({
"
_id
"
:
"
http://100%.json
"
,
"
title
"
:
"
Hi There Again
"
},
{
"
max_retry
"
:
1
},
o
.
f
);
o
.
clock
.
tick
(
1000
);
o
.
server
.
respond
();
o
.
tick
(
o
);
o
.
server
.
restore
();
o
.
jio
.
stop
();
});
...
...
@@ -3554,51 +3643,87 @@ test ("PutAttachment", function(){
o
.
jio
=
JIO
.
newJio
({
"
type
"
:
"
dav
"
,
"username": "davputattm",
"password": "checkpwd",
"url": "https://ca-davstorage:8080"
"
url
"
:
"
https://ca-davstorage:8080
"
,
"
auth_type
"
:
"
basic
"
,
"
username
"
:
"
admin
"
,
"
password
"
:
"
pwd
"
});
// putAttachment without doc id => id required
o.spy(o, "status", 20, "PutAttachment without doc id");
o.jio.putAttachment({}, o.f);
o.clock.tick(5000);
// putAttachment without attachment id => attachment id required
o.spy(o, "status", 22, "PutAttachment without attachment id");
o.jio.putAttachment({"id": "putattmt1"}, o.f);
o.clock.tick(5000);
// putAttachment without document id => 20 Id Required
o
.
spy
(
o
,
"
status
"
,
20
,
"
PutAttachment without doc id -> 20
"
);
o
.
jio
.
putAttachment
({
"
_attachment
"
:
"
body.html
"
},
o
.
f
);
o
.
tick
(
o
);
// putAttachment without underlying document => not found
o.addFakeServerResponse("dav", "GET", "putattmtx", 22, "HTML RESPONSE");
o.spy(o, "status", 22, "PutAttachment without document");
o.jio.putAttachment({"id": "putattmtx.putattmt2"}, o.f);
o.clock.tick(5000);
o.server.respond();
// putAttachment without attachment id => 22 Attachment Id Required
o
.
spy
(
o
,
"
status
"
,
22
,
"
PutAttachment without attachment id -> 22
"
);
o
.
jio
.
putAttachment
({
"
_id
"
:
"
http://100%.json
"
},
o
.
f
);
o
.
tick
(
o
);
// putAttachment with document without data
o.answer = JSON.stringify({"_id": "putattmt1", "title": "myPutAttm1"});
o.addFakeServerResponse("dav", "GET", "putattmt1", 200, o.answer);
o.addFakeServerResponse("dav", "PUT", "putattmt1", 201, "HTML RESPONSE");
o.addFakeServerResponse("dav", "PUT", "putattmt1.putattmt2", 201,"HTML"+
+ "RESPONSE");
o.spy(o, "value", {"ok": true, "id": "putattmt1/putattmt2"},
"PutAttachment with document, without data");
o.jio.putAttachment({"id": "putattmt1/putattmt2"}, o.f);
o.clock.tick(5000);
// putAttachment without underlying document => 404 Not Found
o
.
server
=
sinon
.
fakeServer
.
create
();
o
.
server
.
respondWith
(
"
GET
"
,
/https:
\/\/
ca-davstorage:8080
\/
http:%252F%252F100%2525_
\.
json/
,
[
404
,
{
"
Content-Type
"
:
"
text/html
"
},
"
<h1>Not Found</h1>
"
]
);
o
.
spy
(
o
,
"
status
"
,
404
,
"
PutAttachment without document -> 404
"
);
o
.
jio
.
putAttachment
({
"
_id
"
:
"
http://100%.json
"
,
"
_attachment
"
:
"
putattmt2
"
},
{
"
max_retry
"
:
1
},
o
.
f
);
o
.
clock
.
tick
(
1000
);
o
.
server
.
respond
();
o
.
tick
(
o
);
o
.
server
.
restore
();
// update attachment
o.answer = JSON.stringify({"_id": "putattmt1", "title": "myPutAttm1"});
o.addFakeServerResponse("dav", "GET", "putattmt1", 200, o.answer);
o.addFakeServerResponse("dav", "PUT", "putattmt1", 201, "HTML RESPONSE");
o.addFakeServerResponse("dav", "PUT", "putattmt1.putattmt2", 201,"HTML"+
"RESPONSE");
o.spy(o, "value", {"ok": true, "id": "putattmt1/putattmt2"},
"Update Attachment, with data");
o.jio.putAttachment({"id": "putattmt1/putattmt2", "data": "abc"}, o.f);
o.clock.tick(5000);
// upload attachment
o
.
server
=
sinon
.
fakeServer
.
create
();
o
.
server
.
respondWith
(
"
GET
"
,
/https:
\/\/
ca-davstorage:8080
\/
http:%252F%252F100%2525_
\.
json/
,
[
200
,
{
"
Content-Type
"
:
"
text/plain
"
},
'
{"_id":"http://100%.json","title":"Hi There!"}
'
]
);
o
.
server
.
respondWith
(
"
PUT
"
,
/https:
\/\/
ca-davstorage:8080
\/
http:%252F%252F100%2525_
\.
json.body_
\.
html/
,
[
200
,
{
"
Content-Type
"
:
"
text/html
"
},
"
<h1>OK!</h1>
"
]
);
o
.
server
.
respondWith
(
"
PUT
"
,
/https:
\/\/
ca-davstorage:8080
\/
http:%252F%252F100%2525_
\.
json/
,
[
200
,
{
"
Content-Type
"
:
"
text/html
"
},
"
<h1>OK!</h1>
"
]
);
o
.
spy
(
o
,
"
value
"
,
{
"
ok
"
:
true
,
"
id
"
:
"
http://100%.json
"
,
"
attachment
"
:
"
body.html
"
},
"
Upload attachment
"
);
o
.
jio
.
putAttachment
({
"
_id
"
:
"
http://100%.json
"
,
"
_attachment
"
:
"
body.html
"
,
"
_mimetype
"
:
"
text/html
"
,
"
_data
"
:
"
<h1>Hi There!!</h1><p>How are you?</p>
"
},
{
"
max_retry
"
:
1
},
o
.
f
);
o
.
clock
.
tick
(
1000
);
o
.
server
.
respond
();
o
.
tick
(
o
);
o
.
server
.
restore
();
o
.
jio
.
stop
();
});
...
...
@@ -3609,52 +3734,52 @@ test ("Get", function(){
o
.
jio
=
JIO
.
newJio
({
"
type
"
:
"
dav
"
,
"username": "davget",
"password": "checkpwd",
"url": "https://ca-davstorage:8080"
"
url
"
:
"
https://ca-davstorage:8080
"
,
"
auth_type
"
:
"
basic
"
,
"
username
"
:
"
admin
"
,
"
password
"
:
"
pwd
"
});
// get inexistent document
o.addFakeServerResponse("dav", "GET", "get1", 404, "HTML RESPONSE");
o.spy(o, "status", 404, "Get non existing document");
o.jio.get("get1", o.f);
o.clock.tick(5000);
o.server.respond();
// get inexistent attachment
o.addFakeServerResponse("dav", "GET", "get1.get2", 404, "HTML RESPONSE");
o.spy(o, "status", 404, "Get non existing attachment");
o.jio.get("get1/get2", o.f);
o.clock.tick(5000);
o
.
server
=
sinon
.
fakeServer
.
create
();
o
.
server
.
respondWith
(
"
GET
"
,
/https:
\/\/
ca-davstorage:8080
\/
http:%252F%252F100%2525_
\.
json/
,
[
404
,
{
"
Content-Type
"
:
"
text/html
"
},
"
<h1>Not Found</h1>
"
]
);
o
.
spy
(
o
,
"
status
"
,
404
,
"
Get non existing document -> 404
"
);
o
.
jio
.
get
({
"
_id
"
:
"
http://100%.json
"
},
{
"
max_retry
"
:
1
},
o
.
f
);
o
.
clock
.
tick
(
1000
);
o
.
server
.
respond
();
o
.
tick
(
o
);
o
.
server
.
restore
();
// get document
o.answer = JSON.stringify({"_id": "get3", "title": "some title"});
o.addFakeServerResponse("dav", "GET", "get3", 200, o.answer);
o.spy(o, "value", {"_id": "get3", "title": "some title"}, "Get document");
o.jio.get("get3", o.f);
o.clock.tick(5000);
o.server.respond();
// get inexistent attachment (document exists)
o.addFakeServerResponse("dav", "GET", "get3.getx", 404, "HTML RESPONSE");
o.spy(o, "status", 404, "Get non existing attachment (doc exists)");
o.jio.get("get3/getx", o.f);
o.clock.tick(5000);
o.server.respond();
// get attachment
o.answer = JSON.stringify({"_id": "get4", "title": "some attachment"});
o.addFakeServerResponse("dav", "GET", "get3.get4", 200, o.answer);
o.spy(o, "value", {"_id": "get4", "title": "some attachment"},
"Get attachment");
o.jio.get("get3/get4", o.f);
o.clock.tick(5000);
o
.
server
=
sinon
.
fakeServer
.
create
();
o
.
server
.
respondWith
(
"
GET
"
,
/https:
\/\/
ca-davstorage:8080
\/
http:%252F%252F100%2525_
\.
json/
,
[
200
,
{
"
Content-Type
"
:
"
text/html
"
},
'
{"_id":"http://100%.json","title":"Hi There!"}
'
]
);
o
.
spy
(
o
,
"
value
"
,
{
"
_id
"
:
"
http://100%.json
"
,
"
title
"
:
"
Hi There!
"
},
"
Get document
"
);
o
.
jio
.
get
({
"
_id
"
:
"
http://100%.json
"
},
{
"
max_retry
"
:
1
},
o
.
f
);
o
.
clock
.
tick
(
1000
);
o
.
server
.
respond
();
o
.
tick
(
o
);
o
.
server
.
restore
();
o
.
jio
.
stop
();
});
/*
test ("Remove", function(){
var o = generateTools(this);
...
...
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