From 8780e1b53c061c54c043fc3aa4cc862478c9b06d Mon Sep 17 00:00:00 2001 From: Doug Martin Date: Wed, 9 Jan 2013 02:59:39 -0600 Subject: [PATCH] fixed issue #13 * Fixed constraint matcher to look up identifiers in property chains --- lib/constraintMatcher.js | 122 ++++++++------ test/constraintMatcher.test.js | 287 +++++++++++++++++++-------------- 2 files changed, 239 insertions(+), 170 deletions(-) diff --git a/lib/constraintMatcher.js b/lib/constraintMatcher.js index 5d933bc..b9cd11b 100644 --- a/lib/constraintMatcher.js +++ b/lib/constraintMatcher.js @@ -2,6 +2,7 @@ "use strict"; var comb = require("comb"), + isArray = comb.isArray, dt = comb.date, array = comb.array, isUndefinedOrNull = comb.isUndefinedOrNull, removeDups = array.removeDuplicates, @@ -10,11 +11,11 @@ vm = require("vm"); var definedFuncs = { - now:function () { + now: function () { return new Date(); }, - Date:function (y, m, d, h, min, s, ms) { + Date: function (y, m, d, h, min, s, ms) { var date = new Date(); if (comb.isNumber(y)) { date.setYear(y); @@ -40,35 +41,35 @@ return date; }, - lengthOf:function (arr, length) { + lengthOf: function (arr, length) { return arr.length === length; }, - isTrue:function (val) { + isTrue: function (val) { return val === true; }, - isFalse:function (val) { + isFalse: function (val) { return val === false; }, - isRegExp:function (val) { + isRegExp: function (val) { return comb.isRexExp(val); }, - isNull:function (actual) { + isNull: function (actual) { return actual === null; }, - isNotNull:function (actual) { + isNotNull: function (actual) { return actual !== null; }, - dateCmp:function (dt1, dt2) { + dateCmp: function (dt1, dt2) { return dt.compare(dt1, dt2); }, - isEmpty:function (val) { + isEmpty: function (val) { return comb.isEmpty(val); } }; @@ -81,15 +82,15 @@ ["isArray", "isNumber", "isHash", "isObject", "isDate", "isBoolean", "isString", "isUndefined", "isDefined", "isUndefinedOrNull", "isPromiseLike", "isFunction", "deepEqual"].forEach(function (k) { - definedFuncs[k] = function (val) { - return comb[k].apply(comb, arguments); - }; - }); + definedFuncs[k] = function (val) { + return comb[k].apply(comb, arguments); + }; + }); var lang = { - equal:function (c1, c2) { + equal: function (c1, c2) { var ret = false; if (c1 === c2) { ret = true; @@ -107,9 +108,10 @@ return ret; }, - getIdentifiers:function (rule) { + getIdentifiers: function (rule) { var ret = []; var rule2 = rule[2]; + if (rule2 === "identifier") { //its an identifier so stop return [rule[0]]; @@ -123,20 +125,34 @@ rule2 !== "unminus") { //its an expression so keep going if (rule2 === "prop") { - return ret.concat(this.getIdentifiers(rule[0])); - } - if (rule[0]) { ret = ret.concat(this.getIdentifiers(rule[0])); - } - if (rule[1]) { - ret = ret.concat(this.getIdentifiers(rule[1])); + if (rule[1]) { + var propChain = rule[1]; + //go through the member variables and collect any identifiers that may be in functions + while (isArray(propChain)) { + if (propChain[2] === "function") { + ret = ret.concat(this.getIdentifiers(propChain[1])); + break; + } else { + propChain = propChain[1]; + } + } + } + + } else { + if (rule[0]) { + ret = ret.concat(this.getIdentifiers(rule[0])); + } + if (rule[1]) { + ret = ret.concat(this.getIdentifiers(rule[1])); + } } } //remove dups and return return removeDups(ret); }, - toConstraints:function (rule, reference) { + toConstraints: function (rule, reference) { var ret = []; var rule2 = rule[2]; if (rule2 === "and") { @@ -165,68 +181,68 @@ }, - parse:function (rule) { + parse: function (rule) { return this[rule[2]](rule[0], rule[1]); }, - and:function (lhs, rhs) { + and: function (lhs, rhs) { return [this.parse(lhs), "&&", this.parse(rhs)].join(" "); }, - or:function (lhs, rhs) { + or: function (lhs, rhs) { return [this.parse(lhs), "||", this.parse(rhs)].join(" "); }, - prop:function (name, prop) { + prop: function (name, prop) { return [this.parse(name), this.parse(prop)].join("."); }, - unminus:function (lhs, rhs) { + unminus: function (lhs, rhs) { return -1 * this.parse(lhs); }, - plus:function (lhs, rhs) { + plus: function (lhs, rhs) { return [this.parse(lhs), "+", this.parse(rhs)].join(" "); }, - minus:function (lhs, rhs) { + minus: function (lhs, rhs) { return [this.parse(lhs), "-", this.parse(rhs)].join(" "); }, - mult:function (lhs, rhs) { + mult: function (lhs, rhs) { return [this.parse(lhs), "*", this.parse(rhs)].join(" "); }, - div:function (lhs, rhs) { + div: function (lhs, rhs) { return [this.parse(lhs), "/", this.parse(rhs)].join(" "); }, - lt:function (lhs, rhs) { + lt: function (lhs, rhs) { return [this.parse(lhs), "<", this.parse(rhs)].join(" "); }, - gt:function (lhs, rhs) { + gt: function (lhs, rhs) { return [this.parse(lhs), ">", this.parse(rhs)].join(" "); }, - lte:function (lhs, rhs) { + lte: function (lhs, rhs) { return [this.parse(lhs), "<=", this.parse(rhs)].join(" "); }, - gte:function (lhs, rhs) { + gte: function (lhs, rhs) { return [this.parse(lhs), ">=", this.parse(rhs)].join(" "); }, - like:function (lhs, rhs) { + like: function (lhs, rhs) { return [this.parse(rhs), ".test(", this.parse(lhs), ")"].join(""); }, - eq:function (lhs, rhs) { + eq: function (lhs, rhs) { return [this.parse(lhs), "===", this.parse(rhs)].join(" "); }, - neq:function (lhs, rhs) { + neq: function (lhs, rhs) { return [this.parse(lhs), "!==", this.parse(rhs)].join(" "); }, - "in":function (lhs, rhs) { + "in": function (lhs, rhs) { return ["[", this.parse(rhs), "].indexOf(", this.parse(lhs), ") != -1"].join(""); }, - "arguments":function (lhs, rhs) { + "arguments": function (lhs, rhs) { var ret = []; if (lhs) { ret.push(this.parse(lhs)); @@ -237,7 +253,7 @@ return ret.join(","); }, - "array":function (lhs, rhs) { + "array": function (lhs, rhs) { var args = []; if (lhs) { args = this.parse(lhs); @@ -250,44 +266,44 @@ return ["[", args.join(","), "]"].join(""); }, - "function":function (lhs, rhs) { + "function": function (lhs, rhs) { var args = this.parse(rhs), f; return [lhs, "(", args, ")"].join(""); }, - string:function (lhs) { + string: function (lhs) { return "'" + lhs + "'"; }, - number:function (lhs) { + number: function (lhs) { return lhs; }, - "boolean":function (lhs) { + "boolean": function (lhs) { return lhs; }, - regexp:function (lhs) { + regexp: function (lhs) { return lhs; }, - identifier:function (lhs, rhs) { + identifier: function (lhs, rhs) { return lhs; }, - "null":function (lhs) { + "null": function (lhs) { return "null"; } }; var toJs = exports.toJs = function (rule) { - var js = lang.parse(rule); + var js = lang.parse(rule); var vars = lang.getIdentifiers(rule); - return ["(function(hash){", vars.map(function(v){ + return ["(function(hash){", vars.map(function (v) { var ret = ["var ", v, " = "]; - if(definedFuncs.hasOwnProperty(v)){ + if (definedFuncs.hasOwnProperty(v)) { ret.push("definedFuncs['", v, "']"); - }else{ + } else { ret.push("hash['", v, "']"); } ret.push(";"); diff --git a/test/constraintMatcher.test.js b/test/constraintMatcher.test.js index 3e63f86..a5f347d 100644 --- a/test/constraintMatcher.test.js +++ b/test/constraintMatcher.test.js @@ -3,219 +3,272 @@ var it = require("it"), assert = require("assert"), parser = require("../lib/parser"), constraintMatcher = require("../lib/constraintMatcher"); - it.describe("constraint matcher", function (it) { + it.describe("constraint matcher",function (it) { it.describe("#match", function (it) { it.should("check equality", function () { - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a == 'a'"))({a:"a"})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a == 10"))({a:10})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a == true"))({a:true})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a == false"))({a:false})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a == 'a'"))({a: "a"})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a == 10"))({a: 10})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a == true"))({a: true})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a == false"))({a: false})); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a == 'a'"))({a:"b"})); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a == 10"))({a:11})); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a == 10"))({a:"10"})); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a == false"))({a:true})); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a == true"))({a:false})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a == 'a'"))({a: "b"})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a == 10"))({a: 11})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a == 10"))({a: "10"})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a == false"))({a: true})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a == true"))({a: false})); }); it.should("check inequality", function () { - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a != 'a'"))({a:"a"})); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a != 10"))({a:10})); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a != true"))({a:true})); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a != false"))({a:false})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a != 'a'"))({a: "a"})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a != 10"))({a: 10})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a != true"))({a: true})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a != false"))({a: false})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a != 'a'"))({a:"b"})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a != 10"))({a:11})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a != 10"))({a:"10"})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a != false"))({a:true})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a != true"))({a:false})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a != 'a'"))({a: "b"})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a != 10"))({a: 11})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a != 10"))({a: "10"})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a != false"))({a: true})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a != true"))({a: false})); }); it.should("check gt operator", function () { - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a > '0'"))({a:"a"})); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a > '0'"))({a:"0"})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a > '0'"))({a: "a"})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a > '0'"))({a: "0"})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a > 0"))({a:1})); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a > 0"))({a:0})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a > 0"))({a: 1})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a > 0"))({a: 0})); }); it.should("check lt operator", function () { - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a < 'b'"))({a:"a"})); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a < '0'"))({a:"0"})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a < 'b'"))({a: "a"})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a < '0'"))({a: "0"})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a < 2"))({a:1})); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a < 0"))({a:0})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a < 2"))({a: 1})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a < 0"))({a: 0})); }); it.should("check gte operator", function () { - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a >= 'a'"))({a:"a"})); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a >= 'a'"))({a:"0"})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a >= 'a'"))({a: "a"})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a >= 'a'"))({a: "0"})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a >= 1"))({a:1})); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a >= 1"))({a:0})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a >= 1"))({a: 1})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a >= 1"))({a: 0})); }); it.should("check lte operator", function () { - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a <= 'a'"))({a:"a"})); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a <= -1"))({a:"0"})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a <= 'a'"))({a: "a"})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a <= -1"))({a: "0"})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a <= 1"))({a:1})); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a <= -1"))({a:0})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a <= -1"))({a:-10})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a <= 1"))({a: 1})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a <= -1"))({a: 0})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a <= -1"))({a: -10})); }); it.should("check lte operator", function () { - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a <= 'a'"))({a:"a"})); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a <= -1"))({a:"0"})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a <= 'a'"))({a: "a"})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a <= -1"))({a: "0"})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a <= 1"))({a:1})); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a <= -1"))({a:0})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a <= -1"))({a:-10})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a <= 1"))({a: 1})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a <= -1"))({a: 0})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a <= -1"))({a: -10})); }); it.should("check like operator", function () { - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a =~ /hello/"))({a:"hello"})); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a =~ /world/"))({a:"hello"})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a =~ /hello/"))({a: "hello"})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a =~ /world/"))({a: "hello"})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a =~ /^hello world$/"))({a:"hello world"})); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a =~ /^hello world$/"))({a:"hello world2"})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a =~ /^hello world$/"))({a: "hello world"})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a =~ /^hello world$/"))({a: "hello world2"})); }); it.should("check and operator", function () { - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.hello eq 'hello' and a.world eq 'world'"))({"a":{hello:"hello", world:"world"}})); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a.hello eq 'hello' and a.world eq 'world'"))({a:{hello:"world", world:"hello"}})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.hello eq 'hello' and a.world eq 'world'"))({"a": {hello: "hello", world: "world"}})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a.hello eq 'hello' and a.world eq 'world'"))({a: {hello: "world", world: "hello"}})); }); it.should("check or operator", function () { - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.hello eq 'hello' or a.world eq 'world'"))({a:{hello:"world", world:"world"}})); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a.hello eq 'hello' or a.world eq 'world'"))({a:{hello:"world", world:"hello"}})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.hello eq a.world"))({a:{hello:"hello", world:"hello"}})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.hello eq 'hello' or a.world eq 'world'"))({a: {hello: "world", world: "world"}})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a.hello eq 'hello' or a.world eq 'world'"))({a: {hello: "world", world: "hello"}})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.hello eq a.world"))({a: {hello: "hello", world: "hello"}})); }); it.should("check with member operator", function () { - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.hello eq a.world"))({a:{hello:"hello", world:"hello"}})); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a.hello eq a.world"))({a:{hello:"hello", world:"world"}})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.hello eq a.world"))({a: {hello: "hello", world: "hello"}})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a.hello eq a.world"))({a: {hello: "hello", world: "world"}})); }); it.should("check with in operator", function () { - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a in [1,2,3,4]"))({a:1})); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a in ['a','b','c']"))({a:1})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a in [1,2,3,4]"))({a: 1})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a in ['a','b','c']"))({a: 1})); }); it.should("allow properties with in", function () { - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.in == 1"))({a:{"in":1}})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.innoculated == 1"))({a:{innoculated:1}})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.in == 1"))({a: {"in": 1}})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.innoculated == 1"))({a: {innoculated: 1}})); }); it.should("check with boolean associativity", function () { - var a = {hello:"hello", world:"world", age:10, name:"bob"}; - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.hello eq a.world || (a.age >= 10 && a.name eq 'bob')"))({a:a})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("(a.hello eq a.world && a.age >= 10) || a.name eq 'bob'"))({a:a})); + var a = {hello: "hello", world: "world", age: 10, name: "bob"}; + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.hello eq a.world || (a.age >= 10 && a.name eq 'bob')"))({a: a})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("(a.hello eq a.world && a.age >= 10) || a.name eq 'bob'"))({a: a})); }); it.should("check with nested properties", function () { - var a = {hello:"hello"}; - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.hello.length eq 5"))({a:a})); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a.hello.size eq 5"))({a:a})); + var a = {hello: "hello"}; + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.hello.length eq 5"))({a: a})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a.hello.size eq 5"))({a: a})); }); it.should("check with function", function () { - var a = {hello:"hello", myFunc:function () { - return this.hello + " world"; - }}; - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.hello.length eq 5 && a.myFunc() eq 'hello world'"))({a:a})); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a.hello.size eq 5 && a.myFunc() eq 'hello world'"))({a:a})); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a.hello eq 5 && a.myFunc() eq 'hello'"))({a:a})); + var a = { + hello: "hello", + myFunc: function () { + return this.hello + " world"; + } + }; + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.hello.length eq 5 && a.myFunc() eq 'hello world'"))({a: a})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a.hello.size eq 5 && a.myFunc() eq 'hello world'"))({a: a})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a.hello eq 5 && a.myFunc() eq 'hello'"))({a: a})); + }); + + it.should("check with functions and identifier args", function () { + var a = { + hello: "hello", + myFunc: function (concat) { + return this.hello + " world"; + } + }; + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.hello.length eq 5 && a.myFunc(b) eq 'hello world'"))({a: a, b: 'world'})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a.hello.size eq 5 && a.myFunc(b) eq 'hello world'"))({a: a, b: 'world'})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a.hello eq 5 && a.myFunc(b) eq 'hello'"))({a: a, b: 'world'})); + }); + + it.should("check with functions in a deep property chain and identifier args", function () { + var a = { + hello: "hello", + b: { + c: { + myFunc: function (concat) { + return a.hello + " world"; + } + } + } + }; + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.hello.length eq 5 && a.b.c.myFunc(b) eq 'hello world'"))({a: a, b: 'world'})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a.hello.size eq 5 && a.b.c.myFunc(b) eq 'hello world'"))({a: a, b: 'world'})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a.hello eq 5 && a.b.c.myFunc(b) eq 'hello'"))({a: a, b: 'world'})); + }); + + it.should("check with functions in a deep property chain that returns an object and identifier args", function () { + var a = { + hello: "hello", + b: { + c: { + myFunc: function (concat) { + return { + d: { + myFunc: function () { + return a.hello + " world"; + } + } + } + } + } + } + }; + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.hello.length eq 5 && a.b.c.myFunc().d.myFunc(b) eq 'hello world'"))({a: a, b: 'world'})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a.hello.size eq 5 && a.b.c.myFunc().d.myFunc(b) eq 'hello world'"))({a: a, b: 'world'})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("a.hello eq 5 && a.b.c.myFunc().d.myFunc(b) eq 'hello'"))({a: a, b: 'world'})); }); it.should("have date helpers", function () { - var a = {myDate:new Date()}; - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.myDate lte now()"))({a:a})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.myDate lte Date(2013)"))({a:a})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.myDate gt yearsAgo(10)"))({a:a})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.myDate lt yearsFromNow(10)"))({a:a})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.myDate gt monthsAgo(10)"))({a:a})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.myDate lt monthsFromNow(10)"))({a:a})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.myDate gt daysAgo(10)"))({a:a})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.myDate lt daysFromNow(10)"))({a:a})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.myDate gt hoursAgo(10)"))({a:a})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.myDate lt hoursFromNow(10)"))({a:a})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.myDate gt minutesAgo(10)"))({a:a})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.myDate lt minutesFromNow(10)"))({a:a})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.myDate gt secondsAgo(10)"))({a:a})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.myDate lt secondsFromNow(10)"))({a:a})); + var a = {myDate: new Date()}; + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.myDate lte now()"))({a: a})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.myDate lte Date(2013)"))({a: a})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.myDate gt yearsAgo(10)"))({a: a})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.myDate lt yearsFromNow(10)"))({a: a})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.myDate gt monthsAgo(10)"))({a: a})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.myDate lt monthsFromNow(10)"))({a: a})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.myDate gt daysAgo(10)"))({a: a})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.myDate lt daysFromNow(10)"))({a: a})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.myDate gt hoursAgo(10)"))({a: a})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.myDate lt hoursFromNow(10)"))({a: a})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.myDate gt minutesAgo(10)"))({a: a})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.myDate lt minutesFromNow(10)"))({a: a})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.myDate gt secondsAgo(10)"))({a: a})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("a.myDate lt secondsFromNow(10)"))({a: a})); }); it.should("create have type helpers", function () { - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("isTrue(a)"))({a:true})); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("isTrue(a)"))({a:false})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("isTrue(a)"))({a: true})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("isTrue(a)"))({a: false})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("isFalse(a)"))({a:false})); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("isFalse(a)"))({a:true})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("isFalse(a)"))({a: false})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("isFalse(a)"))({a: true})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("isNumber(a)"))({a:1})); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("isNumber(a)"))({a:false})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("isNumber(a)"))({a: 1})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("isNumber(a)"))({a: false})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("isBoolean(a)"))({a:true})); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("isBoolean(a)"))({a:1})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("isBoolean(a)"))({a: true})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("isBoolean(a)"))({a: 1})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("isDate(a)"))({a:new Date()})); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("isDate(a)"))({a:1})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("isDate(a)"))({a: new Date()})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("isDate(a)"))({a: 1})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("isRegExp(a)"))({a:/a/})); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("isRegExp(a)"))({a:"/a/"})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("isRegExp(a)"))({a: /a/})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("isRegExp(a)"))({a: "/a/"})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("isDefined(a)"))({a:1})); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("isDefined(a)"))({a:undefined})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("isDefined(a)"))({a: 1})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("isDefined(a)"))({a: undefined})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("isUndefined(a)"))({a:undefined})); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("isUndefined(a)"))({a:false})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("isUndefined(a)"))({a: undefined})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("isUndefined(a)"))({a: false})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("isNotNull(a)"))({a:1})); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("isNotNull(a)"))({a:null})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("isNotNull(a)"))({a: 1})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("isNotNull(a)"))({a: null})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("isEmpty(a)"))({a:{}})); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("isEmpty(a)"))({a:{b:"c"}})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("isEmpty(a)"))({a: {}})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("isEmpty(a)"))({a: {b: "c"}})); - assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("lengthOf(a, 3)"))({a:[1, 2, 3]})); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("lengthOf(a, 3)"))({a:[1]})); + assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("lengthOf(a, 3)"))({a: [1, 2, 3]})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("lengthOf(a, 3)"))({a: [1]})); assert.isTrue(constraintMatcher.getMatcher(parser.parseConstraint("deepEqual(a, b) && deepEqual(c,d) && deepEqual(e, f)"))({ - a:[1, 2, 3], - b:[1, 2, 3], - c:new Date(2000, 10, 10, 10, 10, 10), - d:new Date(2000, 10, 10, 10, 10, 10), - e:{ - a:new Date(2000, 10, 10, 10, 10, 10), - b:new Date(2000, 10, 10, 10, 10, 10) + a: [1, 2, 3], + b: [1, 2, 3], + c: new Date(2000, 10, 10, 10, 10, 10), + d: new Date(2000, 10, 10, 10, 10, 10), + e: { + a: new Date(2000, 10, 10, 10, 10, 10), + b: new Date(2000, 10, 10, 10, 10, 10) }, - f:{ - a:new Date(2000, 10, 10, 10, 10, 10), - b:new Date(2000, 10, 10, 10, 10, 10) + f: { + a: new Date(2000, 10, 10, 10, 10, 10), + b: new Date(2000, 10, 10, 10, 10, 10) } })); - assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("deepEqual(a, b)"))({a:[1], b:new Date()})); + assert.isFalse(constraintMatcher.getMatcher(parser.parseConstraint("deepEqual(a, b)"))({a: [1], b: new Date()})); }); }); @@ -368,5 +421,5 @@ }); }); - }).as(module); + }).as(module).run(); })(); \ No newline at end of file