...
 
Commits (33)
...@@ -26,7 +26,7 @@ TESTDIR = test ...@@ -26,7 +26,7 @@ TESTDIR = test
EXAMPLEDIR = examples EXAMPLEDIR = examples
EXTERNALDIR = external EXTERNALDIR = external
VERSION = 3.36.0 VERSION = 3.37.0
JIOVERSION = ${DISTDIR}/jio-v${VERSION}.js JIOVERSION = ${DISTDIR}/jio-v${VERSION}.js
JIOLATEST = ${DISTDIR}/jio-latest.js JIOLATEST = ${DISTDIR}/jio-latest.js
JIONODEVERSION = ${DISTDIR}/jio-v${VERSION}-node.js JIONODEVERSION = ${DISTDIR}/jio-v${VERSION}-node.js
...@@ -59,6 +59,11 @@ ${LINTDIR}/queries/query.js: ${SRCDIR}/queries/query.js ...@@ -59,6 +59,11 @@ ${LINTDIR}/queries/query.js: ${SRCDIR}/queries/query.js
${JSLINT} ${LINTOPTS} $< ${JSLINT} ${LINTOPTS} $<
@cat $< > $@ @cat $< > $@
${LINTDIR}/indexeddb/indexeddb.js: ${SRCDIR}/indexeddb/indexeddb.js
@mkdir -p $(@D)
${JSLINT} ${LINTOPTS} $<
@cat $< > $@
${LINTDIR}/${TESTDIR}/jio.storage/%.js: ${TESTDIR}/jio.storage/%.js ${LINTDIR}/${TESTDIR}/jio.storage/%.js: ${TESTDIR}/jio.storage/%.js
@mkdir -p $(@D) @mkdir -p $(@D)
${JSLINT} ${LINTOPTS} --predef QUnit --predef RSVP --predef jIO $< ${JSLINT} ${LINTOPTS} --predef QUnit --predef RSVP --predef jIO $<
...@@ -104,10 +109,12 @@ lint: $(patsubst ${TESTDIR}/jio.storage/%.js, ${LINTDIR}/${TESTDIR}/jio.storage/ ...@@ -104,10 +109,12 @@ lint: $(patsubst ${TESTDIR}/jio.storage/%.js, ${LINTDIR}/${TESTDIR}/jio.storage/
$(patsubst ${EXAMPLEDIR}/%.js, ${LINTDIR}/${EXAMPLEDIR}/%.js, $(wildcard ${EXAMPLEDIR}/*.js)) \ $(patsubst ${EXAMPLEDIR}/%.js, ${LINTDIR}/${EXAMPLEDIR}/%.js, $(wildcard ${EXAMPLEDIR}/*.js)) \
${LINTDIR}/queries/query.js \ ${LINTDIR}/queries/query.js \
${LINTDIR}/jio.date/jiodate.js \ ${LINTDIR}/jio.date/jiodate.js \
${LINTDIR}/indexeddb/indexeddb.js \
${LINTDIR}/jio.js \ ${LINTDIR}/jio.js \
${LINTDIR}/node/jio.js \ ${LINTDIR}/node/jio.js \
${LINTDIR}/${TESTDIR}/node.js \ ${LINTDIR}/${TESTDIR}/node.js \
${LINTDIR}/${TESTDIR}/node/node-require.js \ ${LINTDIR}/${TESTDIR}/node/node-require.js \
${LINTDIR}/${TESTDIR}/node/ajax.tests.js \
$(patsubst ${SRCDIR}/jio.storage/%.js, ${LINTDIR}/jio.storage/%.js, $(wildcard ${SRCDIR}/jio.storage/*.js)) $(patsubst ${SRCDIR}/jio.storage/%.js, ${LINTDIR}/jio.storage/%.js, $(wildcard ${SRCDIR}/jio.storage/*.js))
############################################# #############################################
...@@ -128,6 +135,7 @@ ${JIOVERSION}: ${EXTERNALDIR}/URI.js \ ...@@ -128,6 +135,7 @@ ${JIOVERSION}: ${EXTERNALDIR}/URI.js \
${SRCDIR}/queries/parser-end.js \ ${SRCDIR}/queries/parser-end.js \
${SRCDIR}/queries/query.js \ ${SRCDIR}/queries/query.js \
${SRCDIR}/jio.date/jiodate.js \ ${SRCDIR}/jio.date/jiodate.js \
${SRCDIR}/indexeddb/indexeddb.js \
${SRCDIR}/jio.js \ ${SRCDIR}/jio.js \
${EXTERNALDIR}/rusha.js \ ${EXTERNALDIR}/rusha.js \
${SRCDIR}/jio.storage/replicatestorage.js \ ${SRCDIR}/jio.storage/replicatestorage.js \
...@@ -149,9 +157,11 @@ ${JIOVERSION}: ${EXTERNALDIR}/URI.js \ ...@@ -149,9 +157,11 @@ ${JIOVERSION}: ${EXTERNALDIR}/URI.js \
${SRCDIR}/jio.storage/localstorage.js \ ${SRCDIR}/jio.storage/localstorage.js \
${SRCDIR}/jio.storage/indexeddbstorage.js \ ${SRCDIR}/jio.storage/indexeddbstorage.js \
${SRCDIR}/jio.storage/cryptstorage.js \ ${SRCDIR}/jio.storage/cryptstorage.js \
${SRCDIR}/jio.storage/websqlstorage.js \
${SRCDIR}/jio.storage/fbstorage.js \ ${SRCDIR}/jio.storage/fbstorage.js \
${SRCDIR}/jio.storage/cloudooostorage.js ${SRCDIR}/jio.storage/cloudooostorage.js \
${SRCDIR}/jio.storage/nocapacitystorage.js \
${SRCDIR}/jio.storage/liststorage.js \
${SRCDIR}/jio.storage/indexstorage2.js
@mkdir -p $(@D) @mkdir -p $(@D)
cat $^ > $@ cat $^ > $@
...@@ -254,6 +264,7 @@ ${EXTERNALDIR}/renderjs-latest.js: ...@@ -254,6 +264,7 @@ ${EXTERNALDIR}/renderjs-latest.js:
clean: clean:
rm -rf ${LINTDIR} rm -rf ${LINTDIR}
rm ${SRCDIR}/queries/build/parser.js
forceclean: clean forceclean: clean
rm -rf ${EXTERNALDIR} ${SRCDIR}/queries/build/parser.js rm -rf ${EXTERNALDIR} ${SRCDIR}/queries/build/parser.js
...@@ -7870,11 +7870,11 @@ var arrayExtend = function () { ...@@ -7870,11 +7870,11 @@ var arrayExtend = function () {
} }
return {type:"complex",operator:operator,query_list:query_list2}; return {type:"complex",operator:operator,query_list:query_list2};
}, simpleQuerySetKey = function (query, key) { }, querySetKey = function (query, key) {
var i; var i;
if (query.type === "complex") { if (query.type === "complex") {
for (i = 0; i < query.query_list.length; ++i) { for (i = 0; i < query.query_list.length; ++i) {
simpleQuerySetKey (query.query_list[i],key); querySetKey(query.query_list[i], key);
} }
return true; return true;
} }
...@@ -7995,7 +7995,7 @@ case 12: ...@@ -7995,7 +7995,7 @@ case 12:
this.$ = $$[$0-1]; this.$ = $$[$0-1];
break; break;
case 13: case 13:
simpleQuerySetKey($$[$0], $$[$0-2]); this.$ = $$[$0]; querySetKey($$[$0], $$[$0-2]); this.$ = $$[$0];
break; break;
case 15: case 15:
$$[$0].operator = $$[$0-1] ; this.$ = $$[$0]; $$[$0].operator = $$[$0-1] ; this.$ = $$[$0];
...@@ -9124,21 +9124,8 @@ return new Parser; ...@@ -9124,21 +9124,8 @@ return new Parser;
* #crossLink "Query/toString:method" * #crossLink "Query/toString:method"
*/ */
ComplexQuery.prototype.toString = function () { ComplexQuery.prototype.toString = function () {
var str_list = [], this_operator = this.operator; /*global objectToSearchText */
if (this.operator === "NOT") { return objectToSearchText(this.toJSON());
str_list.push("NOT (");
str_list.push(this.query_list[0].toString());
str_list.push(")");
return str_list.join(" ");
}
this.query_list.forEach(function (query) {
str_list.push("(");
str_list.push(query.toString());
str_list.push(")");
str_list.push(this_operator);
});
str_list.length -= 1;
return str_list.join(" ");
}; };
/** /**
...@@ -9237,21 +9224,60 @@ return new Parser; ...@@ -9237,21 +9224,60 @@ return new Parser;
}; };
function objectToSearchText(query) { function objectToSearchText(query) {
var str_list = []; var i = 0,
if (query.type === "complex") { query_list = null,
str_list.push("("); string_list = null,
(query.query_list || []).forEach(function (sub_query) { operator = "",
str_list.push(objectToSearchText(sub_query)); common_key = "";
str_list.push(query.operator);
});
str_list.length -= 1;
str_list.push(")");
return str_list.join(" ");
}
if (query.type === "simple") { if (query.type === "simple") {
return (query.key ? query.key + ": " : "") + return (query.key ? query.key + ": " : "") +
(query.operator || "") + ' "' + query.value + '"'; (query.operator || "") + ' "' + query.value + '"';
} }
if (query.type === "complex") {
query_list = query.query_list;
if (!query_list || query_list.length === 0) {
return "";
}
operator = query.operator || "";
if (operator === "NOT") {
// fallback to AND operator if several queries are given
// i.e. `NOT ( a AND b )`
return "NOT ( " + objectToSearchText(
{type: "complex", operator: "AND", query_list: query_list}
) + " )";
}
if (query_list.length === 1) {
return objectToSearchText(query_list[0]);
}
common_key = query_list[i].key;
for (i = 1; i < query_list.length; i += 1) {
if (query_list[i].type !== "simple" ||
query_list[i].key !== common_key) {
break;
}
}
string_list = [];
if (i === query_list.length) {
for (i = 0; i < query_list.length; i += 1) {
string_list.push(
(query_list[i].operator || "") +
' "' + query_list[i].value + '"'
);
}
} else {
common_key = "";
for (i = 0; i < query_list.length; i += 1) {
string_list.push(objectToSearchText(query_list[i]));
}
}
if (string_list.length > 1) {
return (common_key ? common_key + ": " : "") +
"( " + string_list.join(" " + operator + " ") + " )";
}
return (common_key ? common_key + ": " : "") +
string_list[0];
}
throw new TypeError("This object is not a query"); throw new TypeError("This object is not a query");
} }
...@@ -9419,8 +9445,7 @@ return new Parser; ...@@ -9419,8 +9445,7 @@ return new Parser;
* #crossLink "Query/toString:method" * #crossLink "Query/toString:method"
*/ */
SimpleQuery.prototype.toString = function () { SimpleQuery.prototype.toString = function () {
return (this.key ? this.key + ":" : "") + return objectToSearchText(this.toJSON());
(this.operator ? " " + this.operator : "") + ' "' + this.value + '"';
}; };
/** /**
...@@ -10090,17 +10115,11 @@ var XMLHttpRequest = global.XMLHttpRequest || module.exports, ...@@ -10090,17 +10115,11 @@ var XMLHttpRequest = global.XMLHttpRequest || module.exports,
* See https://www.nexedi.com/licensing for rationale and options. * See https://www.nexedi.com/licensing for rationale and options.
*/ */
/*global window, RSVP, Blob, XMLHttpRequest, QueryFactory, Query, atob, /*global window, RSVP, Blob, XMLHttpRequest, QueryFactory, Query, atob,
FileReader, ArrayBuffer, Uint8Array, navigator */ FileReader, ArrayBuffer, Uint8Array */
(function (window, RSVP, Blob, QueryFactory, Query, atob, (function (window, RSVP, Blob, QueryFactory, Query, atob,
FileReader, ArrayBuffer, Uint8Array, navigator) { FileReader, ArrayBuffer, Uint8Array) {
"use strict"; "use strict";
if (window.openDatabase === undefined) {
window.openDatabase = function () {
throw new Error('WebSQL is not supported by ' + navigator.userAgent);
};
}
/* Safari does not define DOMError */ /* Safari does not define DOMError */
if (window.DOMError === undefined) { if (window.DOMError === undefined) {
window.DOMError = {}; window.DOMError = {};
...@@ -10546,6 +10565,7 @@ var XMLHttpRequest = global.XMLHttpRequest || module.exports, ...@@ -10546,6 +10565,7 @@ var XMLHttpRequest = global.XMLHttpRequest || module.exports,
if (context.hasCapacity("list") && if (context.hasCapacity("list") &&
((options.query === undefined) || context.hasCapacity("query")) && ((options.query === undefined) || context.hasCapacity("query")) &&
((options.sort_on === undefined) || context.hasCapacity("sort")) && ((options.sort_on === undefined) || context.hasCapacity("sort")) &&
((options.group_by === undefined) || context.hasCapacity("group")) &&
((options.select_list === undefined) || ((options.select_list === undefined) ||
context.hasCapacity("select")) && context.hasCapacity("select")) &&
((options.include_docs === undefined) || ((options.include_docs === undefined) ||
...@@ -10632,7 +10652,7 @@ var XMLHttpRequest = global.XMLHttpRequest || module.exports, ...@@ -10632,7 +10652,7 @@ var XMLHttpRequest = global.XMLHttpRequest || module.exports,
window.jIO = jIO; window.jIO = jIO;
}(window, RSVP, Blob, QueryFactory, Query, atob, }(window, RSVP, Blob, QueryFactory, Query, atob,
FileReader, ArrayBuffer, Uint8Array, navigator)); FileReader, ArrayBuffer, Uint8Array));
/* /*
* Copyright 2018, Nexedi SA * Copyright 2018, Nexedi SA
* *
...@@ -14178,7 +14198,7 @@ var jIO = window.jIO, ...@@ -14178,7 +14198,7 @@ var jIO = window.jIO,
ERP5Storage.prototype.hasCapacity = function (name) { ERP5Storage.prototype.hasCapacity = function (name) {
return ((name === "list") || (name === "query") || return ((name === "list") || (name === "query") ||
(name === "select") || (name === "limit") || (name === "select") || (name === "limit") ||
(name === "sort")); (name === "sort") || (name === "group"));
}; };
function isSingleLocalRoles(parsed_query) { function isSingleLocalRoles(parsed_query) {
...@@ -14246,7 +14266,8 @@ var jIO = window.jIO, ...@@ -14246,7 +14266,8 @@ var jIO = window.jIO,
local_roles, local_roles,
local_role_found = false, local_role_found = false,
selection_domain, selection_domain,
sort_list = []; sort_list = [],
group_list = [];
if (options.query) { if (options.query) {
parsed_query = jIO.QueryFactory.create(options.query); parsed_query = jIO.QueryFactory.create(options.query);
result_list = isSingleLocalRoles(parsed_query); result_list = isSingleLocalRoles(parsed_query);
...@@ -14318,6 +14339,10 @@ var jIO = window.jIO, ...@@ -14318,6 +14339,10 @@ var jIO = window.jIO,
} }
} }
if (options.group_by) {
group_list = options.group_by;
}
if (selection_domain) { if (selection_domain) {
selection_domain = JSON.stringify(selection_domain); selection_domain = JSON.stringify(selection_domain);
} }
...@@ -14331,6 +14356,7 @@ var jIO = window.jIO, ...@@ -14331,6 +14356,7 @@ var jIO = window.jIO,
select_list: options.select_list || ["title", "reference"], select_list: options.select_list || ["title", "reference"],
limit: options.limit, limit: options.limit,
sort_on: sort_list, sort_on: sort_list,
group_by: group_list,
local_roles: local_roles, local_roles: local_roles,
selection_domain: selection_domain selection_domain: selection_domain
}) })
......
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
* See https://www.nexedi.com/licensing for rationale and options. * See https://www.nexedi.com/licensing for rationale and options.
*/ */
/*global console, btoa, Blob*/ /*global console, btoa, Blob, indexedDB*/
/*jslint nomen: true, maxlen: 200*/ /*jslint nomen: true, maxlen: 200*/
(function (window, QUnit, jIO, rJS) { (function (window, QUnit, jIO, rJS) {
"use strict"; "use strict";
...@@ -28,7 +28,9 @@ ...@@ -28,7 +28,9 @@
ok = QUnit.ok, ok = QUnit.ok,
stop = QUnit.stop, stop = QUnit.stop,
start = QUnit.start, start = QUnit.start,
deepEqual = QUnit.deepEqual; deepEqual = QUnit.deepEqual,
test_signature_database = 'test_signature_storage_scenario';
rJS(window) rJS(window)
...@@ -60,12 +62,22 @@ ...@@ -60,12 +62,22 @@
return g.run({ return g.run({
type: "query", type: "query",
sub_storage: { sub_storage: {
type: "uuid", type: "list",
signature_storage: {
type: "indexeddb",
database: test_signature_database
},
sub_storage: { sub_storage: {
type: "union", type: "nocapacity",
storage_list: [{ sub_storage: {
type: "memory" type: "uuid",
}] sub_storage: {
type: "union",
storage_list: [{
type: "memory"
}]
}
}
} }
} }
}); });
...@@ -362,6 +374,9 @@ ...@@ -362,6 +374,9 @@
.then(function () { .then(function () {
return jio.repair(); return jio.repair();
}) })
.then(function () {
return indexedDB.deleteDatabase('jio:' + test_signature_database);
})
.fail(function (error) { .fail(function (error) {
console.error("---"); console.error("---");
......
{ {
"name": "jio", "name": "jio",
"version": "v3.36.0", "version": "v3.37.0",
"license": "GPLv3+", "license": "GPLv3+",
"author": "Nexedi SA", "author": "Nexedi SA",
"contributors": [ "contributors": [
......
/*
* Copyright 2019, Nexedi SA
*
* This program is free software: you can Use, Study, Modify and Redistribute
* it under the terms of the GNU General Public License version 3, or (at your
* option) any later version, as published by the Free Software Foundation.
*
* You can also Link and Combine this program with other software covered by
* the terms of any of the Free Software licenses or any of the Open Source
* Initiative approved licenses and Convey the resulting work. Corresponding
* source of such a combination shall include the source code for all other
* software used.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See COPYING file for full licensing terms.
* See https://www.nexedi.com/licensing for rationale and options.
*/
/*jslint nomen: true */
/*global indexedDB, RSVP, IDBOpenDBRequest, DOMError, Event, Set, DOMException,
window*/
(function (indexedDB, RSVP, IDBOpenDBRequest, DOMError, DOMException) {
"use strict";
function waitForIDBRequest(request) {
return new RSVP.Promise(function (resolve, reject) {
request.onerror = reject;
request.onsuccess = resolve;
});
}
function waitForAllSynchronousCursor(request, callback) {
var force_cancellation = false;
function canceller() {
force_cancellation = true;
}
function resolver(resolve, reject) {
request.onerror = reject;
request.onsuccess = function (evt) {
var cursor = evt.target.result;
if (cursor && !force_cancellation) {
try {
callback(cursor);
} catch (error) {
reject(error);
}
// continue to next iteration
cursor["continue"]();
} else {
resolve();
}
};
}
return new RSVP.Promise(resolver, canceller);
}
function waitForOpenIndexedDB(db_name, version, upgrade_handler, callback) {
var request;
function canceller() {
if ((request !== undefined) && (request.result !== undefined)) {
request.result.close();
}
}
function resolver(resolve, reject) {
// Open DB //
request = indexedDB.open(db_name, version);
request.onerror = function (error) {
canceller();
if ((error !== undefined) &&
(error.target instanceof IDBOpenDBRequest) &&
((error.target.error instanceof DOMError) ||
(error.target.error instanceof DOMException))) {
reject("Connection to: " + db_name + " failed: " +
error.target.error.message);
} else {
reject(error);
}
};
request.onabort = function () {
canceller();
reject("Aborting connection to: " + db_name);
};
request.ontimeout = function () {
reject("Connection to: " + db_name + " timeout");
};
request.onblocked = function () {
canceller();
reject("Connection to: " + db_name + " was blocked");
};
// Create DB if necessary //
request.onupgradeneeded = upgrade_handler;
request.onversionchange = function () {
canceller();
reject(db_name + " was upgraded");
};
request.onsuccess = function () {
var result;
try {
result = callback(request.result);
} catch (error) {
reject(error);
}
return new RSVP.Queue()
.push(function () {
return result;
})
.push(function (final_result) {
canceller();
resolve(final_result);
}, function (error) {
canceller();
reject(error);
});
};
}
return new RSVP.Promise(resolver, canceller);
}
function waitForRepairableOpenIndexedDB(db_name, version, index_keys,
sub_storage_description, signature_storage_name, upgrade_handler,
callback) {
var handleUpgradeNeeded = function (evt) {
return upgrade_handler(evt, index_keys, sub_storage_description,
signature_storage_name);
};
return waitForOpenIndexedDB(db_name, version, handleUpgradeNeeded,
callback);
}
function waitForTransaction(db, stores, flag, callback) {
var tx = db.transaction(stores, flag);
function canceller() {
try {
tx.abort();
} catch (unused) {
// Transaction already finished
return;
}
}
function resolver(resolve, reject) {
var result;
try {
result = callback(tx);
} catch (error) {
reject(error);
}
tx.oncomplete = function () {
return new RSVP.Queue()
.push(function () {
return result;
})
.push(resolve, function (error) {
canceller();
reject(error);
});
};
tx.onerror = function (error) {
canceller();
reject(error);
};
tx.onabort = function (evt) {
reject(evt.target);
};
return tx;
}
return new RSVP.Promise(resolver, canceller);
}
window.waitForTransaction = waitForTransaction;
window.waitForOpenIndexedDB = waitForOpenIndexedDB;
window.waitForIDBRequest = waitForIDBRequest;
window.waitForAllSynchronousCursor = waitForAllSynchronousCursor;
window.waitForRepairableOpenIndexedDB = waitForRepairableOpenIndexedDB;
}(indexedDB, RSVP, IDBOpenDBRequest, DOMError, DOMException));
\ No newline at end of file \ No newline at end of file
...@@ -18,17 +18,11 @@ ...@@ -18,17 +18,11 @@
* See https://www.nexedi.com/licensing for rationale and options. * See https://www.nexedi.com/licensing for rationale and options.
*/ */
/*global window, RSVP, Blob, XMLHttpRequest, QueryFactory, Query, atob, /*global window, RSVP, Blob, XMLHttpRequest, QueryFactory, Query, atob,
FileReader, ArrayBuffer, Uint8Array, navigator */ FileReader, ArrayBuffer, Uint8Array */
(function (window, RSVP, Blob, QueryFactory, Query, atob, (function (window, RSVP, Blob, QueryFactory, Query, atob,
FileReader, ArrayBuffer, Uint8Array, navigator) { FileReader, ArrayBuffer, Uint8Array) {
"use strict"; "use strict";
if (window.openDatabase === undefined) {
window.openDatabase = function () {
throw new Error('WebSQL is not supported by ' + navigator.userAgent);
};
}
/* Safari does not define DOMError */ /* Safari does not define DOMError */
if (window.DOMError === undefined) { if (window.DOMError === undefined) {
window.DOMError = {}; window.DOMError = {};
...@@ -474,6 +468,7 @@ ...@@ -474,6 +468,7 @@
if (context.hasCapacity("list") && if (context.hasCapacity("list") &&
((options.query === undefined) || context.hasCapacity("query")) && ((options.query === undefined) || context.hasCapacity("query")) &&
((options.sort_on === undefined) || context.hasCapacity("sort")) && ((options.sort_on === undefined) || context.hasCapacity("sort")) &&
((options.group_by === undefined) || context.hasCapacity("group")) &&
((options.select_list === undefined) || ((options.select_list === undefined) ||
context.hasCapacity("select")) && context.hasCapacity("select")) &&
((options.include_docs === undefined) || ((options.include_docs === undefined) ||
...@@ -560,4 +555,4 @@ ...@@ -560,4 +555,4 @@
window.jIO = jIO; window.jIO = jIO;
}(window, RSVP, Blob, QueryFactory, Query, atob, }(window, RSVP, Blob, QueryFactory, Query, atob,
FileReader, ArrayBuffer, Uint8Array, navigator)); FileReader, ArrayBuffer, Uint8Array));
...@@ -419,7 +419,7 @@ ...@@ -419,7 +419,7 @@
ERP5Storage.prototype.hasCapacity = function (name) { ERP5Storage.prototype.hasCapacity = function (name) {
return ((name === "list") || (name === "query") || return ((name === "list") || (name === "query") ||
(name === "select") || (name === "limit") || (name === "select") || (name === "limit") ||
(name === "sort")); (name === "sort") || (name === "group"));
}; };
function isSingleLocalRoles(parsed_query) { function isSingleLocalRoles(parsed_query) {
...@@ -487,7 +487,8 @@ ...@@ -487,7 +487,8 @@
local_roles, local_roles,
local_role_found = false, local_role_found = false,
selection_domain, selection_domain,
sort_list = []; sort_list = [],
group_list = [];
if (options.query) { if (options.query) {
parsed_query = jIO.QueryFactory.create(options.query); parsed_query = jIO.QueryFactory.create(options.query);
result_list = isSingleLocalRoles(parsed_query); result_list = isSingleLocalRoles(parsed_query);
...@@ -559,6 +560,10 @@ ...@@ -559,6 +560,10 @@
} }
} }
if (options.group_by) {
group_list = options.group_by;
}
if (selection_domain) { if (selection_domain) {
selection_domain = JSON.stringify(selection_domain); selection_domain = JSON.stringify(selection_domain);
} }
...@@ -572,6 +577,7 @@ ...@@ -572,6 +577,7 @@
select_list: options.select_list || ["title", "reference"], select_list: options.select_list || ["title", "reference"],
limit: options.limit, limit: options.limit,
sort_on: sort_list, sort_on: sort_list,
group_by: group_list,
local_roles: local_roles, local_roles: local_roles,
selection_domain: selection_domain selection_domain: selection_domain
}) })
......
...@@ -150,7 +150,12 @@ ...@@ -150,7 +150,12 @@
_linshare_uuid: entry_list[i].uuid _linshare_uuid: entry_list[i].uuid
}; };
if (options.include_docs === true) { if (options.include_docs === true) {
entry.doc = JSON.parse(entry_list[i].metaData) || {}; try {
entry.doc = JSON.parse(entry_list[i].metaData) || {};
} catch (error) {
// Metadata are not always JSON
entry.doc = {};
}
} }
result_list.push(entry); result_list.push(entry);
......
/*
* Copyright 2019, Nexedi SA
*
* This program is free software: you can Use, Study, Modify and Redistribute
* it under the terms of the GNU General Public License version 3, or (at your
* option) any later version, as published by the Free Software Foundation.
*
* You can also Link and Combine this program with other software covered by
* the terms of any of the Free Software licenses or any of the Open Source
* Initiative approved licenses and Convey the resulting work. Corresponding
* source of such a combination shall include the source code for all other
* software used.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See COPYING file for full licensing terms.
* See https://www.nexedi.com/licensing for rationale and options.
*/
/*jslint nomen: true*/
/*global Set*/
(function (jIO) {
"use strict";
function ListStorage(spec) {
this._sub_storage = jIO.createJIO(spec.sub_storage);
this._signature_storage = jIO.createJIO(spec.signature_storage);
}
ListStorage.prototype.get = function () {
return this._sub_storage.get.apply(this._sub_storage, arguments);
};
ListStorage.prototype.allAttachments = function () {
return this._sub_storage.allAttachments.apply(this._sub_storage, arguments);
};
ListStorage.prototype.post = function (value) {
var gadget = this;
return gadget._sub_storage.post(value)
.push(function (id) {
return gadget._signature_storage.put(id, {})
.push(function () {
return id;
});
});
};
ListStorage.prototype.put = function (id, value) {
var gadget = this;
return gadget._sub_storage.put(id, value)
.push(function (result) {
return gadget._signature_storage.put(id, {})
.push(function () {
return result;
});
});
};
ListStorage.prototype.remove = function (id) {
var gadget = this;
return gadget._sub_storage.remove(id)
.push(function (result) {
return gadget._signature_storage.remove(id)
.push(function () {
return result;
});
});
};
ListStorage.prototype.getAttachment = function () {
return this._sub_storage.getAttachment.apply(this._sub_storage, arguments);
};
ListStorage.prototype.putAttachment = function () {
return this._sub_storage.putAttachment.apply(this._sub_storage, arguments);
};
ListStorage.prototype.removeAttachment = function () {
return this._sub_storage.removeAttachment.apply(this._sub_storage,
arguments);
};
ListStorage.prototype.repair = function () {
return this._sub_storage.repair.apply(this._sub_storage, arguments);
};
ListStorage.prototype.hasCapacity = function (name) {
if (name === "list") {
return this._signature_storage.hasCapacity('list');
}
return false;
};
ListStorage.prototype.buildQuery = function () {
return this._signature_storage.buildQuery();
};
jIO.addStorage('list', ListStorage);
}(jIO));
\ No newline at end of file \ No newline at end of file
/*
* Copyright 2019, Nexedi SA
*
* This program is free software: you can Use, Study, Modify and Redistribute
* it under the terms of the GNU General Public License version 3, or (at your
* option) any later version, as published by the Free Software Foundation.
*
* You can also Link and Combine this program with other software covered by
* the terms of any of the Free Software licenses or any of the Open Source
* Initiative approved licenses and Convey the resulting work. Corresponding
* source of such a combination shall include the source code for all other
* software used.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See COPYING file for full licensing terms.
* See https://www.nexedi.com/licensing for rationale and options.
*/
/*jslint nomen: true*/
(function (jIO) {
"use strict";
function NoCapacityStorage(spec) {
this._sub_storage = jIO.createJIO(spec.sub_storage);
}
NoCapacityStorage.prototype.get = function () {
return this._sub_storage.get.apply(this._sub_storage, arguments);
};
NoCapacityStorage.prototype.allAttachments = function () {
return this._sub_storage.allAttachments.apply(this._sub_storage, arguments);
};
NoCapacityStorage.prototype.post = function () {
return this._sub_storage.post.apply(this._sub_storage, arguments);
};
NoCapacityStorage.prototype.put = function () {
return this._sub_storage.put.apply(this._sub_storage, arguments);
};
NoCapacityStorage.prototype.remove = function () {
return this._sub_storage.remove.apply(this._sub_storage, arguments);
};
NoCapacityStorage.prototype.getAttachment = function () {
return this._sub_storage.getAttachment.apply(this._sub_storage, arguments);
};
NoCapacityStorage.prototype.putAttachment = function () {
return this._sub_storage.putAttachment.apply(this._sub_storage, arguments);
};
NoCapacityStorage.prototype.removeAttachment = function () {
return this._sub_storage.removeAttachment.apply(this._sub_storage,
arguments);
};
NoCapacityStorage.prototype.repair = function () {
return this._sub_storage.repair.apply(this._sub_storage, arguments);
};
jIO.addStorage('nocapacity', NoCapacityStorage);
}(jIO));
\ No newline at end of file \ No newline at end of file
...@@ -190,11 +190,10 @@ ...@@ -190,11 +190,10 @@
try { try {
return window.atob(str); return window.atob(str);
} catch (err) { } catch (err) {
var buffer; var buffer = Buffer.from(str.toString(), 'base64');
if (str instanceof Buffer) { // Provide the same behaviour than the browser atob
buffer = str; if (buffer.toString('base64') !== str) {
} else { throw new Error('The string to be decoded is not correctly encoded.');
buffer = Buffer.from(str.toString(), 'base64');
} }
return buffer.toString('binary'); return buffer.toString('binary');
} }
...@@ -206,13 +205,7 @@ ...@@ -206,13 +205,7 @@
try { try {
return window.btoa(str); return window.btoa(str);
} catch (err) { } catch (err) {
var buffer; return Buffer.from(str.toString(), 'binary').toString('base64');
if (str instanceof Buffer) {
buffer = str;
} else {
buffer = Buffer.from(str.toString(), 'binary');
}
return buffer.toString('base64');
} }
} }
...@@ -220,8 +213,8 @@ ...@@ -220,8 +213,8 @@
}(window, WeakMap, ArrayBuffer, Uint8Array)); }(window, WeakMap, ArrayBuffer, Uint8Array));
var XMLHttpRequest = global.XMLHttpRequest || module.exports, global.XMLHttpRequest = module.exports;
Blob = window.Blob, var Blob = window.Blob,
atob = window.atob, atob = window.atob,
btoa = window.btoa, btoa = window.btoa,
FileReader = window.FileReader, FileReader = window.FileReader,
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
*/ */
/*global window */ /*global window */
(function (window, jIO, Blob) { (function (window, jIO, Blob, RSVP) {
"use strict"; "use strict";
var FormData, var FormData,
...@@ -41,32 +41,71 @@ ...@@ -41,32 +41,71 @@
}; };
window.FormData = FormData; window.FormData = FormData;
function convertToBlob(promise, convert) {
if (!convert) {
return promise;
}
var result;
if (promise instanceof RSVP.Queue) {
result = promise;
} else {
result = new RSVP.Queue()
.push(function () {
return promise;
});
}
return result
.push(function (evt) {
evt.target.response = new Blob(
[evt.target.response || evt.target.responseText],
{type: evt.target.getResponseHeader('Content-Type')}
);
return evt;
});
}
originalAjax = jIO.util.ajax; originalAjax = jIO.util.ajax;
jIO.util.ajax = function ajax(param) { jIO.util.ajax = function ajax(param) {
var result,
need_convertion = (param.dataType === 'blob');
// Copy the param dict document (no need for deep copy) to
// allow tests to check them
param = Object.assign({}, param);
if (need_convertion) {
param.dataType = 'arraybuffer';
}
if (param.data instanceof Blob) { if (param.data instanceof Blob) {
// Blob is not supported by xhr2, so convert to ArrayBuffer instead // Blob is not supported by xhr2, so convert to ArrayBuffer instead
return jIO.util.readBlobAsArrayBuffer(param.data).then(function (data) { result = new RSVP.Queue()
param.data = data.target.result; .push(function () {
return originalAjax(param); return jIO.util.readBlobAsArrayBuffer(param.data);
}); })
} .push(function (evt) {
param.data = evt.target.result;
if (param.data instanceof FormData) { return originalAjax(param);
});
} else if (param.data instanceof FormData) {
// Implement minimal FormData for erp5storage // Implement minimal FormData for erp5storage
if (!param.hasOwnProperty('headers')) { if (!param.hasOwnProperty('headers')) {
param.headers = {}; param.headers = {};
} else {
// Copy the param dict document (no need for deep copy) to
// allow tests to check them
param.headers = Object.assign({}, param.headers);
} }
param.headers["Content-Type"] = "multipart\/form-data; boundary=" + param.headers["Content-Type"] = "multipart\/form-data; boundary=" +
param.data.boundary; param.data.boundary;
param.data.body += '--' + param.data.boundary + '--\r\n'; param.data.body += '--' + param.data.boundary + '--\r\n';
param.data = param.data.body; param.data = param.data.body;
return originalAjax(param); result = originalAjax(param);
} else {
result = originalAjax(param);
} }
return originalAjax(param); return convertToBlob(result, need_convertion);
}; };
}(window, window.jIO, window.Blob)); }(window, window.jIO, window.Blob, window.RSVP));
// Define a global variable to allow storages to access jIO // Define a global variable to allow storages to access jIO
var jIO = window.jIO, var jIO = window.jIO,
......
...@@ -105,7 +105,7 @@ case 12: ...@@ -105,7 +105,7 @@ case 12:
this.$ = $$[$0-1]; this.$ = $$[$0-1];
break; break;
case 13: case 13:
simpleQuerySetKey($$[$0], $$[$0-2]); this.$ = $$[$0]; querySetKey($$[$0], $$[$0-2]); this.$ = $$[$0];
break; break;
case 15: case 15:
$$[$0].operator = $$[$0-1] ; this.$ = $$[$0]; $$[$0].operator = $$[$0-1] ; this.$ = $$[$0];
......
...@@ -61,7 +61,7 @@ boolean_expression ...@@ -61,7 +61,7 @@ boolean_expression
expression expression
: LEFT_PARENTHESE search_text RIGHT_PARENTHESE { $$ = $2; } : LEFT_PARENTHESE search_text RIGHT_PARENTHESE { $$ = $2; }
| WORD DEFINITION expression { simpleQuerySetKey($3, $1); $$ = $3; } | WORD DEFINITION expression { querySetKey($3, $1); $$ = $3; }
| value { $$ = $1; } | value { $$ = $1; }
; ;
......
...@@ -58,11 +58,11 @@ var arrayExtend = function () { ...@@ -58,11 +58,11 @@ var arrayExtend = function () {
} }
return {type:"complex",operator:operator,query_list:query_list2}; return {type:"complex",operator:operator,query_list:query_list2};
}, simpleQuerySetKey = function (query, key) { }, querySetKey = function (query, key) {
var i; var i;
if (query.type === "complex") { if (query.type === "complex") {
for (i = 0; i < query.query_list.length; ++i) { for (i = 0; i < query.query_list.length; ++i) {
simpleQuerySetKey (query.query_list[i],key); querySetKey(query.query_list[i], key);
} }
return true; return true;
} }
......
...@@ -573,21 +573,8 @@ ...@@ -573,21 +573,8 @@
* #crossLink "Query/toString:method" * #crossLink "Query/toString:method"
*/ */
ComplexQuery.prototype.toString = function () { ComplexQuery.prototype.toString = function () {
var str_list = [], this_operator = this.operator; /*global objectToSearchText */
if (this.operator === "NOT") { return objectToSearchText(this.toJSON());
str_list.push("NOT (");
str_list.push(this.query_list[0].toString());
str_list.push(")");
return str_list.join(" ");
}
this.query_list.forEach(function (query) {
str_list.push("(");
str_list.push(query.toString());
str_list.push(")");
str_list.push(this_operator);
});
str_list.length -= 1;
return str_list.join(" ");
}; };
/** /**
...@@ -686,21 +673,60 @@ ...@@ -686,21 +673,60 @@
}; };
function objectToSearchText(query) { function objectToSearchText(query) {
var str_list = []; var i = 0,
if (query.type === "complex") { query_list = null,
str_list.push("("); string_list = null,
(query.query_list || []).forEach(function (sub_query) { operator = "",
str_list.push(objectToSearchText(sub_query)); common_key = "";
str_list.push(query.operator);
});
str_list.length -= 1;
str_list.push(")");
return str_list.join(" ");
}
if (query.type === "simple") { if (query.type === "simple") {
return (query.key ? query.key + ": " : "") + return (query.key ? query.key + ": " : "") +
(query.operator || "") + ' "' + query.value + '"'; (query.operator || "") + ' "' + query.value + '"';
} }
if (query.type === "complex") {
query_list = query.query_list;
if (!query_list || query_list.length === 0) {
return "";
}
operator = query.operator || "";
if (operator === "NOT") {
// fallback to AND operator if several queries are given
// i.e. `NOT ( a AND b )`
return "NOT ( " + objectToSearchText(
{type: "complex", operator: "AND", query_list: query_list}
) + " )";
}
if (query_list.length === 1) {
return objectToSearchText(query_list[0]);
}
common_key = query_list[i].key;
for (i = 1; i < query_list.length; i += 1) {
if (query_list[i].type !== "simple" ||
query_list[i].key !== common_key) {
break;
}
}
string_list = [];
if (i === query_list.length) {
for (i = 0; i < query_list.length; i += 1) {
string_list.push(
(query_list[i].operator || "") +
' "' + query_list[i].value + '"'
);
}
} else {
common_key = "";
for (i = 0; i < query_list.length; i += 1) {
string_list.push(objectToSearchText(query_list[i]));
}
}
if (string_list.length > 1) {
return (common_key ? common_key + ": " : "") +
"( " + string_list.join(" " + operator + " ") + " )";
}
return (common_key ? common_key + ": " : "") +
string_list[0];
}
throw new TypeError("This object is not a query"); throw new TypeError("This object is not a query");
} }
...@@ -868,8 +894,7 @@ ...@@ -868,8 +894,7 @@
* #crossLink "Query/toString:method" * #crossLink "Query/toString:method"
*/ */
SimpleQuery.prototype.toString = function () { SimpleQuery.prototype.toString = function () {
return (this.key ? this.key + ":" : "") + return objectToSearchText(this.toJSON());
(this.operator ? " " + this.operator : "") + ' "' + this.value + '"';
}; };
/** /**
......
...@@ -709,6 +709,8 @@ ...@@ -709,6 +709,8 @@
this.server.autoRespond = true; this.server.autoRespond = true;
this.server.autoRespondAfter = 5; this.server.autoRespondAfter = 5;
this.spy_ajax = sinon.spy(jIO.util, "ajax");
this.jio = jIO.createJIO({ this.jio = jIO.createJIO({
type: "dropbox", type: "dropbox",
access_token: token access_token: token
...@@ -717,6 +719,8 @@ ...@@ -717,6 +719,8 @@
teardown: function () { teardown: function () {
this.server.restore(); this.server.restore();
delete this.server; delete this.server;
this.spy_ajax.restore();
delete this.spy_ajax;
} }
}); });
...@@ -789,14 +793,15 @@ ...@@ -789,14 +793,15 @@
test("putAttachment document", function () { test("putAttachment document", function () {
var blob = new Blob(["foo"], {"type": "xapplication/foo"}), var blob = new Blob(["foo"], {"type": "xapplication/foo"}),
url_put_att = "https://content.dropboxapi.com/2/files/upload", url_put_att = "https://content.dropboxapi.com/2/files/upload",
server = this.server; server = this.server,
context = this;
this.server.respondWith("POST", url_put_att, [204, { this.server.respondWith("POST", url_put_att, [204, {
"Content-Type": "text/xml" "Content-Type": "text/xml"
}, ""]); }, ""]);
stop(); stop();
expect(7); expect(11);
this.jio.putAttachment( this.jio.putAttachment(
"/putAttachment1/", "/putAttachment1/",
...@@ -804,20 +809,26 @@ ...@@ -804,20 +809,26 @@
blob blob
) )
.then(function () { .then(function () {
ok(context.spy_ajax.calledOnce, "ajax count " +
context.spy_ajax.callCount);
equal(context.spy_ajax.firstCall.args[0].type, "POST");
equal(context.spy_ajax.firstCall.args[0].url, url_put_att);
deepEqual(context.spy_ajax.firstCall.args[0].xhrFields, undefined);
deepEqual(context.spy_ajax.firstCall.args[0].headers, {
"Authorization": "Bearer sample_token",
"Content-Type": "application/octet-stream",
"Dropbox-API-Arg": '{"path":"/putAttachment1/attachment1",' +
'"mode":"overwrite",' +
'"autorename":false,"mute":false}'
});
equal(context.spy_ajax.firstCall.args[0].data, blob);
equal(server.requests.length, 1); equal(server.requests.length, 1);
equal(server.requests[0].method, "POST"); equal(server.requests[0].method, "POST");
equal(server.requests[0].url, url_put_att); equal(server.requests[0].url, url_put_att);
equal(server.requests[0].status, 204); equal(server.requests[0].status, 204);
equal(server.requests[0].responseText, ""); equal(server.requests[0].responseText, "");
deepEqual(server.requests[0].requestHeaders, {
"Authorization": "Bearer sample_token",
"Content-Type": "application/octet-stream;charset=utf-8",
"Dropbox-API-Arg": '{"path":"/putAttachment1/attachment1",' +
'"mode":"overwrite",' +
'"autorename":false,"mute":false}'
});
equal(server.requests[0].requestBody, blob);
}) })
.fail(function (error) { .fail(function (error) {
ok(false, error); ok(false, error);
...@@ -992,8 +1003,12 @@ ...@@ -992,8 +1003,12 @@
type: "dropbox", type: "dropbox",
access_token: token access_token: token
}); });
this.spy_ajax = sinon.spy(jIO.util, "ajax");
}, },
teardown: function () { teardown: function () {
this.spy_ajax.restore();
delete this.spy_ajax;
this.server.restore(); this.server.restore();
delete this.server; delete this.server;
} }
...@@ -1064,7 +1079,7 @@ ...@@ -1064,7 +1079,7 @@
test("getAttachment document", function () { test("getAttachment document", function () {
var url = "https://content.dropboxapi.com/2/files/download", var url = "https://content.dropboxapi.com/2/files/download",
server = this.server; context = this;
this.server.respondWith("POST", url, [200, { this.server.respondWith("POST", url, [200, {
"Content-Type": "text/xplain" "Content-Type": "text/xplain"
}, "foo\nbaré"]); }, "foo\nbaré"]);
...@@ -1077,20 +1092,20 @@ ...@@ -1077,20 +1092,20 @@
"attachment1" "attachment1"
) )
.then(function (result) { .then(function (result) {
equal(server.requests.length, 1); equal(context.spy_ajax.callCount, 1);
equal(server.requests[0].method, "POST"); equal(context.spy_ajax.firstCall.args[0].type, "POST");
equal(server.requests[0].url, url); equal(context.spy_ajax.firstCall.args[0].url, url);
equal(server.requests[0].status, 200); equal(context.spy_ajax.firstCall.args[0].data, undefined);
equal(server.requests[0].requestBody, undefined); equal(context.spy_ajax.firstCall.args[0].dataType, 'blob');
equal(server.requests[0].responseText, "foo\nbaré"); deepEqual(context.spy_ajax.firstCall.args[0].xhrFields, undefined);
deepEqual(server.requests[0].requestHeaders, { deepEqual(context.spy_ajax.firstCall.args[0].headers, {
"Authorization": "Bearer sample_token", "Authorization": "Bearer sample_token",
"Content-Type": "text/plain;charset=utf-8",
"Dropbox-API-Arg": '{"path":"/getAttachment1/attachment1"}' "Dropbox-API-Arg": '{"path":"/getAttachment1/attachment1"}'
}); });
ok(result instanceof Blob, "Data is Blob"); ok(result instanceof Blob, "Data is Blob");
deepEqual(result.type, "text/xplain", "Check mimetype"); deepEqual(result.type, "text/xplain", "Check mimetype");
return jIO.util.readBlobAsText(result); return jIO.util.readBlobAsText(result);
}) })
.then(function (result) { .then(function (result) {
......
...@@ -427,6 +427,8 @@ ...@@ -427,6 +427,8 @@
this.server.autoRespond = true; this.server.autoRespond = true;
this.server.autoRespondAfter = 5; this.server.autoRespondAfter = 5;
this.spy_ajax = sinon.spy(jIO.util, "ajax");
this.jio = jIO.createJIO({ this.jio = jIO.createJIO({
type: "gdrive", type: "gdrive",
access_token: token access_token: token
...@@ -435,6 +437,8 @@ ...@@ -435,6 +437,8 @@
teardown: function () { teardown: function () {
this.server.restore(); this.server.restore();
delete this.server; delete this.server;
this.spy_ajax.restore();
delete this.spy_ajax;
} }
}); });
...@@ -464,13 +468,14 @@ ...@@ -464,13 +468,14 @@
var blob = new Blob(["foo"]), var blob = new Blob(["foo"]),
url_put_att = domain + "/upload/drive/v2/files/sampleId?" + url_put_att = domain + "/upload/drive/v2/files/sampleId?" +
"uploadType=media&access_token=" + token, "uploadType=media&access_token=" + token,
server = this.server; server = this.server,
context = this;
this.server.respondWith("PUT", url_put_att, [204, { this.server.respondWith("PUT", url_put_att, [204, {
"Content-Type": "text/xml" "Content-Type": "text/xml"
}, '{"mimeType": "text/xml"}']); }, '{"mimeType": "text/xml"}']);
stop(); stop();
expect(7); expect(11);
this.jio.putAttachment( this.jio.putAttachment(
"sampleId", "sampleId",
...@@ -478,16 +483,20 @@ ...@@ -478,16 +483,20 @@
blob blob
) )
.then(function () { .then(function () {
ok(context.spy_ajax.calledOnce, "ajax count " +
context.spy_ajax.callCount);
equal(context.spy_ajax.firstCall.args[0].type, "PUT");
equal(context.spy_ajax.firstCall.args[0].url, url_put_att);
deepEqual(context.spy_ajax.firstCall.args[0].xhrFields, undefined);
deepEqual(context.spy_ajax.firstCall.args[0].headers, undefined);
equal(context.spy_ajax.firstCall.args[0].data, blob);
equal(server.requests.length, 1); equal(server.requests.length, 1);
equal(server.requests[0].method, "PUT"); equal(server.requests[0].method, "PUT");
equal(server.requests[0].url, url_put_att); equal(server.requests[0].url, url_put_att);
equal(server.requests[0].status, 204); equal(server.requests[0].status, 204);
equal(server.requests[0].responseText, "{\"mimeType\": \"text/xml\"}"); equal(server.requests[0].responseText, "{\"mimeType\": \"text/xml\"}");
deepEqual(server.requests[0].requestHeaders, {
"Content-Type": "text/plain;charset=utf-8"
});
equal(server.requests[0].requestBody, blob);
}) })
.fail(function (error) { .fail(function (error) {
ok(false, error); ok(false, error);
......
...@@ -294,6 +294,55 @@ ...@@ -294,6 +294,55 @@
}); });
}); });
test("get all documents, include docs and unexpected metadata", function () {
var search_url = domain + "/linshare/webservice/rest/user/v2/documents/",
search_result = JSON.stringify([
{
uuid: 'uuid1',
name: 'foo1',
modificationDate: '2',
metaData: 'unexpectedfoo'
}
]),
server = this.server;
this.server.respondWith("GET", search_url, [200, {
"Content-Type": "application/json"
}, search_result]);
stop();
expect(7);
this.jio.allDocs({include_docs: true})
.then(function (result) {
deepEqual(result, {
data: {
rows: [{
_linshare_uuid: "uuid1",
id: "foo1",
value: {},
doc: {}
}],
total_rows: 1
}
}, "Check document");
equal(server.requests.length, 1);
equal(server.requests[0].method, "GET");
equal(server.requests[0].url, search_url);
equal(server.requests[0].requestBody, undefined);
equal(server.requests[0].withCredentials, true);
deepEqual(server.requests[0].requestHeaders, {
"Accept": "application/json"
});
})
.fail(function (error) {
ok(false, error);
})
.always(function () {
start();
});
});
test("get all documents and keep only one doc per name", function () { test("get all documents and keep only one doc per name", function () {
var search_url = domain + "/linshare/webservice/rest/user/v2/documents/", var search_url = domain + "/linshare/webservice/rest/user/v2/documents/",
search_result = JSON.stringify([ search_result = JSON.stringify([
......
/*
* Copyright 2019, Nexedi SA
*
* This program is free software: you can Use, Study, Modify and Redistribute
* it under the terms of the GNU General Public License version 3, or (at your
* option) any later version, as published by the Free Software Foundation.
*
* You can also Link and Combine this program with other software covered by
* the terms of any of the Free Software licenses or any of the Open Source
* Initiative approved licenses and Convey the resulting work. Corresponding
* source of such a combination shall include the source code for all other
* software used.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See COPYING file for full licensing terms.
* See https://www.nexedi.com/licensing for rationale and options.
*/
/*jslint nomen: true */
/*global Blob*/
(function (jIO, QUnit) {
"use strict";
var test = QUnit.test,
stop = QUnit.stop,
expect = QUnit.expect,
deepEqual = QUnit.deepEqual,
ok = QUnit.ok,
start = QUnit.start,
equal = QUnit.equal,
module = QUnit.module,
throws = QUnit.throws;
/////////////////////////////////////////////////////////////////
// Custom test substorage definition
/////////////////////////////////////////////////////////////////
function DummyStorage() {
return this;
}
jIO.addStorage('dummystorage', DummyStorage);
/////////////////////////////////////////////////////////////////
// NoCapacityStorage constructor
/////////////////////////////////////////////////////////////////
module("NoCapacityStorage.constructor");
test("create storage", function () {
var jio = jIO.createJIO({
type: "nocapacity",
sub_storage: {
type: "dummystorage"
}
});
equal(jio.__type, "nocapacity");
equal(jio.__storage._sub_storage.__type, "dummystorage");
});
/////////////////////////////////////////////////////////////////
// NoCapacityStorage.get
/////////////////////////////////////////////////////////////////
module("NoCapacityStorage.get");
test("get called substorage get", function () {
stop();
expect(2);
var jio = jIO.createJIO({
type: "nocapacity",
sub_storage: {
type: "dummystorage"
}
});
DummyStorage.prototype.get = function (id) {
equal(id, "1");
return {"name": "test_name"};
};
jio.get("1")
.then(function (result) {
deepEqual(result, {
"name": "test_name"
});
})
.fail(function (error) {
ok(false, error);
})
.always(function () {
start();
});
});
/////////////////////////////////////////////////////////////////
// NoCapacityStorage.allAttachments
/////////////////////////////////////////////////////////////////
module("NoCapacityStorage.allAttachments");
test("allAttachments called substorage allAttachments", function () {
stop();
expect(2);
var jio = jIO.createJIO({
type: "nocapacity",
sub_storage: {
type: "dummystorage"
}
});
DummyStorage.prototype.allAttachments = function (id) {
equal(id, "1");
return {attachmentname: {}};
};
jio.allAttachments("1")
.then(function (result) {
deepEqual(result, {
attachmentname: {}
});
})
.fail(function (error) {
ok(false, error);
})
.always(function () {
start();
});
});
/////////////////////////////////////////////////////////////////
// NoCapacityStorage.post
/////////////////////////////////////////////////////////////////
module("NoCapacityStorage.post");
test("post called substorage post", function () {
stop();
expect(2);
var jio = <