UNPKG

data-matching

Version:

Matches a data object against a reference value

1,045 lines (900 loc) 21.9 kB
const dm = require("../src/index"); const MatchingError = dm.MatchingError; const THROW_MATCHING_ERROR = true; const catch_ME = (f) => { try { f(); } catch (e) { if ((!e) instanceof MatchingError) { throw "should have thrown MatchingError"; } return e; } throw "Shold have thrown a MatchingError"; }; test("check null", () => { var expected = { a: null, b: 2, }; var received = { a: null, b: 2, }; var dict = {}; var res = dm.full_match(expected)( received, dict, !THROW_MATCHING_ERROR, "root", ); expect(res).toEqual("object matched"); }); test("check non_zero", () => { var expected = { a: 1, b: dm.non_zero, }; var received = { a: 1, b: 2, }; var dict = {}; var res; res = dm.full_match(expected)( received, dict, !THROW_MATCHING_ERROR, "root", ); expect(res).toEqual("object matched"); received.b = 0; res = dm.full_match(expected)( received, dict, !THROW_MATCHING_ERROR, "root", ); expect(res).toEqual(false); }); test("check non_blank_str", () => { var expected = { a: "aaa", b: dm.non_blank_str, }; var received = { a: "aaa", b: "bbb", }; var dict = {}; var res; res = dm.full_match(expected)( received, dict, !THROW_MATCHING_ERROR, "root", ); expect(res).toEqual("object matched"); received.b = ""; res = dm.full_match(expected)( received, dict, !THROW_MATCHING_ERROR, "root", ); expect(res).toEqual(false); }); test("partial_match: arrays matched", () => { var expected = [1, 2, 3, 4, [5, 6, 7]]; var received = [1, 2, 3, 4, [5, 6, 7]]; var dict = {}; var res = dm.partial_match(expected)(received, dict); expect(res).toEqual("array matched"); }); test("partial_match: arrays matched (irrelevant elements declared with dm._ (anything))", () => { var expected = [dm._, 2, dm._, 4, [5, dm._, 7]]; var received = [1, 2, 3, 4, [5, 6, 7]]; var dict = {}; var res = dm.partial_match(expected)(received, dict); expect(res).toEqual("array matched"); }); test("partial_match: arrays differ in length", () => { var expected = [1, 2, 3, 4, [5, 6, 7]]; var received = [1, 2, 3, 4, [5, 6, 7, 8]]; var dict = {}; var res = dm.partial_match(expected)(received, dict); expect(res).toEqual(false); }); test("full_match: arrays differ in length", () => { var expected = [1, 2, 3, 4, [5, 6, 7]]; var received = [1, 2, 3, 4, [5, 6, 7, 8]]; var dict = {}; var res = dm.full_match(expected)( received, dict, !THROW_MATCHING_ERROR, "root", ); expect(res).toEqual(false); }); test("full_match: arrays differ in length (throw matching error)", () => { var expected = [1, 2, 3, 4, [5, 6, 7]]; var received = [1, 2, 3, 4, [5, 6, 7, 8]]; var dict = {}; err = catch_ME(() => dm.full_match(expected)(received, dict, THROW_MATCHING_ERROR, "root"), ); expect(err.reason).toEqual( "arrays lengths do not match: expected_len=3 received_len=4", ); expect(err.path).toEqual("root[4]"); }); test("full_match", () => { var expected = { connection: { ip: "192.168.88.74" }, media: [ { type: "application", port: 9, protocol: "TCP/MRCPv2", payloads: ["0"], setup: "active", connection: dm._, resource: "speechsynth", }, { type: "audio", port: 14238, protocol: "RTP/AVP", payloads: ["0", "8", "96"], }, ], }; var received = { media: [ { type: "application", port: 9, protocol: "TCP/MRCPv2", payloads: ["0"], setup: "active", connection: "new", resource: "speechsynth", }, { type: "audio", port: 14238, protocol: "RTP/AVP", payloads: ["0", "8", "96"], }, ], connection: { ip: "192.168.88.74" }, }; var dict = {}; var res = dm.full_match(expected)( received, dict, !THROW_MATCHING_ERROR, "root", ); expect(res).toEqual("object matched"); }); test("partial_match: no array match", () => { var expected = [1, 2, 3, 4, [5, 6, 7]]; var received = [1, 2, 3, 4, [5, 6, 77]]; var dict = {}; var res = dm.partial_match(expected)( received, dict, !THROW_MATCHING_ERROR, "root", ); expect(res).toEqual(false); }); test("partial_match: no array match (throw matching error)", () => { var expected = [1, 2, 3, 4, [5, 6, 7]]; var received = [1, 2, 3, 4, [5, 6, 77]]; var dict = {}; err = catch_ME(() => dm.full_match(expected)(received, dict, THROW_MATCHING_ERROR, "root"), ); expect(err.reason).toEqual("expected='7' received='77'"); expect(err.path).toEqual("root[4][2]"); }); test("partial_match: dicts matched", () => { var expected = { a: 1, b: 2, c: ["zero", 1, true, dm._], d: 'sip:!{user}@!{domain}', }; var received = { a: 1, b: 2, c: ["zero", 1, true, 4], d: 'sip:bob@biloxi.com', e: "something extra", }; var dict = {}; var res = dm.partial_match(expected)( received, dict, THROW_MATCHING_ERROR, "root", ); expect(res).toEqual("object matched"); expect(dict.user).toEqual('bob'); expect(dict.domain).toEqual('biloxi.com'); }); test("partial_match: absent", () => { var expected = { a: dm.absent, b: { AA: 1, BB: 2, }, c: [ "zero", 1, true, (x) => { return x == "three"; }, ], }; var received = { b: 2, b: { AA: 1, BB: 2, }, c: ["zero", 1, true, "three"], }; var dict = {}; var res = dm.partial_match(expected)(received, dict); expect(res).toEqual("object matched"); }); test("partial_match: not absent", () => { var expected = { a: dm.absent, b: 2, c: 3, }; var received = { a: 1, b: 2, c: 3, }; var dict = {}; var res = dm.partial_match(expected)( received, dict, !THROW_MATCHING_ERROR, "root", ); expect(res).toEqual(false); }); test("partial_match: not absent (throw matching error)", () => { var expected = { a: dm.absent, b: 2, c: 3, }; var received = { a: 1, b: 2, c: 3, }; var dict = {}; err = catch_ME(() => dm.full_match(expected)(received, dict, THROW_MATCHING_ERROR, "root"), ); expect(err.reason).toEqual("should be absent"); expect(err.path).toEqual("root.a"); }); test("str_equal", () => { var expected = { a: dm.str_equal(1), b: dm.str_equal("2"), c: dm.str_equal("3"), }; var received = { a: 1, b: 2, c: "3", }; var dict = {}; var res = dm.partial_match(expected)( received, dict, THROW_MATCHING_ERROR, "root", ); expect(res).toEqual("object matched"); }); test("any_of: first matcher", () => { var matcher = dm.any_of([ dm.full_match({ a: 1, b: 2, c: dm.collect("c"), }), dm.partial_match({ aa: 10, bb: 20, cc: dm.collect("cc"), }), ]); var dict = {}; expect( matcher( { a: 1, b: 2, c: 3, }, dict, THROW_MATCHING_ERROR, "root", ), ).toBeTruthy(); expect(dict.c).toBe(3); }); test("any_of: second matcher", () => { var matcher = dm.any_of([ dm.full_match({ a: 1, b: 2, c: dm.collect("c"), }), dm.partial_match({ aa: 10, bb: 20, cc: dm.collect("cc"), }), ]); var dict = {}; expect( matcher( { aa: 10, bb: 20, cc: 30, }, dict, THROW_MATCHING_ERROR, "root", ), ).toBeTruthy(); expect(dict.cc).toBe(30); }); test("any_of: collect matches", () => { var matcher = dm.full_match({ type: dm.collect("type"), connection: dm.any_of(["new", "existing"], "connection"), resource: dm.any_of(["speechsynch", "speechrecog"], "resource"), }); var dict = {}; expect( matcher( { type: "application", connection: "new", resource: "speechrecog", }, dict, THROW_MATCHING_ERROR, "root", ), ).toBeTruthy(); expect(dict.type).toBe("application"); expect(dict.connection).toBe("new"); expect(dict.resource).toBe("speechrecog"); }); test("any_of: no match", () => { var matcher = dm.any_of([ dm.full_match({ a: 1, b: 2, c: dm.collect("c"), }), dm.partial_match({ aa: 10, bb: 20, cc: dm.collect("cc"), }), ]); var dict = {}; expect( matcher( { aaa: 100, bbb: 200, ccc: 300, }, dict, !THROW_MATCHING_ERROR, "root", ), ).toBeFalsy(); }); test("any_of: no taint from previous matcher (dict)", () => { var matcher = dm.any_of([ dm.full_match({ a: 1, b: dm.collect("b"), c: 3, }), dm.partial_match({ aa: 10, bb: 20, cc: dm.collect("cc"), }), ]); var dict = {}; expect( matcher( { a: 1, b: 2, c: 300000, // will cause match failure for the first matcher aa: 10, bb: 20, cc: 30, }, dict, !THROW_MATCHING_ERROR, "root", ), ).toBeTruthy(); expect(dict.a).toBe(undefined); expect(dict.b).toBe(undefined); expect(dict.c).toBe(undefined); expect(dict.aa).toBe(undefined); expect(dict.bb).toBe(undefined); expect(dict.cc).toBe(30); }); test("any_of: no taint from previous matcher (array)", () => { var matcher = dm.any_of([ dm.full_match([1, dm.collect("b"), 3]), dm.partial_match([1, 2, dm.collect("cc")]), ]); var dict = {}; expect( matcher([1, 2, 30], dict, !THROW_MATCHING_ERROR, "root"), ).toBeTruthy(); expect(dict.b).toBe(undefined); expect(dict.cc).toBe(30); }); test("unordered_list (dict elements): normal order", () => { var matcher = dm.unordered_list([ dm.full_match({ a: 1, b: dm.collect("b"), c: 3 }), dm.partial_match({ aa: 10, bb: 20, cc: dm.collect("cc") }), ]); var dict = {}; expect( matcher( [ { a: 1, b: 2, c: 3 }, { aa: 10, bb: 20, cc: 30 }, ], dict, THROW_MATCHING_ERROR, "root", ), ).toBeTruthy(); expect(dict.b).toBe(2); expect(dict.cc).toBe(30); }); test("unordered_list (dict elements): reverse order", () => { var matcher = dm.unordered_list([ dm.full_match({ a: 1, b: dm.collect("b"), c: 3 }), dm.partial_match({ aa: 10, bb: 20, cc: dm.collect("cc") }), ]); var dict = {}; expect( matcher( [ { aa: 10, bb: 20, cc: 30 }, { a: 1, b: 2, c: 3 }, ], dict, THROW_MATCHING_ERROR, "root", ), ).toBeTruthy(); expect(dict.b).toBe(2); expect(dict.cc).toBe(30); }); test("unordered_list (dict elements): plain dicts", () => { var matcher = dm.unordered_list([ { a: 1, b: dm.collect("b"), c: 3 }, { aa: 10, bb: 20, cc: dm.collect("cc") }, ]); var dict = {}; expect( matcher( [ { aa: 10, bb: 20, cc: 30 }, { a: 1, b: 2, c: 3 }, ], dict, THROW_MATCHING_ERROR, "root", ), ).toBeTruthy(); expect(dict.b).toBe(2); expect(dict.cc).toBe(30); }); test("unordered_list (dict elements): matcher function and plain dict", () => { var matcher = dm.unordered_list([ dm.partial_match({ a: 1, b: dm.collect("b"), c: 3 }), { aa: 10, bb: 20, cc: dm.collect("cc") }, ]); var dict = {}; expect( matcher( [ { aa: 10, bb: 20, cc: 30 }, { a: 1, b: 2, c: 3 }, ], dict, THROW_MATCHING_ERROR, "root", ), ).toBeTruthy(); expect(dict.b).toBe(2); expect(dict.cc).toBe(30); }); test("unordered_list (array elements): normal order", () => { var matcher = dm.unordered_list([ dm.full_match([1, dm.collect("b"), 3]), dm.partial_match([10, 20, dm.collect("cc")]), ]); var dict = {}; expect( matcher( [ [1, 2, 3], [10, 20, 30], ], dict, THROW_MATCHING_ERROR, "root", ), ).toBeTruthy(); expect(dict.b).toBe(2); expect(dict.cc).toBe(30); }); test("unordered_list (array_elements): plain arrays", () => { var matcher = dm.unordered_list([ [1, dm.collect("b"), 3], [10, 20, dm.collect("cc")], ]); var dict = {}; expect( matcher( [ [10, 20, 30], [1, 2, 3], ], dict, THROW_MATCHING_ERROR, "root", ), ).toBeTruthy(); expect(dict.b).toBe(2); expect(dict.cc).toBe(30); }); test("unordered_list (array_elements): matcher function and plain array", () => { var matcher = dm.unordered_list([ [1, dm.collect("b"), 3], dm.partial_match([10, 20, dm.collect("cc")]), ]); var dict = {}; expect( matcher( [ [10, 20, 30], [1, 2, 3], ], dict, THROW_MATCHING_ERROR, "root", ), ).toBeTruthy(); expect(dict.b).toBe(2); expect(dict.cc).toBe(30); }); test("unordered_list: irrelevant elements declared with dm._ (anything)", () => { var matcher = dm.unordered_list([ [1, dm.collect("b"), dm._], dm.partial_match([dm._, dm._, dm.collect("cc")]), ]); var dict = {}; expect( matcher( [ [10, 20, 30], [1, 2, 3], ], dict, THROW_MATCHING_ERROR, "root", ), ).toBeTruthy(); expect(dict.b).toBe(2); expect(dict.cc).toBe(30); }); test("collect with matcher)", () => { var matcher = dm.collect("main", [ [10, dm.collect("b"), dm._], dm.partial_match([dm._, dm._, dm.collect("cc")]), ]); var received = [ [10, 20, 30], [1, 2, 3], ]; var dict = {}; expect(matcher(received, dict, !THROW_MATCHING_ERROR, "root")).toBeTruthy(); expect(dict.b).toBe(20); expect(dict.cc).toBe(3); expect(dict.main).toBe(received); }); test("pop_match with object", () => { const item1 = { id: 1, name: "user1", }; const item2 = { id: 2, name: "user2", }; const items = [item1, item2]; const dict = {}; const item = dm.pop_match( { name: "user2", id: dm.collect("id"), }, items, dict, ); expect(item).toEqual(item2); expect(dict.id).toEqual(2); expect(items).toEqual([item1]); }); test("pop_match with object and string collection", () => { const item1 = { id: 1, name: "user1", surname: "bla-bla", }; const item2 = { id: 2, name: "user2", surname: "ble-ble", }; const items = [item1, item2]; const dict = {}; const item = dm.pop_match( { name: "user!{id}", surname: "bla-!{_}", }, items, dict, ); expect(item).toEqual(item1); expect(dict.id).toEqual("1"); expect(items).toEqual([item2]); }); test("pop_match with function", () => { const item1 = { id: 1, name: "user1", }; const item2 = { id: 2, name: "user2", }; const items = [item1, item2]; const dict = {}; const item = dm.pop_match( (received, dict) => { if (received.name == "user2") return true; }, items, dict, ); expect(item).toEqual(item2); expect(items).toEqual([item1]); }); test("reverse_pop_match with object", () => { const item1 = { id: 1, name: "user1", }; const item2 = { id: 2, name: "user2", }; const items = [item1, item2]; const dict = {}; const item = dm.reverse_pop_match( { name: "user2", id: 2, }, items, dict, ); expect(item).toEqual(item2); expect(items).toEqual([item1]); }); test("reverse_pop_match with object and string collection", () => { const item1 = { id: 1, name: "user!{id}", }; const item2 = { id: 2, name: "user!{id}", }; const items = [item1, item2]; const dict = {}; const item = dm.reverse_pop_match( { name: "user2", id: 2, }, items, dict, ); expect(item).toEqual(item2); expect(dict.id).toEqual("2"); expect(items).toEqual([item1]); }); test("reverse_pop_match with function", () => { const item1 = { id: 1, name: "user1", }; const item2 = (received, dict) => { if (received.name == "user2") return true; }; const items = [item1, item2]; const dict = {}; const item = dm.reverse_pop_match( { id: 2, name: "user2", }, items, dict, ); expect(item).toEqual(item2); expect(items).toEqual([item1]); }); test("push", () => { var expected = { id: dm.push('ids'), }; var received = { name: 'john', id: 10, }; var dict = {}; var res = dm.partial_match(expected)( received, dict, !THROW_MATCHING_ERROR, "root", ); expect(res).toEqual("object matched"); expect(dict).toEqual({ids: [10]}); var received2 = { name: 'bob', id: 20, }; res = dm.partial_match(expected)( received2, dict, !THROW_MATCHING_ERROR, "root" ); expect(res).toEqual("object matched"); expect(dict).toEqual({ids: [10, 20]}); }); test("pop", () => { var expected = { id: dm.pop('ids'), }; var received = { name: 'john', id: 20, }; var dict = {} expect(() => { dm.partial_match(expected)( received, dict, THROW_MATCHING_ERROR, "root" ) }).toThrow("'ids' is undefined") dict = {ids: 'abc'} expect(() => { dm.partial_match(expected)( received, dict, THROW_MATCHING_ERROR, "root" ) }).toThrow("'ids' is not an Array") dict = {ids: [30,20,10]} res = dm.partial_match(expected)( received, dict, THROW_MATCHING_ERROR, "root" ) expect(res).toEqual("object matched") expect(dict).toEqual({ids: [30, 10]}) }); test("xml", () => { var expected = [ { "IVR": [ { "Section": [ { "Wait": [], ":@": { "length": dm.collect("length") } }, { "Play": [ { "#text": "welcome.mp3" } ] }, { "SendFax": [ { "#text": "faxes/main_office_map.tiff" } ], ":@": { "header": "Your Invoice" } } ], ":@": { "name": "main" } } ] } ]; var received = ` <IVR> <Section name="main"> <Wait length="1"/> <Play>welcome.mp3</Play> <SendFax header="Your Invoice">faxes/main_office_map.tiff</SendFax> </Section> </IVR> ` var dict = {} res = dm.xml(expected)( received, dict, !THROW_MATCHING_ERROR, "root" ); expect(res).toEqual("array matched"); expect(dict).toEqual({length: "1"}); });