Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
J
jio
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Eugene Shen
jio
Commits
176f9543
Commit
176f9543
authored
May 26, 2014
by
Caleb James DeLisle
Committed by
Tristan Cavelier
May 28, 2014
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Updated XWiki storage and tests to fit new version of JIO
parent
e79f94f9
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
1398 additions
and
578 deletions
+1398
-578
src/jio.storage/xwikistorage.js
src/jio.storage/xwikistorage.js
+729
-346
test/jio.storage/xwikistorage.tests.js
test/jio.storage/xwikistorage.tests.js
+665
-232
test/tests.html
test/tests.html
+4
-0
No files found.
src/jio.storage/xwikistorage.js
View file @
176f9543
/*jslint indent: 2,
/*jslint
indent: 2,
maxlen: 80,
maxlen: 80,
nomen: true
plusplus: true,
nomen: true,
regexp: true
*/
*/
/*global
/*global
define: true,
define: true,
exports: true,
require: true,
jIO: true,
jIO: true,
jQuery: true,
jQuery: true,
XMLHttpRequest: true,
Blob: true,
FormData: true,
window: true,
window: true,
setTimeout: true
XMLHttpRequest,
FormData
*/
*/
/**
/**
* JIO XWiki Storage. Type = 'xwiki'.
* JIO XWiki Storage. Type = 'xwiki'.
* XWiki Document/Attachment storage.
* XWiki Document/Attachment storage.
*/
*/
(
function
()
{
(
function
(
dependencies
,
module
)
{
"
use strict
"
;
"
use strict
"
;
if
(
typeof
define
===
'
function
'
&&
define
.
amd
)
{
return
define
(
dependencies
,
module
);
}
if
(
typeof
exports
===
'
object
'
)
{
return
module
(
require
(
'
jio
'
),
require
(
'
jquery
'
));
}
module
(
jIO
,
jQuery
);
}([
'
jio
'
,
'
jquery
'
],
function
(
jIO
,
$
)
{
"
use strict
"
;
function
detectWiki
()
{
// try first the meta tag, then look for js,
// then finally fail over to 'xwiki'...
return
$
(
'
meta[name="wiki"]
'
).
attr
(
'
content
'
)
||
(
window
.
XWiki
||
{}).
currentWiki
||
'
xwiki
'
;
}
function
detectXWikiURL
(
wiki
)
{
var
loc
,
action
,
idx
;
loc
=
window
.
location
.
href
;
action
=
(
window
.
XWiki
||
{}).
contextAction
||
'
view
'
;
idx
=
loc
.
indexOf
(
'
/wiki/
'
+
wiki
+
'
/
'
+
action
+
'
/
'
);
if
(
idx
!==
-
1
)
{
return
loc
.
substring
(
0
,
idx
);
}
idx
=
loc
.
indexOf
(
'
/bin/
'
+
action
+
'
/
'
);
if
(
idx
!==
-
1
)
{
// single wiki host:port/xwiki/bin/view/Main/WebHome
return
loc
.
substring
(
0
,
idx
);
}
throw
new
Error
(
"
Unable to detect XWiki URL
"
);
}
var
$
,
store
;
/**
store
=
function
(
spec
,
my
)
{
* Checks if an object has no enumerable keys
*
* @param {Object} obj The object
* @return {Boolean} true if empty, else false
*/
function
objectIsEmpty
(
obj
)
{
var
k
;
for
(
k
in
obj
)
{
if
(
obj
.
hasOwnProperty
(
k
))
{
return
false
;
}
}
return
true
;
}
function
detectIsPathBasedMultiwiki
(
xwikiurl
)
{
var
loc
=
window
.
location
.
href
;
if
(
loc
.
indexOf
(
xwikiurl
+
'
/wiki/
'
)
===
0
)
{
return
true
;
}
if
(
loc
.
indexOf
(
xwikiurl
+
'
/bin/
'
)
===
0
)
{
return
false
;
}
// warn the user that we're unusure?
return
false
;
}
/**
* The JIO XWikiStorage extension
*
* @class XWikiStorage
* @constructor
*/
function
XWikiStorage
(
spec
)
{
spec
=
spec
||
{};
spec
=
spec
||
{};
var
that
,
priv
,
xwikistorage
;
var
priv
=
{};
// the wiki to store stuff in
priv
.
wiki
=
spec
.
wiki
||
detectWiki
();
// URL location of the wiki
// XWiki doesn't currently allow cross-domain requests.
priv
.
xwikiurl
=
(
spec
.
xwikiurl
!==
undefined
)
?
spec
.
xwikiurl
:
detectXWikiURL
(
priv
.
wiki
);
// Which URL to load for getting the Anti-CSRF form token, used for testing.
priv
.
formTokenPath
=
spec
.
formTokenPath
||
priv
.
xwikiurl
;
that
=
my
.
basicStorage
(
spec
,
my
);
priv
.
pathBasedMultiwiki
=
(
spec
.
pathBasedMultiwiki
!==
undefined
)
priv
=
{}
;
?
spec
.
pathBasedMultiwiki
:
detectIsPathBasedMultiwiki
(
priv
.
xwikiurl
)
;
/**
/**
* Get the Space and Page components of a documkent ID.
* Get the Space and Page components of a documkent ID.
...
@@ -35,6 +114,7 @@
...
@@ -35,6 +114,7 @@
* @return a map of { 'space':<Space>, 'page':<Page> }
* @return a map of { 'space':<Space>, 'page':<Page> }
*/
*/
priv
.
getParts
=
function
(
id
)
{
priv
.
getParts
=
function
(
id
)
{
if
(
id
.
indexOf
(
'
/
'
)
===
-
1
)
{
if
(
id
.
indexOf
(
'
/
'
)
===
-
1
)
{
return
{
return
{
space
:
'
Main
'
,
space
:
'
Main
'
,
...
@@ -103,37 +183,21 @@
...
@@ -103,37 +183,21 @@
+
priv
.
wiki
+
'
/spaces/
'
+
parts
.
space
+
'
/pages/
'
+
parts
.
page
;
+
priv
.
wiki
+
'
/spaces/
'
+
parts
.
space
+
'
/pages/
'
+
parts
.
page
;
};
};
/**
priv
.
getURL
=
function
(
action
,
space
,
page
)
{
* Make an HTML5 Blob object.
var
out
=
[
priv
.
xwikiurl
];
* Equivilant to the `new Blob()` constructor.
if
(
!
priv
.
pathBasedMultiwiki
)
{
* Will fall back on deprecated BlobBuilder if necessary.
out
.
push
(
'
bin
'
);
*/
}
else
{
priv
.
makeBlob
=
function
(
contentArray
,
options
)
{
out
.
push
(
'
wiki
'
,
priv
.
wiki
);
var
i
,
bb
,
BB
;
try
{
// use the constructor if possible.
return
new
Blob
(
contentArray
,
options
);
}
catch
(
err
)
{
// fall back on the blob builder.
BB
=
(
window
.
MozBlobBuilder
||
window
.
WebKitBlobBuilder
||
window
.
BlobBuilder
);
bb
=
new
BB
();
for
(
i
=
0
;
i
<
contentArray
.
length
;
i
+=
1
)
{
bb
.
append
(
contentArray
[
i
]);
}
return
bb
.
getBlob
(
options
?
options
.
type
:
undefined
);
}
}
};
out
.
push
(
action
,
space
,
page
);
return
out
.
join
(
'
/
'
);
priv
.
isBlob
=
function
(
potentialBlob
)
{
return
potentialBlob
!==
undefined
&&
potentialBlob
.
toString
()
===
"
[object Blob]
"
;
};
};
/*
/*
* Wrapper for the xwikistorage based on localstorage JiO store.
* Wrapper for the xwikistorage based on localstorage JiO store.
*/
*/
xwiki
storage
=
{
priv
.
_storage
=
this
.
_
storage
=
{
/**
/**
* Get content of an XWikiDocument.
* Get content of an XWikiDocument.
*
*
...
@@ -143,7 +207,60 @@
...
@@ -143,7 +207,60 @@
*/
*/
getItem
:
function
(
docId
,
andThen
)
{
getItem
:
function
(
docId
,
andThen
)
{
var
success
=
function
(
jqxhr
)
{
function
attachSuccess
(
doc
,
jqxhr
)
{
var
out
=
{},
xd
;
if
(
jqxhr
.
status
!==
200
)
{
andThen
(
null
,
{
"
status
"
:
jqxhr
.
status
,
"
statusText
"
:
jqxhr
.
statusText
,
"
error
"
:
""
,
"
message
"
:
"
Failed to get attachments for document [
"
+
docId
+
"
]
"
,
"
reason
"
:
""
});
return
;
}
try
{
xd
=
$
(
jqxhr
.
responseText
);
xd
.
find
(
'
attachment
'
).
each
(
function
()
{
var
attach
=
{},
attachXML
=
$
(
this
);
attachXML
.
find
(
'
mimeType
'
).
each
(
function
()
{
attach
.
content_type
=
$
(
this
).
text
();
});
attachXML
.
find
(
'
size
'
).
each
(
function
()
{
attach
.
length
=
Number
(
$
(
this
).
text
());
});
attach
.
digest
=
"
unknown-0
"
;
attachXML
.
find
(
'
name
'
).
each
(
function
()
{
out
[
$
(
this
).
text
()]
=
attach
;
});
});
doc
.
_attachments
=
out
;
andThen
(
doc
,
null
);
}
catch
(
err
)
{
andThen
(
null
,
{
status
:
500
,
statusText
:
"
internal error
"
,
error
:
err
,
message
:
err
.
message
,
reason
:
""
});
}
}
function
getAttachments
(
doc
)
{
$
.
ajax
({
url
:
priv
.
getDocRestURL
(
docId
)
+
'
/attachments
'
,
type
:
"
GET
"
,
async
:
true
,
dataType
:
'
xml
'
,
complete
:
function
(
jqxhr
)
{
attachSuccess
(
doc
,
jqxhr
);
}
});
}
function
success
(
jqxhr
)
{
var
out
,
xd
;
var
out
,
xd
;
out
=
{};
out
=
{};
try
{
try
{
...
@@ -165,7 +282,7 @@
...
@@ -165,7 +282,7 @@
out
.
content
=
$
(
this
).
text
();
out
.
content
=
$
(
this
).
text
();
});
});
out
.
_id
=
docId
;
out
.
_id
=
docId
;
andThen
(
out
,
null
);
getAttachments
(
out
);
}
catch
(
err
)
{
}
catch
(
err
)
{
andThen
(
null
,
{
andThen
(
null
,
{
status
:
500
,
status
:
500
,
...
@@ -175,7 +292,7 @@
...
@@ -175,7 +292,7 @@
reason
:
""
reason
:
""
});
});
}
}
}
;
}
$
.
ajax
({
$
.
ajax
({
url
:
priv
.
getDocRestURL
(
docId
),
url
:
priv
.
getDocRestURL
(
docId
),
...
@@ -184,7 +301,7 @@
...
@@ -184,7 +301,7 @@
dataType
:
'
xml
'
,
dataType
:
'
xml
'
,
// Use complete instead of success and error because phantomjs
// Use complete instead of success and error because phantomjs
// sometimes causes error to be called with ht
ml
return code 200.
// sometimes causes error to be called with ht
tp
return code 200.
complete
:
function
(
jqxhr
)
{
complete
:
function
(
jqxhr
)
{
if
(
jqxhr
.
status
===
404
)
{
if
(
jqxhr
.
status
===
404
)
{
andThen
(
null
,
null
);
andThen
(
null
,
null
);
...
@@ -217,14 +334,10 @@
...
@@ -217,14 +334,10 @@
// need to do this manually, jquery doesn't support returning blobs.
// need to do this manually, jquery doesn't support returning blobs.
xhr
=
new
XMLHttpRequest
();
xhr
=
new
XMLHttpRequest
();
parts
=
priv
.
getParts
(
docId
);
parts
=
priv
.
getParts
(
docId
);
url
=
priv
.
xwikiurl
+
'
/bin/download/
'
+
parts
.
space
+
url
=
priv
.
getURL
(
'
download
'
,
parts
.
space
,
parts
.
page
)
+
"
/
"
+
parts
.
page
+
"
/
"
+
fileName
+
'
?cb=
'
+
Math
.
random
();
'
/
'
+
fileName
+
'
?cb=
'
+
Math
.
random
();
xhr
.
open
(
'
GET
'
,
url
,
true
);
xhr
.
open
(
'
GET
'
,
url
,
true
);
if
(
priv
.
useBlobs
)
{
xhr
.
responseType
=
'
blob
'
;
xhr
.
responseType
=
'
blob
'
;
}
else
{
xhr
.
responseType
=
'
text
'
;
}
xhr
.
onload
=
function
()
{
xhr
.
onload
=
function
()
{
if
(
xhr
.
status
===
200
)
{
if
(
xhr
.
status
===
200
)
{
...
@@ -259,13 +372,12 @@
...
@@ -259,13 +372,12 @@
setItem
:
function
(
id
,
doc
,
andThen
)
{
setItem
:
function
(
id
,
doc
,
andThen
)
{
priv
.
doWithFormToken
(
function
(
formToken
,
err
)
{
priv
.
doWithFormToken
(
function
(
formToken
,
err
)
{
if
(
err
)
{
if
(
err
)
{
that
.
error
(
err
);
andThen
(
err
);
return
;
return
;
}
}
var
parts
=
priv
.
getParts
(
id
);
var
parts
=
priv
.
getParts
(
id
);
$
.
ajax
({
$
.
ajax
({
url
:
priv
.
xwikiurl
+
"
/bin/preview/
"
+
url
:
priv
.
getURL
(
'
preview
'
,
parts
.
space
,
parts
.
page
),
parts
.
space
+
'
/
'
+
parts
.
page
,
type
:
"
POST
"
,
type
:
"
POST
"
,
async
:
true
,
async
:
true
,
dataType
:
'
text
'
,
dataType
:
'
text
'
,
...
@@ -308,26 +420,26 @@
...
@@ -308,26 +420,26 @@
* @param docId the ID of the document to attach to.
* @param docId the ID of the document to attach to.
* @param fileName the attachment file name.
* @param fileName the attachment file name.
* @param mimeType the MIME type of the attachment content.
* @param mimeType the MIME type of the attachment content.
* @param
content
the attachment content.
* @param
blob
the attachment content.
* @param andThen a callback taking one parameter, the error if any.
* @param andThen a callback taking one parameter, the error if any.
*/
*/
setAttachment
:
function
(
docId
,
fileName
,
mimeType
,
content
,
andThen
)
{
setAttachment
:
function
(
docId
,
fileName
,
blob
,
andThen
)
{
priv
.
doWithFormToken
(
function
(
formToken
,
err
)
{
priv
.
doWithFormToken
(
function
(
formToken
,
err
)
{
var
parts
,
blob
,
fd
,
xhr
;
var
parts
,
fd
,
xhr
;
if
(
err
)
{
if
(
err
)
{
that
.
error
(
err
);
andThen
(
err
);
return
;
return
;
}
}
parts
=
priv
.
getParts
(
docId
);
parts
=
priv
.
getParts
(
docId
);
blob
=
priv
.
isBlob
(
content
)
?
content
:
priv
.
makeBlob
([
content
],
{
type
:
mimeType
});
fd
=
new
FormData
();
fd
=
new
FormData
();
fd
.
append
(
"
filepath
"
,
blob
,
fileName
);
fd
.
append
(
"
filepath
"
,
blob
,
fileName
);
fd
.
append
(
"
form_token
"
,
formToken
);
fd
.
append
(
"
form_token
"
,
formToken
);
xhr
=
new
XMLHttpRequest
();
xhr
=
new
XMLHttpRequest
();
xhr
.
open
(
'
POST
'
,
priv
.
xwikiurl
+
"
/bin/upload/
"
+
xhr
.
open
(
parts
.
space
+
'
/
'
+
parts
.
page
,
true
);
'
POST
'
,
priv
.
getURL
(
'
upload
'
,
parts
.
space
,
parts
.
page
),
true
);
xhr
.
onload
=
function
()
{
xhr
.
onload
=
function
()
{
if
(
xhr
.
status
===
302
||
xhr
.
status
===
200
)
{
if
(
xhr
.
status
===
302
||
xhr
.
status
===
200
)
{
andThen
(
null
);
andThen
(
null
);
...
@@ -349,13 +461,12 @@
...
@@ -349,13 +461,12 @@
removeItem
:
function
(
id
,
andThen
)
{
removeItem
:
function
(
id
,
andThen
)
{
priv
.
doWithFormToken
(
function
(
formToken
,
err
)
{
priv
.
doWithFormToken
(
function
(
formToken
,
err
)
{
if
(
err
)
{
if
(
err
)
{
that
.
error
(
err
);
andThen
(
err
);
return
;
return
;
}
}
var
parts
=
priv
.
getParts
(
id
);
var
parts
=
priv
.
getParts
(
id
);
$
.
ajax
({
$
.
ajax
({
url
:
priv
.
xwikiurl
+
"
/bin/delete/
"
+
url
:
priv
.
getURL
(
'
delete
'
,
parts
.
space
,
parts
.
page
),
parts
.
space
+
'
/
'
+
parts
.
page
,
type
:
"
POST
"
,
type
:
"
POST
"
,
async
:
true
,
async
:
true
,
dataType
:
'
text
'
,
dataType
:
'
text
'
,
...
@@ -383,12 +494,12 @@
...
@@ -383,12 +494,12 @@
var
parts
=
priv
.
getParts
(
docId
);
var
parts
=
priv
.
getParts
(
docId
);
priv
.
doWithFormToken
(
function
(
formToken
,
err
)
{
priv
.
doWithFormToken
(
function
(
formToken
,
err
)
{
if
(
err
)
{
if
(
err
)
{
that
.
error
(
err
);
andThen
(
err
);
return
;
return
;
}
}
$
.
ajax
({
$
.
ajax
({
url
:
priv
.
xwikiurl
+
"
/bin/delattachment/
"
+
parts
.
space
+
'
/
'
+
url
:
priv
.
getURL
(
'
delattachment
'
,
parts
.
space
,
parts
.
page
)
+
parts
.
page
+
'
/
'
+
fileName
,
'
/
'
+
fileName
,
type
:
"
POST
"
,
type
:
"
POST
"
,
async
:
true
,
async
:
true
,
dataType
:
'
text
'
,
dataType
:
'
text
'
,
...
@@ -411,322 +522,594 @@
...
@@ -411,322 +522,594 @@
}
}
});
});
});
});
}
},
};
// ==================== Tools ====================
/**
/**
* Gets a document list from the xwiki storage.
* Update [doc] the document object and remove [doc] keys
* It will retreive an array containing files meta data owned by
* which are not in [new_doc]. It only changes [doc] keys not starting
* the user.
* with an underscore.
* @method allDocs
* ex: doc: {key:value1,_key:value2} with
*/
* new_doc: {key:value3,_key:value4} updates
allDocs
:
function
(
includeDocs
,
andThen
)
{
* doc: {key:value3,_key:value2}.
var
getData
=
function
(
callback
)
{
* @param {object} doc The original document object.
$
.
ajax
({
* @param {object} new_doc The new document object
url
:
priv
.
xwikiurl
+
'
/rest/wikis/xwiki/pages?cb=
'
+
Date
.
now
(),
*/
type
:
"
GET
"
,
priv
.
documentObjectUpdate
=
function
(
doc
,
new_doc
)
{
async
:
true
,
var
k
;
dataType
:
'
xml
'
,
for
(
k
in
doc
)
{
success
:
function
(
xmlData
)
{
if
(
doc
.
hasOwnProperty
(
k
))
{
var
data
=
[];
if
(
k
[
0
]
!==
'
_
'
)
{
$
(
xmlData
).
find
(
'
fullName
'
).
each
(
function
()
{
delete
doc
[
k
];
data
[
data
.
length
]
=
$
(
this
).
text
();
});
callback
(
data
);
},
error
:
function
(
error
)
{
andThen
(
null
,
error
);
}
});
};
getData
(
function
(
rows
,
err
)
{
var
i
,
next
;
next
=
function
(
i
)
{
priv
.
_storage
.
getItem
(
rows
[
i
].
id
,
function
(
doc
,
err
)
{
if
(
err
)
{
andThen
(
null
,
err
);
return
;
}
rows
[
i
].
doc
=
doc
;
if
(
i
<
rows
.
length
)
{
next
(
i
+
1
);
}
else
{
andThen
(
rows
);
}
});
};
if
(
err
)
{
return
andThen
(
null
,
err
);
}
}
}
for
(
i
=
0
;
i
<
rows
.
length
;
i
++
)
{
}
rows
[
i
]
=
{
for
(
k
in
new_doc
)
{
id
:
rows
[
i
],
if
(
new_doc
.
hasOwnProperty
(
k
))
{
key
:
rows
[
i
],
if
(
k
[
0
]
!==
'
_
'
)
{
value
:
{}
doc
[
k
]
=
new_doc
[
k
]
;
}
;
}
}
}
if
(
includeDocs
)
{
next
(
0
);
}
else
{
andThen
(
rows
);
}
});
}
}
};
};
}
/**
/**
* Checks if an object has no enumerable keys
* Create a document in local storage.
* @method objectIsEmpty
*
* @param {object} obj The object
* @method post
* @return {boolean} true if empty, else false
* @param {Object} command The JIO command
*/
* @param {Object} metadata The metadata to store
priv
.
objectIsEmpty
=
function
(
obj
)
{
* @param {Object} options The command options
var
k
;
*/
for
(
k
in
obj
)
{
XWikiStorage
.
prototype
.
post
=
function
(
command
,
metadata
)
{
if
(
obj
.
hasOwnProperty
(
k
))
{
var
doc_id
=
metadata
.
_id
,
that
=
this
;
return
false
;
if
(
!
doc_id
)
{
}
doc_id
=
jIO
.
util
.
generateUuid
();
}
that
.
_storage
.
getItem
(
doc_id
,
function
(
doc
,
err
)
{
if
(
err
)
{
command
.
error
(
err
);
return
;
}
}
return
true
;
if
(
doc
===
null
)
{
};
// the document does not exist
doc
=
jIO
.
util
.
deepClone
(
metadata
);
// ==================== attributes ====================
doc
.
_id
=
doc_id
;
// the wiki to store stuff in
delete
doc
.
_attachments
;
priv
.
wiki
=
spec
.
wiki
||
'
xwiki
'
;
that
.
_storage
.
setItem
(
doc_id
,
doc
,
function
(
err
)
{
if
(
err
)
{
// unused
command
.
error
(
priv
.
username
=
spec
.
username
;
"
failed
"
,
priv
.
language
=
spec
.
language
;
"
failed to upload document
"
,
String
(
err
)
// URL location of the wiki, unused since
);
// XWiki doesn't currently allow cross-domain requests.
}
else
{
priv
.
xwikiurl
=
spec
.
xwikiurl
||
command
.
success
({
"
id
"
:
doc_id
});
window
.
location
.
href
.
replace
(
/
\/
xwiki
\/
bin
\/
/
,
'
/xwiki
\n
'
)
}
.
split
(
'
\n
'
)[
0
];
});
// should be: s@/xwiki/bin/.*$@/xwiki@
}
else
{
// but jslint gets in the way.
// the document already exists
command
.
error
(
// Which URL to load for getting the Anti-CSRF form token, used for testing.
"
conflict
"
,
priv
.
formTokenPath
=
spec
.
formTokenPath
||
priv
.
xwikiurl
;
"
document exists
"
,
"
Cannot create a new document
"
// If true then Blob objects will be returned by
);
// getAttachment() rather than strings.
}
priv
.
useBlobs
=
spec
.
useBlobs
||
false
;
});
};
// If true then Blob objects will be returned by
/**
// getAttachment() rather than strings.
* Create or update a document in local storage.
priv
.
useBlobs
=
spec
.
useBlobs
||
false
;
*
* @method put
* @param {Object} command The JIO command
* @param {Object} metadata The metadata to store
* @param {Object} options The command options
*/
XWikiStorage
.
prototype
.
put
=
function
(
command
,
metadata
)
{
var
tmp
,
status
,
that
=
this
;
that
.
_storage
.
getItem
(
metadata
.
_id
,
function
(
doc
,
err
)
{
if
(
err
)
{
command
.
error
(
err
);
return
;
}
if
(
doc
===
null
||
doc
===
undefined
)
{
// the document does not exist
doc
=
jIO
.
util
.
deepClone
(
metadata
);
delete
doc
.
_attachments
;
status
=
"
created
"
;
}
else
{
// the document already exists
tmp
=
jIO
.
util
.
deepClone
(
metadata
);
tmp
.
_attachments
=
doc
.
_attachments
;
doc
=
tmp
;
status
=
"
no_content
"
;
}
// write
that
.
_storage
.
setItem
(
metadata
.
_id
,
doc
,
function
(
err
)
{
if
(
err
)
{
command
.
error
(
err
);
return
;
}
command
.
success
(
status
);
});
});
};
/**
* Add an attachment to a document
*
* @method putAttachment
* @param {Object} command The JIO command
* @param {Object} param The given parameters
* @param {Object} options The command options
*/
XWikiStorage
.
prototype
.
putAttachment
=
function
(
command
,
param
)
{
var
that
=
this
,
status
=
"
created
"
;
that
.
_storage
.
getItem
(
param
.
_id
,
function
(
doc
,
err
)
{
if
(
err
)
{
return
command
.
error
(
err
);
}
if
(
doc
===
null
)
{
// the document does not exist
return
command
.
error
(
"
not_found
"
,
"
missing
"
,
"
Impossible to add attachment
"
);
}
that
.
specToStore
=
function
()
{
// the document already exists
return
{
// download data
"
username
"
:
priv
.
username
,
if
((
doc
.
_attachments
||
{})[
param
.
_attachment
])
{
"
language
"
:
priv
.
language
,
status
=
"
no_content
"
;
"
xwikiurl
"
:
priv
.
xwikiurl
}
};
that
.
_storage
.
setAttachment
(
param
.
_id
,
};
param
.
_attachment
,
param
.
_blob
,
function
(
err
)
{
if
(
err
)
{
command
.
error
(
err
);
}
else
{
// XWiki doesn't do digests of attachments
// so we'll calculate it on the client side.
jIO
.
util
.
readBlobAsBinaryString
(
param
.
_blob
).
then
(
function
(
e
)
{
command
.
success
(
status
,
{
"
digest
"
:
jIO
.
util
.
makeBinaryStringDigest
(
e
.
target
.
result
)}
);
});
}
});
});
};
// can't fo wrong since no parameters are required.
/**
that
.
validateState
=
function
()
{
* Get a document
return
''
;
*
};
* @method get
* @param {Object} command The JIO command
* @param {Object} param The given parameters
* @param {Object} options The command options
*/
XWikiStorage
.
prototype
.
get
=
function
(
command
,
param
)
{
this
.
_storage
.
getItem
(
param
.
_id
,
function
(
ret
,
err
)
{
if
(
err
)
{
command
.
error
(
err
);
return
;
}
if
(
ret
===
null
)
{
command
.
error
(
"
not_found
"
,
"
missing
"
,
"
Cannot find document
"
);
}
else
{
command
.
success
({
"
data
"
:
ret
});
}
});
};
// ==================== commands ====================
/**
/**
* Get an attachment
* Create a document in local storage.
*
* @method post
* @method getAttachment
* @param {object} command The JIO command
* @param {Object} command The JIO command
*/
* @param {Object} param The given parameters
that
.
post
=
function
(
command
)
{
* @param {Object} options The command options
var
docId
=
command
.
getDocId
();
*/
if
(
!
(
typeof
docId
===
"
string
"
&&
docId
!==
""
))
{
XWikiStorage
.
prototype
.
getAttachment
=
function
(
command
,
param
)
{
setTimeout
(
function
()
{
var
that
=
this
;
that
.
error
({
that
.
_storage
.
getItem
(
param
.
_id
,
function
(
doc
,
err
)
{
"
status
"
:
405
,
if
(
err
)
{
"
statusText
"
:
"
Method Not Allowed
"
,
return
command
.
error
(
err
);
"
error
"
:
"
method_not_allowed
"
,
}
"
message
"
:
"
Cannot create document which id is undefined
"
,
if
(
doc
===
null
)
{
"
reason
"
:
"
Document id is undefined
"
return
command
.
error
(
"
not_found
"
,
"
missing document
"
,
"
Cannot find document
"
);
}
if
(
typeof
doc
.
_attachments
!==
'
object
'
||
typeof
doc
.
_attachments
[
param
.
_attachment
]
!==
'
object
'
)
{
return
command
.
error
(
"
not_found
"
,
"
missing attachment
"
,
"
Cannot find attachment
"
);
}
that
.
_storage
.
getAttachment
(
param
.
_id
,
param
.
_attachment
,
function
(
blob
,
err
)
{
var
attach
=
doc
.
_attachments
[
param
.
_attachment
];
if
(
err
)
{
return
command
.
error
(
err
);
}
if
(
blob
.
size
!==
attach
.
length
)
{
return
command
.
error
(
"
incomplete
"
,
"
attachment size incorrect
"
,
"
expected [
"
+
attach
.
size
+
"
] bytes, got [
"
+
blob
.
size
+
"
]
"
);
}
command
.
success
({
"
data
"
:
blob
,
"
digest
"
:
attach
.
digest
||
""
,
"
content_type
"
:
attach
.
content_type
||
""
});
});
});
});
return
;
});
};
/**
* Remove a document
*
* @method remove
* @param {Object} command The JIO command
* @param {Object} param The given parameters
* @param {Object} options The command options
*/
XWikiStorage
.
prototype
.
remove
=
function
(
command
,
param
)
{
this
.
_storage
.
removeItem
(
param
.
_id
,
function
(
err
)
{
if
(
err
)
{
command
.
error
(
err
);
}
else
{
command
.
success
();
}
}
xwikistorage
.
getItem
(
docId
,
function
(
doc
,
err
)
{
});
if
(
err
)
{
};
that
.
error
(
err
);
}
else
if
(
doc
===
null
)
{
// the document does not exist
xwikistorage
.
setItem
(
command
.
getDocId
(),
command
.
cloneDoc
(),
function
(
err
)
{
if
(
err
)
{
that
.
error
(
err
);
}
else
{
that
.
success
({
"
ok
"
:
true
,
"
id
"
:
command
.
getDocId
()
});
}
});
}
else
{
// the document already exists
that
.
error
({
"
status
"
:
409
,
"
statusText
"
:
"
Conflicts
"
,
"
error
"
:
"
conflicts
"
,
"
message
"
:
"
Cannot create a new document
"
,
"
reason
"
:
"
Document already exists (use 'put' to modify it)
"
});
}
});
};
/**
/**
* Create or update a document in local storage.
* Remove an attachment
* @method put
*
* @param {object} command The JIO command
* @method removeAttachment
*/
* @param {Object} command The JIO command
that
.
put
=
function
(
command
)
{
* @param {Object} param The given parameters
xwikistorage
.
getItem
(
command
.
getDocId
(),
function
(
doc
,
err
)
{
* @param {Object} options The command options
if
(
err
)
{
*/
that
.
error
(
err
);
XWikiStorage
.
prototype
.
removeAttachment
=
function
(
command
,
param
)
{
}
else
if
(
doc
===
null
)
{
var
that
=
this
;
doc
=
command
.
cloneDoc
();
that
.
_storage
.
getItem
(
param
.
_id
,
function
(
doc
,
err
)
{
}
else
{
if
(
err
)
{
priv
.
documentObjectUpdate
(
doc
,
command
.
cloneDoc
());
return
command
.
error
(
err
);
}
}
// write
if
(
typeof
doc
!==
'
object
'
||
doc
===
null
)
{
xwikistorage
.
setItem
(
command
.
getDocId
(),
doc
,
function
(
err
)
{
return
command
.
error
(
"
not_found
"
,
"
missing document
"
,
"
Document not found
"
);
}
if
(
typeof
doc
.
_attachments
!==
"
object
"
||
typeof
doc
.
_attachments
[
param
.
_attachment
]
!==
"
object
"
)
{
return
command
.
error
(
"
not_found
"
,
"
missing attachment
"
,
"
Attachment not found
"
);
}
that
.
_storage
.
removeAttachment
(
param
.
_id
,
param
.
_attachment
,
function
(
err
)
{
if
(
err
)
{
if
(
err
)
{
that
.
error
(
err
);
command
.
error
(
err
);
}
else
{
}
else
{
that
.
success
({
command
.
success
();
"
ok
"
:
true
,
"
id
"
:
command
.
getDocId
()
});
}
}
});
});
});
};
/**
* Get all filenames belonging to a user from the document index
*
* @method allDocs
* @param {Object} command The JIO command
* @param {Object} param The given parameters
* @param {Object} options The command options
*/
XWikiStorage
.
prototype
.
allDocs
=
function
(
command
,
param
,
options
)
{
var
i
,
document_list
,
document_object
,
delete_id
,
that
=
this
;
param
.
unused
=
true
;
document_list
=
[];
if
(
options
.
query
===
undefined
&&
options
.
sort_on
===
undefined
&&
options
.
select_list
===
undefined
&&
options
.
include_docs
===
undefined
)
{
that
.
_storage
.
allDocs
(
options
.
include_docs
,
function
(
rows
,
err
)
{
if
(
err
)
{
return
command
.
error
(
err
);
}
command
.
success
({
"
data
"
:
{
"
rows
"
:
rows
,
"
total_rows
"
:
rows
.
length
}});
});
});
};
/**
}
else
{
* Add an attachment to a document
* @method putAttachment
that
.
_storage
.
allDocs
(
true
,
function
(
rows
,
err
)
{
* @param {object} command The JIO command
*/
that
.
putAttachment
=
function
(
command
)
{
xwikistorage
.
getItem
(
command
.
getDocId
(),
function
(
doc
,
err
)
{
if
(
err
)
{
if
(
err
)
{
that
.
error
(
err
);
return
command
.
error
(
err
);
}
else
if
(
doc
===
null
)
{
}
// the document does not exist
for
(
i
=
0
;
i
<
rows
.
length
;
i
++
)
{
that
.
error
({
document_list
.
push
(
rows
[
i
].
doc
);
"
status
"
:
404
,
"
statusText
"
:
"
Not Found
"
,
"
error
"
:
"
not_found
"
,
"
message
"
:
"
Impossible to add attachment
"
,
"
reason
"
:
"
Document not found
"
});
}
else
{
// Document exists, upload attachment.
xwikistorage
.
setAttachment
(
command
.
getDocId
(),
command
.
getAttachmentId
(),
command
.
getAttachmentMimeType
(),
command
.
getAttachmentData
(),
function
(
err
)
{
if
(
err
)
{
that
.
error
(
err
);
}
else
{
that
.
success
({
"
ok
"
:
true
,
"
id
"
:
command
.
getDocId
()
+
"
/
"
+
command
.
getAttachmentId
()
});
}
});
}
}
});
});
};
/**
options
.
select_list
=
options
.
select_list
||
[];
* Get a document or attachment
if
(
options
.
select_list
.
indexOf
(
"
_id
"
)
===
-
1
)
{
* @method get
options
.
select_list
.
push
(
"
_id
"
);
* @param {object} command The JIO command
delete_id
=
true
;
*/
}
that
.
get
=
that
.
getAttachment
=
function
(
command
)
{
if
(
options
.
include_docs
===
true
)
{
if
(
typeof
command
.
getAttachmentId
()
===
"
string
"
)
{
document_object
=
{};
// seeking for an attachment
document_list
.
forEach
(
function
(
meta
)
{
xwikistorage
.
getAttachment
(
command
.
getDocId
(),
document_object
[
meta
.
_id
]
=
meta
;
command
.
getAttachmentId
(),
});
function
(
attach
,
err
)
{
}
if
(
err
)
{
jIO
.
QueryFactory
.
create
(
options
.
query
||
""
,
this
.
_key_schema
).
that
.
error
(
err
);
exec
(
document_list
,
options
).
then
(
function
()
{
}
else
if
(
attach
!==
null
)
{
document_list
=
document_list
.
map
(
function
(
value
)
{
that
.
success
(
attach
);
var
o
=
{
}
else
{
"
id
"
:
value
.
_id
,
that
.
error
({
"
key
"
:
value
.
_id
"
status
"
:
404
,
};
"
statusText
"
:
"
Not Found
"
,
if
(
options
.
include_docs
===
true
)
{
"
error
"
:
"
not_found
"
,
o
.
doc
=
document_object
[
value
.
_id
];
"
message
"
:
"
Cannot find the attachment
"
,
delete
document_object
[
value
.
_id
];
"
reason
"
:
"
Attachment does not exist
"
});
}
}
if
(
delete_id
)
{
delete
value
.
_id
;
}
o
.
value
=
value
;
return
o
;
});
});
}
else
{
command
.
success
({
"
data
"
:
{
// seeking for a document
"
total_rows
"
:
document_list
.
length
,
xwikistorage
.
getItem
(
command
.
getDocId
(),
function
(
doc
,
err
)
{
"
rows
"
:
document_list
if
(
err
)
{
}});
that
.
error
(
err
);
}
else
if
(
doc
!==
null
)
{
that
.
success
(
doc
);
}
else
{
that
.
error
({
"
status
"
:
404
,
"
statusText
"
:
"
Not Found
"
,
"
error
"
:
"
not_found
"
,
"
message
"
:
"
Cannot find the document
"
,
"
reason
"
:
"
Document does not exist
"
});
}
});
});
}
};
/**
* Check the storage or a specific document
*
* @method check
* @param {Object} command The JIO command
* @param {Object} param The command parameters
* @param {Object} options The command options
*/
XWikiStorage
.
prototype
.
check
=
function
(
command
,
param
)
{
this
.
genericRepair
(
command
,
param
,
false
);
};
/**
* Repair the storage or a specific document
*
* @method repair
* @param {Object} command The JIO command
* @param {Object} param The command parameters
* @param {Object} options The command options
*/
XWikiStorage
.
prototype
.
repair
=
function
(
command
,
param
)
{
this
.
genericRepair
(
command
,
param
,
true
);
};
/**
* A generic method that manage check or repair command
*
* @method genericRepair
* @param {Object} command The JIO command
* @param {Object} param The command parameters
* @param {Boolean} repair If true then repair else just check
*/
XWikiStorage
.
prototype
.
genericRepair
=
function
(
command
,
param
,
repair
)
{
var
that
=
this
,
final_result
;
function
referenceAttachment
(
param
,
attachment
)
{
if
(
param
.
referenced_attachments
.
indexOf
(
attachment
)
!==
-
1
)
{
return
;
}
}
};
var
i
=
param
.
unreferenced_attachments
.
indexOf
(
attachment
);
if
(
i
!==
-
1
)
{
param
.
unreferenced_attachments
.
splice
(
i
,
1
);
}
param
.
referenced_attachments
[
param
.
referenced_attachments
.
length
]
=
attachment
;
}
/**
function
attachmentFound
(
param
,
attachment
)
{
* Remove a document or attachment
if
(
param
.
referenced_attachments
.
indexOf
(
attachment
)
!==
-
1
)
{
* @method remove
return
;
* @param {object} command The JIO command
}
*/
if
(
param
.
unreferenced_attachments
.
indexOf
(
attachment
)
!==
-
1
)
{
that
.
remove
=
that
.
removeAttachment
=
function
(
command
)
{
return
;
var
objId
,
complete
;
}
// notFoundError = function (word) {
param
.
unreferenced_attachments
[
param
.
unreferenced_attachments
.
length
]
=
// that.error({
attachment
;
// "status": 404,
}
// "statusText": "Not Found",
// "error": "not_found",
function
repairOne
(
param
,
repair
)
{
// "message": word + " not found",
var
i
,
doc
,
modified
;
// "reason": "missing"
doc
=
that
.
_storage
.
getItem
(
param
.
_id
);
// });
if
(
doc
===
null
)
{
// };
return
;
// OK
}
objId
=
command
.
getDocId
();
complete
=
function
(
err
)
{
// check document type
if
(
err
)
{
if
(
typeof
doc
!==
'
object
'
||
doc
===
null
)
{
that
.
error
(
err
);
// wrong document
}
else
{
if
(
!
repair
)
{
that
.
success
({
return
{
"
error
"
:
true
,
"
answers
"
:
[
"
ok
"
:
true
,
"
conflict
"
,
"
id
"
:
objId
"
corrupted
"
,
});
"
Document is unrecoverable
"
]};
}
// delete the document
that
.
_storage
.
removeItem
(
param
.
_id
);
return
;
// OK
}
// good document type
// repair json document
if
(
!
repair
)
{
if
(
!
(
new
jIO
.
Metadata
(
doc
).
check
()))
{
return
{
"
error
"
:
true
,
"
answers
"
:
[
"
conflict
"
,
"
corrupted
"
,
"
Some metadata might be lost
"
]};
}
}
};
if
(
typeof
command
.
getAttachmentId
()
===
"
string
"
)
{
objId
+=
'
/
'
+
command
.
getAttachmentId
();
xwikistorage
.
removeAttachment
(
command
.
getDocId
(),
command
.
getAttachmentId
(),
complete
);
}
else
{
}
else
{
xwikistorage
.
removeItem
(
objId
,
complete
);
modified
=
jIO
.
util
.
uniqueJSONStringify
(
doc
)
!==
jIO
.
util
.
uniqueJSONStringify
(
new
jIO
.
Metadata
(
doc
).
format
().
_dict
);
}
}
};
if
(
doc
.
_attachments
!==
undefined
)
{
if
(
typeof
doc
.
_attachments
!==
'
object
'
)
{
if
(
!
repair
)
{
return
{
"
error
"
:
true
,
"
answers
"
:
[
"
conflict
"
,
"
corrupted
"
,
"
Attachments are unrecoverable
"
]};
}
delete
doc
.
_attachments
;
that
.
_storage
.
setItem
(
param
.
_id
,
doc
);
return
;
// OK
}
for
(
i
in
doc
.
_attachments
)
{
if
(
doc
.
_attachments
.
hasOwnProperty
(
i
))
{
// check attachment existence
if
(
that
.
_storage
.
getItem
(
param
.
_id
+
"
/
"
+
i
)
!==
'
string
'
)
{
if
(
!
repair
)
{
return
{
"
error
"
:
true
,
"
answers
"
:
[
"
conflict
"
,
"
missing attachment
"
,
"
Attachment
\"
"
+
i
+
"
\"
of
\"
"
+
param
.
_id
+
"
\"
is missing
"
]};
}
delete
doc
.
_attachments
[
i
];
if
(
objectIsEmpty
(
doc
.
_attachments
))
{
delete
doc
.
_attachments
;
}
modified
=
true
;
}
else
{
// attachment exists
// check attachment metadata
// check length
referenceAttachment
(
param
,
param
.
_id
+
"
/
"
+
doc
.
_attachments
[
i
]);
if
(
doc
.
_attachments
[
i
].
length
!==
undefined
&&
typeof
doc
.
_attachments
[
i
].
length
!==
'
number
'
)
{
if
(
!
repair
)
{
return
{
"
error
"
:
true
,
"
answers
"
:
[
"
conflict
"
,
"
corrupted
"
,
"
Attachment metadata length corrupted
"
]};
}
// It could take a long time to get the length, no repair.
// length can be omited
delete
doc
.
_attachments
[
i
].
length
;
}
// It could take a long time to regenerate the hash, no check.
// Impossible to discover the attachment content type.
}
}
}
}
if
(
modified
)
{
that
.
_storage
.
setItem
(
param
.
_id
,
doc
);
}
// OK
}
/**
function
repairAll
(
param
,
repair
)
{
* Get all filenames belonging to a user from the document index
var
i
,
result
;
* @method allDocs
for
(
i
in
that
.
_database
)
{
* @param {object} command The JIO command
if
(
that
.
_database
.
hasOwnProperty
(
i
))
{
*/
// browsing every entry
that
.
allDocs
=
function
()
{
setTimeout
(
function
()
{
that
.
error
({
"
status
"
:
405
,
"
statusText
"
:
"
Method Not Allowed
"
,
"
error
"
:
"
method_not_allowed
"
,
"
message
"
:
"
Your are not allowed to use this command
"
,
"
reason
"
:
"
xwikistorage forbids AllDocs command executions
"
});
});
};
return
that
;
// is part of the user space
if
(
/^
[^\/]
+
\/[^\/]
+$/
.
test
(
i
))
{
// this is an attachment
attachmentFound
(
param
,
i
);
}
else
if
(
/^
[^\/]
+$/
.
test
(
i
))
{
// this is a document
param
.
_id
=
i
;
result
=
repairOne
(
param
,
repair
);
if
(
result
)
{
return
result
;
}
}
else
{
// this is pollution
that
.
_storage
.
removeItem
(
i
);
}
}
}
// remove unreferenced attachments
for
(
i
=
0
;
i
<
param
.
unreferenced_attachments
.
length
;
i
+=
1
)
{
that
.
_storage
.
removeItem
(
param
.
unreferenced_attachments
[
i
]);
}
}
param
.
referenced_attachments
=
[];
param
.
unreferenced_attachments
=
[];
if
(
typeof
param
.
_id
===
'
string
'
)
{
final_result
=
repairOne
(
param
,
repair
)
||
{};
}
else
{
final_result
=
repairAll
(
param
,
repair
)
||
{};
}
if
(
final_result
.
error
)
{
return
command
.
error
.
apply
(
command
,
final_result
.
answers
||
[]);
}
command
.
success
.
apply
(
command
,
final_result
.
answers
||
[]);
};
};
if
(
typeof
define
===
'
function
'
&&
define
.
amd
)
{
jIO
.
addStorage
(
'
xwiki
'
,
XWikiStorage
);
define
([
'
jquery
'
,
'
jio
'
],
function
(
jquery
,
jIO
)
{
$
=
jquery
;
jIO
.
addStorageType
(
'
xwiki
'
,
store
);
});
}
else
{
jIO
.
addStorageType
(
'
xwiki
'
,
store
);
$
=
jQuery
;
}
}
(
));
}));
test/jio.storage/xwikistorage.tests.js
View file @
176f9543
/*jslint indent: 2, maxlen: 80, nomen: true */
/*jslint
/*global define, jIO, jio_tests, test, ok, sinon, module */
indent: 2,
maxlen: 80,
plusplus: true,
nomen: true,
regexp: true
*/
/*global
define,
jIO,
test,
ok,
sinon,
module,
clearTimeout,
setTimeout,
start,
stop,
deepEqual
*/
// define([module_name], [dependencies], module);
// define([module_name], [dependencies], module);
(
function
(
dependencies
,
module
)
{
(
function
(
dependencies
,
module
)
{
...
@@ -7,34 +25,103 @@
...
@@ -7,34 +25,103 @@
if
(
typeof
define
===
'
function
'
&&
define
.
amd
)
{
if
(
typeof
define
===
'
function
'
&&
define
.
amd
)
{
return
define
(
dependencies
,
module
);
return
define
(
dependencies
,
module
);
}
}
module
(
jIO
,
jio_tests
);
module
(
jIO
);
}([
'
jio
'
,
'
jio_tests
'
,
'
xwikistorage
'
],
function
(
jIO
,
util
)
{
}([
'
jio
'
,
'
xwikistorage
'
],
function
(
jIO
)
{
"
use strict
"
;
"
use strict
"
;
function
generateTools
()
{
function
nThen
(
next
)
{
var
o
=
{
var
funcs
=
[],
clock
:
sinon
.
useFakeTimers
(),
timeouts
=
[],
spy
:
util
.
ospy
,
calls
=
0
,
tick
:
util
.
otick
abort
,
ret
,
waitFor
;
waitFor
=
function
(
func
)
{
calls
++
;
return
function
()
{
if
(
func
)
{
func
.
apply
(
null
,
arguments
);
}
calls
=
(
calls
||
1
)
-
1
;
while
(
!
calls
&&
funcs
.
length
&&
!
abort
)
{
funcs
.
shift
()(
waitFor
);
}
};
};
};
function
addFakeServerResponse
(
type
,
method
,
path
,
status
,
response
)
{
waitFor
.
abort
=
function
()
{
/*jslint unparam: true */
timeouts
.
forEach
(
clearTimeout
);
o
.
server
.
respondWith
(
method
,
new
RegExp
(
path
),
[
abort
=
1
;
status
,
};
{
"
Content-Type
"
:
'
application/xml
'
},
ret
=
{
response
nThen
:
function
(
next
)
{
]);
if
(
!
abort
)
{
}
if
(
!
calls
)
{
o
.
addFakeServerResponse
=
addFakeServerResponse
;
next
(
waitFor
);
return
o
;
}
else
{
funcs
.
push
(
next
);
}
}
return
ret
;
},
orTimeout
:
function
(
func
,
milliseconds
)
{
var
cto
,
timeout
;
if
(
abort
)
{
return
ret
;
}
if
(
!
milliseconds
)
{
throw
new
Error
(
"
Must specify milliseconds to orTimeout()
"
);
}
timeout
=
setTimeout
(
function
()
{
var
f
;
while
(
f
!==
cto
)
{
f
=
funcs
.
shift
();
}
func
(
waitFor
);
calls
=
(
calls
||
1
)
-
1
;
while
(
!
calls
&&
funcs
.
length
)
{
funcs
.
shift
()(
waitFor
);
}
},
milliseconds
);
cto
=
function
()
{
var
i
;
for
(
i
=
0
;
i
<
timeouts
.
length
;
i
++
)
{
if
(
timeouts
[
i
]
===
timeout
)
{
timeouts
.
splice
(
i
,
1
);
clearTimeout
(
timeout
);
return
;
}
}
throw
new
Error
(
'
timeout not listed in array
'
);
};
funcs
.
push
(
cto
);
timeouts
.
push
(
timeout
);
return
ret
;
}
};
return
ret
.
nThen
(
next
);
}
}
module
(
'
XWikiStorage
'
);
module
(
'
XWikiStorage
'
);
function
setUp
(
that
)
{
function
setUp
()
{
var
o
=
generateTools
(
that
);
var
o
=
{
o
.
server
=
sinon
.
fakeServer
.
create
();
sinon
:
sinon
.
sandbox
.
create
()
o
.
jio
=
jIO
.
newJio
({
type
:
'
xwiki
'
,
formTokenPath
:
'
form_token
'
});
};
o
.
addFakeServerResponse
=
function
(
type
,
method
,
path
,
status
,
response
,
t
)
{
t
=
t
||
'
application/xml
'
;
/*jslint unparam: true */
o
.
sinon
.
server
.
respondWith
(
method
,
new
RegExp
(
path
),
[
status
,
{
"
Content-Type
"
:
t
},
response
]);
};
o
.
sinon
.
useFakeTimers
();
o
.
sinon
.
useFakeServer
();
o
.
respond
=
function
()
{
o
.
sinon
.
clock
.
tick
(
5000
);
o
.
sinon
.
server
.
respond
();
};
o
.
jio
=
jIO
.
createJIO
(
{
type
:
'
xwiki
'
,
formTokenPath
:
'
form_token
'
,
xwikiurl
:
''
}
);
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
GET
"
,
"
form_token
"
,
200
,
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
GET
"
,
"
form_token
"
,
200
,
'
<meta name="form_token" content="OMGHAX"/>
'
);
'
<meta name="form_token" content="OMGHAX"/>
'
);
o
.
_addFakeServerResponse
=
o
.
addFakeServerResponse
;
o
.
_addFakeServerResponse
=
o
.
addFakeServerResponse
;
...
@@ -46,11 +133,11 @@
...
@@ -46,11 +133,11 @@
o
.
assertReqs
=
function
(
count
,
message
)
{
o
.
assertReqs
=
function
(
count
,
message
)
{
var
i
,
j
,
req
,
expected
,
ex
;
var
i
,
j
,
req
,
expected
,
ex
;
o
.
requests
=
(
o
.
requests
||
0
)
+
count
;
o
.
requests
=
(
o
.
requests
||
0
)
+
count
;
ok
(
o
.
server
.
requests
.
length
===
o
.
requests
,
ok
(
o
.
s
inon
.
s
erver
.
requests
.
length
===
o
.
requests
,
message
+
"
[expected [
"
+
count
+
"
] got [
"
+
message
+
"
[expected [
"
+
count
+
"
] got [
"
+
(
o
.
server
.
requests
.
length
-
(
o
.
requests
-
count
))
+
"
]]
"
);
(
o
.
s
inon
.
s
erver
.
requests
.
length
-
(
o
.
requests
-
count
))
+
"
]]
"
);
for
(
i
=
1
;
i
<=
count
;
i
+=
1
)
{
for
(
i
=
1
;
i
<=
count
;
i
+=
1
)
{
req
=
o
.
s
erver
.
requests
[
o
.
server
.
requests
.
length
-
i
];
req
=
o
.
s
inon
.
server
.
requests
[
o
.
sinon
.
server
.
requests
.
length
-
i
];
if
(
!
req
)
{
if
(
!
req
)
{
break
;
break
;
}
}
...
@@ -70,242 +157,588 @@
...
@@ -70,242 +157,588 @@
return
o
;
return
o
;
}
}
function
nThenTest
(
o
,
nt
)
{
stop
();
nt
.
nThen
(
function
()
{
o
.
sinon
.
restore
();
start
();
}).
orTimeout
(
function
()
{
o
.
sinon
.
restore
();
ok
(
0
);
start
();
},
1000
);
}
test
(
"
Post
"
,
function
()
{
test
(
"
Post
"
,
function
()
{
var
o
=
setUp
(
this
);
var
o
=
setUp
(
this
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
// post non empty document
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
POST
"
,
"
myFile1
"
,
201
,
"
HTML RESPONSE
"
);
o
.
jio
.
post
({
"
_id
"
:
"
myFile1
"
,
"
title
"
:
"
hello there
"
}).
then
(
waitFor
(
function
(
ret
)
{
deepEqual
({
id
:
"
myFile1
"
,
method
:
"
post
"
,
result
:
"
success
"
,
status
:
201
,
statusText
:
"
Created
"
},
ret
);
}));
o
.
respond
();
}).
nThen
(
function
()
{
o
.
assertReqs
(
3
,
"
post -> 1 request to get csrf token, 1 to get doc and 1 to post data
"
);
}));
});
// post without id
test
(
"
Post2
"
,
function
()
{
o
.
spy
(
o
,
"
status
"
,
405
,
"
Post without id
"
);
o
.
jio
.
post
({},
o
.
f
);
var
o
=
setUp
(
this
);
o
.
clock
.
tick
(
5000
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
o
.
assertReqs
(
0
,
"
no id -> no request
"
);
// post but document already exists (post = error!, put = ok)
// post non empty document
o
.
answer
=
'
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
'
+
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
POST
"
,
"
myFile
"
,
201
,
"
HTML RESPONSE
"
);
'
<page xmlns="http://www.xwiki.org"><title>hello there</title></page>
'
;
o
.
spy
(
o
,
"
value
"
,
{
"
id
"
:
"
myFile
"
,
"
ok
"
:
true
},
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
GET
"
,
"
pages/myFile2
"
,
200
,
o
.
answer
);
"
Create = POST non empty document
"
);
o
.
jio
.
post
({
"
_id
"
:
"
myFile
"
,
"
title
"
:
"
hello there
"
},
o
.
f
);
o
.
jio
.
post
({
"
_id
"
:
"
myFile2
"
,
"
title
"
:
"
hello again
"
}).
o
.
clock
.
tick
(
5000
);
then
(
function
()
{
o
.
server
.
respond
();
ok
(
0
);
o
.
assertReqs
(
},
waitFor
(
function
(
err
)
{
3
,
deepEqual
({
"
put -> 1 request to get csrf token, 1 to get doc and 1 to post data
"
error
:
"
conflict
"
,
);
id
:
"
myFile2
"
,
message
:
"
Cannot create a new document
"
,
method
:
"
post
"
,
reason
:
"
document exists
"
,
result
:
"
error
"
,
status
:
409
,
statusText
:
"
Conflict
"
},
err
);
}));
o
.
respond
();
}).
nThen
(
function
()
{
o
.
assertReqs
(
2
,
"
post w/ existing doc -> 2 request to get doc then fail
"
);
}));
// post but document already exists (post = error!, put = ok)
o
.
answer
=
'
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
'
+
'
<page xmlns="http://www.xwiki.org"><title>hello there</title></page>
'
;
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
GET
"
,
"
myFile2
"
,
200
,
o
.
answer
);
o
.
spy
(
o
,
"
status
"
,
409
,
"
Post but document already exists
"
);
o
.
jio
.
post
({
"
_id
"
:
"
myFile2
"
,
"
title
"
:
"
hello again
"
},
o
.
f
);
o
.
clock
.
tick
(
5000
);
o
.
server
.
respond
();
o
.
assertReqs
(
1
,
"
post w/ existing doc -> 1 request to get doc then fail
"
);
util
.
closeAndcleanUpJio
(
o
.
jio
);
});
});
test
(
"
Put
"
,
function
()
{
test
(
"
Put
NoId
"
,
function
()
{
var
o
=
setUp
(
this
);
var
o
=
setUp
(
this
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
// put without id => id required
o
.
jio
.
put
({}).
then
(
function
()
{
ok
(
0
);
},
waitFor
(
function
(
err
)
{
deepEqual
({
"
error
"
:
"
bad_request
"
,
"
message
"
:
"
Document id must be a non empty string.
"
,
"
method
"
:
"
put
"
,
"
reason
"
:
"
wrong document id
"
,
"
result
"
:
"
error
"
,
"
status
"
:
400
,
"
statusText
"
:
"
Bad Request
"
},
err
);
}));
}).
nThen
(
function
()
{
o
.
assertReqs
(
0
,
"
put w/o id -> 0 requests
"
);
}));
});
// put without id => id required
test
(
"
Put
"
,
function
()
{
o
.
spy
(
o
,
"
status
"
,
20
,
"
Put without id
"
);
var
o
=
setUp
(
this
);
o
.
jio
.
put
({},
o
.
f
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
o
.
clock
.
tick
(
5000
);
o
.
assertReqs
(
0
,
"
put w/o id -> 0 requests
"
);
// put non empty document
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
POST
"
,
"
put1
"
,
201
,
"
HTML RESPONSE
"
);
// put non empty document
o
.
jio
.
put
({
"
_id
"
:
"
put1
"
,
"
title
"
:
"
myPut1
"
}).
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
POST
"
,
"
put1
"
,
201
,
"
HTML RESPONSE
"
);
then
(
waitFor
(
function
(
res
)
{
o
.
spy
(
o
,
"
value
"
,
{
"
ok
"
:
true
,
"
id
"
:
"
put1
"
},
deepEqual
({
"
Create = PUT non empty document
"
);
"
id
"
:
"
put1
"
,
o
.
jio
.
put
({
"
_id
"
:
"
put1
"
,
"
title
"
:
"
myPut1
"
},
o
.
f
);
"
method
"
:
"
put
"
,
o
.
clock
.
tick
(
5000
);
"
result
"
:
"
success
"
,
o
.
server
.
respond
();
"
status
"
:
201
,
o
.
assertReqs
(
"
statusText
"
:
"
Created
"
3
,
},
res
);
"
put normal doc -> 1 req to get doc, 1 for csrf token, 1 to post
"
}));
);
o
.
respond
();
}).
nThen
(
function
()
{
o
.
assertReqs
(
3
,
"
put normal doc -> 1 req to get doc (404), 1 for csrf token, 1 to post
"
);
}));
});
// put but document already exists = update
test
(
"
PutUpdateDoc
"
,
function
()
{
o
.
answer
=
'
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
'
+
var
o
=
setUp
(
this
);
'
<page xmlns="http://www.xwiki.org"><title>mtPut1</title></page>
'
;
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
GET
"
,
"
put2
"
,
200
,
o
.
answer
);
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
POST
"
,
"
put2
"
,
201
,
"
HTML RESPONSE
"
);
// put but document already exists = update
o
.
spy
(
o
,
"
value
"
,
{
"
ok
"
:
true
,
"
id
"
:
"
put2
"
},
"
Updated the document
"
);
o
.
answer
=
'
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
'
+
o
.
jio
.
put
({
"
_id
"
:
"
put2
"
,
"
title
"
:
"
myPut2abcdedg
"
},
o
.
f
);
'
<page xmlns="http://www.xwiki.org"><title>mtPut1</title></page>
'
;
o
.
clock
.
tick
(
5000
);
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
GET
"
,
"
put2
"
,
200
,
o
.
answer
);
o
.
server
.
respond
();
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
POST
"
,
"
put2
"
,
201
,
"
HTML RESPONSE
"
);
o
.
assertReqs
(
3
,
o
.
jio
.
put
({
"
_id
"
:
"
put2
"
,
"
title
"
:
"
myPut2abcdedg
"
}).
"
put update doc -> 1 req to get doc, 1 for csrf token, 1 to post
"
then
(
waitFor
(
function
(
ret
)
{
);
deepEqual
({
"
id
"
:
"
put2
"
,
"
method
"
:
"
put
"
,
"
result
"
:
"
success
"
,
"
status
"
:
204
,
"
statusText
"
:
"
No Content
"
},
ret
);
}));
o
.
respond
();
}).
nThen
(
function
()
{
o
.
assertReqs
(
4
,
"
put update doc -> 2 req to get doc, 1 for csrf token, 1 to post
"
);
}));
});
util
.
closeAndcleanUpJio
(
o
.
jio
);
test
(
"
PutAttachmentNoDocId
"
,
function
()
{
var
o
=
setUp
(
this
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
// putAttachment without doc id => id required
o
.
jio
.
putAttachment
({},
function
()
{
ok
(
0
);
},
waitFor
(
function
(
err
)
{
deepEqual
({
"
attachment
"
:
undefined
,
"
error
"
:
"
bad_request
"
,
"
message
"
:
"
Document id must be a non empty string.
"
,
"
method
"
:
"
putAttachment
"
,
"
reason
"
:
"
wrong document id
"
,
"
result
"
:
"
error
"
,
"
status
"
:
400
,
"
statusText
"
:
"
Bad Request
"
},
err
);
}));
o
.
respond
();
}).
nThen
(
function
()
{
o
.
assertReqs
(
0
,
"
put attach w/o doc id -> 0 requests
"
);
}));
});
});
test
(
"
PutAttachment
"
,
function
()
{
test
(
"
PutAttachmentNoAttachId
"
,
function
()
{
var
o
=
setUp
(
this
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
// putAttachment without attachment id => attachment id required
o
.
jio
.
putAttachment
({
"
_id
"
:
"
putattmt1
"
},
function
()
{
ok
(
0
);
},
waitFor
(
function
(
err
)
{
deepEqual
({
"
attachment
"
:
undefined
,
"
error
"
:
"
bad_request
"
,
"
id
"
:
"
putattmt1
"
,
"
message
"
:
"
Attachment id must be a non empty string.
"
,
"
method
"
:
"
putAttachment
"
,
"
reason
"
:
"
wrong attachment id
"
,
"
result
"
:
"
error
"
,
"
status
"
:
400
,
"
statusText
"
:
"
Bad Request
"
},
err
);
}));
o
.
respond
();
}).
nThen
(
function
()
{
o
.
assertReqs
(
0
,
"
put attach w/o attach id -> 0 requests
"
);
}));
});
test
(
"
PutAttachmentUnderlyingDocumentNonexistant
"
,
function
()
{
var
o
=
setUp
(
this
);
var
o
=
setUp
(
this
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
// putAttachment without underlying document => not found
o
.
jio
.
putAttachment
(
{
"
_id
"
:
"
putattmtx
"
,
"
_attachment
"
:
"
putattmt2
"
,
"
_data
"
:
""
},
function
()
{
ok
(
0
);
},
waitFor
(
function
(
err
)
{
deepEqual
({
"
attachment
"
:
"
putattmt2
"
,
"
error
"
:
"
not_found
"
,
"
id
"
:
"
putattmtx
"
,
"
message
"
:
"
Impossible to add attachment
"
,
"
method
"
:
"
putAttachment
"
,
"
reason
"
:
"
missing
"
,
"
result
"
:
"
error
"
,
"
status
"
:
404
,
"
statusText
"
:
"
Not Found
"
},
err
);
})
);
o
.
respond
();
}).
nThen
(
function
()
{
o
.
assertReqs
(
1
,
"
put attach w/o existing document -> 1 request to get doc
"
);
}));
});
// putAttachment without doc id => id required
test
(
"
GetNonexistantDoc
"
,
function
()
{
o
.
spy
(
o
,
"
status
"
,
20
,
"
PutAttachment without doc id
"
);
var
o
=
setUp
(
this
);
o
.
jio
.
putAttachment
({},
o
.
f
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
o
.
clock
.
tick
(
5000
);
// get inexistent document
o
.
assertReqs
(
0
,
"
put attach w/o doc id -> 0 requests
"
);
o
.
jio
.
get
({
_id
:
"
get_nonexistant_doc
"
},
function
()
{
ok
(
0
);
// putAttachment without attachment id => attachment id required
},
waitFor
(
function
(
err
)
{
o
.
spy
(
o
,
"
status
"
,
22
,
"
PutAttachment without attachment id
"
);
deepEqual
({
o
.
jio
.
putAttachment
({
"
_id
"
:
"
putattmt1
"
},
o
.
f
);
"
error
"
:
"
not_found
"
,
o
.
clock
.
tick
(
5000
);
"
id
"
:
"
get_nonexistant_doc
"
,
o
.
assertReqs
(
0
,
"
put attach w/o attach id -> 0 requests
"
);
"
message
"
:
"
Cannot find document
"
,
"
method
"
:
"
get
"
,
// putAttachment without underlying document => not found
"
reason
"
:
"
missing
"
,
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
GET
"
,
"
putattmtx
"
,
404
,
"
HTML RESPONSE
"
);
"
result
"
:
"
error
"
,
o
.
spy
(
o
,
"
status
"
,
404
,
"
PutAttachment without document
"
);
"
status
"
:
404
,
o
.
jio
.
putAttachment
({
"
_id
"
:
"
putattmtx
"
,
"
_attachment
"
:
"
putattmt2
"
},
o
.
f
);
"
statusText
"
:
"
Not Found
"
o
.
clock
.
tick
(
5000
);
},
err
);
o
.
server
.
respond
();
}));
o
.
assertReqs
(
1
,
"
put attach w/o existing document -> 1 request to get doc
"
);
o
.
respond
();
// putAttachment with document without data
o
.
answer
=
'
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
'
+
}).
nThen
(
function
()
{
'
<page xmlns="http://www.xwiki.org"><title>myPutAttm</title></page>
'
;
o
.
assertReqs
(
1
,
"
try to get nonexistent doc -> 1 request
"
);
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
GET
"
,
"
putattmt1
"
,
200
,
o
.
answer
);
}));
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
POST
"
,
"
putattmt1/putattmt2
"
,
201
,
"
HTML RESPONSE
"
);
o
.
spy
(
o
,
"
value
"
,
{
"
ok
"
:
true
,
"
id
"
:
"
putattmt1/putattmt2
"
},
"
PutAttachment with document, without data
"
);
o
.
jio
.
putAttachment
({
"
_id
"
:
"
putattmt1
"
,
"
_attachment
"
:
"
putattmt2
"
},
o
.
f
);
o
.
clock
.
tick
(
5000
);
o
.
server
.
respond
();
o
.
assertReqs
(
3
,
"
put attach -> 1 request to get document, 1 to put
"
+
"
attach, 1 to get csrf token
"
);
util
.
closeAndcleanUpJio
(
o
.
jio
);
});
});
test
(
"
Get
"
,
function
()
{
test
(
"
GetAttachInNonexistantDoc
"
,
function
()
{
var
o
=
setUp
(
this
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
o
.
jio
.
getAttachment
(
{
"
_id
"
:
"
noSuchDoc
"
,
"
_attachment
"
:
"
its_attachment
"
},
function
()
{
ok
(
0
);
},
waitFor
(
function
(
err
)
{
deepEqual
({
"
attachment
"
:
"
its_attachment
"
,
"
error
"
:
"
not_found
"
,
"
id
"
:
"
noSuchDoc
"
,
"
message
"
:
"
Cannot find document
"
,
"
method
"
:
"
getAttachment
"
,
"
reason
"
:
"
missing document
"
,
"
result
"
:
"
error
"
,
"
status
"
:
404
,
"
statusText
"
:
"
Not Found
"
},
err
);
})
);
o
.
respond
();
}).
nThen
(
function
()
{
o
.
assertReqs
(
1
,
"
try to get nonexistent attach -> 1 request
"
);
}));
});
test
(
"
GetDoc
"
,
function
()
{
var
o
=
setUp
(
this
);
var
o
=
setUp
(
this
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
o
.
answer
=
'
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
'
+
'
<page xmlns="http://www.xwiki.org"><title>some title</title></page>
'
;
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
GET
"
,
"
get_doc
"
,
200
,
o
.
answer
);
o
.
jio
.
get
({
_id
:
"
get_doc
"
}).
then
(
waitFor
(
function
(
ret
)
{
deepEqual
({
"
data
"
:
{
"
_attachments
"
:
{},
"
_id
"
:
"
get_doc
"
,
"
title
"
:
"
some title
"
},
"
id
"
:
"
get_doc
"
,
"
method
"
:
"
get
"
,
"
result
"
:
"
success
"
,
"
status
"
:
200
,
"
statusText
"
:
"
Ok
"
},
ret
);
}));
o
.
respond
();
}).
nThen
(
function
()
{
o
.
assertReqs
(
2
,
"
get document -> 2 request
"
);
}));
});
// get inexistent document
test
(
"
GetNonexistantAttach
"
,
function
()
{
o
.
spy
(
o
,
"
status
"
,
404
,
"
Get non existing document
"
);
var
o
=
setUp
(
this
);
o
.
jio
.
get
(
"
get1
"
,
o
.
f
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
o
.
clock
.
tick
(
5000
);
o
.
server
.
respond
();
// get inexistent attachment (document exists)
o
.
assertReqs
(
1
,
"
try to get nonexistent doc -> 1 request
"
);
o
.
answer
=
'
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
'
+
'
<page xmlns="http://www.xwiki.org"><title>some title</title></page>
'
;
// get inexistent attachment
o
.
addFakeServerResponse
(
o
.
spy
(
o
,
"
status
"
,
404
,
"
Get non existing attachment
"
);
"
xwiki
"
,
o
.
jio
.
get
(
"
get1/get2
"
,
o
.
f
);
"
GET
"
,
o
.
clock
.
tick
(
5000
);
"
get_nonexistant_attach
"
,
o
.
server
.
respond
();
200
,
o
.
assertReqs
(
1
,
"
try to get nonexistent attach -> 1 request
"
);
o
.
answer
);
// get document
o
.
answer
=
'
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
'
+
o
.
jio
.
getAttachment
(
'
<page xmlns="http://www.xwiki.org"><title>some title</title></page>
'
;
{
"
_id
"
:
"
get_nonexistant_attach
"
,
"
_attachment
"
:
"
nxattach
"
},
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
GET
"
,
"
get3
"
,
200
,
o
.
answer
);
function
()
{
o
.
spy
(
o
,
"
value
"
,
{
"
_id
"
:
"
get3
"
,
"
title
"
:
"
some title
"
},
"
Get document
"
);
ok
(
0
);
o
.
jio
.
get
(
"
get3
"
,
o
.
f
);
},
o
.
clock
.
tick
(
5000
);
waitFor
(
function
(
err
)
{
o
.
server
.
respond
();
deepEqual
({
o
.
assertReqs
(
1
,
"
get document -> 1 request
"
);
"
attachment
"
:
"
nxattach
"
,
"
error
"
:
"
not_found
"
,
// get inexistent attachment (document exists)
"
id
"
:
"
get_nonexistant_attach
"
,
o
.
spy
(
o
,
"
status
"
,
404
,
"
Get non existing attachment (doc exists)
"
);
"
message
"
:
"
Cannot find attachment
"
,
o
.
jio
.
get
({
"
_id
"
:
"
get3
"
,
"
_attachment
"
:
"
getx
"
},
o
.
f
);
"
method
"
:
"
getAttachment
"
,
o
.
clock
.
tick
(
5000
);
"
reason
"
:
"
missing attachment
"
,
o
.
server
.
respond
();
"
result
"
:
"
error
"
,
o
.
assertReqs
(
1
,
"
get nonexistant attachment -> 1 request
"
);
"
status
"
:
404
,
"
statusText
"
:
"
Not Found
"
// get attachment
},
err
);
o
.
answer
=
JSON
.
stringify
({
"
_id
"
:
"
get4
"
,
"
title
"
:
"
some attachment
"
});
})
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
GET
"
,
"
get3/get4
"
,
200
,
o
.
answer
);
);
o
.
spy
(
o
,
"
value
"
,
{
"
_id
"
:
"
get4
"
,
"
title
"
:
"
some attachment
"
},
"
Get attachment
"
);
o
.
respond
();
o
.
jio
.
get
({
"
_id
"
:
"
get3
"
,
"
_attachment
"
:
"
get4
"
},
o
.
f
);
o
.
clock
.
tick
(
5000
);
}).
nThen
(
function
()
{
o
.
server
.
respond
();
o
.
assertReqs
(
2
,
"
get nonexistant attachment -> 2 request to get doc
"
);
o
.
assertReqs
(
1
,
"
get attachment -> 1 request
"
);
}));
});
util
.
closeAndcleanUpJio
(
o
.
jio
);
test
(
"
GetAttachHappyPath
"
,
function
()
{
var
o
=
setUp
(
this
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
// get attachment
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
GET
"
,
"
spaces/Main/pages/get_attachment$
"
,
200
,
'
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
'
+
'
<page xmlns="http://www.xwiki.org"><title>some title</title></page>
'
);
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
GET
"
,
"
spaces/Main/pages/get_attachment/attachments
"
,
200
,
'
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
'
+
'
<attachments xmlns="http://www.xwiki.org">
'
+
'
<attachment><name>attach_name</name></attachment>
'
+
'
</attachments>
'
);
// We can't fully test this
// because sinon doesn't support HTML5 blob responses.
//o.addFakeServerResponse(
// "xwiki", "GET", "download/Main/get_attachment/attach_name", 200,
// "content", "application/octet-stream");
o
.
jio
.
getAttachment
(
{
"
_id
"
:
"
get_attachment
"
,
"
_attachment
"
:
"
attach_name
"
},
waitFor
(
function
(
ret
)
{
deepEqual
({
"
attachment
"
:
"
attach_name
"
,
"
error
"
:
"
err_network_error
"
,
"
id
"
:
"
get_attachment
"
,
"
message
"
:
"
Failed to get attachment [get_attachment/attach_name]
"
,
"
method
"
:
"
getAttachment
"
,
"
reason
"
:
"
Error getting data from network
"
,
"
result
"
:
"
error
"
,
"
status
"
:
404
,
"
statusText
"
:
"
Not Found
"
},
ret
);
})
);
o
.
respond
();
}).
nThen
(
function
()
{
o
.
assertReqs
(
3
,
"
get attachment -> 2 requests to get doc, 1 for attach
"
);
}));
});
});
test
(
"
Remove
"
,
function
()
{
test
(
"
RemoveNonexistantDocument
"
,
function
()
{
var
o
=
setUp
(
this
);
var
o
=
setUp
(
this
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
// remove inexistent document
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
GET
"
,
"
remove1
"
,
404
,
"
HTML RESPONSE
"
);
o
.
jio
.
remove
({
"
_id
"
:
"
remove1
"
},
waitFor
(
function
(
ret
)
{
deepEqual
({
"
error
"
:
"
error
"
,
"
id
"
:
"
remove1
"
,
"
message
"
:
"
Failed to delete document [remove1]
"
,
"
method
"
:
"
remove
"
,
"
reason
"
:
"
Not Found
"
,
"
result
"
:
"
error
"
,
"
status
"
:
404
,
"
statusText
"
:
"
Not Found
"
},
ret
);
}));
o
.
respond
();
}).
nThen
(
function
()
{
o
.
assertReqs
(
2
,
"
remove nonexistent doc -> 1 request for csrf and 1 for doc
"
);
}));
});
// remove inexistent document
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
GET
"
,
"
remove1
"
,
404
,
"
HTML RESPONSE
"
);
o
.
spy
(
o
,
"
status
"
,
404
,
"
Remove non existening document
"
);
o
.
jio
.
remove
({
"
_id
"
:
"
remove1
"
},
o
.
f
);
o
.
clock
.
tick
(
5000
);
o
.
server
.
respond
();
o
.
assertReqs
(
2
,
"
remove nonexistent doc -> 1 request for csrf and 1 for doc
"
);
// remove inexistent document/attachment
test
(
"
RemoveNonexistantAttachment
"
,
function
()
{
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
GET
"
,
"
remove1/remove2
"
,
404
,
"
HTML
"
+
var
o
=
setUp
(
this
);
"
RESPONSE
"
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
o
.
spy
(
o
,
"
status
"
,
404
,
"
Remove inexistent document/attachment
"
);
o
.
jio
.
removeAttachment
({
"
_id
"
:
"
remove1
"
,
"
_attachment
"
:
"
remove2
"
},
o
.
f
);
// remove inexistent document/attachment
o
.
clock
.
tick
(
5000
);
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
GET
"
,
"
remove1/remove2
"
,
404
,
"
HTML
"
+
o
.
server
.
respond
();
"
RESPONSE
"
);
o
.
assertReqs
(
2
,
o
.
jio
.
removeAttachment
(
"
remove nonexistant attach -> 1 request for csrf and 1 for doc
"
{
"
_id
"
:
"
remove1
"
,
"
_attachment
"
:
"
remove2
"
},
);
function
()
{
ok
(
0
);
},
waitFor
(
function
(
err
)
{
deepEqual
({
"
attachment
"
:
"
remove2
"
,
"
error
"
:
"
not_found
"
,
"
id
"
:
"
remove1
"
,
"
message
"
:
"
Document not found
"
,
"
method
"
:
"
removeAttachment
"
,
"
reason
"
:
"
missing document
"
,
"
result
"
:
"
error
"
,
"
status
"
:
404
,
"
statusText
"
:
"
Not Found
"
},
err
);
})
);
o
.
respond
();
}).
nThen
(
function
()
{
o
.
assertReqs
(
1
,
"
remove nonexistant attach -> 1 request for doc
"
);
}));
});
// remove document
//o.answer = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' +
// '<page xmlns="http://www.xwiki.org"><title>some doc</title></page>';
//o.addFakeServerResponse("xwiki", "GET", "remove3", 200, o.answer);
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
POST
"
,
"
bin/delete/Main/remove3
"
,
200
,
"
HTML RESPONSE
"
);
o
.
spy
(
o
,
"
value
"
,
{
"
ok
"
:
true
,
"
id
"
:
"
remove3
"
},
"
Remove document
"
);
o
.
jio
.
remove
({
"
_id
"
:
"
remove3
"
},
o
.
f
);
o
.
clock
.
tick
(
5000
);
o
.
server
.
respond
();
o
.
assertReqs
(
2
,
"
remove document -> 1 request for csrf and 1 for deleting doc
"
);
o
.
answer
=
JSON
.
stringify
({
test
(
"
RemoveDocument
"
,
function
()
{
"
_id
"
:
"
remove4
"
,
var
o
=
setUp
(
this
);
"
title
"
:
"
some doc
"
,
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
"
_attachments
"
:
{
"
remove5
"
:
{
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
POST
"
,
"
delete/Main/remove3
"
,
"
length
"
:
4
,
200
,
"
HTML RESPONSE
"
);
"
digest
"
:
"
md5-d41d8cd98f00b204e9800998ecf8427e
"
}
o
.
jio
.
remove
({
"
_id
"
:
"
remove3
"
}).
then
(
waitFor
(
function
(
ret
)
{
}
deepEqual
({
});
"
id
"
:
"
remove3
"
,
// remove attachment
"
method
"
:
"
remove
"
,
o
.
addFakeServerResponse
(
"
result
"
:
"
success
"
,
"
xwiki
"
,
"
status
"
:
204
,
"
POST
"
,
"
statusText
"
:
"
No Content
"
"
delattachment/Main/remove4/remove5
"
,
},
ret
);
200
,
}));
"
HTML RESPONSE
"
);
o
.
respond
();
o
.
spy
(
o
,
"
value
"
,
{
"
ok
"
:
true
,
"
id
"
:
"
remove4/remove5
"
},
"
Remove attachment
"
);
}).
nThen
(
function
()
{
o
.
jio
.
removeAttachment
({
"
_id
"
:
"
remove4
"
,
"
_attachment
"
:
"
remove5
"
},
o
.
f
);
o
.
assertReqs
(
o
.
clock
.
tick
(
5000
);
2
,
o
.
server
.
respond
();
"
remove document -> 1 request for csrf and 1 for deleting doc
"
o
.
assertReqs
(
2
,
"
remove attach -> 1 request for csrf and 1 for deletion
"
);
);
}));
util
.
closeAndcleanUpJio
(
o
.
jio
);
});
test
(
"
RemoveAttachment
"
,
function
()
{
var
o
=
setUp
(
this
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
// remove attachment
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
GET
"
,
"
spaces/Main/pages/remove4$
"
,
200
,
'
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
'
+
'
<page xmlns="http://www.xwiki.org"><title>some title</title></page>
'
);
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
GET
"
,
"
spaces/Main/pages/remove4/attachments
"
,
200
,
'
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
'
+
'
<attachments xmlns="http://www.xwiki.org">
'
+
'
<attachment><name>remove5</name></attachment>
'
+
'
</attachments>
'
);
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
POST
"
,
"
delattachment/Main/remove4/remove5
"
,
200
,
"
HTML RESPONSE
"
);
o
.
jio
.
removeAttachment
(
{
"
_id
"
:
"
remove4
"
,
"
_attachment
"
:
"
remove5
"
}
).
always
(
waitFor
(
function
(
ret
)
{
deepEqual
({
"
attachment
"
:
"
remove5
"
,
"
id
"
:
"
remove4
"
,
"
method
"
:
"
removeAttachment
"
,
"
result
"
:
"
success
"
,
"
status
"
:
204
,
"
statusText
"
:
"
No Content
"
},
ret
);
}));
o
.
respond
();
}).
nThen
(
function
()
{
o
.
assertReqs
(
4
,
"
remove attach -> get doc, get attachments, get csrf, remove attach
"
);
}));
});
});
}));
}));
test/tests.html
View file @
176f9543
...
@@ -32,6 +32,10 @@
...
@@ -32,6 +32,10 @@
<script
src=
"queries/key-localstorage.tests.js"
></script>
<script
src=
"queries/key-localstorage.tests.js"
></script>
<script
src=
"jio.storage/localstorage.tests.js"
></script>
<script
src=
"jio.storage/localstorage.tests.js"
></script>
<script
src=
"../lib/jquery/jquery.min.js"
></script>
<script
src=
"../src/jio.storage/xwikistorage.js"
></script>
<script
src=
"jio.storage/xwikistorage.tests.js"
></script>
<script
src=
"../src/jio.storage/davstorage.js"
></script>
<script
src=
"../src/jio.storage/davstorage.js"
></script>
<script
src=
"jio.storage/davstorage.tests.js"
></script>
<script
src=
"jio.storage/davstorage.tests.js"
></script>
...
...
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