Commit bd61250f authored by Sven Franck's avatar Sven Franck

indexStorage: putAttachment new API and qunit tests

parent 06d0b3f4
...@@ -117,33 +117,49 @@ jIO.addStorageType('indexed', function (spec, my) { ...@@ -117,33 +117,49 @@ jIO.addStorageType('indexed', function (spec, my) {
return new_index_object; return new_index_object;
}; };
/**
* Determine if a key/value pair exists in an object by VALUE
* @method searchObjectByValue
* @param {object} indexToSearch The index to search
* @param {string} docid The document id to find
* @param {string} passback The value that should be returned
* @return {boolean} true/false
*/
priv.searchIndexByValue = function (indexToSearch, docid, passback) {
var key, obj, prop;
for (key in indexToSearch) {
obj = indexToSearch[key];
for (prop in obj) {
if (obj[prop] === docid) {
return passback === "bool" ? true : key;
}
}
}
return false;
}
/** /**
* Find id in indices * Find id in indices
* @method docidInIndex * @method isDocidInIndex
* @param {object} indices The file containing the indeces * @param {object} indices The file containing the indeces
* @param {object} doc The document which should be added to the index * @param {object} doc The document which should be added to the index
* @return {boolean} true/false * @return {boolean} true/false
*/ */
priv.docidInIndex = function (indices, doc) { priv.isDocidInIndex = function (indices, doc) {
var i, j, l = priv.indices.length, elements_to_check, var index, i, l = priv.indices.length;
index, index_name, index_length;
// loop indices // loop indices
for (i = 0; i < l; i += 1) { for (i = 0; i < l; i += 1) {
index = priv.indices[i]; index = {};
index_name = index["name"]; index.reference = priv.indices[i];
index_length = index.fields.length; index.name = index.reference["name"];
elements_to_check = priv.getObjectSize(indices[index_name]); index.size = priv.getObjectSize(indices[index.name]);
if (elements_to_check > 0) { if (index.size > 0) {
for (var key in indices[index_name]) { if (priv.searchIndexByValue(indices[index.name], doc._id, "bool")) {
var obj = indices[index_name][key]; return true
for (var prop in obj) { };
if (obj[prop] === doc._id) {
return true;
}
}
}
} }
} }
return false; return false;
...@@ -154,35 +170,48 @@ jIO.addStorageType('indexed', function (spec, my) { ...@@ -154,35 +170,48 @@ jIO.addStorageType('indexed', function (spec, my) {
* @param {object} indices The file containing the indeces * @param {object} indices The file containing the indeces
* @param {object} doc The document which should be added to the index * @param {object} doc The document which should be added to the index
*/ */
priv.updateIndeces = function (indices, doc) { priv.updateIndices = function (indices, doc) {
var i, j, k, m, value, var i, j, k, m, index,value, label, key, l = priv.indices.length;
index, index_name, index_length, index_field_array,
l = priv.indices.length,
docid = doc._id;
// loop indices // loop indices
for (i = 0; i < l; i += 1) { for (i = 0; i < l; i += 1) {
index = priv.indices[i]; // index object (reference and current iteration)
index_name = index["name"]; index = {};
index_length = index.fields.length; index.reference = priv.indices[i];
index_field_array = []; index.reference_size = index.reference.fields.length;
index.name = index.reference["name"];
index.field_array = [];
index.current = indices[index.name];
index.current_size = priv.getObjectSize(index.current);
// loop index fields [keywords] // build array of values to create entries in index
for (j = 0; j < index_length; j += 1) { for (j = 0; j < index.reference_size; j += 1) {
value = doc[index.fields[j]]; label = index.reference.fields[j]
value = doc[label];
if (value !== undefined) { if (value !== undefined) {
index_field_array.push(value); // add a new entry
index.field_array.push(value);
// remove existing entries with same docid
// because items are stored as "keyword:id" pairs this is tricky
if (index.current_size > 0) {
key = priv.searchIndexByValue(indices[index.name], doc._id, "key");
if (!!key) {
delete index.current[key];
} }
} }
}
m = index_field_array.length; }
// create keyword entries
if (index.current !== undefined) {
m = index.field_array.length;
if (m) { if (m) {
for (k = 0; k < m; k += 1) { for (k = 0; k < m; k += 1) {
if (indices[index_name] !== undefined) { index.current_keyword = [index.field_array[k]];
if (indices[index_name][index_field_array[k]] === undefined) { if (index.current[index.current_keyword] === undefined) {
indices[index_name][index_field_array[k]] = []; index.current[index.current_keyword] = [];
} }
indices[index_name][index_field_array[k]].push(docid); index.current[index.current_keyword].push(doc._id);
} }
} }
} }
...@@ -194,8 +223,9 @@ jIO.addStorageType('indexed', function (spec, my) { ...@@ -194,8 +223,9 @@ jIO.addStorageType('indexed', function (spec, my) {
* Post document to substorage and create/update index file(s) * Post document to substorage and create/update index file(s)
* @method post * @method post
* @param {object} command The JIO command * @param {object} command The JIO command
* @param {string} source The source of the function call
*/ */
that.post = function (command) { priv.postOrput = function (command, source) {
var f = {}, indices, doc, docid; var f = {}, indices, doc, docid;
doc = command.cloneDoc(); doc = command.cloneDoc();
docid = command.getDocId(); docid = command.getDocId();
...@@ -214,16 +244,25 @@ jIO.addStorageType('indexed', function (spec, my) { ...@@ -214,16 +244,25 @@ jIO.addStorageType('indexed', function (spec, my) {
priv.index_suffix, priv.index_suffix,
option, option,
function (response) { function (response) {
console.log("index file found, we post(put)");
console.log( indices );
indices = response; indices = response;
f.postDocument("put"); f.postDocument("put");
}, },
function (err) { function (err) {
switch (err.status) { switch (err.status) {
case 404: case 404:
if (source !== 'PUTATTACHMENT') {
indices = priv.createEmptyIndexArray(); indices = priv.createEmptyIndexArray();
f.postDocument("post"); f.postDocument("post");
} else {
that.error({
"status": 404,
"statusText": "Not Found",
"error": "not found",
"message": "Document not found",
"reason": "Document not found"
});
return;
}
break; break;
default: default:
err.message = "Cannot retrieve index array"; err.message = "Cannot retrieve index array";
...@@ -234,9 +273,7 @@ jIO.addStorageType('indexed', function (spec, my) { ...@@ -234,9 +273,7 @@ jIO.addStorageType('indexed', function (spec, my) {
); );
}; };
f.postDocument = function (index_update_method) { f.postDocument = function (index_update_method) {
// if the index file already has an entry with this id, if (priv.isDocidInIndex(indices, doc) && source === 'POST') {
// the document already exists
if (priv.docidInIndex(indices, doc) && index_update_method === 'POST') {
// POST the document already exists // POST the document already exists
that.error({ that.error({
"status": 409, "status": 409,
...@@ -247,20 +284,37 @@ jIO.addStorageType('indexed', function (spec, my) { ...@@ -247,20 +284,37 @@ jIO.addStorageType('indexed', function (spec, my) {
}); });
return; return;
} else { } else {
indices = priv.updateIndeces(indices, doc); if (source !== 'PUTATTACHMENT') {
indices = priv.updateIndices(indices, doc);
}
that.addJob( that.addJob(
"post", source === 'PUTATTACHMENT' ? "putAttachment" : "post",
priv.substorage, priv.substorage,
doc, doc,
command.cloneOption(), command.cloneOption(),
function () { function () {
if (source !== 'PUTATTACHMENT') {
f.sendIndices(index_update_method); f.sendIndices(index_update_method);
} else {
docid = docid + '/' + command.getAttachmentId();
that.success({
"ok": true,
"id": docid
});
}
}, },
function (err) { function (err) {
switch (err.status) { switch (err.status) {
case 409: case 409:
// file already exists // file already exists
if (source !== 'PUTATTACHMENT') {
f.sendIndices(index_update_method); f.sendIndices(index_update_method);
} else {
that.success({
"ok": true,
"id": docid
});
}
break; break;
default: default:
err.message = "Cannot upload document"; err.message = "Cannot upload document";
...@@ -299,168 +353,68 @@ jIO.addStorageType('indexed', function (spec, my) { ...@@ -299,168 +353,68 @@ jIO.addStorageType('indexed', function (spec, my) {
* @method put * @method put
* @param {object} command The JIO command * @param {object} command The JIO command
*/ */
that.put = function (command) { that.post = function (command) {
that.post(command); priv.postOrput(command, 'POST');
};
/*
/**
* @method formatToFileObject
* @param {} row
* @return {} obj
*//*
priv.formatToFileObject = function (row) {
var k, obj = {
_id: row.id
};
for (k in row.value) {
if (row.value.hasOwnProperty(k)) {
obj[k] = row.value[k];
}
}
return obj;
};
*/
/**
* @method allDocs
* @param {} files_object
* @return {} obj
*//*
priv.allDocs = function (files_object) {
var k, obj = {
rows: []
}, i = 0;
for (k in files_object) {
if (files_object.hasOwnProperty(k)) {
obj.rows[i] = {};
obj.rows[i].value = files_object[k];
obj.rows[i].id = obj.rows[i].key = obj.rows[i].value._id;
delete obj.rows[i].value._id;
i += 1;
}
}
obj.total_rows = obj.rows.length;
return obj;
};
*/
/**
* @method setFileArray
* @param {} file_array
*//*
priv.setFileArray = function (file_array) {
var i, obj = {};
for (i = 0; i < file_array.length; i += 1) {
obj[file_array[i].id] = priv.formatToFileObject(file_array[i]);
}
localStorage.setItem(storage_file_object_name, obj);
};
*/
/**
* @method getFileObject
* @param {} docid
* @return {} obj
*//*
priv.getFileObject = function (docid) {
var obj = localStorage.getItem(storage_file_object_name) || {};
return obj[docid];
};
*/
/**
* @method addFile
* @param {} file_obj
*//*
priv.addFile = function (file_obj) {
var obj = localStorage.getItem(storage_file_object_name) || {};
obj[file_obj._id] = file_obj;
localStorage.setItem(storage_file_object_name, obj);
};
*/
/**
* @method removeFile
* @param {} docid
*//*
priv.removeFile = function (docid) {
var obj = localStorage.getItem(storage_file_object_name) || {};
delete obj[docid];
localStorage.setItem(storage_file_object_name, obj);
};
*/
/**
* updates the storage.
* It will retreive all files from a storage. It is an asynchronous task
* so the update can be on going even if IndexedStorage has already
* returned the result.
* @method update
*//*
priv.update = function () {
that.addJob(
'allDocs',
priv.sub_storage_spec,
null,
{max_retry: 3},
function (response) {
priv.setFileArray(response.rows);
},
function () {}
);
}; };
*/
/** /**
* Add put job to substorage and create/update index file(s) * Update the document metadata and update the index
* @method put * @method put
* @param {object} command The JIO command * @param {object} command The JIO command
*//* */
that.put = function (command) { that.put = function (command) {
var cloned_doc = command.cloneDoc(), priv.postOrput(command, 'PUT');
cloned_option = command.cloneOption(); };
// create/update indexStorage
// fwd job /**
that.addJob('put', priv.sub_storage_spec, cloned_doc, * Add an attachment to a document (no index modification)
cloned_option, * @method putAttachment
function (response) { * @param {object} command The JIO command
priv.update(); */
that.success(response); that.putAttachment = function (command) {
}, priv.postOrput(command, 'PUTATTACHMENT');
function (error) {
that.error(error);
}
);
}; };
*//** /**
* Loads a document. * Get the document metadata or attachment.
* Options:
* - {boolean} revs Add simple revision history (false by default).
* - {boolean} revs_info Add revs info (false by default).
* - {boolean} conflicts Add conflict object (false by default).
* @method get * @method get
*//* * @param {object} command The JIO command
*/
that.get = function (command) { that.get = function (command) {
// jslint unused var file_array var option, docid;
var success = function (val) { option = command.cloneOption();
that.success(val); if (option.max_retry === 0) {
}, option.max_retry = 3;
error = function (err) { }
that.error(err); if (command.getAttachmentId() !== undefined) {
}, docid = command.getDocId() + '/' + command.getAttachmentId();
get = function () {
var cloned_option = command.cloneOption();
that.addJob('get', priv.sub_storage_spec, command.cloneDoc(),
cloned_option, success, error);
that.end();
};
priv.indexStorage();
priv.update();
if (command.getOption('metadata_only')) {
setTimeout(function () {
var file_obj = priv.getFileObject(command.getDocId());
if (file_obj && (file_obj._last_modified || file_obj._creation_date)) {
that.success(file_obj);
} else { } else {
get(); docid = command.getDocId();
} }
that.addJob(
"get",
priv.substorage,
docid,
option,
function (response) {
that.success(response);
},
function (err) {
that.error({
"status": 404,
"statusText": "Not Found",
"error": "not_found",
"message": "Cannot find the attachment",
"reason": "Document/Attachment not found"
}); });
} else {
get();
} }
}; // end get );
*//** };
/**
* Removes a document. * Removes a document.
* @method remove * @method remove
*//* *//*
......
...@@ -2653,13 +2653,16 @@ test ("Post", function () { ...@@ -2653,13 +2653,16 @@ test ("Post", function () {
o.tick(o); o.tick(o);
// check document // check document
o.indexPost = { o.fakeIndex = {
"_id": "ipost_indices.json",
"indexAB": {"keyword_abc":["some_id"], "keyword_def":["some_id"]}, "indexAB": {"keyword_abc":["some_id"], "keyword_def":["some_id"]},
"indexA": {"keyword_abc":["some_id"]} "indexA": {"keyword_abc":["some_id"]}
}; };
deepEqual( o.jio.get("ipost_indices.json",function(err, response){
o.jio.get("ipost_indices.json"), o.indexPost, "Check index file" o.actualIndex = response;
); deepEqual(o.actualIndex, o.fakeIndex, "Check index file");
});
o.tick(o);
// post with escapable characters // post with escapable characters
o.doc = {"_id": "other_id", "title": "myPost2", o.doc = {"_id": "other_id", "title": "myPost2",
...@@ -2689,7 +2692,7 @@ test ("Put", function(){ ...@@ -2689,7 +2692,7 @@ test ("Put", function(){
"type": "indexed", "type": "indexed",
"indices": [ "indices": [
{"name":"indexA", "fields":["author"]}, {"name":"indexA", "fields":["author"]},
{"name":"indexAB", "fields":["author","findMeC"]} {"name":"indexAB", "fields":["author","year"]}
], ],
"sub_storage": { "sub_storage": {
"type": "local", "type": "local",
...@@ -2711,33 +2714,35 @@ test ("Put", function(){ ...@@ -2711,33 +2714,35 @@ test ("Put", function(){
o.tick(o); o.tick(o);
// check index file // check index file
o.indexPut = { o.fakeIndex = {
"indexA": {"John Doe": ["put1"]}, "indexA": {"John Doe": ["put1"]},
"indexAB": {"John Doe": ["put1"]}, "indexAB": {"John Doe": ["put1"]},
"_id": "iput_indices.json" "_id": "iput_indices.json"
}; };
deepEqual( o.jio.get("iput_indices.json",function(err, response){
o.jio.get("iput_indices.json"), o.indexPut, "Check index file", o.actualIndex = response;
o.index, "Check index file" deepEqual(o.actualIndex, o.fakeIndex, "Check index file");
); });
o.tick(o);
// modify a document - modify keyword on index! // modify document - modify keyword on index!
o.doc = {"_id": "put1", "title": "myPuttter1", "author":"Jane Doe"}; o.doc = {"_id": "put1", "title": "myPuttter1", "author":"Jane Doe"};
o.spy (o, "value", {"ok": true, "id": "put1"}, o.spy (o, "value", {"ok": true, "id": "put1"},
"Modify document, update index file"); "Modify document, update keyword on index");
o.jio.put(o.doc, o.f); o.jio.put(o.doc, o.f);
o.tick(o); o.tick(o);
// check index file // check index file
o.index = { o.fakeIndex = {
"indexA": {"Jane Doe": ["put1"]}, "indexA": {"Jane Doe": ["put1"]},
"indexAB": {"Jane Doe": ["put1"]}, "indexAB": {"Jane Doe": ["put1"]},
"_id": "iput_indices.json" "_id": "iput_indices.json"
}; };
deepEqual( o.jio.get("iput_indices.json",function(err, response){
o.jio.get("iput_indices.json"), o.indexPut, "Check index file", o.actualIndex = response;
o.index, "Check index file" deepEqual(o.actualIndex, o.fakeIndex, "Check index file");
); });
o.tick(o);
// add new document with same keyword! // add new document with same keyword!
o.doc = {"_id": "new_doc", "title": "myPut2", "author":"Jane Doe"}; o.doc = {"_id": "new_doc", "title": "myPut2", "author":"Jane Doe"};
...@@ -2747,15 +2752,36 @@ test ("Put", function(){ ...@@ -2747,15 +2752,36 @@ test ("Put", function(){
o.tick(o); o.tick(o);
// check index file // check index file
o.index = { o.fakeIndex = {
"indexA": {"Jane Doe": ["put1", "new_doc"] }, "indexA": {"Jane Doe": ["put1", "new_doc"] },
"indexAB": {"Jane Doe": ["put1", "new_doc"]}, "indexAB": {"Jane Doe": ["put1", "new_doc"]},
"_id": "iput_indices.json" "_id": "iput_indices.json"
}; };
deepEqual( o.jio.get("iput_indices.json",function(err, response){
o.jio.get("iput_indices.json"), o.indexPut, "Check index file", o.actualIndex = response;
o.index, "Check index file" deepEqual(o.actualIndex, o.fakeIndex, "Check index file");
); });
o.tick(o);
// add second keyword to index file
o.doc = {"_id": "put1", "title": "myPut2", "author":"Jane Doe",
"year":"1912"};
o.spy (o, "value", {"ok": true, "id": "put1"},
"add second keyword to index file");
o.jio.put(o.doc, o.f);
o.tick(o);
// check index file
o.fakeIndex = {
"indexA": {"Jane Doe": ["put1"] },
"indexAB": {"Jane Doe": ["put1"],"1912": ["put1"]},
"_id": "iput_indices.json"
};
o.jio.get("iput_indices.json",function(err, response){
o.actualIndex = response;
deepEqual(o.actualIndex, o.fakeIndex, "Check index file");
});
o.tick(o);
// remove a keyword from an existing document // remove a keyword from an existing document
o.doc = {"_id": "new_doc", "title": "myPut2"}; o.doc = {"_id": "new_doc", "title": "myPut2"};
...@@ -2765,64 +2791,185 @@ test ("Put", function(){ ...@@ -2765,64 +2791,185 @@ test ("Put", function(){
o.tick(o); o.tick(o);
// check index file // check index file
o.index = { o.fakeIndex = {
"indexA": {"Jane Doe": ["put1"] }, "indexA": {"Jane Doe": ["put1"] },
"indexAB": {"Jane Doe": ["put1"]}, "indexAB": {"Jane Doe": ["put1"], "1912": ["put1"]},
"_id": "iput_indices.json" "_id": "iput_indices.json"
}; };
deepEqual( o.jio.get("iput_indices.json",function(err, response){
o.jio.get("iput_indices.json"), o.indexPut, "Check index file", o.actualIndex = response;
o.index, "Check index file" deepEqual(o.actualIndex, o.fakeIndex, "Check index file");
); });
o.tick(o);
o.jio.stop(); o.jio.stop();
}); });
test ("PutAttachment", function(){
/* // not sure these need to be run, because the index does not change
test ('Document load', function () { // and only small modifications have been made to handle putAttachment
var o = {}; o.clock = this.sandbox.useFakeTimers(); // tests are from localStorage putAttachment
o.clock.tick(base_tick); var o = generateTools(this);
o.jio = JIO.newJio({type:'indexed',storage:{type:'dummyall3tries'}});
// loading must take long time with dummyall3tries
o.f = this.spy();
o.jio.get('memo',{max_retry:3,metadata_only:true},o.f);
o.clock.tick(1000);
ok(!o.f.called,'Callback must not be called');
// wait long time too retreive list
o.clock.tick(1000);
// now we can test if the document metadata are loaded faster. o.jio = JIO.newJio({
o.doc = {_id:'memo',_last_modified:25000,_creation_date:20000}; "type": "indexed",
o.f2 = function (err,val) { "indices": [
deepEqual (err||val,o.doc,'Document metadata retrieved'); {"name":"indexA", "fields":["author"]},
}; {"name":"indexAB", "fields":["author","year"]}
this.spy(o,'f2'); ],
o.jio.get('memo',{max_retry:3,metadata_only:true},o.f2); "sub_storage": {
o.clock.tick(1000); "type": "local",
if (!o.f2.calledOnce) { "username": "iputatt",
if (o.f2.called) { "application_name": "iputatt"
ok (false, 'too much results'); }
} else { });
ok (false, 'no response');
// putAttachment without doc id
// error 20 -> document id required
o.spy(o, "status", 20, "PutAttachment without doc id");
o.jio.putAttachment({}, o.f);
o.tick(o);
// putAttachment without attachment id
// error 22 -> attachment id required
o.spy(o, "status", 22, "PutAttachment without attachment id");
o.jio.putAttachment({"id": "putattmt1"}, o.f);
o.tick(o);
// putAttachment without document
// error 404 -> not found
o.spy(o, "status", 404, "PutAttachment without document");
o.jio.putAttachment({"id": "putattmt1/putattmt2"}, o.f);
o.tick(o);
// putAttachment with document
o.doc = {"_id": "putattmt1","title": "myPutAttmt1"};
o.spy (o, "value", {"ok": true, "id": "putattmt1"},
"Put underlying document");
o.jio.put(o.doc, o.f);
o.tick(o);
o.spy(o, "value", {"ok": true, "id": "putattmt1/putattmt2"},
"PutAttachment with document, without data");
o.jio.putAttachment({"id": "putattmt1/putattmt2"}, o.f);
o.tick(o);
// check document
deepEqual(
localstorage.getItem("jio/localstorage/iputatt/iputatt/putattmt1"),
{
"_id": "putattmt1",
"title": "myPutAttmt1",
"_attachments": {
"putattmt2": {
"length": 0,
// md5("")
"digest": "md5-d41d8cd98f00b204e9800998ecf8427e"
}
}
},
"Check document"
);
// check attachment
deepEqual(
localstorage.getItem(
"jio/localstorage/iputatt/iputatt/putattmt1/putattmt2"),
"", "Check attachment"
);
// update attachment
o.spy(o, "value", {"ok": true, "id": "putattmt1/putattmt2"},
"Update Attachment, with data");
o.jio.putAttachment({"id": "putattmt1/putattmt2", "data": "abc"}, o.f);
o.tick(o);
// check document
deepEqual(
localstorage.getItem("jio/localstorage/iputatt/iputatt/putattmt1"),
{
"_id": "putattmt1",
"title": "myPutAttmt1",
"_attachments": {
"putattmt2": {
"length": 3,
// md5("abc")
"digest": "md5-900150983cd24fb0d6963f7d28e17f72"
} }
} }
},
"Check document"
);
// check attachment
deepEqual(
localstorage.getItem(
"jio/localstorage/iputatt/iputatt/putattmt1/putattmt2"),
"abc", "Check attachment"
);
o.jio.stop();
});
/*
test ("Get", function(){
var o = generateTools(this);
o.jio = JIO.newJio({
"type": "local",
"username": "uget",
"application_name": "aget"
});
// get inexistent document
o.spy(o, "status", 404, "Get inexistent document");
o.jio.get("get1", o.f);
o.tick(o);
// get inexistent attachment
o.spy(o, "status", 404, "Get inexistent attachment");
o.jio.get("get1/get2", o.f);
o.tick(o);
// test a simple document loading // adding a document
o.doc2 = {_id:'file',_last_modified:17000, o.doc_get1 = {
_creation_date:11000,content:'content file'}; "_id": "get1",
o.f3 = function (err,val) { "title": "myGet1"
deepEqual (err||val,o.doc2,'Simple document loading');
}; };
this.spy(o,'f3'); localstorage.setItem("jio/localstorage/uget/aget/get1", o.doc_get1);
o.jio.get('file',{max_retry:3},o.f3);
o.clock.tick(2000); // get document
if (!o.f3.calledOnce) { o.spy(o, "value", o.doc_get1, "Get document");
ok (false, 'no response / too much results'); o.jio.get("get1", o.f);
o.tick(o);
// get inexistent attachment (document exists)
o.spy(o, "status", 404, "Get inexistent attachment (document exists)");
o.jio.get("get1/get2", o.f);
o.tick(o);
// adding an attachment
o.doc_get1["_attachments"] = {
"get2": {
"length": 2,
// md5("de")
"digest": "md5-5f02f0889301fd7be1ac972c11bf3e7d"
} }
};
localstorage.setItem("jio/localstorage/uget/aget/get1", o.doc_get1);
localstorage.setItem("jio/localstorage/uget/aget/get1/get2", "de");
// get attachment
o.spy(o, "value", "de", "Get attachment");
o.jio.get("get1/get2", o.f);
o.tick(o);
o.jio.stop(); o.jio.stop();
}); });
*/
/*
test ('Get document list', function () { test ('Get document list', function () {
var o = {}; o.clock = this.sandbox.useFakeTimers(); var o = {}; o.clock = this.sandbox.useFakeTimers();
o.clock.tick(base_tick); o.clock.tick(base_tick);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment