UNPKG

can-query-logic

Version:
410 lines (309 loc) 12.4 kB
var types = require("./and-or-not"); var QUnit = require("steal-qunit"); var set = require("../set"); var makeEnum = require("../types/make-enum"); var is = require("./comparisons"); QUnit.module("can-query-logic/and-or"); // There is a need for "subset" and "superset" // Might have "real numbers" // But want even and odds and integers // Can't "build up" to real with all those other combinations QUnit.test("AND intersection basics", function(assert) { var AndObject = types.KeysAnd; var isJustin = new AndObject({ name: "Justin" }); var is35 = new AndObject({ age: 35 }); var is35AndJustin = set.intersection(is35, isJustin); assert.deepEqual(is35AndJustin.values,{ name: "Justin", age: 35 },"35 and justin"); var isJustinAnd35 = set.intersection(isJustin, is35); assert.deepEqual(isJustinAnd35.values,{ name: "Justin", age: 35 },"justin and 34"); var is34 = new AndObject({ age: 34 }); is35 = new AndObject({ age: 35 }); var is34and35 = set.intersection(is35, is34); assert.equal(is34and35,set.EMPTY,"can't be 34 and 35"); }); QUnit.test("AND union basics", function(assert) { var AndObject = types.KeysAnd; var isJustin = new AndObject({ name: "Justin" }); var is35 = new AndObject({ age: 35 }); var is35OrJustin = set.union(is35, isJustin); assert.deepEqual(is35OrJustin,new types.ValuesOr([is35, isJustin]),"35 and justin"); }); QUnit.test("AND / OR / NOT union", function(assert) { var isJustin = new types.KeysAnd({name: "Justin"}), isNotJustin = new types.KeysAnd({name: new types.ValuesNot("Justin")}); assert.equal( set.union(isJustin,isNotJustin), set.UNIVERSAL, "{name: 'j'} U {name: NOT('j')}"); var everything = new types.KeysAnd({}); assert.equal( set.union(isJustin,everything), set.UNIVERSAL, "{name: 'j'} U {}"); var isJustinAnd21 = new types.KeysAnd({name: "Justin", age: 22}); assert.equal( set.union(isJustin,isJustinAnd21), isJustin, "super and subset"); assert.equal( set.union(isJustinAnd21,isJustinAnd21), isJustinAnd21, "union with itself"); }); QUnit.test("AND / OR / NOT difference", function(assert) { // CASE: prop in A not in B // `{name: "Justin"} \ {age: 35} -> {name: "justin", age: NOT(35)}` var is35 = new types.KeysAnd({age: 35}), isJustin = new types.KeysAnd({name: "Justin"}), isJustinAnd35 = new types.KeysAnd({name: "Justin", age: 35}), isJustinAndNot35 = new types.KeysAnd({ name: "Justin", age: new types.ValuesNot(35) }), result; result = set.difference(isJustin, is35); // CASE: overlaping sets assert.deepEqual(result, isJustinAndNot35, 'OVERLAP: {name: "Justin"} \\ {age: 35} -> {name: "justin", age: NOT(35)}'); // CASE: same set assert.deepEqual( set.difference(is35, is35), set.EMPTY, 'SAME SET: {age: 35} \\ {age: 35} -> EMPTY'); // CASE: subset assert.deepEqual( set.difference(isJustinAnd35, is35), set.EMPTY, 'SUPERSET: {age: 35, name: "Justin"} \\ {age: 35} -> EMPTY'); // CASE: superset assert.deepEqual( set.difference(isJustin, isJustinAnd35), isJustinAndNot35, '{name: "Justin"} \\ {age: 35, name: "Justin"} -> {name: "justin", age: NOT(35)}'); // CASE: DISJOINT - same prop different values // `{age: 35} \ {age: 32} -> {age: 35}` result = set.difference(is35, new types.KeysAnd({age: 32})); assert.deepEqual(result, new types.KeysAnd({age: 35}), 'DISJOINT: {age: 35} \\ {age: 32} -> {age: 35}'); // CASE: DISJOINT - completely disjoint - no intersection of values // `{age: 34, name: "Justin"} \ {age: 35} -> {age: 34, name: "Justin"}` result = set.difference(new types.KeysAnd({age: 34, name: "Justin"}), is35); assert.deepEqual(result, new types.KeysAnd({age: 34, name: "Justin"}), 'DISJOINT: {age: 34, name: "Justin"} \\ {age: 35} -> {age: 34, name: "Justin"}'); // CASE: DISJOINT - can't peform -> double NOT of props // {foo: "bar"} \ {name: "Justin", age: 35} -> {foo: "bar", NOT(And(name: "J", age: 35)) } // this kind of property based and can not be done. result = set.difference( new types.KeysAnd({foo: "bar"}), isJustinAnd35 ); assert.deepEqual(result,set.UNDEFINABLE, 'DISJOINT: {foo: "bar"} \\ {name: "Justin", age: 35} -> UNDEFINABLE'); // CASE: // {} \ {name: "Justin", age: 35} -> OR[ AND(name: NOT("Justin")), AND(age: NOT(35)) ] result = set.difference(set.UNIVERSAL, isJustinAnd35); var compare = new types.ValuesOr([ new types.KeysAnd({name: new types.ValuesNot("Justin")}), new types.KeysAnd({age: new types.ValuesNot(35)}) ]); assert.deepEqual(result,compare, 'UNIVESAL: {} \\ {name: "Justin", age: 35} -> OR[ AND(name: NOT("Justin")), AND(age: NOT(35)) ]'); // CASE: // {} \ {bar: IS_UNIVERSAL} result = set.difference(new types.KeysAnd({foo: 2}), new types.KeysAnd({foo: 2, bar : set.UNIVERSAL})); assert.deepEqual(result,set.EMPTY, 'UNIVESAL: {foo:2} \ {foo:2, bar: IS_UNIVERSAL} -> set.EMPTY'); // FUTURE CASES: // { color: ["r", "g"] }, { color: "r", status: a } -> OR( {c: g}, {c:r, NOT: a} ) // {color: [r, g]} \ {color: [r]} -> {color: [g]} // {color: [r, g], status: [a, c]} \ {color: [r], status: [a]} -> OR( {g X a}, {g X c}, {r X c} ) }); QUnit.test("AND / OR / NOT isSubset", function(assert) { var res; res = set.isSubset( new types.KeysAnd({ type: 'FOLDER' }), new types.KeysAnd({ type: 'FOLDER' }) ); assert.ok(res, 'equal sets'); res = set.isSubset( new types.KeysAnd({ type: 'FOLDER', parentId: 5 }), new types.KeysAnd({ type: 'FOLDER' })); assert.ok(res, 'sub set'); res = set.isSubset( new types.KeysAnd({ type: 'FOLDER' }), new types.KeysAnd({ type: 'FOLDER', parentId: 5 }) ); assert.notOk(res, 'wrong way'); res = set.isSubset( new types.KeysAnd({ type: 'FOLDER', parentId: 7 }), new types.KeysAnd({ type: 'FOLDER', parentId: 5 }) ); assert.ok(!res, 'different values'); }); QUnit.test("union AND with ENUM", function(assert) { function Color(){} var ColorSet = makeEnum(Color, ["red","green","blue"]); var qA = new types.KeysAnd({ type: 'FOLDER', status: new ColorSet("red") }), qB = new types.KeysAnd({ type: 'FOLDER', status: new ColorSet("green") }); var res = set.union(qA, qB); assert.deepEqual(res, new types.KeysAnd({ type: 'FOLDER', status: new ColorSet(["red","green"]) }), "able to do a union" ); }); QUnit.test("AND isMember", function(assert) { var folderAnd35 = new types.KeysAnd({ type: 'FOLDER', age: 35 }); assert.ok( folderAnd35.isMember({type: 'FOLDER', age: 35}) ); assert.ok( folderAnd35.isMember({type: 'FOLDER', age: 35, extra: "value"}) ); assert.notOk( folderAnd35.isMember({type: 'FOLDER', age: 36}) ); assert.notOk( folderAnd35.isMember({type: 'folder', age: 35}) ); assert.notOk( folderAnd35.isMember({type: 'FOLDER'}) ); assert.notOk( folderAnd35.isMember({age: 35}) ); var isJustinPostCollege = new types.KeysAnd({ name: {first: "Justin"}, age: 33 }); assert.ok( isJustinPostCollege.isMember({ name: {first: "Justin", last: "Meyer"}, age: 33 }), "is member"); }); QUnit.test("OR isMember", function(assert) { var isFolder = new types.KeysAnd({ type: 'FOLDER'}), is35 = new types.KeysAnd({ age: 35 }), isFolderOr35 = new types.ValuesOr([isFolder, is35]); assert.ok( isFolderOr35.isMember({type: 'FOLDER', age: 35}), "both" ); assert.notOk( isFolderOr35.isMember({}), "empty" ); assert.ok( isFolderOr35.isMember({type: 'FOLDER', age: 36}) ); assert.ok( isFolderOr35.isMember({type: 'folder', age: 35}) ); assert.notOk( isFolderOr35.isMember({type: 'folder', age: 36}) ); assert.ok( isFolderOr35.isMember({type: 'FOLDER'}) ); assert.ok( isFolderOr35.isMember({age: 35}) ); }); QUnit.test("And nested objects", function(assert) { var res; var isNameFirstJustin = new types.KeysAnd({ name: {first: "Justin"}}); var isNameFirstJustin2 = new types.KeysAnd({ name: {first: "Justin"}}); res = set.isEqual(isNameFirstJustin, isNameFirstJustin2); assert.equal(res, true); }); QUnit.module("can-query-logic/not"); // There is a need for "subset" and "superset" // Might have "real numbers" // But want even and odds and integers // Can't "build up" to real with all those other combinations QUnit.test("union basics", function(assert) { assert.equal( set.union( new types.ValuesNot(1), 1), set.UNIVERSAL, "is univesal set"); }); QUnit.test("difference with universal", function(assert) { // everything NOT 1, but not the universe assert.equal( set.difference( new types.ValuesNot(1), set.UNIVERSAL), set.EMPTY, "not 1 \\ univesal = 1"); assert.deepEqual( set.difference( set.UNIVERSAL, 1), new types.ValuesNot(1), "1 \\ univesal = not 1"); }); QUnit.test("And with nested.properties", function(assert) { assert.equal( set.isSubset( new types.KeysAnd({ "name.first": "Justin", "name.last": "Meyer" }), new types.KeysAnd({ "name.last": "Meyer" }) ), true, "dot.ed properties work with subset" ); assert.equal( new types.KeysAnd({ "name.first": "Justin", "name.last": "Meyer" }).isMember({name: {first: "Justin", last: "Meyer"}}), true, "dot.ed properties isMember match" ); assert.equal( new types.KeysAnd({ "name.first": "Justin", "name.last": "Meyer" }).isMember({name: {first: "Ramiya", last: "Meyer"}}), false, "dot.ed properties isMember dont match" ); }); QUnit.test("And with nested ands", function(assert) { assert.equal( set.isSubset( new types.KeysAnd({ name: new types.KeysAnd({ first: "Justin", last: "Meyer" }) }), new types.KeysAnd({ name: new types.KeysAnd({ last: "Meyer" }) }) ), true, "properties work with subset" ); assert.deepEqual( set.intersection( new types.KeysAnd({ name: new types.KeysAnd({ first: "Justin" }) }), new types.KeysAnd({ name: new types.KeysAnd({ last: "Meyer" }) }) ), new types.KeysAnd({ name: new types.KeysAnd({ first: "Justin", last: "Meyer" }) }), "properties work with intersection" ); assert.equal( new types.KeysAnd({ name: new types.KeysAnd({ first: "Justin", last: "Meyer" }) }).isMember({name: {first: "Justin", last: "Meyer"}}), true, "dot.ed properties isMember match" ); assert.equal( new types.KeysAnd({ name: new types.KeysAnd({ first: "Justin", last: "Meyer" }) }).isMember({name: {first: "Ramiya", last: "Meyer"}}), false, "dot.ed properties isMember dont match" ); }); QUnit.test("union with comparisons", function(assert) { var isGtJustinAndGt35 = new types.KeysAnd({ name: new is.GreaterThan("Justin"), age: new is.GreaterThan(35) }); var isGt25 = new types.KeysAnd({ age: new is.GreaterThan(25) }); var result = set.union(isGtJustinAndGt35, isGt25); assert.deepEqual(result, isGt25); // if filtering in fewer dimensions is a superset, use that var a = new types.KeysAnd({ name: new is.GreaterThan("Justin"), age: new is.GreaterThan(35), count: new is.GreaterThan(10) }); var b = new types.KeysAnd({ age: new is.GreaterThan(25), count: new is.GreaterThan(9) }); result = set.union(b, a); assert.deepEqual(result, b); });