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
Boris Kocherov
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
Show 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
"
);
}
/**
* 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
;
}
var
$
,
store
;
function
detectIsPathBasedMultiwiki
(
xwikiurl
)
{
store
=
function
(
spec
,
my
)
{
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 ====================
/**
/**
* Update [doc] the document object and remove [doc] keys
* Gets a document list from the xwiki storage.
* which are not in [new_doc]. It only changes [doc] keys not starting
* It will retreive an array containing files meta data owned by
* with an underscore.
* the user.
* ex: doc: {key:value1,_key:value2} with
* @method allDocs
* new_doc: {key:value3,_key:value4} updates
* doc: {key:value3,_key:value2}.
* @param {object} doc The original document object.
* @param {object} new_doc The new document object
*/
*/
priv
.
documentObjectUpdate
=
function
(
doc
,
new_doc
)
{
allDocs
:
function
(
includeDocs
,
andThen
)
{
var
k
;
var
getData
=
function
(
callback
)
{
for
(
k
in
doc
)
{
$
.
ajax
({
if
(
doc
.
hasOwnProperty
(
k
))
{
url
:
priv
.
xwikiurl
+
'
/rest/wikis/xwiki/pages?cb=
'
+
Date
.
now
(),
if
(
k
[
0
]
!==
'
_
'
)
{
type
:
"
GET
"
,
delete
doc
[
k
];
async
:
true
,
}
dataType
:
'
xml
'
,
}
success
:
function
(
xmlData
)
{
}
var
data
=
[];
for
(
k
in
new_doc
)
{
$
(
xmlData
).
find
(
'
fullName
'
).
each
(
function
()
{
if
(
new_doc
.
hasOwnProperty
(
k
))
{
data
[
data
.
length
]
=
$
(
this
).
text
();
if
(
k
[
0
]
!==
'
_
'
)
{
});
doc
[
k
]
=
new_doc
[
k
];
callback
(
data
);
}
},
}
error
:
function
(
error
)
{
andThen
(
null
,
error
);
}
}
});
};
};
/**
getData
(
function
(
rows
,
err
)
{
* Checks if an object has no enumerable keys
var
i
,
next
;
* @method objectIsEmpty
next
=
function
(
i
)
{
* @param {object} obj The object
priv
.
_storage
.
getItem
(
rows
[
i
].
id
,
function
(
doc
,
err
)
{
* @return {boolean} true if empty, else false
if
(
err
)
{
*/
andThen
(
null
,
err
);
priv
.
objectIsEmpty
=
function
(
obj
)
{
return
;
var
k
;
for
(
k
in
obj
)
{
if
(
obj
.
hasOwnProperty
(
k
))
{
return
false
;
}
}
rows
[
i
].
doc
=
doc
;
if
(
i
<
rows
.
length
)
{
next
(
i
+
1
);
}
else
{
andThen
(
rows
);
}
}
return
true
;
});
};
// ==================== attributes ====================
// the wiki to store stuff in
priv
.
wiki
=
spec
.
wiki
||
'
xwiki
'
;
// unused
priv
.
username
=
spec
.
username
;
priv
.
language
=
spec
.
language
;
// URL location of the wiki, unused since
// XWiki doesn't currently allow cross-domain requests.
priv
.
xwikiurl
=
spec
.
xwikiurl
||
window
.
location
.
href
.
replace
(
/
\/
xwiki
\/
bin
\/
/
,
'
/xwiki
\n
'
)
.
split
(
'
\n
'
)[
0
];
// should be: s@/xwiki/bin/.*$@/xwiki@
// but jslint gets in the way.
// Which URL to load for getting the Anti-CSRF form token, used for testing.
priv
.
formTokenPath
=
spec
.
formTokenPath
||
priv
.
xwikiurl
;
// 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.
priv
.
useBlobs
=
spec
.
useBlobs
||
false
;
that
.
specToStore
=
function
()
{
return
{
"
username
"
:
priv
.
username
,
"
language
"
:
priv
.
language
,
"
xwikiurl
"
:
priv
.
xwikiurl
};
};
if
(
err
)
{
return
andThen
(
null
,
err
);
}
for
(
i
=
0
;
i
<
rows
.
length
;
i
++
)
{
rows
[
i
]
=
{
id
:
rows
[
i
],
key
:
rows
[
i
],
value
:
{}
};
};
}
// can't fo wrong since no parameters are required.
if
(
includeDocs
)
{
that
.
validateState
=
function
()
{
next
(
0
);
return
''
;
}
else
{
andThen
(
rows
);
}
});
}
};
};
}
// ==================== commands ====================
/**
/**
* Create a document in local storage.
* Create a document in local storage.
*
* @method post
* @method post
* @param {object} command The JIO command
* @param {Object} command The JIO command
* @param {Object} metadata The metadata to store
* @param {Object} options The command options
*/
*/
that
.
post
=
function
(
command
)
{
XWikiStorage
.
prototype
.
post
=
function
(
command
,
metadata
)
{
var
docId
=
command
.
getDocId
();
var
doc_id
=
metadata
.
_id
,
that
=
this
;
if
(
!
(
typeof
docId
===
"
string
"
&&
docId
!==
""
))
{
if
(
!
doc_id
)
{
setTimeout
(
function
()
{
doc_id
=
jIO
.
util
.
generateUuid
();
that
.
error
({
"
status
"
:
405
,
"
statusText
"
:
"
Method Not Allowed
"
,
"
error
"
:
"
method_not_allowed
"
,
"
message
"
:
"
Cannot create document which id is undefined
"
,
"
reason
"
:
"
Document id is undefined
"
});
});
return
;
}
}
xwikistorage
.
getItem
(
docI
d
,
function
(
doc
,
err
)
{
that
.
_storage
.
getItem
(
doc_i
d
,
function
(
doc
,
err
)
{
if
(
err
)
{
if
(
err
)
{
that
.
error
(
err
);
command
.
error
(
err
);
}
else
if
(
doc
===
null
)
{
return
;
}
if
(
doc
===
null
)
{
// the document does not exist
// the document does not exist
xwikistorage
.
setItem
(
command
.
getDocId
(),
doc
=
jIO
.
util
.
deepClone
(
metadata
);
command
.
cloneDoc
(),
doc
.
_id
=
doc_id
;
function
(
err
)
{
delete
doc
.
_attachments
;
that
.
_storage
.
setItem
(
doc_id
,
doc
,
function
(
err
)
{
if
(
err
)
{
if
(
err
)
{
that
.
error
(
err
);
command
.
error
(
"
failed
"
,
"
failed to upload document
"
,
String
(
err
)
);
}
else
{
}
else
{
that
.
success
({
command
.
success
({
"
id
"
:
doc_id
});
"
ok
"
:
true
,
"
id
"
:
command
.
getDocId
()
});
}
}
});
});
}
else
{
}
else
{
// the document already exists
// the document already exists
that
.
error
({
command
.
error
(
"
status
"
:
409
,
"
conflict
"
,
"
statusText
"
:
"
Conflicts
"
,
"
document exists
"
,
"
error
"
:
"
conflicts
"
,
"
Cannot create a new document
"
"
message
"
:
"
Cannot create a new document
"
,
);
"
reason
"
:
"
Document already exists (use 'put' to modify it)
"
});
}
}
});
});
};
};
/**
/**
* Create or update a document in local storage.
* Create or update a document in local storage.
*
* @method put
* @method put
* @param {object} command The JIO command
* @param {Object} command The JIO command
* @param {Object} metadata The metadata to store
* @param {Object} options The command options
*/
*/
that
.
put
=
function
(
command
)
{
XWikiStorage
.
prototype
.
put
=
function
(
command
,
metadata
)
{
xwikistorage
.
getItem
(
command
.
getDocId
(),
function
(
doc
,
err
)
{
var
tmp
,
status
,
that
=
this
;
that
.
_storage
.
getItem
(
metadata
.
_id
,
function
(
doc
,
err
)
{
if
(
err
)
{
if
(
err
)
{
that
.
error
(
err
);
command
.
error
(
err
);
}
else
if
(
doc
===
null
)
{
return
;
doc
=
command
.
cloneDoc
();
}
else
{
priv
.
documentObjectUpdate
(
doc
,
command
.
cloneDoc
());
}
}
// write
if
(
doc
===
null
||
doc
===
undefined
)
{
xwikistorage
.
setItem
(
command
.
getDocId
(),
doc
,
function
(
err
)
{
// the document does not exist
if
(
err
)
{
doc
=
jIO
.
util
.
deepClone
(
metadata
);
that
.
error
(
err
);
delete
doc
.
_attachments
;
status
=
"
created
"
;
}
else
{
}
else
{
that
.
success
({
// the document already exists
"
ok
"
:
true
,
tmp
=
jIO
.
util
.
deepClone
(
metadata
);
"
id
"
:
command
.
getDocId
()
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
* Add an attachment to a document
*
* @method putAttachment
* @method putAttachment
* @param {object} command The JIO command
* @param {Object} command The JIO command
* @param {Object} param The given parameters
* @param {Object} options The command options
*/
*/
that
.
putAttachment
=
function
(
command
)
{
XWikiStorage
.
prototype
.
putAttachment
=
function
(
command
,
param
)
{
xwikistorage
.
getItem
(
command
.
getDocId
(),
function
(
doc
,
err
)
{
var
that
=
this
,
status
=
"
created
"
;
that
.
_storage
.
getItem
(
param
.
_id
,
function
(
doc
,
err
)
{
if
(
err
)
{
if
(
err
)
{
that
.
error
(
err
);
return
command
.
error
(
err
);
}
else
if
(
doc
===
null
)
{
}
if
(
doc
===
null
)
{
// the document does not exist
// the document does not exist
that
.
error
({
return
command
.
error
(
"
status
"
:
404
,
"
not_found
"
,
"
statusText
"
:
"
Not Found
"
,
"
missing
"
,
"
error
"
:
"
not_found
"
,
"
Impossible to add attachment
"
"
message
"
:
"
Impossible to add attachment
"
,
);
"
reason
"
:
"
Document not found
"
}
});
}
else
{
// the document already exists
// Document exists, upload attachment.
// download data
xwikistorage
.
setAttachment
(
command
.
getDocId
(),
if
((
doc
.
_attachments
||
{})[
param
.
_attachment
])
{
command
.
getAttachmentId
(),
status
=
"
no_content
"
;
command
.
getAttachmentMimeType
(),
}
command
.
getAttachmentData
(),
that
.
_storage
.
setAttachment
(
param
.
_id
,
param
.
_attachment
,
param
.
_blob
,
function
(
err
)
{
function
(
err
)
{
if
(
err
)
{
if
(
err
)
{
that
.
error
(
err
);
command
.
error
(
err
);
}
else
{
}
else
{
that
.
success
({
// XWiki doesn't do digests of attachments
"
ok
"
:
true
,
// so we'll calculate it on the client side.
"
id
"
:
command
.
getDocId
()
+
"
/
"
+
command
.
getAttachmentId
()
jIO
.
util
.
readBlobAsBinaryString
(
param
.
_blob
).
then
(
function
(
e
)
{
command
.
success
(
status
,
{
"
digest
"
:
jIO
.
util
.
makeBinaryStringDigest
(
e
.
target
.
result
)}
);
});
});
}
}
});
});
}
});
});
};
};
/**
/**
* Get a document or attachment
* Get a document
*
* @method get
* @method get
* @param {object} command The JIO command
* @param {Object} command The JIO command
* @param {Object} param The given parameters
* @param {Object} options The command options
*/
*/
that
.
get
=
that
.
getAttachment
=
function
(
command
)
{
XWikiStorage
.
prototype
.
get
=
function
(
command
,
param
)
{
if
(
typeof
command
.
getAttachmentId
()
===
"
string
"
)
{
this
.
_storage
.
getItem
(
param
.
_id
,
function
(
ret
,
err
)
{
// seeking for an attachment
if
(
err
)
{
command
.
error
(
err
);
return
;
}
xwikistorage
.
getAttachment
(
command
.
getDocId
(),
if
(
ret
===
null
)
{
command
.
getAttachmentId
(),
command
.
error
(
function
(
attach
,
err
)
{
"
not_found
"
,
if
(
err
)
{
"
missing
"
,
that
.
error
(
err
);
"
Cannot find document
"
}
else
if
(
attach
!==
null
)
{
);
that
.
success
(
attach
);
}
else
{
}
else
{
that
.
error
({
command
.
success
({
"
data
"
:
ret
});
"
status
"
:
404
,
"
statusText
"
:
"
Not Found
"
,
"
error
"
:
"
not_found
"
,
"
message
"
:
"
Cannot find the attachment
"
,
"
reason
"
:
"
Attachment does not exist
"
});
}
}
});
});
}
else
{
};
// seeking for a document
xwikistorage
.
getItem
(
command
.
getDocId
(),
function
(
doc
,
err
)
{
/**
* Get an attachment
*
* @method getAttachment
* @param {Object} command The JIO command
* @param {Object} param The given parameters
* @param {Object} options The command options
*/
XWikiStorage
.
prototype
.
getAttachment
=
function
(
command
,
param
)
{
var
that
=
this
;
that
.
_storage
.
getItem
(
param
.
_id
,
function
(
doc
,
err
)
{
if
(
err
)
{
if
(
err
)
{
that
.
error
(
err
);
return
command
.
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
"
});
}
}
});
if
(
doc
===
null
)
{
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
||
""
});
});
});
};
};
/**
/**
* Remove a document or attachment
* Remove a document
*
* @method remove
* @method remove
* @param {object} command The JIO command
* @param {Object} command The JIO command
* @param {Object} param The given parameters
* @param {Object} options The command options
*/
*/
that
.
remove
=
that
.
removeAttachment
=
function
(
command
)
{
XWikiStorage
.
prototype
.
remove
=
function
(
command
,
param
)
{
var
objId
,
complete
;
this
.
_storage
.
removeItem
(
param
.
_id
,
function
(
err
)
{
// notFoundError = function (word) {
// that.error({
// "status": 404,
// "statusText": "Not Found",
// "error": "not_found",
// "message": word + " not found",
// "reason": "missing"
// });
// };
objId
=
command
.
getDocId
();
complete
=
function
(
err
)
{
if
(
err
)
{
if
(
err
)
{
that
.
error
(
err
);
command
.
error
(
err
);
}
else
{
}
else
{
that
.
success
({
command
.
success
();
"
ok
"
:
true
,
"
id
"
:
objId
});
}
}
});
};
};
if
(
typeof
command
.
getAttachmentId
()
===
"
string
"
)
{
objId
+=
'
/
'
+
command
.
getAttachmentId
();
/**
xwikistorage
.
removeAttachment
(
command
.
getDocId
(),
* Remove an attachment
command
.
getAttachmentId
(),
*
complete
);
* @method removeAttachment
* @param {Object} command The JIO command
* @param {Object} param The given parameters
* @param {Object} options The command options
*/
XWikiStorage
.
prototype
.
removeAttachment
=
function
(
command
,
param
)
{
var
that
=
this
;
that
.
_storage
.
getItem
(
param
.
_id
,
function
(
doc
,
err
)
{
if
(
err
)
{
return
command
.
error
(
err
);
}
if
(
typeof
doc
!==
'
object
'
||
doc
===
null
)
{
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
)
{
command
.
error
(
err
);
}
else
{
}
else
{
xwikistorage
.
removeItem
(
objId
,
complete
);
command
.
success
(
);
}
}
});
});
};
};
/**
/**
* Get all filenames belonging to a user from the document index
* Get all filenames belonging to a user from the document index
*
* @method allDocs
* @method allDocs
* @param {object} command The JIO command
* @param {Object} command The JIO command
* @param {Object} param The given parameters
* @param {Object} options The command options
*/
*/
that
.
allDocs
=
function
()
{
XWikiStorage
.
prototype
.
allDocs
=
function
(
command
,
param
,
options
)
{
setTimeout
(
function
()
{
var
i
,
document_list
,
document_object
,
delete_id
,
that
=
this
;
that
.
error
({
param
.
unused
=
true
;
"
status
"
:
405
,
document_list
=
[];
"
statusText
"
:
"
Method Not Allowed
"
,
if
(
options
.
query
===
undefined
&&
options
.
sort_on
===
undefined
&&
"
error
"
:
"
method_not_allowed
"
,
options
.
select_list
===
undefined
&&
"
message
"
:
"
Your are not allowed to use this command
"
,
options
.
include_docs
===
undefined
)
{
"
reason
"
:
"
xwikistorage forbids AllDocs command executions
"
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
{
that
.
_storage
.
allDocs
(
true
,
function
(
rows
,
err
)
{
if
(
err
)
{
return
command
.
error
(
err
);
}
for
(
i
=
0
;
i
<
rows
.
length
;
i
++
)
{
document_list
.
push
(
rows
[
i
].
doc
);
}
});
options
.
select_list
=
options
.
select_list
||
[];
if
(
options
.
select_list
.
indexOf
(
"
_id
"
)
===
-
1
)
{
options
.
select_list
.
push
(
"
_id
"
);
delete_id
=
true
;
}
if
(
options
.
include_docs
===
true
)
{
document_object
=
{};
document_list
.
forEach
(
function
(
meta
)
{
document_object
[
meta
.
_id
]
=
meta
;
});
}
jIO
.
QueryFactory
.
create
(
options
.
query
||
""
,
this
.
_key_schema
).
exec
(
document_list
,
options
).
then
(
function
()
{
document_list
=
document_list
.
map
(
function
(
value
)
{
var
o
=
{
"
id
"
:
value
.
_id
,
"
key
"
:
value
.
_id
};
if
(
options
.
include_docs
===
true
)
{
o
.
doc
=
document_object
[
value
.
_id
];
delete
document_object
[
value
.
_id
];
}
if
(
delete_id
)
{
delete
value
.
_id
;
}
o
.
value
=
value
;
return
o
;
});
});
command
.
success
({
"
data
"
:
{
"
total_rows
"
:
document_list
.
length
,
"
rows
"
:
document_list
}});
});
}
};
};
return
that
;
/**
* 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
);
};
};
if
(
typeof
define
===
'
function
'
&&
define
.
amd
)
{
/**
define
([
'
jquery
'
,
'
jio
'
],
function
(
jquery
,
jIO
)
{
* Repair the storage or a specific document
$
=
jquery
;
*
jIO
.
addStorageType
(
'
xwiki
'
,
store
);
* @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
)
{
if
(
param
.
referenced_attachments
.
indexOf
(
attachment
)
!==
-
1
)
{
return
;
}
if
(
param
.
unreferenced_attachments
.
indexOf
(
attachment
)
!==
-
1
)
{
return
;
}
param
.
unreferenced_attachments
[
param
.
unreferenced_attachments
.
length
]
=
attachment
;
}
function
repairOne
(
param
,
repair
)
{
var
i
,
doc
,
modified
;
doc
=
that
.
_storage
.
getItem
(
param
.
_id
);
if
(
doc
===
null
)
{
return
;
// OK
}
// check document type
if
(
typeof
doc
!==
'
object
'
||
doc
===
null
)
{
// wrong document
if
(
!
repair
)
{
return
{
"
error
"
:
true
,
"
answers
"
:
[
"
conflict
"
,
"
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
"
]};
}
}
else
{
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
{
}
else
{
jIO
.
addStorageType
(
'
xwiki
'
,
store
);
// attachment exists
$
=
jQuery
;
// 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
)
{
var
i
,
result
;
for
(
i
in
that
.
_database
)
{
if
(
that
.
_database
.
hasOwnProperty
(
i
))
{
// browsing every entry
// 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
||
[]);
};
jIO
.
addStorage
(
'
xwiki
'
,
XWikiStorage
);
}
(
));
}));
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
funcs
=
[],
timeouts
=
[],
calls
=
0
,
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
);
}
};
};
waitFor
.
abort
=
function
()
{
timeouts
.
forEach
(
clearTimeout
);
abort
=
1
;
};
ret
=
{
nThen
:
function
(
next
)
{
if
(
!
abort
)
{
if
(
!
calls
)
{
next
(
waitFor
);
}
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
'
);
function
setUp
()
{
var
o
=
{
var
o
=
{
clock
:
sinon
.
useFakeTimers
(),
sinon
:
sinon
.
sandbox
.
create
()
spy
:
util
.
ospy
,
tick
:
util
.
otick
};
};
function
addFakeServerResponse
(
type
,
method
,
path
,
status
,
response
)
{
o
.
addFakeServerResponse
=
function
(
type
,
method
,
path
,
status
,
response
,
t
)
{
t
=
t
||
'
application/xml
'
;
/*jslint unparam: true */
/*jslint unparam: true */
o
.
server
.
respondWith
(
method
,
new
RegExp
(
path
),
[
o
.
sinon
.
server
.
respondWith
(
method
,
new
RegExp
(
path
),
[
status
,
status
,
{
"
Content-Type
"
:
'
application/xml
'
},
{
"
Content-Type
"
:
t
},
response
response
]);
]);
}
};
o
.
addFakeServerResponse
=
addFakeServerResponse
;
o
.
sinon
.
useFakeTimers
();
return
o
;
o
.
sinon
.
useFakeServer
();
}
module
(
'
XWikiStorage
'
);
o
.
respond
=
function
()
{
o
.
sinon
.
clock
.
tick
(
5000
);
o
.
sinon
.
server
.
respond
();
};
function
setUp
(
that
)
{
o
.
jio
=
jIO
.
createJIO
(
var
o
=
generateTools
(
that
);
{
type
:
'
xwiki
'
,
formTokenPath
:
'
form_token
'
,
xwikiurl
:
''
}
o
.
server
=
sinon
.
fakeServer
.
create
();
);
o
.
jio
=
jIO
.
newJio
({
type
:
'
xwiki
'
,
formTokenPath
:
'
form_token
'
});
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,227 +157,559 @@
...
@@ -70,227 +157,559 @@
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 without id
o
.
spy
(
o
,
"
status
"
,
405
,
"
Post without id
"
);
o
.
jio
.
post
({},
o
.
f
);
o
.
clock
.
tick
(
5000
);
o
.
assertReqs
(
0
,
"
no id -> no request
"
);
// post non empty document
// post non empty document
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
POST
"
,
"
myFile
"
,
201
,
"
HTML RESPONSE
"
);
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
POST
"
,
"
myFile1
"
,
201
,
"
HTML RESPONSE
"
);
o
.
spy
(
o
,
"
value
"
,
{
"
id
"
:
"
myFile
"
,
"
ok
"
:
true
},
o
.
jio
.
post
({
"
_id
"
:
"
myFile1
"
,
"
title
"
:
"
hello there
"
}).
"
Create = POST non empty document
"
);
then
(
waitFor
(
function
(
ret
)
{
o
.
jio
.
post
({
"
_id
"
:
"
myFile
"
,
"
title
"
:
"
hello there
"
},
o
.
f
);
deepEqual
({
o
.
clock
.
tick
(
5000
);
id
:
"
myFile1
"
,
o
.
server
.
respond
();
method
:
"
post
"
,
result
:
"
success
"
,
status
:
201
,
statusText
:
"
Created
"
},
ret
);
}));
o
.
respond
();
}).
nThen
(
function
()
{
o
.
assertReqs
(
o
.
assertReqs
(
3
,
3
,
"
pu
t -> 1 request to get csrf token, 1 to get doc and 1 to post data
"
"
pos
t -> 1 request to get csrf token, 1 to get doc and 1 to post data
"
);
);
}));
});
test
(
"
Post2
"
,
function
()
{
var
o
=
setUp
(
this
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
// post but document already exists (post = error!, put = ok)
// post but document already exists (post = error!, put = ok)
o
.
answer
=
'
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
'
+
o
.
answer
=
'
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
'
+
'
<page xmlns="http://www.xwiki.org"><title>hello there</title></page>
'
;
'
<page xmlns="http://www.xwiki.org"><title>hello there</title></page>
'
;
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
GET
"
,
"
myFile2
"
,
200
,
o
.
answer
);
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
GET
"
,
"
pages/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
.
jio
.
post
({
"
_id
"
:
"
myFile2
"
,
"
title
"
:
"
hello again
"
}).
o
.
clock
.
tick
(
5000
);
then
(
function
()
{
o
.
server
.
respond
();
ok
(
0
);
o
.
assertReqs
(
1
,
"
post w/ existing doc -> 1 request to get doc then fail
"
);
},
waitFor
(
function
(
err
)
{
deepEqual
({
util
.
closeAndcleanUpJio
(
o
.
jio
);
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
"
);
}));
});
});
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
// put without id => id required
o
.
spy
(
o
,
"
status
"
,
20
,
"
Put without id
"
);
o
.
jio
.
put
({}).
then
(
function
()
{
o
.
jio
.
put
({},
o
.
f
);
ok
(
0
);
o
.
clock
.
tick
(
5000
);
},
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
"
);
o
.
assertReqs
(
0
,
"
put w/o id -> 0 requests
"
);
}));
});
test
(
"
Put
"
,
function
()
{
var
o
=
setUp
(
this
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
// put non empty document
// put non empty document
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
POST
"
,
"
put1
"
,
201
,
"
HTML RESPONSE
"
);
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
POST
"
,
"
put1
"
,
201
,
"
HTML RESPONSE
"
);
o
.
spy
(
o
,
"
value
"
,
{
"
ok
"
:
true
,
"
id
"
:
"
put1
"
},
o
.
jio
.
put
({
"
_id
"
:
"
put1
"
,
"
title
"
:
"
myPut1
"
}).
"
Create = PUT non empty document
"
);
then
(
waitFor
(
function
(
res
)
{
o
.
jio
.
put
({
"
_id
"
:
"
put1
"
,
"
title
"
:
"
myPut1
"
},
o
.
f
);
deepEqual
({
o
.
clock
.
tick
(
5000
);
"
id
"
:
"
put1
"
,
o
.
server
.
respond
();
"
method
"
:
"
put
"
,
"
result
"
:
"
success
"
,
"
status
"
:
201
,
"
statusText
"
:
"
Created
"
},
res
);
}));
o
.
respond
();
}).
nThen
(
function
()
{
o
.
assertReqs
(
o
.
assertReqs
(
3
,
3
,
"
put normal doc -> 1 req to get doc
, 1 for csrf token, 1 to post
"
"
put normal doc -> 1 req to get doc (404)
, 1 for csrf token, 1 to post
"
);
);
}));
});
test
(
"
PutUpdateDoc
"
,
function
()
{
var
o
=
setUp
(
this
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
// put but document already exists = update
// put but document already exists = update
o
.
answer
=
'
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
'
+
o
.
answer
=
'
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
'
+
'
<page xmlns="http://www.xwiki.org"><title>mtPut1</title></page>
'
;
'
<page xmlns="http://www.xwiki.org"><title>mtPut1</title></page>
'
;
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
GET
"
,
"
put2
"
,
200
,
o
.
answer
);
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
GET
"
,
"
put2
"
,
200
,
o
.
answer
);
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
POST
"
,
"
put2
"
,
201
,
"
HTML RESPONSE
"
);
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
POST
"
,
"
put2
"
,
201
,
"
HTML RESPONSE
"
);
o
.
spy
(
o
,
"
value
"
,
{
"
ok
"
:
true
,
"
id
"
:
"
put2
"
},
"
Updated the document
"
);
o
.
jio
.
put
({
"
_id
"
:
"
put2
"
,
"
title
"
:
"
myPut2abcdedg
"
},
o
.
f
);
o
.
jio
.
put
({
"
_id
"
:
"
put2
"
,
"
title
"
:
"
myPut2abcdedg
"
}).
o
.
clock
.
tick
(
5000
);
then
(
waitFor
(
function
(
ret
)
{
o
.
server
.
respond
();
deepEqual
({
"
id
"
:
"
put2
"
,
"
method
"
:
"
put
"
,
"
result
"
:
"
success
"
,
"
status
"
:
204
,
"
statusText
"
:
"
No Content
"
},
ret
);
}));
o
.
respond
();
}).
nThen
(
function
()
{
o
.
assertReqs
(
o
.
assertReqs
(
3
,
4
,
"
put update doc -> 1
req to get doc, 1 for csrf token, 1 to post
"
"
put update doc -> 2
req to get doc, 1 for csrf token, 1 to post
"
);
);
util
.
closeAndcleanUpJio
(
o
.
jio
);
})
);
});
});
test
(
"
PutAttachment
"
,
function
()
{
test
(
"
PutAttachmentNoDocId
"
,
function
()
{
var
o
=
setUp
(
this
);
var
o
=
setUp
(
this
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
// putAttachment without doc id => id required
// putAttachment without doc id => id required
o
.
spy
(
o
,
"
status
"
,
20
,
"
PutAttachment without doc id
"
);
o
.
jio
.
putAttachment
({},
function
()
{
o
.
jio
.
putAttachment
({},
o
.
f
);
ok
(
0
);
o
.
clock
.
tick
(
5000
);
},
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
"
);
o
.
assertReqs
(
0
,
"
put attach w/o doc id -> 0 requests
"
);
}));
});
test
(
"
PutAttachmentNoAttachId
"
,
function
()
{
var
o
=
setUp
(
this
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
// putAttachment without attachment id => attachment id required
// putAttachment without attachment id => attachment id required
o
.
spy
(
o
,
"
status
"
,
22
,
"
PutAttachment without attachment id
"
);
o
.
jio
.
putAttachment
({
"
_id
"
:
"
putattmt1
"
},
function
()
{
o
.
jio
.
putAttachment
({
"
_id
"
:
"
putattmt1
"
},
o
.
f
);
ok
(
0
);
o
.
clock
.
tick
(
5000
);
},
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
"
);
o
.
assertReqs
(
0
,
"
put attach w/o attach id -> 0 requests
"
);
}));
});
test
(
"
PutAttachmentUnderlyingDocumentNonexistant
"
,
function
()
{
var
o
=
setUp
(
this
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
// putAttachment without underlying document => not found
// putAttachment without underlying document => not found
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
GET
"
,
"
putattmtx
"
,
404
,
"
HTML RESPONSE
"
);
o
.
jio
.
putAttachment
(
o
.
spy
(
o
,
"
status
"
,
404
,
"
PutAttachment without document
"
);
{
"
_id
"
:
"
putattmtx
"
,
"
_attachment
"
:
"
putattmt2
"
,
"
_data
"
:
""
},
o
.
jio
.
putAttachment
({
"
_id
"
:
"
putattmtx
"
,
"
_attachment
"
:
"
putattmt2
"
},
o
.
f
);
function
()
{
o
.
clock
.
tick
(
5000
);
ok
(
0
);
o
.
server
.
respond
();
},
o
.
assertReqs
(
1
,
"
put attach w/o existing document -> 1 request to get doc
"
);
waitFor
(
function
(
err
)
{
deepEqual
({
// putAttachment with document without data
"
attachment
"
:
"
putattmt2
"
,
o
.
answer
=
'
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
'
+
"
error
"
:
"
not_found
"
,
'
<page xmlns="http://www.xwiki.org"><title>myPutAttm</title></page>
'
;
"
id
"
:
"
putattmtx
"
,
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
GET
"
,
"
putattmt1
"
,
200
,
o
.
answer
);
"
message
"
:
"
Impossible to add attachment
"
,
o
.
addFakeServerResponse
(
"
method
"
:
"
putAttachment
"
,
"
xwiki
"
,
"
reason
"
:
"
missing
"
,
"
POST
"
,
"
result
"
:
"
error
"
,
"
putattmt1/putattmt2
"
,
"
status
"
:
404
,
201
,
"
statusText
"
:
"
Not Found
"
"
HTML RESPONSE
"
},
err
);
})
);
);
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
()
{
o
.
respond
();
var
o
=
setUp
(
this
);
}).
nThen
(
function
()
{
o
.
assertReqs
(
1
,
"
put attach w/o existing document -> 1 request to get doc
"
);
}));
});
test
(
"
GetNonexistantDoc
"
,
function
()
{
var
o
=
setUp
(
this
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
// get inexistent document
// get inexistent document
o
.
spy
(
o
,
"
status
"
,
404
,
"
Get non existing document
"
);
o
.
jio
.
get
({
_id
:
"
get_nonexistant_doc
"
},
function
()
{
o
.
jio
.
get
(
"
get1
"
,
o
.
f
);
ok
(
0
);
o
.
clock
.
tick
(
5000
);
},
waitFor
(
function
(
err
)
{
o
.
server
.
respond
();
deepEqual
({
"
error
"
:
"
not_found
"
,
"
id
"
:
"
get_nonexistant_doc
"
,
"
message
"
:
"
Cannot find document
"
,
"
method
"
:
"
get
"
,
"
reason
"
:
"
missing
"
,
"
result
"
:
"
error
"
,
"
status
"
:
404
,
"
statusText
"
:
"
Not Found
"
},
err
);
}));
o
.
respond
();
}).
nThen
(
function
()
{
o
.
assertReqs
(
1
,
"
try to get nonexistent doc -> 1 request
"
);
o
.
assertReqs
(
1
,
"
try to get nonexistent doc -> 1 request
"
);
}));
});
// get inexistent attachment
test
(
"
GetAttachInNonexistantDoc
"
,
function
()
{
o
.
spy
(
o
,
"
status
"
,
404
,
"
Get non existing attachment
"
);
var
o
=
setUp
(
this
);
o
.
jio
.
get
(
"
get1/get2
"
,
o
.
f
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
o
.
clock
.
tick
(
5000
);
o
.
jio
.
getAttachment
(
o
.
server
.
respond
();
{
"
_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
"
);
o
.
assertReqs
(
1
,
"
try to get nonexistent attach -> 1 request
"
);
}));
});
// get document
test
(
"
GetDoc
"
,
function
()
{
var
o
=
setUp
(
this
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
o
.
answer
=
'
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
'
+
o
.
answer
=
'
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
'
+
'
<page xmlns="http://www.xwiki.org"><title>some title</title></page>
'
;
'
<page xmlns="http://www.xwiki.org"><title>some title</title></page>
'
;
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
GET
"
,
"
get3
"
,
200
,
o
.
answer
);
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
GET
"
,
"
get_doc
"
,
200
,
o
.
answer
);
o
.
spy
(
o
,
"
value
"
,
{
"
_id
"
:
"
get3
"
,
"
title
"
:
"
some title
"
},
"
Get document
"
);
o
.
jio
.
get
(
"
get3
"
,
o
.
f
);
o
.
jio
.
get
({
_id
:
"
get_doc
"
}).
then
(
waitFor
(
function
(
ret
)
{
o
.
clock
.
tick
(
5000
);
deepEqual
({
o
.
server
.
respond
();
"
data
"
:
{
o
.
assertReqs
(
1
,
"
get document -> 1 request
"
);
"
_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
"
);
}));
});
test
(
"
GetNonexistantAttach
"
,
function
()
{
var
o
=
setUp
(
this
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
// get inexistent attachment (document exists)
// get inexistent attachment (document exists)
o
.
spy
(
o
,
"
status
"
,
404
,
"
Get non existing attachment (doc exists)
"
);
o
.
answer
=
'
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
'
+
o
.
jio
.
get
({
"
_id
"
:
"
get3
"
,
"
_attachment
"
:
"
getx
"
},
o
.
f
);
'
<page xmlns="http://www.xwiki.org"><title>some title</title></page>
'
;
o
.
clock
.
tick
(
5000
);
o
.
addFakeServerResponse
(
o
.
server
.
respond
();
"
xwiki
"
,
o
.
assertReqs
(
1
,
"
get nonexistant attachment -> 1 request
"
);
"
GET
"
,
"
get_nonexistant_attach
"
,
200
,
o
.
answer
);
o
.
jio
.
getAttachment
(
{
"
_id
"
:
"
get_nonexistant_attach
"
,
"
_attachment
"
:
"
nxattach
"
},
function
()
{
ok
(
0
);
},
waitFor
(
function
(
err
)
{
deepEqual
({
"
attachment
"
:
"
nxattach
"
,
"
error
"
:
"
not_found
"
,
"
id
"
:
"
get_nonexistant_attach
"
,
"
message
"
:
"
Cannot find attachment
"
,
"
method
"
:
"
getAttachment
"
,
"
reason
"
:
"
missing attachment
"
,
"
result
"
:
"
error
"
,
"
status
"
:
404
,
"
statusText
"
:
"
Not Found
"
},
err
);
})
);
o
.
respond
();
}).
nThen
(
function
()
{
o
.
assertReqs
(
2
,
"
get nonexistant attachment -> 2 request to get doc
"
);
}));
});
test
(
"
GetAttachHappyPath
"
,
function
()
{
var
o
=
setUp
(
this
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
// get attachment
// get attachment
o
.
answer
=
JSON
.
stringify
({
"
_id
"
:
"
get4
"
,
"
title
"
:
"
some attachment
"
});
o
.
addFakeServerResponse
(
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
GET
"
,
"
get3/get4
"
,
200
,
o
.
answer
);
"
xwiki
"
,
o
.
spy
(
o
,
"
value
"
,
{
"
_id
"
:
"
get4
"
,
"
title
"
:
"
some attachment
"
},
"
GET
"
,
"
Get attachment
"
);
"
spaces/Main/pages/get_attachment$
"
,
o
.
jio
.
get
({
"
_id
"
:
"
get3
"
,
"
_attachment
"
:
"
get4
"
},
o
.
f
);
200
,
o
.
clock
.
tick
(
5000
);
'
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
'
+
o
.
server
.
respond
();
'
<page xmlns="http://www.xwiki.org"><title>some title</title></page>
'
o
.
assertReqs
(
1
,
"
get attachment -> 1 request
"
);
);
o
.
addFakeServerResponse
(
util
.
closeAndcleanUpJio
(
o
.
jio
);
"
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
// remove inexistent document
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
GET
"
,
"
remove1
"
,
404
,
"
HTML RESPONSE
"
);
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
.
jio
.
remove
({
"
_id
"
:
"
remove1
"
},
waitFor
(
function
(
ret
)
{
o
.
clock
.
tick
(
5000
);
deepEqual
({
o
.
server
.
respond
();
"
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
(
o
.
assertReqs
(
2
,
2
,
"
remove nonexistent doc -> 1 request for csrf and 1 for doc
"
"
remove nonexistent doc -> 1 request for csrf and 1 for doc
"
);
);
}));
});
test
(
"
RemoveNonexistantAttachment
"
,
function
()
{
var
o
=
setUp
(
this
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
// remove inexistent document/attachment
// remove inexistent document/attachment
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
GET
"
,
"
remove1/remove2
"
,
404
,
"
HTML
"
+
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
GET
"
,
"
remove1/remove2
"
,
404
,
"
HTML
"
+
"
RESPONSE
"
);
"
RESPONSE
"
);
o
.
spy
(
o
,
"
status
"
,
404
,
"
Remove inexistent document/attachment
"
);
o
.
jio
.
removeAttachment
({
"
_id
"
:
"
remove1
"
,
"
_attachment
"
:
"
remove2
"
},
o
.
f
);
o
.
jio
.
removeAttachment
(
o
.
clock
.
tick
(
5000
);
{
"
_id
"
:
"
remove1
"
,
"
_attachment
"
:
"
remove2
"
},
o
.
server
.
respond
();
function
()
{
o
.
assertReqs
(
ok
(
0
);
2
,
},
"
remove nonexistant attach -> 1 request for csrf and 1 for doc
"
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
);
})
);
);
// remove document
o
.
respond
();
//o.answer = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' +
// '<page xmlns="http://www.xwiki.org"><title>some doc</title></page>';
}).
nThen
(
function
()
{
//o.addFakeServerResponse("xwiki", "GET", "remove3", 200, o.answer);
o
.
assertReqs
(
1
,
"
remove nonexistant attach -> 1 request for doc
"
);
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
POST
"
,
"
bin/delete/Main/remove3
"
,
}));
});
test
(
"
RemoveDocument
"
,
function
()
{
var
o
=
setUp
(
this
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
POST
"
,
"
delete/Main/remove3
"
,
200
,
"
HTML RESPONSE
"
);
200
,
"
HTML RESPONSE
"
);
o
.
spy
(
o
,
"
value
"
,
{
"
ok
"
:
true
,
"
id
"
:
"
remove3
"
},
"
Remove document
"
);
o
.
jio
.
remove
({
"
_id
"
:
"
remove3
"
},
o
.
f
);
o
.
jio
.
remove
({
"
_id
"
:
"
remove3
"
}).
then
(
waitFor
(
function
(
ret
)
{
o
.
clock
.
tick
(
5000
);
deepEqual
({
o
.
server
.
respond
();
"
id
"
:
"
remove3
"
,
"
method
"
:
"
remove
"
,
"
result
"
:
"
success
"
,
"
status
"
:
204
,
"
statusText
"
:
"
No Content
"
},
ret
);
}));
o
.
respond
();
}).
nThen
(
function
()
{
o
.
assertReqs
(
o
.
assertReqs
(
2
,
2
,
"
remove document -> 1 request for csrf and 1 for deleting doc
"
"
remove document -> 1 request for csrf and 1 for deleting doc
"
);
);
}));
o
.
answer
=
JSON
.
stringify
({
"
_id
"
:
"
remove4
"
,
"
title
"
:
"
some doc
"
,
"
_attachments
"
:
{
"
remove5
"
:
{
"
length
"
:
4
,
"
digest
"
:
"
md5-d41d8cd98f00b204e9800998ecf8427e
"
}
}
});
});
test
(
"
RemoveAttachment
"
,
function
()
{
var
o
=
setUp
(
this
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
// remove attachment
// 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
(
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
xwiki
"
,
"
POST
"
,
"
POST
"
,
...
@@ -298,14 +717,28 @@
...
@@ -298,14 +717,28 @@
200
,
200
,
"
HTML RESPONSE
"
"
HTML RESPONSE
"
);
);
o
.
spy
(
o
,
"
value
"
,
{
"
ok
"
:
true
,
"
id
"
:
"
remove4/remove5
"
},
"
Remove attachment
"
);
o
.
jio
.
removeAttachment
(
o
.
jio
.
removeAttachment
({
"
_id
"
:
"
remove4
"
,
"
_attachment
"
:
"
remove5
"
},
o
.
f
);
{
"
_id
"
:
"
remove4
"
,
"
_attachment
"
:
"
remove5
"
}
o
.
clock
.
tick
(
5000
);
).
always
(
waitFor
(
function
(
ret
)
{
o
.
server
.
respond
();
deepEqual
({
o
.
assertReqs
(
2
,
"
remove attach -> 1 request for csrf and 1 for deletion
"
);
"
attachment
"
:
"
remove5
"
,
"
id
"
:
"
remove4
"
,
util
.
closeAndcleanUpJio
(
o
.
jio
);
"
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