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
Tomáš Peterka
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,
nomen: true
plusplus: true,
nomen: true,
regexp: true
*/
/*global
define: true,
exports: true,
require: true,
jIO: true,
jQuery: true,
XMLHttpRequest: true,
Blob: true,
FormData: true,
window: true,
setTimeout: true
XMLHttpRequest,
FormData
*/
/**
* JIO XWiki Storage. Type = 'xwiki'.
* XWiki Document/Attachment storage.
*/
(
function
()
{
(
function
(
dependencies
,
module
)
{
"
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
;
store
=
function
(
spec
,
my
)
{
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
||
{};
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
=
{}
;
priv
.
pathBasedMultiwiki
=
(
spec
.
pathBasedMultiwiki
!==
undefined
)
?
spec
.
pathBasedMultiwiki
:
detectIsPathBasedMultiwiki
(
priv
.
xwikiurl
)
;
/**
* Get the Space and Page components of a documkent ID.
...
...
@@ -35,6 +114,7 @@
* @return a map of { 'space':<Space>, 'page':<Page> }
*/
priv
.
getParts
=
function
(
id
)
{
if
(
id
.
indexOf
(
'
/
'
)
===
-
1
)
{
return
{
space
:
'
Main
'
,
...
...
@@ -103,37 +183,21 @@
+
priv
.
wiki
+
'
/spaces/
'
+
parts
.
space
+
'
/pages/
'
+
parts
.
page
;
};
/**
* Make an HTML5 Blob object.
* Equivilant to the `new Blob()` constructor.
* Will fall back on deprecated BlobBuilder if necessary.
*/
priv
.
makeBlob
=
function
(
contentArray
,
options
)
{
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
);
priv
.
getURL
=
function
(
action
,
space
,
page
)
{
var
out
=
[
priv
.
xwikiurl
];
if
(
!
priv
.
pathBasedMultiwiki
)
{
out
.
push
(
'
bin
'
);
}
else
{
out
.
push
(
'
wiki
'
,
priv
.
wiki
);
}
};
priv
.
isBlob
=
function
(
potentialBlob
)
{
return
potentialBlob
!==
undefined
&&
potentialBlob
.
toString
()
===
"
[object Blob]
"
;
out
.
push
(
action
,
space
,
page
);
return
out
.
join
(
'
/
'
);
};
/*
* Wrapper for the xwikistorage based on localstorage JiO store.
*/
xwiki
storage
=
{
priv
.
_storage
=
this
.
_
storage
=
{
/**
* Get content of an XWikiDocument.
*
...
...
@@ -143,7 +207,60 @@
*/
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
;
out
=
{};
try
{
...
...
@@ -165,7 +282,7 @@
out
.
content
=
$
(
this
).
text
();
});
out
.
_id
=
docId
;
andThen
(
out
,
null
);
getAttachments
(
out
);
}
catch
(
err
)
{
andThen
(
null
,
{
status
:
500
,
...
...
@@ -175,7 +292,7 @@
reason
:
""
});
}
}
;
}
$
.
ajax
({
url
:
priv
.
getDocRestURL
(
docId
),
...
...
@@ -184,7 +301,7 @@
dataType
:
'
xml
'
,
// 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
)
{
if
(
jqxhr
.
status
===
404
)
{
andThen
(
null
,
null
);
...
...
@@ -217,14 +334,10 @@
// need to do this manually, jquery doesn't support returning blobs.
xhr
=
new
XMLHttpRequest
();
parts
=
priv
.
getParts
(
docId
);
url
=
priv
.
xwikiurl
+
'
/bin/download/
'
+
parts
.
space
+
"
/
"
+
parts
.
page
+
"
/
"
+
fileName
+
'
?cb=
'
+
Math
.
random
();
url
=
priv
.
getURL
(
'
download
'
,
parts
.
space
,
parts
.
page
)
+
'
/
'
+
fileName
+
'
?cb=
'
+
Math
.
random
();
xhr
.
open
(
'
GET
'
,
url
,
true
);
if
(
priv
.
useBlobs
)
{
xhr
.
responseType
=
'
blob
'
;
}
else
{
xhr
.
responseType
=
'
text
'
;
}
xhr
.
onload
=
function
()
{
if
(
xhr
.
status
===
200
)
{
...
...
@@ -259,13 +372,12 @@
setItem
:
function
(
id
,
doc
,
andThen
)
{
priv
.
doWithFormToken
(
function
(
formToken
,
err
)
{
if
(
err
)
{
that
.
error
(
err
);
andThen
(
err
);
return
;
}
var
parts
=
priv
.
getParts
(
id
);
$
.
ajax
({
url
:
priv
.
xwikiurl
+
"
/bin/preview/
"
+
parts
.
space
+
'
/
'
+
parts
.
page
,
url
:
priv
.
getURL
(
'
preview
'
,
parts
.
space
,
parts
.
page
),
type
:
"
POST
"
,
async
:
true
,
dataType
:
'
text
'
,
...
...
@@ -308,26 +420,26 @@
* @param docId the ID of the document to attach to.
* @param fileName the attachment file name.
* @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.
*/
setAttachment
:
function
(
docId
,
fileName
,
mimeType
,
content
,
andThen
)
{
setAttachment
:
function
(
docId
,
fileName
,
blob
,
andThen
)
{
priv
.
doWithFormToken
(
function
(
formToken
,
err
)
{
var
parts
,
blob
,
fd
,
xhr
;
var
parts
,
fd
,
xhr
;
if
(
err
)
{
that
.
error
(
err
);
andThen
(
err
);
return
;
}
parts
=
priv
.
getParts
(
docId
);
blob
=
priv
.
isBlob
(
content
)
?
content
:
priv
.
makeBlob
([
content
],
{
type
:
mimeType
});
fd
=
new
FormData
();
fd
.
append
(
"
filepath
"
,
blob
,
fileName
);
fd
.
append
(
"
form_token
"
,
formToken
);
xhr
=
new
XMLHttpRequest
();
xhr
.
open
(
'
POST
'
,
priv
.
xwikiurl
+
"
/bin/upload/
"
+
parts
.
space
+
'
/
'
+
parts
.
page
,
true
);
xhr
.
open
(
'
POST
'
,
priv
.
getURL
(
'
upload
'
,
parts
.
space
,
parts
.
page
),
true
);
xhr
.
onload
=
function
()
{
if
(
xhr
.
status
===
302
||
xhr
.
status
===
200
)
{
andThen
(
null
);
...
...
@@ -349,13 +461,12 @@
removeItem
:
function
(
id
,
andThen
)
{
priv
.
doWithFormToken
(
function
(
formToken
,
err
)
{
if
(
err
)
{
that
.
error
(
err
);
andThen
(
err
);
return
;
}
var
parts
=
priv
.
getParts
(
id
);
$
.
ajax
({
url
:
priv
.
xwikiurl
+
"
/bin/delete/
"
+
parts
.
space
+
'
/
'
+
parts
.
page
,
url
:
priv
.
getURL
(
'
delete
'
,
parts
.
space
,
parts
.
page
),
type
:
"
POST
"
,
async
:
true
,
dataType
:
'
text
'
,
...
...
@@ -383,12 +494,12 @@
var
parts
=
priv
.
getParts
(
docId
);
priv
.
doWithFormToken
(
function
(
formToken
,
err
)
{
if
(
err
)
{
that
.
error
(
err
);
andThen
(
err
);
return
;
}
$
.
ajax
({
url
:
priv
.
xwikiurl
+
"
/bin/delattachment/
"
+
parts
.
space
+
'
/
'
+
parts
.
page
+
'
/
'
+
fileName
,
url
:
priv
.
getURL
(
'
delattachment
'
,
parts
.
space
,
parts
.
page
)
+
'
/
'
+
fileName
,
type
:
"
POST
"
,
async
:
true
,
dataType
:
'
text
'
,
...
...
@@ -411,322 +522,594 @@
}
});
});
}
};
},
// ==================== Tools ====================
/**
* Update [doc] the document object and remove [doc] keys
* which are not in [new_doc]. It only changes [doc] keys not starting
* with an underscore.
* ex: doc: {key:value1,_key:value2} with
* 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
* Gets a document list from the xwiki storage.
* It will retreive an array containing files meta data owned by
* the user.
* @method allDocs
*/
priv
.
documentObjectUpdate
=
function
(
doc
,
new_doc
)
{
var
k
;
for
(
k
in
doc
)
{
if
(
doc
.
hasOwnProperty
(
k
))
{
if
(
k
[
0
]
!==
'
_
'
)
{
delete
doc
[
k
];
}
}
}
for
(
k
in
new_doc
)
{
if
(
new_doc
.
hasOwnProperty
(
k
))
{
if
(
k
[
0
]
!==
'
_
'
)
{
doc
[
k
]
=
new_doc
[
k
];
}
}
allDocs
:
function
(
includeDocs
,
andThen
)
{
var
getData
=
function
(
callback
)
{
$
.
ajax
({
url
:
priv
.
xwikiurl
+
'
/rest/wikis/xwiki/pages?cb=
'
+
Date
.
now
(),
type
:
"
GET
"
,
async
:
true
,
dataType
:
'
xml
'
,
success
:
function
(
xmlData
)
{
var
data
=
[];
$
(
xmlData
).
find
(
'
fullName
'
).
each
(
function
()
{
data
[
data
.
length
]
=
$
(
this
).
text
();
});
callback
(
data
);
},
error
:
function
(
error
)
{
andThen
(
null
,
error
);
}
});
};
/**
* Checks if an object has no enumerable keys
* @method objectIsEmpty
* @param {object} obj The object
* @return {boolean} true if empty, else false
*/
priv
.
objectIsEmpty
=
function
(
obj
)
{
var
k
;
for
(
k
in
obj
)
{
if
(
obj
.
hasOwnProperty
(
k
))
{
return
false
;
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
);
}
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.
that
.
validateState
=
function
()
{
return
''
;
}
if
(
includeDocs
)
{
next
(
0
);
}
else
{
andThen
(
rows
);
}
});
}
};
}
// ==================== commands ====================
/**
* Create a document in local storage.
*
* @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
)
{
var
docId
=
command
.
getDocId
();
if
(
!
(
typeof
docId
===
"
string
"
&&
docId
!==
""
))
{
setTimeout
(
function
()
{
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
.
prototype
.
post
=
function
(
command
,
metadata
)
{
var
doc_id
=
metadata
.
_id
,
that
=
this
;
if
(
!
doc_id
)
{
doc_id
=
jIO
.
util
.
generateUuid
();
}
xwikistorage
.
getItem
(
docI
d
,
function
(
doc
,
err
)
{
that
.
_storage
.
getItem
(
doc_i
d
,
function
(
doc
,
err
)
{
if
(
err
)
{
that
.
error
(
err
);
}
else
if
(
doc
===
null
)
{
command
.
error
(
err
);
return
;
}
if
(
doc
===
null
)
{
// the document does not exist
xwikistorage
.
setItem
(
command
.
getDocId
(),
command
.
cloneDoc
(),
function
(
err
)
{
doc
=
jIO
.
util
.
deepClone
(
metadata
);
doc
.
_id
=
doc_id
;
delete
doc
.
_attachments
;
that
.
_storage
.
setItem
(
doc_id
,
doc
,
function
(
err
)
{
if
(
err
)
{
that
.
error
(
err
);
command
.
error
(
"
failed
"
,
"
failed to upload document
"
,
String
(
err
)
);
}
else
{
that
.
success
({
"
ok
"
:
true
,
"
id
"
:
command
.
getDocId
()
});
command
.
success
({
"
id
"
:
doc_id
});
}
});
}
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)
"
});
command
.
error
(
"
conflict
"
,
"
document exists
"
,
"
Cannot create a new document
"
);
}
});
};
/**
* Create or update a document in local storage.
*
* @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
.
getItem
(
command
.
getDocId
(),
function
(
doc
,
err
)
{
XWikiStorage
.
prototype
.
put
=
function
(
command
,
metadata
)
{
var
tmp
,
status
,
that
=
this
;
that
.
_storage
.
getItem
(
metadata
.
_id
,
function
(
doc
,
err
)
{
if
(
err
)
{
that
.
error
(
err
);
}
else
if
(
doc
===
null
)
{
doc
=
command
.
cloneDoc
();
}
else
{
priv
.
documentObjectUpdate
(
doc
,
command
.
cloneDoc
());
command
.
error
(
err
);
return
;
}
// write
xwikistorage
.
setItem
(
command
.
getDocId
(),
doc
,
function
(
err
)
{
if
(
err
)
{
that
.
error
(
err
);
if
(
doc
===
null
||
doc
===
undefined
)
{
// the document does not exist
doc
=
jIO
.
util
.
deepClone
(
metadata
);
delete
doc
.
_attachments
;
status
=
"
created
"
;
}
else
{
that
.
success
({
"
ok
"
:
true
,
"
id
"
:
command
.
getDocId
()
});
// 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} command The JIO command
* @param {Object} param The given parameters
* @param {Object} options The command options
*/
that
.
putAttachment
=
function
(
command
)
{
xwikistorage
.
getItem
(
command
.
getDocId
(),
function
(
doc
,
err
)
{
XWikiStorage
.
prototype
.
putAttachment
=
function
(
command
,
param
)
{
var
that
=
this
,
status
=
"
created
"
;
that
.
_storage
.
getItem
(
param
.
_id
,
function
(
doc
,
err
)
{
if
(
err
)
{
that
.
error
(
err
);
}
else
if
(
doc
===
null
)
{
return
command
.
error
(
err
);
}
if
(
doc
===
null
)
{
// the document does not exist
that
.
error
({
"
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
(),
return
command
.
error
(
"
not_found
"
,
"
missing
"
,
"
Impossible to add attachment
"
);
}
// the document already exists
// download data
if
((
doc
.
_attachments
||
{})[
param
.
_attachment
])
{
status
=
"
no_content
"
;
}
that
.
_storage
.
setAttachment
(
param
.
_id
,
param
.
_attachment
,
param
.
_blob
,
function
(
err
)
{
if
(
err
)
{
that
.
error
(
err
);
command
.
error
(
err
);
}
else
{
that
.
success
({
"
ok
"
:
true
,
"
id
"
:
command
.
getDocId
()
+
"
/
"
+
command
.
getAttachmentId
()
// 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
)}
);
});
}
});
}
});
};
/**
* Get a document or attachment
* Get a document
*
* @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
)
{
if
(
typeof
command
.
getAttachmentId
()
===
"
string
"
)
{
// seeking for an attachment
xwikistorage
.
getAttachment
(
command
.
getDocId
(),
command
.
getAttachmentId
(),
function
(
attach
,
err
)
{
if
(
err
)
{
that
.
error
(
err
);
}
else
if
(
attach
!==
null
)
{
that
.
success
(
attach
);
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
{
that
.
error
({
"
status
"
:
404
,
"
statusText
"
:
"
Not Found
"
,
"
error
"
:
"
not_found
"
,
"
message
"
:
"
Cannot find the attachment
"
,
"
reason
"
:
"
Attachment does not exist
"
});
command
.
success
({
"
data
"
:
ret
});
}
});
}
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
)
{
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
"
});
return
command
.
error
(
err
);
}
});
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
* @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
)
{
var
objId
,
complete
;
// 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
)
{
XWikiStorage
.
prototype
.
remove
=
function
(
command
,
param
)
{
this
.
_storage
.
removeItem
(
param
.
_id
,
function
(
err
)
{
if
(
err
)
{
that
.
error
(
err
);
command
.
error
(
err
);
}
else
{
that
.
success
({
"
ok
"
:
true
,
"
id
"
:
objId
});
command
.
success
();
}
});
};
if
(
typeof
command
.
getAttachmentId
()
===
"
string
"
)
{
objId
+=
'
/
'
+
command
.
getAttachmentId
();
xwikistorage
.
removeAttachment
(
command
.
getDocId
(),
command
.
getAttachmentId
(),
complete
);
/**
* Remove an attachment
*
* @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
{
xwikistorage
.
removeItem
(
objId
,
complete
);
command
.
success
(
);
}
});
});
};
/**
* Get all filenames belonging to a user from the document index
*
* @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
()
{
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
"
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
{
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
)
{
$
=
jquery
;
jIO
.
addStorageType
(
'
xwiki
'
,
store
);
});
/**
* 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
)
{
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
{
jIO
.
addStorageType
(
'
xwiki
'
,
store
);
$
=
jQuery
;
// 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
)
{
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 */
/*global define, jIO, jio_tests, test, ok, sinon, module */
/*jslint
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);
(
function
(
dependencies
,
module
)
{
...
...
@@ -7,34 +25,103 @@
if
(
typeof
define
===
'
function
'
&&
define
.
amd
)
{
return
define
(
dependencies
,
module
);
}
module
(
jIO
,
jio_tests
);
}([
'
jio
'
,
'
jio_tests
'
,
'
xwikistorage
'
],
function
(
jIO
,
util
)
{
module
(
jIO
);
}([
'
jio
'
,
'
xwikistorage
'
],
function
(
jIO
)
{
"
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
=
{
clock
:
sinon
.
useFakeTimers
(),
spy
:
util
.
ospy
,
tick
:
util
.
otick
sinon
:
sinon
.
sandbox
.
create
()
};
function
addFakeServerResponse
(
type
,
method
,
path
,
status
,
response
)
{
o
.
addFakeServerResponse
=
function
(
type
,
method
,
path
,
status
,
response
,
t
)
{
t
=
t
||
'
application/xml
'
;
/*jslint unparam: true */
o
.
server
.
respondWith
(
method
,
new
RegExp
(
path
),
[
o
.
sinon
.
server
.
respondWith
(
method
,
new
RegExp
(
path
),
[
status
,
{
"
Content-Type
"
:
'
application/xml
'
},
{
"
Content-Type
"
:
t
},
response
]);
}
o
.
addFakeServerResponse
=
addFakeServerResponse
;
return
o
;
}
};
o
.
sinon
.
useFakeTimers
();
o
.
sinon
.
useFakeServer
();
module
(
'
XWikiStorage
'
);
o
.
respond
=
function
()
{
o
.
sinon
.
clock
.
tick
(
5000
);
o
.
sinon
.
server
.
respond
();
};
function
setUp
(
that
)
{
var
o
=
generateTools
(
that
);
o
.
server
=
sinon
.
fakeServer
.
create
();
o
.
jio
=
jIO
.
newJio
({
type
:
'
xwiki
'
,
formTokenPath
:
'
form_token
'
});
o
.
jio
=
jIO
.
createJIO
(
{
type
:
'
xwiki
'
,
formTokenPath
:
'
form_token
'
,
xwikiurl
:
''
}
);
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
GET
"
,
"
form_token
"
,
200
,
'
<meta name="form_token" content="OMGHAX"/>
'
);
o
.
_addFakeServerResponse
=
o
.
addFakeServerResponse
;
...
...
@@ -46,11 +133,11 @@
o
.
assertReqs
=
function
(
count
,
message
)
{
var
i
,
j
,
req
,
expected
,
ex
;
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 [
"
+
(
o
.
server
.
requests
.
length
-
(
o
.
requests
-
count
))
+
"
]]
"
);
(
o
.
s
inon
.
s
erver
.
requests
.
length
-
(
o
.
requests
-
count
))
+
"
]]
"
);
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
)
{
break
;
}
...
...
@@ -70,227 +157,559 @@
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
()
{
var
o
=
setUp
(
this
);
// 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
"
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
// post non empty document
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
POST
"
,
"
myFile
"
,
201
,
"
HTML RESPONSE
"
);
o
.
spy
(
o
,
"
value
"
,
{
"
id
"
:
"
myFile
"
,
"
ok
"
:
true
},
"
Create = POST non empty document
"
);
o
.
jio
.
post
({
"
_id
"
:
"
myFile
"
,
"
title
"
:
"
hello there
"
},
o
.
f
);
o
.
clock
.
tick
(
5000
);
o
.
server
.
respond
();
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
,
"
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)
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
);
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
GET
"
,
"
pages/myFile2
"
,
200
,
o
.
answer
);
o
.
jio
.
post
({
"
_id
"
:
"
myFile2
"
,
"
title
"
:
"
hello again
"
}).
then
(
function
()
{
ok
(
0
);
},
waitFor
(
function
(
err
)
{
deepEqual
({
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
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
// put without id => id required
o
.
spy
(
o
,
"
status
"
,
20
,
"
Put without id
"
);
o
.
jio
.
put
({},
o
.
f
);
o
.
clock
.
tick
(
5000
);
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
"
);
}));
});
test
(
"
Put
"
,
function
()
{
var
o
=
setUp
(
this
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
// put non empty document
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
POST
"
,
"
put1
"
,
201
,
"
HTML RESPONSE
"
);
o
.
spy
(
o
,
"
value
"
,
{
"
ok
"
:
true
,
"
id
"
:
"
put1
"
},
"
Create = PUT non empty document
"
);
o
.
jio
.
put
({
"
_id
"
:
"
put1
"
,
"
title
"
:
"
myPut1
"
},
o
.
f
);
o
.
clock
.
tick
(
5000
);
o
.
server
.
respond
();
o
.
jio
.
put
({
"
_id
"
:
"
put1
"
,
"
title
"
:
"
myPut1
"
}).
then
(
waitFor
(
function
(
res
)
{
deepEqual
({
"
id
"
:
"
put1
"
,
"
method
"
:
"
put
"
,
"
result
"
:
"
success
"
,
"
status
"
:
201
,
"
statusText
"
:
"
Created
"
},
res
);
}));
o
.
respond
();
}).
nThen
(
function
()
{
o
.
assertReqs
(
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
o
.
answer
=
'
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
'
+
'
<page xmlns="http://www.xwiki.org"><title>mtPut1</title></page>
'
;
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
GET
"
,
"
put2
"
,
200
,
o
.
answer
);
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
.
clock
.
tick
(
5000
);
o
.
server
.
respond
();
o
.
jio
.
put
({
"
_id
"
:
"
put2
"
,
"
title
"
:
"
myPut2abcdedg
"
}).
then
(
waitFor
(
function
(
ret
)
{
deepEqual
({
"
id
"
:
"
put2
"
,
"
method
"
:
"
put
"
,
"
result
"
:
"
success
"
,
"
status
"
:
204
,
"
statusText
"
:
"
No Content
"
},
ret
);
}));
o
.
respond
();
}).
nThen
(
function
()
{
o
.
assertReqs
(
3
,
"
put update doc -> 1
req to get doc, 1 for csrf token, 1 to post
"
4
,
"
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
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
// putAttachment without doc id => id required
o
.
spy
(
o
,
"
status
"
,
20
,
"
PutAttachment without doc id
"
);
o
.
jio
.
putAttachment
({},
o
.
f
);
o
.
clock
.
tick
(
5000
);
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
(
"
PutAttachmentNoAttachId
"
,
function
()
{
var
o
=
setUp
(
this
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
// putAttachment without attachment id => attachment id required
o
.
spy
(
o
,
"
status
"
,
22
,
"
PutAttachment without attachment id
"
);
o
.
jio
.
putAttachment
({
"
_id
"
:
"
putattmt1
"
},
o
.
f
);
o
.
clock
.
tick
(
5000
);
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
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
// putAttachment without underlying document => not found
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
GET
"
,
"
putattmtx
"
,
404
,
"
HTML RESPONSE
"
);
o
.
spy
(
o
,
"
status
"
,
404
,
"
PutAttachment without document
"
);
o
.
jio
.
putAttachment
({
"
_id
"
:
"
putattmtx
"
,
"
_attachment
"
:
"
putattmt2
"
},
o
.
f
);
o
.
clock
.
tick
(
5000
);
o
.
server
.
respond
();
o
.
assertReqs
(
1
,
"
put attach w/o existing document -> 1 request to get doc
"
);
// putAttachment with document without data
o
.
answer
=
'
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
'
+
'
<page xmlns="http://www.xwiki.org"><title>myPutAttm</title></page>
'
;
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
GET
"
,
"
putattmt1
"
,
200
,
o
.
answer
);
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
POST
"
,
"
putattmt1/putattmt2
"
,
201
,
"
HTML RESPONSE
"
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
.
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
o
.
spy
(
o
,
"
status
"
,
404
,
"
Get non existing document
"
);
o
.
jio
.
get
(
"
get1
"
,
o
.
f
);
o
.
clock
.
tick
(
5000
);
o
.
server
.
respond
();
o
.
jio
.
get
({
_id
:
"
get_nonexistant_doc
"
},
function
()
{
ok
(
0
);
},
waitFor
(
function
(
err
)
{
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
"
);
}));
});
// get inexistent attachment
o
.
spy
(
o
,
"
status
"
,
404
,
"
Get non existing attachment
"
);
o
.
jio
.
get
(
"
get1/get2
"
,
o
.
f
);
o
.
clock
.
tick
(
5000
);
o
.
server
.
respond
();
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
"
);
}));
});
// 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"?>
'
+
'
<page xmlns="http://www.xwiki.org"><title>some title</title></page>
'
;
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
GET
"
,
"
get3
"
,
200
,
o
.
answer
);
o
.
spy
(
o
,
"
value
"
,
{
"
_id
"
:
"
get3
"
,
"
title
"
:
"
some title
"
},
"
Get document
"
);
o
.
jio
.
get
(
"
get3
"
,
o
.
f
);
o
.
clock
.
tick
(
5000
);
o
.
server
.
respond
();
o
.
assertReqs
(
1
,
"
get document -> 1 request
"
);
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
"
);
}));
});
test
(
"
GetNonexistantAttach
"
,
function
()
{
var
o
=
setUp
(
this
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
// get inexistent attachment (document exists)
o
.
spy
(
o
,
"
status
"
,
404
,
"
Get non existing attachment (doc exists)
"
);
o
.
jio
.
get
({
"
_id
"
:
"
get3
"
,
"
_attachment
"
:
"
getx
"
},
o
.
f
);
o
.
clock
.
tick
(
5000
);
o
.
server
.
respond
();
o
.
assertReqs
(
1
,
"
get nonexistant attachment -> 1 request
"
);
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_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
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
.
jio
.
get
({
"
_id
"
:
"
get3
"
,
"
_attachment
"
:
"
get4
"
},
o
.
f
);
o
.
clock
.
tick
(
5000
);
o
.
server
.
respond
();
o
.
assertReqs
(
1
,
"
get attachment -> 1 request
"
);
util
.
closeAndcleanUpJio
(
o
.
jio
);
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
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
// 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
.
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
"
);
}));
});
test
(
"
RemoveNonexistantAttachment
"
,
function
()
{
var
o
=
setUp
(
this
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
// remove inexistent document/attachment
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
GET
"
,
"
remove1/remove2
"
,
404
,
"
HTML
"
+
"
RESPONSE
"
);
o
.
spy
(
o
,
"
status
"
,
404
,
"
Remove inexistent document/attachment
"
);
o
.
jio
.
removeAttachment
({
"
_id
"
:
"
remove1
"
,
"
_attachment
"
:
"
remove2
"
},
o
.
f
);
o
.
clock
.
tick
(
5000
);
o
.
server
.
respond
();
o
.
assertReqs
(
2
,
"
remove nonexistant attach -> 1 request for csrf and 1 for doc
"
o
.
jio
.
removeAttachment
(
{
"
_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
);
})
);
// 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
"
,
o
.
respond
();
}).
nThen
(
function
()
{
o
.
assertReqs
(
1
,
"
remove nonexistant attach -> 1 request for doc
"
);
}));
});
test
(
"
RemoveDocument
"
,
function
()
{
var
o
=
setUp
(
this
);
nThenTest
(
o
,
nThen
(
function
(
waitFor
)
{
o
.
addFakeServerResponse
(
"
xwiki
"
,
"
POST
"
,
"
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
.
jio
.
remove
({
"
_id
"
:
"
remove3
"
}).
then
(
waitFor
(
function
(
ret
)
{
deepEqual
({
"
id
"
:
"
remove3
"
,
"
method
"
:
"
remove
"
,
"
result
"
:
"
success
"
,
"
status
"
:
204
,
"
statusText
"
:
"
No Content
"
},
ret
);
}));
o
.
respond
();
}).
nThen
(
function
()
{
o
.
assertReqs
(
2
,
"
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
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
"
,
...
...
@@ -298,14 +717,28 @@
200
,
"
HTML RESPONSE
"
);
o
.
spy
(
o
,
"
value
"
,
{
"
ok
"
:
true
,
"
id
"
:
"
remove4/remove5
"
},
"
Remove attachment
"
);
o
.
jio
.
removeAttachment
({
"
_id
"
:
"
remove4
"
,
"
_attachment
"
:
"
remove5
"
},
o
.
f
);
o
.
clock
.
tick
(
5000
);
o
.
server
.
respond
();
o
.
assertReqs
(
2
,
"
remove attach -> 1 request for csrf and 1 for deletion
"
);
util
.
closeAndcleanUpJio
(
o
.
jio
);
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 @@
<script
src=
"queries/key-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=
"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