Commit 60ff4878 authored by Tristan Cavelier's avatar Tristan Cavelier

JIOQuery behavior changed to match ERP5 query one

- Choice of wildcard removed
- Tests changed
- Serialization test added
parent cffdaeb3
...@@ -48,8 +48,12 @@ inherits(ComplexQuery, Query); ...@@ -48,8 +48,12 @@ inherits(ComplexQuery, Query);
/** /**
* #crossLink "Query/match:method" * #crossLink "Query/match:method"
*/ */
ComplexQuery.prototype.match = function (item, wildcard_character) { ComplexQuery.prototype.match = function (item) {
return this[this.operator](item, wildcard_character); var operator = this.operator;
if (!(/^(?:AND|OR|NOT)$/i.test(operator))) {
operator = "AND";
}
return this[operator.toUpperCase()](item);
}; };
/** /**
...@@ -79,6 +83,7 @@ ComplexQuery.prototype.serialized = function () { ...@@ -79,6 +83,7 @@ ComplexQuery.prototype.serialized = function () {
}); });
return s; return s;
}; };
ComplexQuery.prototype.toJSON = ComplexQuery.prototype.serialized;
/** /**
* Comparison operator, test if all sub queries match the * Comparison operator, test if all sub queries match the
...@@ -86,13 +91,12 @@ ComplexQuery.prototype.serialized = function () { ...@@ -86,13 +91,12 @@ ComplexQuery.prototype.serialized = function () {
* *
* @method AND * @method AND
* @param {Object} item The item to match * @param {Object} item The item to match
* @param {String} wildcard_character The wildcard character
* @return {Boolean} true if all match, false otherwise * @return {Boolean} true if all match, false otherwise
*/ */
ComplexQuery.prototype.AND = function (item, wildcard_character) { ComplexQuery.prototype.AND = function (item) {
var j, promises = []; var j, promises = [];
for (j = 0; j < this.query_list.length; j += 1) { for (j = 0; j < this.query_list.length; j += 1) {
promises.push(this.query_list[j].match(item, wildcard_character)); promises.push(this.query_list[j].match(item));
} }
function cancel() { function cancel() {
...@@ -133,13 +137,12 @@ ComplexQuery.prototype.AND = function (item, wildcard_character) { ...@@ -133,13 +137,12 @@ ComplexQuery.prototype.AND = function (item, wildcard_character) {
* *
* @method OR * @method OR
* @param {Object} item The item to match * @param {Object} item The item to match
* @param {String} wildcard_character The wildcard character
* @return {Boolean} true if one match, false otherwise * @return {Boolean} true if one match, false otherwise
*/ */
ComplexQuery.prototype.OR = function (item, wildcard_character) { ComplexQuery.prototype.OR = function (item) {
var j, promises = []; var j, promises = [];
for (j = 0; j < this.query_list.length; j += 1) { for (j = 0; j < this.query_list.length; j += 1) {
promises.push(this.query_list[j].match(item, wildcard_character)); promises.push(this.query_list[j].match(item));
} }
function cancel() { function cancel() {
...@@ -180,12 +183,11 @@ ComplexQuery.prototype.OR = function (item, wildcard_character) { ...@@ -180,12 +183,11 @@ ComplexQuery.prototype.OR = function (item, wildcard_character) {
* *
* @method NOT * @method NOT
* @param {Object} item The item to match * @param {Object} item The item to match
* @param {String} wildcard_character The wildcard character
* @return {Boolean} true if one match, false otherwise * @return {Boolean} true if one match, false otherwise
*/ */
ComplexQuery.prototype.NOT = function (item, wildcard_character) { ComplexQuery.prototype.NOT = function (item) {
return sequence([function () { return sequence([function () {
return this.query_list[0].match(item, wildcard_character); return this.query_list[0].match(item);
}, function (answer) { }, function (answer) {
return !answer; return !answer;
}]); }]);
......
...@@ -62,7 +62,11 @@ var arrayExtend = function () { ...@@ -62,7 +62,11 @@ var arrayExtend = function () {
return newlist; return newlist;
}, mkSimpleQuery = function (key, value, operator) { }, mkSimpleQuery = function (key, value, operator) {
return {"type": "simple", "operator": "=", "key": key, "value": value}; var object = {"type": "simple", "key": key, "value": value};
if (operator !== undefined) {
object.operator = operator;
}
return object;
}, mkNotQuery = function (query) { }, mkNotQuery = function (query) {
if (query.operator === "NOT") { if (query.operator === "NOT") {
......
...@@ -56,7 +56,6 @@ function Query() { ...@@ -56,7 +56,6 @@ function Query() {
* @method exec * @method exec
* @param {Array} item_list The list of object * @param {Array} item_list The list of object
* @param {Object} [option] Some operation option * @param {Object} [option] Some operation option
* @param {String} [option.wildcard_character="%"] The wildcard character
* @param {Array} [option.select_list] A object keys to retrieve * @param {Array} [option.select_list] A object keys to retrieve
* @param {Array} [option.sort_on] Couples of object keys and "ascending" * @param {Array} [option.sort_on] Couples of object keys and "ascending"
* or "descending" * or "descending"
...@@ -75,14 +74,11 @@ Query.prototype.exec = function (item_list, option) { ...@@ -75,14 +74,11 @@ Query.prototype.exec = function (item_list, option) {
throw new TypeError("Query().exec(): " + throw new TypeError("Query().exec(): " +
"Optional argument 2 is not of type 'object'"); "Optional argument 2 is not of type 'object'");
} }
if (option.wildcard_character === undefined) {
option.wildcard_character = '%';
}
for (i = 0; i < item_list.length; i += 1) { for (i = 0; i < item_list.length; i += 1) {
if (!item_list[i]) { if (!item_list[i]) {
promises.push(RSVP.resolve(false)); promises.push(RSVP.resolve(false));
} else { } else {
promises.push(this.match(item_list[i], option.wildcard_character)); promises.push(this.match(item_list[i]));
} }
} }
return sequence([function () { return sequence([function () {
...@@ -113,7 +109,6 @@ Query.prototype.exec = function (item_list, option) { ...@@ -113,7 +109,6 @@ Query.prototype.exec = function (item_list, option) {
* *
* @method match * @method match
* @param {Object} item The object to test * @param {Object} item The object to test
* @param {String} wildcard_character The wildcard character to use
* @return {Boolean} true if match, false otherwise * @return {Boolean} true if match, false otherwise
*/ */
Query.prototype.match = function () { Query.prototype.match = function () {
......
/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */ /*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */
/*global _export: true, to_export: true */ /*global _export: true */
function objectToSearchText(query) { function objectToSearchText(query) {
var str_list = []; var str_list = [];
...@@ -15,7 +15,7 @@ function objectToSearchText(query) { ...@@ -15,7 +15,7 @@ function objectToSearchText(query) {
} }
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 + '"';
} }
throw new TypeError("This object is not a query"); throw new TypeError("This object is not a query");
} }
......
/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */ /*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */
/*global Query: true, inherits: true, query_class_dict: true, _export: true, /*global Query: true, inherits: true, query_class_dict: true, _export: true,
convertStringToRegExp, RSVP */ searchTextToRegExp, RSVP */
var checkKeySchema = function (key_schema) { var checkKeySchema = function (key_schema) {
var prop; var prop;
...@@ -54,10 +54,9 @@ function SimpleQuery(spec, key_schema) { ...@@ -54,10 +54,9 @@ function SimpleQuery(spec, key_schema) {
* *
* @attribute operator * @attribute operator
* @type String * @type String
* @default "="
* @optional * @optional
*/ */
this.operator = spec.operator || "="; this.operator = spec.operator;
/** /**
* Key of the object which refers to the value to compare * Key of the object which refers to the value to compare
...@@ -105,15 +104,28 @@ var checkKey = function (key) { ...@@ -105,15 +104,28 @@ var checkKey = function (key) {
/** /**
* #crossLink "Query/match:method" * #crossLink "Query/match:method"
*/ */
SimpleQuery.prototype.match = function (item, wildcard_character) { SimpleQuery.prototype.match = function (item) {
var object_value = null, var object_value = null,
equal_match = null, equal_match = null,
cast_to = null, cast_to = null,
matchMethod = null, matchMethod = null,
operator = this.operator,
value = null, value = null,
key = this.key; key = this.key;
matchMethod = this[this.operator]; /*jslint regexp: true */
if (!(/^(?:!?=|<=?|>=?)$/i.test(operator))) {
// `operator` is not correct, we have to change it to "like" or "="
if (/%/.test(this.value)) {
// `value` contains a non escaped `%`
operator = "like";
} else {
// `value` does not contain non escaped `%`
operator = "=";
}
}
matchMethod = this[operator];
if (this._key_schema.key_set && this._key_schema.key_set[key] !== undefined) { if (this._key_schema.key_set && this._key_schema.key_set[key] !== undefined) {
key = this._key_schema.key_set[key]; key = this._key_schema.key_set[key];
...@@ -133,7 +145,8 @@ SimpleQuery.prototype.match = function (item, wildcard_character) { ...@@ -133,7 +145,8 @@ SimpleQuery.prototype.match = function (item, wildcard_character) {
// equal_match overrides the default '=' operator // equal_match overrides the default '=' operator
if (equal_match !== undefined) { if (equal_match !== undefined) {
matchMethod = (this.operator === '=') ? equal_match : matchMethod; matchMethod = (operator === "=" || operator === "like" ?
equal_match : matchMethod);
} }
value = this.value; value = this.value;
...@@ -155,28 +168,32 @@ SimpleQuery.prototype.match = function (item, wildcard_character) { ...@@ -155,28 +168,32 @@ SimpleQuery.prototype.match = function (item, wildcard_character) {
if (object_value === undefined || value === undefined) { if (object_value === undefined || value === undefined) {
return RSVP.resolve(false); return RSVP.resolve(false);
} }
return matchMethod(object_value, value, wildcard_character); return matchMethod(object_value, value);
}; };
/** /**
* #crossLink "Query/toString:method" * #crossLink "Query/toString:method"
*/ */
SimpleQuery.prototype.toString = function () { SimpleQuery.prototype.toString = function () {
return (this.key ? this.key + ": " : "") + (this.operator || "=") + ' "' + return (this.key ? this.key + ":" : "") +
this.value + '"'; (this.operator ? " " + this.operator : "") + ' "' + this.value + '"';
}; };
/** /**
* #crossLink "Query/serialized:method" * #crossLink "Query/serialized:method"
*/ */
SimpleQuery.prototype.serialized = function () { SimpleQuery.prototype.serialized = function () {
return { var object = {
"type": "simple", "type": "simple",
"operator": this.operator,
"key": this.key, "key": this.key,
"value": this.value "value": this.value
}; };
if (this.operator !== undefined) {
object.operator = this.operator;
}
return object;
}; };
SimpleQuery.prototype.toJSON = SimpleQuery.prototype.serialized;
/** /**
* Comparison operator, test if this query value matches the item value * Comparison operator, test if this query value matches the item value
...@@ -184,11 +201,40 @@ SimpleQuery.prototype.serialized = function () { ...@@ -184,11 +201,40 @@ SimpleQuery.prototype.serialized = function () {
* @method = * @method =
* @param {String} object_value The value to compare * @param {String} object_value The value to compare
* @param {String} comparison_value The comparison value * @param {String} comparison_value The comparison value
* @param {String} wildcard_character The wildcard_character
* @return {Boolean} true if match, false otherwise * @return {Boolean} true if match, false otherwise
*/ */
SimpleQuery.prototype["="] = function (object_value, comparison_value, SimpleQuery.prototype["="] = function (object_value, comparison_value) {
wildcard_character) { var value, i;
if (!Array.isArray(object_value)) {
object_value = [object_value];
}
for (i = 0; i < object_value.length; i += 1) {
value = object_value[i];
if (typeof value === 'object' && value.hasOwnProperty('content')) {
value = value.content;
}
if (typeof value.cmp === "function") {
return RSVP.resolve(value.cmp(comparison_value) === 0);
}
if (
searchTextToRegExp(comparison_value.toString(), false).
test(value.toString())
) {
return RSVP.resolve(true);
}
}
return RSVP.resolve(false);
};
/**
* Comparison operator, test if this query value matches the item value
*
* @method like
* @param {String} object_value The value to compare
* @param {String} comparison_value The comparison value
* @return {Boolean} true if match, false otherwise
*/
SimpleQuery.prototype.like = function (object_value, comparison_value) {
var value, i; var value, i;
if (!Array.isArray(object_value)) { if (!Array.isArray(object_value)) {
object_value = [object_value]; object_value = [object_value];
...@@ -198,15 +244,11 @@ SimpleQuery.prototype["="] = function (object_value, comparison_value, ...@@ -198,15 +244,11 @@ SimpleQuery.prototype["="] = function (object_value, comparison_value,
if (typeof value === 'object' && value.hasOwnProperty('content')) { if (typeof value === 'object' && value.hasOwnProperty('content')) {
value = value.content; value = value.content;
} }
if (value.cmp !== undefined) { if (typeof value.cmp === "function") {
return RSVP.resolve(value.cmp(comparison_value, return RSVP.resolve(value.cmp(comparison_value) === 0);
wildcard_character) === 0);
} }
if ( if (
convertStringToRegExp( searchTextToRegExp(comparison_value.toString()).test(value.toString())
comparison_value.toString(),
wildcard_character
).test(value.toString())
) { ) {
return RSVP.resolve(true); return RSVP.resolve(true);
} }
...@@ -220,11 +262,9 @@ SimpleQuery.prototype["="] = function (object_value, comparison_value, ...@@ -220,11 +262,9 @@ SimpleQuery.prototype["="] = function (object_value, comparison_value,
* @method != * @method !=
* @param {String} object_value The value to compare * @param {String} object_value The value to compare
* @param {String} comparison_value The comparison value * @param {String} comparison_value The comparison value
* @param {String} wildcard_character The wildcard_character
* @return {Boolean} true if not match, false otherwise * @return {Boolean} true if not match, false otherwise
*/ */
SimpleQuery.prototype["!="] = function (object_value, comparison_value, SimpleQuery.prototype["!="] = function (object_value, comparison_value) {
wildcard_character) {
var value, i; var value, i;
if (!Array.isArray(object_value)) { if (!Array.isArray(object_value)) {
object_value = [object_value]; object_value = [object_value];
...@@ -234,15 +274,12 @@ SimpleQuery.prototype["!="] = function (object_value, comparison_value, ...@@ -234,15 +274,12 @@ SimpleQuery.prototype["!="] = function (object_value, comparison_value,
if (typeof value === 'object' && value.hasOwnProperty('content')) { if (typeof value === 'object' && value.hasOwnProperty('content')) {
value = value.content; value = value.content;
} }
if (value.cmp !== undefined) { if (typeof value.cmp === "function") {
return RSVP.resolve(value.cmp(comparison_value, return RSVP.resolve(value.cmp(comparison_value) !== 0);
wildcard_character) !== 0);
} }
if ( if (
convertStringToRegExp( searchTextToRegExp(comparison_value.toString(), false).
comparison_value.toString(), test(value.toString())
wildcard_character
).test(value.toString())
) { ) {
return RSVP.resolve(false); return RSVP.resolve(false);
} }
...@@ -267,7 +304,7 @@ SimpleQuery.prototype["<"] = function (object_value, comparison_value) { ...@@ -267,7 +304,7 @@ SimpleQuery.prototype["<"] = function (object_value, comparison_value) {
if (typeof value === 'object' && value.hasOwnProperty('content')) { if (typeof value === 'object' && value.hasOwnProperty('content')) {
value = value.content; value = value.content;
} }
if (value.cmp !== undefined) { if (typeof value.cmp === "function") {
return RSVP.resolve(value.cmp(comparison_value) < 0); return RSVP.resolve(value.cmp(comparison_value) < 0);
} }
return RSVP.resolve(value < comparison_value); return RSVP.resolve(value < comparison_value);
...@@ -291,7 +328,7 @@ SimpleQuery.prototype["<="] = function (object_value, comparison_value) { ...@@ -291,7 +328,7 @@ SimpleQuery.prototype["<="] = function (object_value, comparison_value) {
if (typeof value === 'object' && value.hasOwnProperty('content')) { if (typeof value === 'object' && value.hasOwnProperty('content')) {
value = value.content; value = value.content;
} }
if (value.cmp !== undefined) { if (typeof value.cmp === "function") {
return RSVP.resolve(value.cmp(comparison_value) <= 0); return RSVP.resolve(value.cmp(comparison_value) <= 0);
} }
return RSVP.resolve(value <= comparison_value); return RSVP.resolve(value <= comparison_value);
...@@ -315,7 +352,7 @@ SimpleQuery.prototype[">"] = function (object_value, comparison_value) { ...@@ -315,7 +352,7 @@ SimpleQuery.prototype[">"] = function (object_value, comparison_value) {
if (typeof value === 'object' && value.hasOwnProperty('content')) { if (typeof value === 'object' && value.hasOwnProperty('content')) {
value = value.content; value = value.content;
} }
if (value.cmp !== undefined) { if (typeof value.cmp === "function") {
return RSVP.resolve(value.cmp(comparison_value) > 0); return RSVP.resolve(value.cmp(comparison_value) > 0);
} }
return RSVP.resolve(value > comparison_value); return RSVP.resolve(value > comparison_value);
...@@ -339,7 +376,7 @@ SimpleQuery.prototype[">="] = function (object_value, comparison_value) { ...@@ -339,7 +376,7 @@ SimpleQuery.prototype[">="] = function (object_value, comparison_value) {
if (typeof value === 'object' && value.hasOwnProperty('content')) { if (typeof value === 'object' && value.hasOwnProperty('content')) {
value = value.content; value = value.content;
} }
if (value.cmp !== undefined) { if (typeof value.cmp === "function") {
return RSVP.resolve(value.cmp(comparison_value) >= 0); return RSVP.resolve(value.cmp(comparison_value) >= 0);
} }
return RSVP.resolve(value >= comparison_value); return RSVP.resolve(value >= comparison_value);
......
...@@ -264,29 +264,27 @@ _export('limit', limit); ...@@ -264,29 +264,27 @@ _export('limit', limit);
* Convert a search text to a regexp. * Convert a search text to a regexp.
* *
* @param {String} string The string to convert * @param {String} string The string to convert
* @param {String} [wildcard_character=undefined] The wildcard chararter * @param {Boolean} [use_wildcard_character=true] Use wildcard "%" and "_"
* @return {RegExp} The search text regexp * @return {RegExp} The search text regexp
*/ */
function convertStringToRegExp(string, wildcard_character) { function searchTextToRegExp(string, use_wildcard_characters) {
if (typeof string !== 'string') { if (typeof string !== 'string') {
throw new TypeError("complex_queries.convertStringToRegExp(): " + throw new TypeError("complex_queries.searchTextToRegExp(): " +
"Argument 1 is not of type 'string'"); "Argument 1 is not of type 'string'");
} }
if (wildcard_character === undefined || if (use_wildcard_characters === false) {
wildcard_character === null || wildcard_character === '') {
return new RegExp("^" + stringEscapeRegexpCharacters(string) + "$"); return new RegExp("^" + stringEscapeRegexpCharacters(string) + "$");
} }
if (typeof wildcard_character !== 'string' || wildcard_character.length > 1) {
throw new TypeError("complex_queries.convertStringToRegExp(): " +
"Optional argument 2 must be a string of length <= 1");
}
return new RegExp("^" + stringEscapeRegexpCharacters(string).replace( return new RegExp("^" + stringEscapeRegexpCharacters(string).replace(
new RegExp(stringEscapeRegexpCharacters(wildcard_character), 'g'), /%/g,
'.*' ".*"
).replace(
/_/g,
"."
) + "$"); ) + "$");
} }
_export('convertStringToRegExp', convertStringToRegExp); _export("searchTextToRegExp", searchTextToRegExp);
/** /**
* sequence(thens): Promise * sequence(thens): Promise
......
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
}; };
test('Simple Key with read_from', function () { test('Simple Key with read_from', function () {
/*jslint unparam: true*/
var docList = function () { var docList = function () {
return [ return [
{'identifier': 'a'}, {'identifier': 'a'},
...@@ -35,12 +34,11 @@ ...@@ -35,12 +34,11 @@
}, },
case_insensitive_identifier: { case_insensitive_identifier: {
read_from: 'identifier', read_from: 'identifier',
equal_match: function (object_value, value, wildcard_character) { equal_match: function (object_value, value) {
return (object_value.toLowerCase() === value.toLowerCase()); return (object_value.toLowerCase() === value.toLowerCase());
} }
} }
}, promise = []; }, promise = [];
/*jslint unparam: false*/
stop(); stop();
......
...@@ -105,44 +105,66 @@ ...@@ -105,44 +105,66 @@
var doc_list = [ var doc_list = [
{"identifier": "a"}, {"identifier": "a"},
{"identifier": "a%"}, {"identifier": "a%"},
{"identifier": "a\\%"},
{"identifier": ["ab", "b"]} {"identifier": ["ab", "b"]}
]; ];
stop(); stop();
complex_queries.QueryFactory.create('identifier: "a%"').exec(doc_list, { complex_queries.QueryFactory.create('identifier: "a%"').exec(
// "wildcard_character": "%" // default doc_list
}).then(function (doc_list) { ).then(function (doc_list) {
deepEqual(doc_list, [ deepEqual(doc_list, [
{"identifier": "a"}, {"identifier": "a"},
{"identifier": "a%"}, {"identifier": "a%"},
{"identifier": "a\\%"},
{"identifier": ["ab", "b"]} {"identifier": ["ab", "b"]}
], 'All documents should be kept'); ], 'All documents should be kept');
doc_list = [ doc_list = [
{"identifier": "a"}, {"identifier": "a"},
{"identifier": "a%"}, {"identifier": "a%"},
{"identifier": "a\\%"},
{"identifier": ["ab", "b"]} {"identifier": ["ab", "b"]}
]; ];
return complex_queries.QueryFactory.create('identifier: "a%"'). return complex_queries.QueryFactory.create('identifier: "a\\%"').
exec(doc_list, {"wildcard_character": null}); exec(doc_list);
}).then(function (doc_list) { }).then(function (doc_list) {
deepEqual(doc_list, [ deepEqual(doc_list, [
{"identifier": "a%"} {"identifier": "a\\%"}
], 'Document "a%" should be kept'); ], 'Only third document should be kept');
// yes.. it's weird but ERP5 acts like that.
// `\` (or "\\") is taken literaly (= /\\/)
doc_list = [ doc_list = [
{"identifier": "a"}, {"identifier": "a"},
{"identifier": "a%"}, {"identifier": "a%"},
{"identifier": "a\\%"},
{"identifier": ["ab", "b"]} {"identifier": ["ab", "b"]}
]; ];
return complex_queries.QueryFactory.create('identifier: "b"').
exec(doc_list, {"wildcard_character": "b"}); return complex_queries.QueryFactory.create('identifier: "__"').
exec(doc_list);
}).then(function (doc_list) { }).then(function (doc_list) {
deepEqual(doc_list, [ deepEqual(doc_list, [
], 'Should keep nothing');
doc_list = [
{"identifier": "a"}, {"identifier": "a"},
{"identifier": "a%"}, {"identifier": "a%"},
{"identifier": "a\\%"},
{"identifier": ["ab", "b"]} {"identifier": ["ab", "b"]}
], 'All documents should be kept'); ];
return complex_queries.QueryFactory.create('identifier: "__%"').
exec(doc_list);
}).then(function (doc_list) {
deepEqual(doc_list, [
{"identifier": "a%"},
{"identifier": "a\\%"},
{"identifier": ["ab", "b"]}
], 'First should not be kept');
// yes.. it's weird but ERP5 acts like that.
// `_` is not considered as wildcard (= /./)
}).always(start); }).always(start);
}); });
...@@ -164,4 +186,46 @@ ...@@ -164,4 +186,46 @@
}).always(start); }).always(start);
}); });
test("JSON query", function () {
var jsoned = complex_queries.QueryFactory.create(
"NOT(a:=b OR c:% AND d:<2)"
).toJSON();
deepEqual(
jsoned,
{
"type": "complex",
"operator": "NOT",
"query_list": [{
"type": "complex",
"operator": "OR",
"query_list": [{
"key": "a",
"operator": "=",
"type": "simple",
"value": "b"
}, {
"type": "complex",
"operator": "AND",
"query_list": [{
"key": "c",
"type": "simple",
"value": "%"
}, {
"key": "d",
"operator": "<",
"type": "simple",
"value": "2"
}]
}]
}]
},
"\"NOT(a:=b OR c:% AND d:<2)\".toJSON()"
);
deepEqual(
complex_queries.parseStringToObject("NOT(a:=b OR c:% AND d:<2)"),
jsoned,
"parseStringToObject(\"NOT(a:=b OR c:% AND d:<2)\");"
);
});
})); }));
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment