UNPKG

deep-compare-by

Version:

Deep compare with a function

195 lines (193 loc) 6.71 kB
const compare = require("./index"); const test = require("tape"); test("Basic compare", t => { t.plan(2); const cmp = compare(null); t.equal(cmp({ a: 1 }, { a: 1 }), true, "Equivalent"); t.equal(cmp({ a: 2 }, { a: 1 }), false, "Not equivalent"); }); test("Null tests", t => { t.plan(4); const cmp = compare(null); t.equal(cmp({ a: 1 }, { a: 1 }), true, "Equivalent null"); t.equal(cmp({ a: 2 }, { a: 1 }), false, "Not equivalent null"); const cmp2 = compare([]); t.equal(cmp2({ a: 1 }, { a: 1 }), true, "Equivalent array"); t.equal(cmp2({ a: 2 }, { a: 1 }), false, "Not equivalent array"); }); test("Empty curry return", t => { t.plan(2); const cmp = compare(); const cmp2 = cmp(null); t.equal(cmp2({ a: 1 }, { a: 1 }), true, "Equivalent"); t.equal(cmp2({ a: 2 }, { a: 1 }), false, "Not equivalent"); }); test("Invalid tests", t => { t.plan(1); const cmp = compare(7); t.throws(()=>{ cmp.tests(); },/Tests invalid/,"Throw invlid tests when evaluated"); }); test("Empty curry return", t => { t.plan(4); const cmp = compare(null,{a:1}); const cmp2 = compare(null,cmp.lhs()); t.equal(cmp({ a: 1 }), true, "Equivalent: 1"); t.equal(cmp({ a: 2 }), false, "Not equivalent: 1"); t.equal(cmp2({ a: 1 }), true, "Equivalent: 2"); t.equal(cmp2({ a: 2 }), false, "Not equivalent: 2"); }); test("No default compare", t => { t.plan(4); const cmp = compare.noDefault((a, b) => b === 3); t.equal(cmp({ a: 1 }, { a: 1 }), false, "Equivalent"); t.equal(cmp({ a: 1 }, { a: 3 }), true, "Pass custom"); const cmp2 = compare((a, b) => b === 3, { a: 1 }); t.equal(cmp2.noDefault({ a: 1 }), false, "Equivalent: later"); t.equal(cmp2.noDefault({ a: 3 }), true, "Pass custom: later"); }); test("Curried first value", t => { t.plan(4); const cmp = compare(null)({ a: 1 }); t.equal(cmp({ a: 1 }), true, "Equivalent"); t.equal(cmp({ a: 3 }), false, "Pass custom"); const cmp2 = compare(null, { a: 1 }); t.equal(cmp({ a: 1 }), true, "Equivalent"); t.equal(cmp({ a: 3 }), false, "Pass custom"); }); test("Non-object compare", t => { t.plan(2); const cmp = compare(null); t.equal(cmp(6, 6), true, "Equal number"); t.equal(cmp(7, 6), false, "Unequal number"); }); test("Empty", t => { t.plan(1); const cmp = compare(null); t.equal(cmp({}, {}), false, "Empty objects"); }); test("Object to not object", t => { t.plan(1); const cmp = compare(null); t.equal(cmp({ a: 1 }, 6), false, "Object and number"); }); test("Partial match", t => { t.plan(2); const cmp = compare(null); t.equal(cmp({ a: 1, b: 2 }, { a: 1 }), false, "Extra in arg1"); t.equal(cmp({ a: 1 }, { a: 1, b: 2 }), false, "Extra in arg2"); }); test("Same key count: different keys", t => { t.plan(2); const cmp = compare(null); t.equal(cmp({ a: 1, b: 2 }, { a: 1, b: 2 }), true, "Same keys: a b"); t.equal(cmp({ a: 1, b: 2 }, { a: 1, c: 2 }), false, "Different keys: a c"); }); test("With function", t => { t.plan(8); const cmp = compare(null); const cmpt = compare((a, b) => ( (typeof a === "function") && (typeof b === "function") && (a.toString() == b.toString()) )); t.equal(cmp({ a: 1, b: () => 2 }, { a: 1, b: () => 2 }), false, "Function not equal"); t.equal(cmpt({ a: 1, b: () => 2 }, { a: 1, b: () => 2 }), true, "Equal by string"); { const testFuncA = () => 2; const testFuncB = () => 2; testFuncA.foo = 3; testFuncA.foo = 2; t.equal(cmpt({ a: 1, b: testFuncA }, { a: 1, b: testFuncB }), true, "Test scope"); } { const cmpt2 = compare((a, b) => a.a === b.a); t.equal(cmpt2({ a: 1, b: 3 }, { a: 1, b: 2, c: 4 }), true, "Compare can pass for objects"); } t.equal(cmpt( () => 2, () => 2 ), true, "Direct functions"); t.equal(cmpt({ a: 1, b: () => 2, c: 3 }, { a: 1, b: () => 2 }), false, "Extra property"); t.equal(cmpt({ a: 1, b: () => 2 }, { a: 1, b: () => 2, c: 3 }), false, "Extra property: switch"); t.equal(cmpt({ a: 1, b: () => 2 }, { a: 1, b: () => 3 }), false, "Diffirent function source"); }); test("Make new compare", t => { t.plan(5); const cmp = compare(null); const cmp2 = compare(null); t.equal(cmp({ a: 1 }, { a: 1 }), true, "Old compare: same"); t.equal(cmp({ a: 2 }, { a: 1 }), false, "Old compare: different"); t.equal(cmp2({ a: 1 }, { a: 1 }), true, "New compare: same"); t.equal(cmp2({ a: 2 }, { a: 1 }), false, "New compare: different"); t.notEqual(cmp, cmp2, "Function are, indeed, different"); }); test("Failed on path", t => { t.plan(4); const cmp = compare(null); const newCmp = compare(null); t.equal(cmp.failPath({ a: { b: { c: 2 } }, d: 3, e: { f: 4 }, }, { a: { b: { c: 2 } }, d: 3, e: { f: 4 }, }), true, "Default fail path"); t.deepEqual(newCmp.failPath({ a: { b: { c: 2 } }, d: 3, e: { f: 4 }, }, { a: { b: { c: 3 } }, d: 3, e: { f: 4 }, }), ['a', 'b', 'c'], "Correct path 1"); t.deepEqual(newCmp.failPath({ a: { b: { c: 2 } }, d: 3, e: { f: 4 }, }, { a: { b: { c: 2 } }, d: 3, e: { f: 5 }, }), ['e', 'f'], "Correct path 2"); t.equal(newCmp.failPath({ a: { b: { c: 2 } }, d: 3, e: { f: 4 }, }, { a: { b: { c: 2 } }, d: 3, e: { f: 4 }, }), true, "Fail path reset on success"); }); test("With function: top level", t => { t.plan(2); const cmp = compare(null); const cmpt = compare((a, b) => (typeof a === typeof b)); t.equal(cmp(1, 2), false, "Default fails"); t.equal(cmpt(1, 2), true, "Modified passes"); }); test("Multiple tests", t => { t.plan(5); const cmp = compare(null); const cmpt = compare([(a, b) => (typeof a === typeof b), (a, b) => (a === 9)]); t.equal(cmp(1, 2), false, "Default 1"); t.equal(cmpt(1, 2), true, "Test 1"); t.equal(cmp(9, "8"), false, "Default 2"); t.equal(cmpt(8, "8"), false, "Fail 2"); t.equal(cmpt(9, "8"), true, "Pass 2"); }); test("Multiple tests: extended", t => { t.plan(5); const cmp = compare(null); const cmpt = compare((a, b) => (typeof a === typeof b)); const cmpt2 = compare(cmpt.tests() .concat([(a, b) => (a === 9)])); t.equal(cmp(1, 2), false, "Default 1"); t.equal(cmpt(1, 2), true, "Test 1"); t.equal(cmpt(9, "8"), false, "Middle version"); t.equal(cmpt2(8, "8"), false, "Fail 2"); t.equal(cmpt2(9, "8"), true, "Pass 2"); });