From 23189f9c405e374e1f00e1df06cbf95eaf9128f8 Mon Sep 17 00:00:00 2001 From: Tristan Cavelier <tristan.cavelier@tiolive.com> Date: Tue, 6 Aug 2013 14:53:53 +0200 Subject: [PATCH] jiotests.js jio tests + local storage tests detached --- test/jio.storage/localstorage.tests.js | 561 +++++++++++++++++++ test/jio/tests.js | 746 +++++++++++++++++++++++++ test/jiotests.js | 683 ---------------------- 3 files changed, 1307 insertions(+), 683 deletions(-) create mode 100644 test/jio.storage/localstorage.tests.js create mode 100644 test/jio/tests.js diff --git a/test/jio.storage/localstorage.tests.js b/test/jio.storage/localstorage.tests.js new file mode 100644 index 0000000..5a7011a --- /dev/null +++ b/test/jio.storage/localstorage.tests.js @@ -0,0 +1,561 @@ +/*jslint indent: 2, maxlen: 80, nomen: true */ +/*global define, jIO, jio_tests, window, test, ok, deepEqual, sinon, expect */ + +// define([module_name], [dependencies], module); +(function (dependencies, module) { + "use strict"; + if (typeof define === 'function' && define.amd) { + return define(dependencies, module); + } + module(jIO, jio_tests); +}(['jio', 'jio_tests', 'localstorage'], function (jIO, util) { + "use strict"; + + function generateTools() { + return { + clock: sinon.useFakeTimers(), + spy: util.ospy, + tick: util.otick + }; + } + + module("LocalStorage"); + + test("Post", function () { + expect(5); + var clock = sinon.useFakeTimers(), jio = jIO.newJio({ + "type": "local", + "username": "upost", + "application_name": "apost" + }); + + // post without id + jio.post({}, function (err, response) { + var uuid; + util. + spyJioCallback('jobstatus', 'done', "Post without id")(err, response); + uuid = (err || response).id; + ok(util.isUuid(uuid), "Uuid should look like " + + "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx : " + uuid); + }); + clock.tick(1000); + + // post non empty document + jio.post( + {"_id": "post1", "title": "myPost1"}, + util.spyJioCallback("value", {"ok": true, "id": "post1"}, "Post") + ); + clock.tick(1000); + + deepEqual( + util.jsonlocalstorage.getItem("jio/localstorage/upost/apost/post1"), + { + "_id": "post1", + "title": "myPost1" + }, + "Check document" + ); + + // post but document already exists + jio.post({"_id": "post1", "title": "myPost2"}, util.spyJioCallback( + "status", + 409, + "Post but document already exists" + )); + clock.tick(1000); + + util.closeAndcleanUpJio(jio); + }); + + test("Put", function () { + expect(5); + var clock = sinon.useFakeTimers(), jio = jIO.newJio({ + "type": "local", + "username": "uput", + "application_name": "aput" + }); + + // put without id + // error 20 -> document id required + jio.put({}, util.spyJioCallback("status", 20, "Put without id")); + clock.tick(1000); + + // put non empty document + jio.put({"_id": "put1", "title": "myPut1"}, util.spyJioCallback("value", { + "ok": true, + "id": "put1" + }, "Creates a document")); + clock.tick(1000); + + // check document + deepEqual( + util.jsonlocalstorage.getItem("jio/localstorage/uput/aput/put1"), + { + "_id": "put1", + "title": "myPut1" + }, + "Check document" + ); + + // put but document already exists + jio.put({"_id": "put1", "title": "myPut2"}, util.spyJioCallback("value", { + "ok": true, + "id": "put1" + }, "Update the document")); + clock.tick(1000); + + // check document + deepEqual( + util.jsonlocalstorage.getItem("jio/localstorage/uput/aput/put1"), + { + "_id": "put1", + "title": "myPut2" + }, + "Check document" + ); + + util.closeAndcleanUpJio(jio); + }); + + test("PutAttachment", function () { + + var o = generateTools(this); + + o.jio = jIO.newJio({ + "type": "local", + "username": "uputattmt", + "application_name": "aputattmt" + }); + + // 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", "_attachment": "putattmt2"}, o.f); + o.tick(o); + + // adding a document + util.jsonlocalstorage.setItem( + "jio/localstorage/uputattmt/aputattmt/putattmt1", + { + "_id": "putattmt1", + "title": "myPutAttmt1" + } + ); + + // putAttachment with document + o.spy(o, "value", + {"ok": true, "id": "putattmt1", "attachment": "putattmt2"}, + "PutAttachment with document, without data"); + o.jio.putAttachment({"_id": "putattmt1", "_attachment": "putattmt2"}, o.f); + o.tick(o); + + // check document + deepEqual( + util.jsonlocalstorage.getItem( + "jio/localstorage/uputattmt/aputattmt/putattmt1" + ), + { + "_id": "putattmt1", + "title": "myPutAttmt1", + "_attachments": { + "putattmt2": { + "length": 0, + // md5("") + "digest": "md5-d41d8cd98f00b204e9800998ecf8427e" + } + } + }, + "Check document" + ); + + // check attachment + deepEqual(util.jsonlocalstorage.getItem( + "jio/localstorage/uputattmt/aputattmt/putattmt1/putattmt2" + ), "", "Check attachment"); + + // update attachment + o.spy(o, "value", + {"ok": true, "id": "putattmt1", "attachment": "putattmt2"}, + "Update Attachment, with data"); + o.jio.putAttachment({ + "_id": "putattmt1", + "_attachment": "putattmt2", + "_data": "abc" + }, o.f); + o.tick(o); + + // check document + deepEqual( + util.jsonlocalstorage.getItem( + "jio/localstorage/uputattmt/aputattmt/putattmt1" + ), + { + "_id": "putattmt1", + "title": "myPutAttmt1", + "_attachments": { + "putattmt2": { + "length": 3, + // md5("abc") + "digest": "md5-900150983cd24fb0d6963f7d28e17f72" + } + } + }, + "Check document" + ); + + // check attachment + deepEqual(util.jsonlocalstorage.getItem( + "jio/localstorage/uputattmt/aputattmt/putattmt1/putattmt2" + ), "abc", "Check attachment"); + + util.closeAndcleanUpJio(o.jio); + }); + + 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({"_id": "get1"}, o.f); + o.tick(o); + + // get inexistent attachment + o.spy(o, "status", 404, "Get inexistent attachment"); + o.jio.getAttachment({"_id": "get1", "_attachment": "get2"}, o.f); + o.tick(o); + + // adding a document + o.doc_get1 = { + "_id": "get1", + "title": "myGet1" + }; + util.jsonlocalstorage.setItem( + "jio/localstorage/uget/aget/get1", + o.doc_get1 + ); + + // get document + o.spy(o, "value", o.doc_get1, "Get document"); + o.jio.get({"_id": "get1"}, o.f); + o.tick(o); + + // get inexistent attachment (document exists) + o.spy(o, "status", 404, "Get inexistent attachment (document exists)"); + o.jio.getAttachment({"_id": "get1", "_attachment": "get2"}, o.f); + o.tick(o); + + // adding an attachment + o.doc_get1._attachments = { + "get2": { + "length": 2, + // md5("de") + "digest": "md5-5f02f0889301fd7be1ac972c11bf3e7d" + } + }; + util.jsonlocalstorage.setItem( + "jio/localstorage/uget/aget/get1", + o.doc_get1 + ); + util.jsonlocalstorage.setItem("jio/localstorage/uget/aget/get1/get2", "de"); + + // get attachment + o.spy(o, "value", "de", "Get attachment"); + o.jio.getAttachment({"_id": "get1", "_attachment": "get2"}, o.f); + o.tick(o); + + util.closeAndcleanUpJio(o.jio); + }); + + test("Remove", function () { + + var o = generateTools(this); + + o.jio = jIO.newJio({ + "type": "local", + "username": "uremove", + "application_name": "aremove" + }); + + // remove inexistent document + o.spy(o, "status", 404, "Remove inexistent document"); + o.jio.remove({"_id": "remove1"}, o.f); + o.tick(o); + + // remove inexistent attachment + o.spy(o, "status", 404, "Remove inexistent attachment"); + o.jio.removeAttachment({"_id": "remove1", "_attachment": "remove2"}, o.f); + o.tick(o); + + // adding a document + attmt + util.jsonlocalstorage.setItem("jio/localstorage/uremove/aremove/remove1", { + "_id": "remove1", + "title": "myRemove1", + "_attachments": { + "remove2": { + "length": 4, + "digest": "md5-blahblah" + } + } + }); + util.jsonlocalstorage.setItem( + "jio/localstorage/uremove/aremove/remove1/remove2", + "fghi" + ); + + // remove attachment + o.spy(o, "value", {"ok": true, "id": "remove1", "attachment": "remove2"}, + "Remove document"); + o.jio.removeAttachment({"_id": "remove1", "_attachment": "remove2"}, o.f); + o.tick(o); + + // remove document + o.spy(o, "value", {"ok": true, "id": "remove1"}, "Remove document"); + o.jio.remove({"_id": "remove1"}, o.f); + o.tick(o); + + // check document + ok(util.jsonlocalstorage.getItem( + "jio/localstorage/uremove/aremove/remove1" + ) === null, "Check document is removed"); + + // adding a document + attmt + util.jsonlocalstorage.setItem("jio/localstorage/uremove/aremove/remove1", { + "_id": "remove1", + "title": "myRemove1", + "_attachments": { + "remove2": { + "length": 4, + "digest": "md5-blahblah" + } + } + }); + util.jsonlocalstorage.setItem( + "jio/localstorage/uremove/aremove/remove1/remove2", "fghi"); + + // remove attachment + o.spy(o, "value", {"ok": true, "id": "remove1"}, + "Remove document and attachment"); + o.jio.remove({"_id": "remove1"}, o.f); + o.tick(o); + ok(util.jsonlocalstorage.getItem( + "jio/localstorage/uremove/aremove/remove1" + ) === null, "Check document is removed"); + ok(util.jsonlocalstorage.getItem( + "jio/localstorage/uremove/aremove/remove1/remove2" + ) === null, "Check attachment is removed"); + + util.closeAndcleanUpJio(o.jio); + }); + + test("AllDocs", function () { + + var o = generateTools(this), i, m = 15; + + o.jio = jIO.newJio({ + "type": "local", + "username": "ualldocs", + "application_name": "aalldocs" + }); + o.localpath = "jio/localstorage/ualldocs/aalldocs"; + + // sample data + o.titles = [ + "Shawshank Redemption", + "Godfather", + "Godfather 2", + "Pulp Fiction", + "The Good, The Bad and The Ugly", + "12 Angry Men", + "The Dark Knight", + "Schindlers List", + "Lord of the Rings - Return of the King", + "Fight Club", + "Star Wars Episode V", + "Lord Of the Rings - Fellowship of the Ring", + "One flew over the Cuckoo's Nest", + "Inception", + "Godfellas" + ]; + o.years = [ + 1994, + 1972, + 1974, + 1994, + 1966, + 1957, + 2008, + 1993, + 2003, + 1999, + 1980, + 2001, + 1975, + 2010, + 1990 + ]; + o.director = [ + "Frank Darabont", + "Francis Ford Coppola", + "Francis Ford Coppola", + "Quentin Tarantino", + "Sergio Leone", + "Sidney Lumet", + "Christopher Nolan", + "Steven Spielberg", + "Peter Jackson", + "David Fincher", + "Irvin Kershner", + "Peter Jackson", + "Milos Forman", + "Christopher Nolan", + "Martin Scorsese" + ]; + + for (i = 0; i < m; i += 1) { + o.fakeDoc = {}; + o.fakeDoc._id = "doc_"+(i < 10 ? "0"+i : i); + o.fakeDoc.title = o.titles[i]; + o.fakeDoc.year = o.years[i]; + o.fakeDoc.author = o.director[i]; + if (i === 5) { + o.fakeDoc._attachments = { + "att": { + "digest": "md5-dontcare", + "content_type": "text/plain", + "length": 3 + } + }; + util.jsonlocalstorage.setItem(o.localpath + "/doc_05/att", "abc"); + } + util.jsonlocalstorage.setItem( + o.localpath+"/doc_"+(i < 10 ? "0"+i : i), + o.fakeDoc + ); + } + + // response + o.allDocsResponse = {}; + o.allDocsResponse.rows = []; + o.allDocsResponse.total_rows = 15; + for (i = 0; i < m; i += 1) { + o.allDocsResponse.rows.push({ + "id": "doc_"+(i < 10 ? "0"+i : i), + "key": "doc_"+(i < 10 ? "0"+i : i), + "value": {} + }); + } + // alldocs + o.spy(o, "value", o.allDocsResponse, "All docs"); + o.jio.allDocs(function (err, response) { + if (response && response.rows) { + response.rows.sort(function (a, b) { + return a.id > b.id ? 1 : a.id < b.id ? -1 : 0; + }); + } + o.f(err, response); + }); + o.tick(o); + + // include docs + o.allDocsResponse = {}; + o.allDocsResponse.rows = []; + o.allDocsResponse.total_rows = m; + for (i = 0; i < m; i += 1) { + o.allDocsResponse.rows.push({ + "id": "doc_"+(i < 10 ? "0"+i : i), + "key": "doc_"+(i < 10 ? "0"+i : i), + "value": {}, + "doc": util.jsonlocalstorage.getItem( + o.localpath+"/doc_"+(i < 10 ? "0"+i : i) + ) + }); + } + + // alldocs + o.spy(o, "value", o.allDocsResponse, "All docs (include docs)"); + o.jio.allDocs({"include_docs": true}, function (err, response) { + if (response && response.rows) { + response.rows.sort(function (a, b) { + return a.id > b.id ? 1 : a.id < b.id ? -1 : 0; + }); + } + o.f(err, response); + }); + o.tick(o); + + // complex queries + o.thisShouldBeTheAnswer4 = {"total_rows": 0, "rows": []}; + o.allDocsResponse.rows.forEach(function (row) { + var new_row; + if (row.doc.year >= 1980) { + new_row = JSON.parse(JSON.stringify(row)); + new_row.value.title = row.doc.title; + new_row.value.year = row.doc.year; + delete new_row.doc; + o.thisShouldBeTheAnswer4.rows.push(new_row); + o.thisShouldBeTheAnswer4.total_rows += 1; + } + }); + o.thisShouldBeTheAnswer4.rows.sort(function (a, b) { + return a.value.year > b.value.year ? -1 : + a.value.year < b.value.year ? 1 : 0; + }); + o.thisShouldBeTheAnswer4.total_rows = 5; + o.thisShouldBeTheAnswer4.rows.length = 5; + + o.spy(o, "value", o.thisShouldBeTheAnswer4, + "allDocs (complex queries year >= 1980, all query options)"); + o.jio.allDocs({ + "query": '(year: >= "1980")', + "limit": [0,5], + "sort_on": [["year", "descending"]], + "select_list": ["title", "year"] + }, o.f); + o.tick(o); + + // empty query returns all + o.thisShouldBeTheAnswer5 = {"total_rows": 0, "rows": []}; + o.allDocsResponse.rows.forEach(function (row) { + var new_row = JSON.parse(JSON.stringify(row)); + new_row.value.title = row.doc.title; + o.thisShouldBeTheAnswer5.rows.push(new_row); + o.thisShouldBeTheAnswer5.total_rows += 1; + }); + o.thisShouldBeTheAnswer5.rows.sort(function (a, b) { + return a.value.title > b.value.title ? -1 : + a.value.title < b.value.title ? 1 : 0; + }); + + o.spy(o, "value", o.thisShouldBeTheAnswer5, + "allDocs (empty query in complex query)"); + + o.jio.allDocs({ + "sort_on": [["title", "descending"]], + "select_list": ["title"], + "include_docs": true + }, o.f); + o.tick(o); + + util.closeAndcleanUpJio(o.jio); + }); + +})); diff --git a/test/jio/tests.js b/test/jio/tests.js new file mode 100644 index 0000000..1b7bb58 --- /dev/null +++ b/test/jio/tests.js @@ -0,0 +1,746 @@ +/*jslint indent: 2, maxlen: 80, nomen: true */ +/*global define, jIO, localStorage, window, test, ok, deepEqual, sinon, + expect */ + +// define([module_name], [dependencies], module); +(function (dependencies, module) { + "use strict"; + if (typeof define === 'function' && define.amd) { + return define(dependencies, module); + } + window.jio_tests = module(jIO); +}(['jio'], function (jIO) { + "use strict"; + var to_export = {}, tmp; + + // localStorage cleanup + for (tmp in localStorage) { + if (localStorage.hasOwnProperty(tmp)) { + if (/^jio\//.test(tmp)) { + localStorage.removeItem(tmp); + } + } + } + + ////////////////////////////////////////////////////////////////////////////// + // Tools + + function spyJioCallback(result_type, value, message) { + return function (err, response) { + var val; + switch (result_type) { + case 'value': + val = err || response; + break; + case 'status': + val = (err || {}).status; + break; + case 'jobstatus': + val = (err ? 'fail' : 'done'); + break; + default: + ok(false, "Unknown case " + result_type); + break; + } + deepEqual(val, value, message); + }; + } + to_export.spyJioCallback = spyJioCallback; + + /** + * Clones all native object in deep. Managed types: Object, Array, String, + * Number, Boolean, Function, null. + * + * @param {A} object The object to clone + * @return {A} The cloned object + */ + function deepClone(object) { + var i, cloned; + if (Array.isArray(object)) { + cloned = []; + for (i = 0; i < object.length; i += 1) { + cloned[i] = deepClone(object[i]); + } + return cloned; + } + if (typeof object === "object") { + cloned = {}; + for (i in object) { + if (object.hasOwnProperty(i)) { + cloned[i] = deepClone(object[i]); + } + } + return cloned; + } + return object; + } + + // XXX docstring + function isUuid(uuid) { + var x = "[0-9a-fA-F]"; + if (typeof uuid !== "string") { + return false; + } + return (uuid.match( + "^" + x + "{8}-" + x + "{4}-" + + x + "{4}-" + x + "{4}-" + x + "{12}$" + ) === null ? false : true); + } + to_export.isUuid = isUuid; + + // XXX docstring + to_export.jsonlocalstorage = { + clear: function () { + return localStorage.clear(); + }, + getItem: function (item) { + var value = localStorage.getItem(item); + return value === null ? null : JSON.parse(value); + }, + setItem: function (item, value) { + return localStorage.setItem(item, JSON.stringify(value)); + }, + removeItem: function (item) { + return localStorage.removeItem(item); + } + }; + + function objectifyDocumentArray(array) { + var obj = {}, k; + for (k = 0; k < array.length; k += 1) { + obj[array[k]._id] = array[k]; + } + return obj; + } + + function closeAndcleanUpJio(jio) { + jio.close(); + to_export.jsonlocalstorage.removeItem("jio/id/" + jio.getId()); + to_export.jsonlocalstorage.removeItem("jio/job_array/" + jio.getId()); + } + to_export.closeAndcleanUpJio = closeAndcleanUpJio; + + function getJioLastJob(jio) { + return (to_export.jsonlocalstorage.getItem( + "jio/job_array/" + jio.getId() + ) || [undefined]).pop(); + } + + ////////////////////////////////////////////////////////////////////////////// + // Compatibility + + function ospy(o, result_type, value, message, function_name) { + function_name = function_name || 'f'; + o[function_name] = function (err, response) { + var val; + switch (result_type) { + case 'value': + val = err || response; + break; + case 'status': + val = (err || {}).status; + break; + case 'jobstatus': + val = (err ? 'fail' : 'done'); + break; + default: + ok(false, "Unknown case " + result_type); + break; + } + deepEqual(val, value, message); + }; + sinon.spy(o, function_name); + } + to_export.ospy = ospy; + + function otick(o, a, b) { + var tick = 10000, function_name = 'f'; + if (typeof a === 'number' && !isNaN(a)) { + tick = a; + a = b; + } + if (typeof a === 'string') { + function_name = a; + } + o.clock.tick(tick); + if (!o[function_name].calledOnce) { + if (o[function_name].called) { + ok(false, 'too much results'); + } else { + ok(false, 'no response'); + } + } + } + to_export.otick = otick; + + ////////////////////////////////////////////////////////////////////////////// + // Dummy Storage + + // XX docstring + function dummyStorage(spec, my) { + var that = my.basicStorage(spec, my); + + that._mode = spec.mode || 'normal'; + that._key = spec.key; + that._value = spec.value; + + if (that._mode === 'spec error') { + throw new TypeError( + "Initialization error set by the storage description." + ); + } + + that.specToStore = function () { + return { + "mode": that._mode, + "key": that._key, + "value": that._value + }; + }; + + that.post = function (command) { + setTimeout(function () { + var metadata = command.cloneDoc(), options = command.cloneOption(); + if (that._mode === 'no response') { + return; + } + // if (that._mode === 'no response + timeout reset') { + // return setTimeout(function () { + // command.resetTimeout(); + // }, that._value); + // } + if (that._mode === 'invalid error response') { + return that.error(); + } + if (that._mode === 'always fail') { + return that.error({ + "error": "conflict", + "message": "", + "reason": "unknown", + "status": 409, + "statusText": "Conflict" + }); + } + if (that._mode === 'post response no id') { + return that.success(); + } + that.success({"id": "document id a", "ok": true}); + }); + }; + + that.put = function (command) { + setTimeout(function () { + var metadata = command.cloneDoc(), options = command.cloneOption(); + if (that._mode === 'retry') { + if (!dummyStorage[that._key]) { + dummyStorage[that._key] = 0; + } + dummyStorage[that._key] += 1; + if (dummyStorage[that._key] === that._value) { + return that.success({"id": metadata._id, "ok": true}); + } + return that.retry(); + } + that.success({"id": metadata._id, "ok": true}); + }); + }; + + that.remove = function (command) { + setTimeout(function () { + var metadata = command.cloneDoc(), options = command.cloneOption(); + that.success({"id": metadata._id, "ok": true}); + }); + }; + + return that; + } + + jIO.addStorageType('dummy', dummyStorage); + to_export.dummyStorage = dummyStorage; + + ////////////////////////////////////////////////////////////////////////////// + // Tests + + module("JIO"); + + /** + * Tests the instance initialization + */ + test('Instanciation', function () { + expect(1); + var jio = jIO.newJio(undefined); + + // tests if jio is an object + ok(typeof jio === 'object', 'Init ok!'); + + // checks the workspace + // XXX nothing to check for the moment, need to be implemented first + + closeAndcleanUpJio(jio); + }); + + module("JIO Dummy Storage"); + + // XXX This will be uncommented when given parameters checking will be implem + // /** + // * Tests wrong commands + // */ + // test('Wrong parameters', function () { + // var result, jio = jIO.newJio({ + // "type": "dummy", + // "mode": "normal" + // }, { + // "workspace": {} + // }); + + // try { + // jio.post(); // post(kwargs, [options], [callbacks]); + // result = "No error thrown"; + // } catch (e1) { + // result = e1.name + ": " + e1.message; + // } + // deepEqual( + // result, + // "TypeError: JIO().post(): Argument 1 is not of type 'object'", + // "Wrong parameter" + // ); + + // try { + // jio.allDocs(); // allDocs([options], [callbacks]); + // result = "No error thrown"; + // } catch (e2) { + // result = e2.name + ": " + e2.message; + // } + // deepEqual(result, "No error thrown", "Good parameter"); + // }); + + // XXX this will be uncommented when validateState will be replaced by a + // simple `throw` in the storage init + // /** + // * Tests a storage initialization error + // */ + // test('Description Error', function () { + // var clock, jio; + // clock = sinon.useFakeTimers(); + // jio = jIO.newJio({ + // "type": "blue" + // }, { + // "workspace": {} + // }); + + // // Tests wrong storage type + // jio.post({}).always(function (answer) { + // deepEqual(answer, { + // "error": "internal_storage_error", + // "message": "Check if the storage description respects the " + + // "constraints provided by the storage designer. (TypeError: " + + // "Unknown storage 'blue')", + // "reason": "invalid description", + // "status": 551, + // "statusText": "Internal Storage Error" + // }, "Unknown storage"); + // }); + // clock.tick(1); + + // // Tests wrong storage description + // jio = jIO.newJio({ + // "type": "dummy", + // "mode": "spec error" + // }, { + // "workspace": {} + // }); + + // jio.post({}).always(function (answer) { + // deepEqual(answer, { + // "error": "internal_storage_error", + // "message": "Check if the storage description respects the " + + // "constraints provided by the storage designer. (TypeError: " + + // "Initialization error set by the storage description.)", + // "reason": "invalid description", + // "status": 551, + // "statusText": "Internal Storage Error" + // }, "Initialization error"); + // }); + // clock.tick(1); + // }); + + + // XXX timeout is not implemented yet + // /** + // * Tests a command which does not respond + // */ + // test('No Response or Response Timeout', function () { + // var clock, jio, state; + // expect(5); + // clock = sinon.useFakeTimers(); + // jio = jIO.newJio({ + // "type": "dummy", + // "mode": "no response" + // }, { + // "workspace": {} + // }); + + // // tests with default timeout + // jio.post({}).always(function (answer) { + // deepEqual(answer, { + // "error": "request_timeout", + // "message": "Operation canceled after around 10000 milliseconds.", + // "reason": "timeout", + // "status": 408, + // "statusText": "Request Timeout" + // }, "Timeout error (default timeout)"); + // }); + // clock.tick(10000); // wait 10 seconds + + // jio = jIO.newJio({ + // "type": "dummy", + // "mode": "no response + timeout reset", + // "value": 5000 // reset after 5 seconds + // }, { + // "workspace": {} + // }); + + // // tests with storage timeout extension + // state = "Not called yet"; + // jio.post({}).always(function (answer) { + // state = "Called"; + // deepEqual(answer, { + // "error": "request_timeout", + // "message": "Operation canceled after around 15000 milliseconds.", + // "reason": "timeout", + // "status": 408, + // "statusText": "Request Timeout" + // }, "Timeout error (storage timeout reset)"); + // }); + // clock.tick(10000); // wait 10 seconds + // deepEqual(state, "Not called yet", "Check callback state."); + // clock.tick(5000); // wait 5 seconds + + // jio = jIO.newJio({ + // "type": "dummy", + // "mode": "no response" + // }, { + // "workspace": {}, + // "default_timeout": 2 + // }); + + // // tests with jio option timeout + // jio.post({}).always(function (answer) { + // deepEqual(answer, { + // "error": "request_timeout", + // "message": "Operation canceled after around 2 milliseconds.", + // "reason": "timeout", + // "status": 408, + // "statusText": "Request Timeout" + // }, "Timeout error (specific default timeout)"); + // }); + // clock.tick(2); + + // // tests with command option timeout + // jio.post({}, {"timeout": 50}).always(function (answer) { + // deepEqual(answer, { + // "error": "request_timeout", + // "message": "Operation canceled after around 50 milliseconds.", + // "reason": "timeout", + // "status": 408, + // "statusText": "Request Timeout" + // }, "Timeout error (command timeout)"); + // }); + // clock.tick(50); + // }); + + // /** + // * Tests wrong responses + // */ + // test('Invalid Response', function () { + // var clock, jio; + // clock = sinon.useFakeTimers(); + // jio = jIO.newJio({ + // "type": "dummy", + // "mode": "post response no id" + // }); + + // jio.post({}, function (err, response) { + // deepEqual(err || response, { + // "error": "internal_storage_error", + // "message": "New document id have to be specified", + // "reason": "invalid response", + // "status": 551, + // "statusText": "Internal Storage Error" + // }, "Invalid Post Response"); + // }); + // clock.tick(1000); + + // closeAndcleanUpJio(jio); + + // jio = jIO.newJio({ + // "type": "dummy", + // "mode": "invalid error response" + // }); + + // jio.post({}, function (err, response) { + // deepEqual(err || response, { + // "error": "internal_storage_error", + // "message": "Unknown status \"undefined\"", + // "reason": "invalid response", + // "status": 551, + // "statusText": "Internal Storage Error" + // }, "Invalid Post Error Response"); + // }); + // clock.tick(1000); + + // closeAndcleanUpJio(jio); + // }); + + /** + * Tests a valid responses + */ + test('Valid Responses & Callbacks', function () { + expect(4); + var clock, jio, message; + clock = sinon.useFakeTimers(); + + jio = jIO.newJio({ + "type": "dummy", + "mode": "normal" + }); + + // Tests post command callbacks post(metadata).always(onResponse) + + // valid response. + message = "Post Command: post(metadata).always(function (answer) {..}) + " + + "valid response."; + jio.post({}, function (err, response) { + deepEqual(err || response, { + "ok": true, + "id": "document id a" + }, message); + }); + clock.tick(1000); + + // Tests post command callbacks post(metadata).done(onSuccess).fail(onError) + message = "Post Command: post(metadata).done(function (answer) {..})." + + "fail(function (answer) {..})"; + jio.post({}, function (answer) { + deepEqual(answer, { + "ok": true, + "id": "document id a" + }, message); + }, function (answer) { + deepEqual(answer, "Should not fail", message); + }); + clock.tick(1000); + + // Tests post command callbacks post(metadata, onResponse) + message = "Post Command: post(metadata, function (err, response) {..})"; + jio.post({}, function (err, response) { + if (err) { + return deepEqual(err, "Should not fail", message); + } + deepEqual(response, { + "ok": true, + "id": "document id a" + }, message); + }); + clock.tick(1000); + + closeAndcleanUpJio(jio); + + // Tests post command callbacks post(metadata, onSuccess, onError) + error + // response. + message = "Post Command: post(metadata, function (response) {..}, " + + "function (err) {..}) + valid error response."; + jio = jIO.newJio({ + "type": "dummy", + "mode": "always fail" + }); + + jio.post({}, function (response) { + deepEqual(response, "Should fail", message); + }, function (err) { + deepEqual(err, { + "status": 409, + "statusText": "Conflict", + "error": "conflict", + "reason": "unknown", + "message": "" + }, message); + }); + clock.tick(1000); + + closeAndcleanUpJio(jio); + }); + + module("JIO Job Management"); + + test("Several Jobs at the same time", function () { + expect(3); + var clock = sinon.useFakeTimers(), jio = jIO.newJio({"type": "dummy"}); + + jio.put({"_id": "file1", "title": "t1"}, spyJioCallback('value', { + "ok": true, + "id": "file1" + }, "job1")); + jio.put({"_id": "file2", "title": "t2"}, spyJioCallback('value', { + "ok": true, + "id": "file2" + }, "job2")); + jio.put({"_id": "file3", "title": "t3"}, spyJioCallback('value', { + "ok": true, + "id": "file3" + }, "job3")); + clock.tick(1000); + + closeAndcleanUpJio(jio); + }); + + test("Similar Jobs at the same time (Update)", function () { + expect(8); + var clock = sinon.useFakeTimers(), jio = jIO.newJio({"type": "dummy"}); + function compareResults(err, response) { + deepEqual(err || response, {"id": "file", "ok": true}, "job ok"); + } + jio.put({"_id": "file", "title": "t"}, compareResults); + jio.put({"_id": "file", "title": "t"}, compareResults); + jio.put({"_id": "file", "title": "t"}, compareResults); + deepEqual(getJioLastJob(jio).id, 1, "Check job queue"); + clock.tick(1000); + + jio.put({"_id": "file", "content": "content"}, compareResults); + jio.remove({"_id": "file", "content": "content"}, compareResults); + jio.put({"_id": "file", "content": "content"}, compareResults); + deepEqual(getJioLastJob(jio).id, 5, "Check job queue"); + clock.tick(10000); + + closeAndcleanUpJio(jio); + }); + + test("Same document jobs at the same time (Wait for job(s))", function () { + expect(6); + var clock = sinon.useFakeTimers(), jio = jIO.newJio({"type": "dummy"}); + + function compareResults(err, response) { + deepEqual(err || response, {"id": "file", "ok": true}, "job ok"); + } + + jio.put({"_id": "file", "content": "content"}, compareResults); + deepEqual( + getJioLastJob(jio).status.waitforjob, + undefined, + "Job 1 is not waiting for someone" + ); + + jio.remove({"_id": "file", "content": "content"}, compareResults); + deepEqual( + getJioLastJob(jio).status.waitforjob, + [1], + "Job 2 is wainting for 1" + ); + + jio.put({"_id": "file"}, compareResults); + deepEqual( + getJioLastJob(jio).status.waitforjob, + [1, 2], + "Job 3 is waiting for 1 and 2" + ); + + clock.tick(1000); + + closeAndcleanUpJio(jio); + }); + + test("Server will be available soon (Wait for time)", function () { + expect(2); + var clock = sinon.useFakeTimers(), jio; + jio = jIO.newJio({ + "type": "dummy", + "mode": "retry", + "key": "035139054", + "value": 3 + }); + jio.put( + {"_id": "file", "content": "content"}, + {"max_retry": 3}, + function (err, response) { + deepEqual(err || response, {"id": "file", "ok": true}, "Job ok"); + } + ); + clock.tick(2000); + + deepEqual(dummyStorage['035139054'], 3, "tried 3 times"); + delete dummyStorage['035139054']; + + closeAndcleanUpJio(jio); + }); + + test("Restore old Jio", function () { + + var o = { + clock: sinon.useFakeTimers(), + spy: ospy, + tick: otick + }; + + function waitUntilLastJobIs(state) { + while (true) { + if (getJioLastJob(o.jio) === undefined) { + ok(false, "No job have state: " + state); + break; + } + if (getJioLastJob(o.jio).status.label === state) { + break; + } + o.clock.tick(25); + } + } + + function waitUntilAJobExists(timeout) { + var cpt = 0, job = false; + while (true) { + if (getJioLastJob(o.jio) !== undefined) { + job = true; + break; + } + if (cpt >= timeout) { + break; + } + o.clock.tick(25); + cpt += 25; + } + ok(job, "Wait until a job is created"); + } + + o.jio = jIO.newJio({ + "type": "dummy", + "mode": "retry", + "key": "12314", + "value": 3 + }); + + o.jio_id = o.jio.getId(); + + o.jio.put({"_id": "file", "title": "myFile"}, {"max_retry":3}, o.f); + waitUntilLastJobIs("initial"); // "on going" or "wait" should work + // xxx also test with waitUntilLastJobIs("on going") ? + o.jio.close(); + + o.jio = jIO.newJio({ + "type": "dummy", + "mode": "retry", + "key": "12314", + "value": 3 + }); + waitUntilAJobExists(30000); // timeout 30 sec + + deepEqual(getJioLastJob(o.jio).command.label, 'put', 'Job restored'); + o.clock.tick(2000); + ok(getJioLastJob(o.jio) === undefined, "Job executed"); + o.clock.tick(1000); + + to_export.jsonlocalstorage.removeItem("jio/id/" + o.jio_id); + to_export.jsonlocalstorage.removeItem("jio/job_array/" + o.jio_id); + closeAndcleanUpJio(o.jio); + + }); + + return to_export; +})); diff --git a/test/jiotests.js b/test/jiotests.js index 7ea47e5..031be94 100644 --- a/test/jiotests.js +++ b/test/jiotests.js @@ -401,59 +401,6 @@ test("Additional Filters", function () { ], 'The first document should be kept'); }); -module ('Jio Global tests'); - -test ( "Jio simple methods", function () { - // Test Jio simple methods - // It checks if we can create several instance of jio at the same - // time. Checks if they don't overlap informations, if they are - // started and stopped correctly and if they are ready when they - // have to be ready. - - var o = generateTools(this); - - o.jio = JIO.newJio(); - ok ( o.jio, 'a new jio -> 1'); - - o.jio2 = JIO.newJio(); - ok ( o.jio2, 'another new jio -> 2'); - - JIO.addStorageType('qunit', empty_fun); - - ok ( o.jio2.getId() !== o.jio.getId(), '1 and 2 must be different'); - - o.jio.stop(); - o.jio2.stop(); - -}); - -// test ( 'Jio Publish/Sububscribe/Unsubscribe methods', function () { -// // Test the Publisher, Subscriber of a single jio. -// // It is just testing if these function are working correctly. -// // The test publishes an event, waits a little, and check if the -// // event has been received by the callback of the previous -// // subscribe. Then, the test unsubscribe the callback function from -// // the event, and publish the same event. If it receives the event, -// // the unsubscribe method is not working correctly. - -// var o = {}; -// o.jio = JIO.newJio(); - -// var spy1 = this.spy(); - -// // Subscribe the pubsub_test event. -// o.callback = o.jio.subscribe('pubsub_test',spy1); -// // And publish the event. -// o.jio.publish('pubsub_test'); -// ok (spy1.calledOnce, 'subscribing & publishing, event called once'); - -// o.jio.unsubscribe('pubsub_test',spy1); -// o.jio.publish('pubsub_test'); -// ok (spy1.calledOnce, 'unsubscribing, same event not called twice'); - -// o.jio.stop(); -// }); - module ( "Jio Dummy Storages" ); test ("All requests ok", function () { @@ -752,636 +699,6 @@ test ("All document found", function () { o.jio.stop(); }); -module ( "Jio Job Managing" ); - -test ("Several Jobs at the same time", function () { - - var o = generateTools(this); - - o.jio = JIO.newJio({"type":"dummyallok"}); - o.spy(o, "value", {"ok": true, "id": "file"}, "job1", "f"); - o.spy(o, "value", {"ok": true, "id": "file2"}, "job2", "f2"); - o.spy(o, "value", {"ok": true, "id": "file3"}, "job3", "f3"); - o.jio.put({"_id": "file", "content": "content"}, o.f); - o.jio.put({"_id": "file2", "content": "content2"}, o.f2); - o.jio.put({"_id": "file3", "content": "content3"}, o.f3); - o.tick(o, 1000, "f"); - o.tick(o, "f2"); - o.tick(o, "f3"); - o.jio.stop(); - -}); - -test ("Similar Jobs at the same time (Update)", function () { - - var o = generateTools(this); - - o.jio = JIO.newJio({"type":"dummyallok"}); - o.spy(o, "value", {"ok": true, "id": "file"}, "job1 ok", "f"); - o.spy(o, "value", {"ok": true, "id": "file"}, "job2 ok", "f2"); - o.spy(o, "value", {"ok": true, "id": "file"}, "job3 ok", "f3"); - o.jio.put({"_id": "file", "content": "content"}, o.f); // 1 - o.jio.put({"_id": "file", "content": "content"}, o.f2); // 2 - o.jio.put({"_id": "file", "content": "content"}, o.f3); // 3 - deepEqual(getLastJob(o.jio.getId()).id, 1, "Check job queue"); - o.tick(o, 1000, "f"); - o.tick(o, "f2"); - o.tick(o, "f3"); - - o.spy(o, "value", {"ok": true, "id": "file"}, "job4 ok", "f"); - o.spy(o, "value", {"ok": true, "id": "file"}, "job5 ok", "f2"); - o.spy(o, "value", {"ok": true, "id": "file"}, "job6 ok", "f3"); - o.jio.put({"_id": "file", "content": "content"}, o.f); // 4 - o.jio.remove({"_id": "file", "content": "content"}, o.f2); // 5 - o.jio.put({"_id": "file", "content": "content"}, o.f3); // 6 - deepEqual(getLastJob(o.jio.getId()).id, 5, "Check job queue"); - o.tick(o, 1000, "f"); - o.tick(o, "f2"); - o.tick(o, "f3"); - - o.jio.stop(); - -}); - -test ("One document aim jobs at the same time (Wait for job(s))" , function () { - - var o = generateTools(this); - - o.jio = JIO.newJio({"type":"dummyallok"}); - o.spy(o, "value", {"ok": true, "id": "file"}, "job1", "f"); - o.spy(o, "value", {"ok": true, "id": "file"}, "job2", "f2"); - o.spy(o, "value", {"ok": true, "id": "file"}, "job3", "f3"); - - o.jio.put({"_id": "file", "content": "content"}, o.f); - o.testLastJobWaitForJob(undefined, "job1 is not waiting for someone"); - - o.jio.remove({"_id": "file", "content": "content"}, o.f2); - o.testLastJobWaitForJob([1], "job2 is waiting"); - - o.jio.put({"_id": "file"}, o.f3); - o.testLastJobWaitForJob([1, 2], "job3 is waiting"); - - o.tick(o, 1000, "f"); - o.tick(o, "f2"); - o.tick(o, "f3"); - - o.spy(o, "value", {"ok": true, "id": "lol"}, "Chaining callbacks"); - o.jio.removeAttachment({ - "_id": "lol", - "_attachment": "hu" - }, function (err, response) { - if (err) { - return; - } - o.jio.remove({"_id": "lol"}, o.f); - }); - o.tick(o, 10000); - - o.jio.stop(); - -}); - -test ("Server will be available soon (Wait for time)" , function () { - - var o = generateTools(this); - o.max_retry = 3; - - o.jio = JIO.newJio({"type":"dummyall3tries"}); - o.spy(o, "value", {"ok": true, "id": "file"}, "job1", "f"); - - o.jio.put({"_id": "file", "content": "content"}, - {"max_retry": o.max_retry}, o.f); - for (o.i = 0; o.i < o.max_retry - 1; o.i += 1) { - o.waitUntilLastJobIs("on going"); - o.waitUntilLastJobIs("wait"); - o.testLastJobWaitForTime("job1 is waiting for time"); - } - - o.tick(o, 1000, "f"); - o.jio.stop(); - -}); - -module ( "Jio Restore"); - -test ("Restore old Jio", function() { - - var o = generateTools(this); - - o.jio = JIO.newJio({ - "type": "dummyall3tries", - "application_name": "jiotests" - }); - - o.jio_id = o.jio.getId(); - - o.jio.put({"_id": "file", "title": "myFile"}, {"max_retry":3}, o.f); - o.waitUntilLastJobIs("initial"); // "on going" or "wait" should work - // xxx also test with o.waitUntilLastJobIs("on going") ? - o.jio.close(); - - o.jio = JIO.newJio({ - "type": "dummyallok", - "application_name": "jiotests" - }); - o.waitUntilAJobExists(30000); // timeout 30 sec - - o.testLastJobLabel("put", "Job restored"); - o.clock.tick(2000); - ok(getLastJob(o.jio.getId()) === undefined, "Job executed"); - o.clock.tick(1000); - - o.jio.stop(); - -}); - -module ( "Jio LocalStorage" ); - -test ("Post", function(){ - - var o = generateTools(this); - - o.jio = JIO.newJio({ - "type": "local", - "username": "upost", - "application_name": "apost" - }); - - // post without id - o.spy (o, "jobstatus", "done", "Post without id"); - o.jio.post({}, function (err, response) { - var uuid; - o.f(err, response); - uuid = (err || response).id; - ok(isUuid(uuid), "Uuid should look like " + - "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx : " + uuid); - }); - o.tick(o); - - // post non empty document - o.spy (o, "value", {"ok": true, "id": "post1"}, "Post"); - o.jio.post({"_id": "post1", "title": "myPost1"}, o.f); - o.tick(o); - - deepEqual( - localstorage.getItem("jio/localstorage/upost/apost/post1"), - { - "_id": "post1", - "title": "myPost1" - }, - "Check document" - ); - - // post but document already exists - o.spy (o, "status", 409, "Post but document already exists"); - o.jio.post({"_id": "post1", "title": "myPost2"}, o.f); - o.tick(o); - - o.jio.stop(); -}); - - -test ("Put", function(){ - - var o = generateTools(this); - - o.jio = JIO.newJio({ - "type": "local", - "username": "uput", - "application_name": "aput" - }); - - // put without id - // error 20 -> document id required - o.spy (o, "status", 20, "Put without id"); - o.jio.put({}, o.f); - o.tick(o); - - // put non empty document - o.spy (o, "value", {"ok": true, "id": "put1"}, "Creates a document"); - o.jio.put({"_id": "put1", "title": "myPut1"}, o.f); - o.tick(o); - - // check document - deepEqual( - localstorage.getItem("jio/localstorage/uput/aput/put1"), - { - "_id": "put1", - "title": "myPut1" - }, - "Check document" - ); - - // put but document already exists - o.spy (o, "value", {"ok": true, "id": "put1"}, "Update the document"); - o.jio.put({"_id": "put1", "title": "myPut2"}, o.f); - o.tick(o); - - // check document - deepEqual( - localstorage.getItem("jio/localstorage/uput/aput/put1"), - { - "_id": "put1", - "title": "myPut2" - }, - "Check document" - ); - - o.jio.stop(); - -}); - -test ("PutAttachment", function(){ - - var o = generateTools(this); - - o.jio = JIO.newJio({ - "type": "local", - "username": "uputattmt", - "application_name": "aputattmt" - }); - - // 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", "_attachment": "putattmt2"}, o.f); - o.tick(o); - - // adding a document - localstorage.setItem("jio/localstorage/uputattmt/aputattmt/putattmt1", { - "_id": "putattmt1", - "title": "myPutAttmt1" - }); - - // putAttachment with document - o.spy(o, "value", - {"ok": true, "id": "putattmt1", "attachment": "putattmt2"}, - "PutAttachment with document, without data"); - o.jio.putAttachment({"_id": "putattmt1", "_attachment": "putattmt2"}, o.f); - o.tick(o); - - // check document - deepEqual( - localstorage.getItem("jio/localstorage/uputattmt/aputattmt/putattmt1"), - { - "_id": "putattmt1", - "title": "myPutAttmt1", - "_attachments": { - "putattmt2": { - "length": 0, - // md5("") - "digest": "md5-d41d8cd98f00b204e9800998ecf8427e" - } - } - }, - "Check document" - ); - - // check attachment - deepEqual( - localstorage.getItem( - "jio/localstorage/uputattmt/aputattmt/putattmt1/putattmt2"), - "", "Check attachment" - ); - - // update attachment - o.spy(o, "value", - {"ok": true, "id": "putattmt1", "attachment": "putattmt2"}, - "Update Attachment, with data"); - o.jio.putAttachment({ - "_id": "putattmt1", - "_attachment": "putattmt2", - "_data": "abc" - }, o.f); - o.tick(o); - - // check document - deepEqual( - localstorage.getItem("jio/localstorage/uputattmt/aputattmt/putattmt1"), - { - "_id": "putattmt1", - "title": "myPutAttmt1", - "_attachments": { - "putattmt2": { - "length": 3, - // md5("abc") - "digest": "md5-900150983cd24fb0d6963f7d28e17f72" - } - } - }, - "Check document" - ); - - // check attachment - deepEqual( - localstorage.getItem( - "jio/localstorage/uputattmt/aputattmt/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({"_id": "get1"}, o.f); - o.tick(o); - - // get inexistent attachment - o.spy(o, "status", 404, "Get inexistent attachment"); - o.jio.getAttachment({"_id": "get1", "_attachment": "get2"}, o.f); - o.tick(o); - - // adding a document - o.doc_get1 = { - "_id": "get1", - "title": "myGet1" - }; - localstorage.setItem("jio/localstorage/uget/aget/get1", o.doc_get1); - - // get document - o.spy(o, "value", o.doc_get1, "Get document"); - o.jio.get({"_id": "get1"}, o.f); - o.tick(o); - - // get inexistent attachment (document exists) - o.spy(o, "status", 404, "Get inexistent attachment (document exists)"); - o.jio.getAttachment({"_id": "get1", "_attachment": "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.getAttachment({"_id": "get1", "_attachment": "get2"}, o.f); - o.tick(o); - - o.jio.stop(); - -}); - -test ("Remove", function(){ - - var o = generateTools(this); - - o.jio = JIO.newJio({ - "type": "local", - "username": "uremove", - "application_name": "aremove" - }); - - // remove inexistent document - o.spy(o, "status", 404, "Remove inexistent document"); - o.jio.remove({"_id": "remove1"}, o.f); - o.tick(o); - - // remove inexistent attachment - o.spy(o, "status", 404, "Remove inexistent attachment"); - o.jio.removeAttachment({"_id": "remove1", "_attachment": "remove2"}, o.f); - o.tick(o); - - // adding a document + attmt - localstorage.setItem("jio/localstorage/uremove/aremove/remove1", { - "_id": "remove1", - "title": "myRemove1", - "_attachments": { - "remove2": { - "length": 4, - "digest": "md5-blahblah" - } - } - }); - localstorage.setItem( - "jio/localstorage/uremove/aremove/remove1/remove2", "fghi"); - - // remove attachment - o.spy(o, "value", {"ok": true, "id": "remove1", "attachment": "remove2"}, - "Remove document"); - o.jio.removeAttachment({"_id": "remove1", "_attachment": "remove2"}, o.f); - o.tick(o); - - // remove document - o.spy(o, "value", {"ok": true, "id": "remove1"}, "Remove document"); - o.jio.remove({"_id": "remove1"}, o.f); - o.tick(o); - - // check document - ok(localstorage.getItem("jio/localstorage/uremove/aremove/remove1")===null, - "Check document is removed"); - - // adding a document + attmt - localstorage.setItem("jio/localstorage/uremove/aremove/remove1", { - "_id": "remove1", - "title": "myRemove1", - "_attachments": { - "remove2": { - "length": 4, - "digest": "md5-blahblah" - } - } - }); - localstorage.setItem( - "jio/localstorage/uremove/aremove/remove1/remove2", "fghi"); - - // remove attachment - o.spy(o, "value", {"ok": true, "id": "remove1"}, - "Remove document and attachment"); - o.jio.remove({"_id": "remove1"}, o.f); - o.tick(o); - ok(localstorage.getItem("jio/localstorage/uremove/aremove/remove1" - )===null, "Check document is removed"); - ok(localstorage.getItem("jio/localstorage/uremove/aremove/remove1/remove2" - )===null, "Check attachment is removed"); - - o.jio.stop(); - -}); - - -test ("AllDocs", function(){ - - var o = generateTools(this), i, m = 15; - - o.jio = JIO.newJio({ - "type": "local", - "username": "ualldocs", - "application_name": "aalldocs" - }); - o.localpath = "jio/localstorage/ualldocs/aalldocs"; - - // sample data - o.titles = ["Shawshank Redemption", "Godfather", "Godfather 2", - "Pulp Fiction", "The Good, The Bad and The Ugly", "12 Angry Men", - "The Dark Knight", "Schindlers List", - "Lord of the Rings - Return of the King", "Fight Club", - "Star Wars Episode V", "Lord Of the Rings - Fellowship of the Ring", - "One flew over the Cuckoo's Nest", "Inception", "Godfellas" - ]; - o.years = [1994,1972,1974,1994,1966,1957,2008,1993,2003,1999,1980,2001, - 1975,2010,1990 - ]; - o.director = ["Frank Darabont", "Francis Ford Coppola", - "Francis Ford Coppola", "Quentin Tarantino", "Sergio Leone", - "Sidney Lumet", "Christopher Nolan", "Steven Spielberg", - "Peter Jackson", "David Fincher", "Irvin Kershner", "Peter Jackson", - "Milos Forman", "Christopher Nolan", " Martin Scorsese" - ] - - for (i = 0; i < m; i += 1) { - o.fakeDoc = {}; - o.fakeDoc._id = "doc_"+(i < 10 ? "0"+i : i); - o.fakeDoc.title = o.titles[i]; - o.fakeDoc.year = o.years[i]; - o.fakeDoc.author = o.director[i]; - if (i === 5) { - o.fakeDoc._attachments = { - "att": { - "digest": "md5-dontcare", - "content_type": "text/plain", - "length": 3 - } - }; - localstorage.setItem(o.localpath + "/doc_05/att", "abc"); - } - localstorage.setItem(o.localpath+"/doc_"+(i < 10 ? "0"+i : i), o.fakeDoc); - } - - // response - o.allDocsResponse = {}; - o.allDocsResponse.rows = []; - o.allDocsResponse.total_rows = 15; - for (i = 0; i < m; i += 1) { - o.allDocsResponse.rows.push({ - "id": "doc_"+(i < 10 ? "0"+i : i), - "key": "doc_"+(i < 10 ? "0"+i : i), - "value": {} - }); - }; - // alldocs - o.spy(o, "value", o.allDocsResponse, "All docs"); - o.jio.allDocs(function (err, response) { - if (response && response.rows) { - response.rows.sort(function (a, b) { - return a.id > b.id ? 1 : a.id < b.id ? -1 : 0; - }); - } - o.f(err, response); - }); - o.tick(o); - - // include docs - o.allDocsResponse = {}; - o.allDocsResponse.rows = []; - o.allDocsResponse.total_rows = m; - for (i = 0; i < m; i += 1) { - o.allDocsResponse.rows.push({ - "id": "doc_"+(i < 10 ? "0"+i : i), - "key": "doc_"+(i < 10 ? "0"+i : i), - "value": {}, - "doc": localstorage.getItem(o.localpath+"/doc_"+(i < 10 ? "0"+i : i)) - }); - }; - - // alldocs - o.spy(o, "value", o.allDocsResponse, "All docs (include docs)"); - o.jio.allDocs({"include_docs": true}, function (err, response) { - if (response && response.rows) { - response.rows.sort(function (a, b) { - return a.id > b.id ? 1 : a.id < b.id ? -1 : 0; - }); - } - o.f(err, response); - }); - o.tick(o); - - // complex queries - o.thisShouldBeTheAnswer4 = {"total_rows": 0, "rows": []}; - o.allDocsResponse.rows.forEach(function (row) { - var new_row; - if (row.doc.year >= 1980) { - new_row = JSON.parse(JSON.stringify(row)); - new_row.value.title = row.doc.title; - new_row.value.year = row.doc.year; - delete new_row.doc; - o.thisShouldBeTheAnswer4.rows.push(new_row); - o.thisShouldBeTheAnswer4.total_rows += 1; - } - }); - o.thisShouldBeTheAnswer4.rows.sort(function (a, b) { - return a.value.year > b.value.year ? -1 : - a.value.year < b.value.year ? 1 : 0; - }); - o.thisShouldBeTheAnswer4.total_rows = 5; - o.thisShouldBeTheAnswer4.rows.length = 5; - - o.spy(o, "value", o.thisShouldBeTheAnswer4, - "allDocs (complex queries year >= 1980, all query options)"); - o.jio.allDocs({ - "query": '(year: >= "1980")', - "limit": [0,5], - "sort_on": [["year", "descending"]], - "select_list": ["title", "year"] - }, o.f); - o.tick(o); - - // empty query returns all - o.thisShouldBeTheAnswer5 = {"total_rows": 0, "rows": []}; - o.allDocsResponse.rows.forEach(function (row) { - var new_row = JSON.parse(JSON.stringify(row)); - new_row.value.title = row.doc.title; - o.thisShouldBeTheAnswer5.rows.push(new_row); - o.thisShouldBeTheAnswer5.total_rows += 1; - }); - o.thisShouldBeTheAnswer5.rows.sort(function (a, b) { - return a.value.title > b.value.title ? -1 : - a.value.title < b.value.title ? 1 : 0; - }); - - o.spy(o, "value", o.thisShouldBeTheAnswer5, - "allDocs (empty query in complex query)"); - - o.jio.allDocs({ - "sort_on": [["title", "descending"]], - "select_list": ["title"], - "include_docs": true - }, o.f); - o.tick(o); - - o.jio.stop(); - -}); - module ( "Jio Revision Storage + Local Storage" ); test ("Post", function(){ -- GitLab