diff --git a/compatible.test.js b/compatible.test.js index 338da5b..141a9f3 100644 --- a/compatible.test.js +++ b/compatible.test.js @@ -13,6 +13,12 @@ for (const file of files) { } } +function correction (x) { + // eslint-disable-next-line no-compare-neg-zero + if (x === -0) return 0 + return x +} + // eslint-disable-next-line no-labels inline: { const logic = new LogicEngine(undefined, { compatible: true }) @@ -25,13 +31,13 @@ inline: { test(`${JSON.stringify(testCase[0])} ${JSON.stringify( testCase[1] )}`, () => { - expect(logic.run(testCase[0], testCase[1])).toStrictEqual(testCase[2]) + expect(correction(logic.run(testCase[0], testCase[1]))).toStrictEqual(testCase[2]) }) test(`${JSON.stringify(testCase[0])} ${JSON.stringify( testCase[1] )} (async)`, async () => { - expect(await asyncLogic.run(testCase[0], testCase[1])).toStrictEqual( + expect(correction(await asyncLogic.run(testCase[0], testCase[1]))).toStrictEqual( testCase[2] ) }) @@ -40,26 +46,26 @@ inline: { testCase[1] )} (built)`, () => { const f = logic.build(testCase[0]) - expect(f(testCase[1])).toStrictEqual(testCase[2]) + expect(correction(f(testCase[1]))).toStrictEqual(testCase[2]) }) test(`${JSON.stringify(testCase[0])} ${JSON.stringify( testCase[1] )} (asyncBuilt)`, async () => { const f = await asyncLogic.build(testCase[0]) - expect(await f(testCase[1])).toStrictEqual(testCase[2]) + expect(correction(await f(testCase[1]))).toStrictEqual(testCase[2]) }) test(`${JSON.stringify(testCase[0])} ${JSON.stringify( testCase[1] )} (noOptimization)`, () => { - expect(logicWithoutOptimization.run(testCase[0], testCase[1])).toStrictEqual(testCase[2]) + expect(correction(logicWithoutOptimization.run(testCase[0], testCase[1]))).toStrictEqual(testCase[2]) }) test(`${JSON.stringify(testCase[0])} ${JSON.stringify( testCase[1] )} (asyncNoOptimization)`, async () => { - expect(await asyncLogicWithoutOptimization.run(testCase[0], testCase[1])).toStrictEqual( + expect(correction(await asyncLogicWithoutOptimization.run(testCase[0], testCase[1]))).toStrictEqual( testCase[2] ) }) @@ -68,14 +74,14 @@ inline: { testCase[1] )} (builtNoOptimization)`, () => { const f = logicWithoutOptimization.build(testCase[0]) - expect(f(testCase[1])).toStrictEqual(testCase[2]) + expect(correction(f(testCase[1]))).toStrictEqual(testCase[2]) }) test(`${JSON.stringify(testCase[0])} ${JSON.stringify( testCase[1] )} (asyncBuiltNoOptimization)`, async () => { const f = await asyncLogicWithoutOptimization.build(testCase[0]) - expect(await f(testCase[1])).toStrictEqual(testCase[2]) + expect(correction(await f(testCase[1]))).toStrictEqual(testCase[2]) }) }) }) @@ -97,13 +103,13 @@ notInline: { test(`${JSON.stringify(testCase[0])} ${JSON.stringify( testCase[1] )}`, () => { - expect(logic.run(testCase[0], testCase[1])).toStrictEqual(testCase[2]) + expect(correction(logic.run(testCase[0], testCase[1]))).toStrictEqual(testCase[2]) }) test(`${JSON.stringify(testCase[0])} ${JSON.stringify( testCase[1] )} (async)`, async () => { - expect(await asyncLogic.run(testCase[0], testCase[1])).toStrictEqual( + expect(correction(await asyncLogic.run(testCase[0], testCase[1]))).toStrictEqual( testCase[2] ) }) @@ -112,26 +118,26 @@ notInline: { testCase[1] )} (built)`, () => { const f = logic.build(testCase[0]) - expect(f(testCase[1])).toStrictEqual(testCase[2]) + expect(correction(f(testCase[1]))).toStrictEqual(testCase[2]) }) test(`${JSON.stringify(testCase[0])} ${JSON.stringify( testCase[1] )} (asyncBuilt)`, async () => { const f = await asyncLogic.build(testCase[0]) - expect(await f(testCase[1])).toStrictEqual(testCase[2]) + expect(correction(await f(testCase[1]))).toStrictEqual(testCase[2]) }) test(`${JSON.stringify(testCase[0])} ${JSON.stringify( testCase[1] )} (noOptimization)`, () => { - expect(logicWithoutOptimization.run(testCase[0], testCase[1])).toStrictEqual(testCase[2]) + expect(correction(logicWithoutOptimization.run(testCase[0], testCase[1]))).toStrictEqual(testCase[2]) }) test(`${JSON.stringify(testCase[0])} ${JSON.stringify( testCase[1] )} (asyncNoOptimization)`, async () => { - expect(await asyncLogicWithoutOptimization.run(testCase[0], testCase[1])).toStrictEqual( + expect(correction(await asyncLogicWithoutOptimization.run(testCase[0], testCase[1]))).toStrictEqual( testCase[2] ) }) @@ -140,14 +146,14 @@ notInline: { testCase[1] )} (builtNoOptimization)`, () => { const f = logicWithoutOptimization.build(testCase[0]) - expect(f(testCase[1])).toStrictEqual(testCase[2]) + expect(correction(f(testCase[1]))).toStrictEqual(testCase[2]) }) test(`${JSON.stringify(testCase[0])} ${JSON.stringify( testCase[1] )} (asyncBuiltNoOptimization)`, async () => { const f = await asyncLogicWithoutOptimization.build(testCase[0]) - expect(await f(testCase[1])).toStrictEqual(testCase[2]) + expect(correction(await f(testCase[1]))).toStrictEqual(testCase[2]) }) }) } diff --git a/compiler.js b/compiler.js index 128eac9..9fad6ec 100644 --- a/compiler.js +++ b/compiler.js @@ -112,7 +112,7 @@ function isDeepSync (method, engine) { if (Array.isArray(method)) return method.every(i => isDeepSync(i, engine)) - if (typeof method === 'object') { + if (method && typeof method === 'object') { const func = Object.keys(method)[0] const lower = method[func] @@ -307,7 +307,7 @@ function processBuiltString (method, str, buildState) { str = str.replace(`__%%%${x}%%%__`, item) }) - const final = `(values, methods, notTraversed, asyncIterators, engine, above, coerceArray) => ${buildState.asyncDetected ? 'async' : ''} (context ${buildState.extraArguments ? ',' + buildState.extraArguments : ''}) => { const result = ${str}; return result }` + const final = `(values, methods, notTraversed, asyncIterators, engine, above, coerceArray) => ${buildState.asyncDetected ? 'async' : ''} (context ${buildState.extraArguments ? ',' + buildState.extraArguments : ''}) => { let prev; const result = ${str}; return result }` // console.log(str) // console.log(final) // eslint-disable-next-line no-eval diff --git a/defaultMethods.js b/defaultMethods.js index 7b5565c..a3800ad 100644 --- a/defaultMethods.js +++ b/defaultMethods.js @@ -52,8 +52,10 @@ function isSyncDeep (method, engine, buildState) { const defaultMethods = { '+': (data) => { + if (!data) return 0 if (typeof data === 'string') return +data if (typeof data === 'number') return +data + if (typeof data === 'boolean') return +data let res = 0 for (let i = 0; i < data.length; i++) res += +data[i] return res @@ -64,20 +66,22 @@ const defaultMethods = { return res }, '/': (data) => { - let res = data[0] + let res = +data[0] for (let i = 1; i < data.length; i++) res /= +data[i] return res }, '-': (data) => { + if (!data) return 0 if (typeof data === 'string') return -data if (typeof data === 'number') return -data + if (typeof data === 'boolean') return -data if (data.length === 1) return -data[0] let res = data[0] for (let i = 1; i < data.length; i++) res -= +data[i] return res }, '%': (data) => { - let res = data[0] + let res = +data[0] for (let i = 1; i < data.length; i++) res %= +data[i] return res }, @@ -446,7 +450,18 @@ const defaultMethods = { return result ? buildState.compile`!(${result})` : false } }, - merge: (arrays) => (Array.isArray(arrays) ? [].concat(...arrays) : [arrays]), + merge: (args) => { + if (!Array.isArray(args)) return [args] + const result = [] + for (let i = 0; i < args.length; i++) { + if (Array.isArray(args[i])) { + for (let j = 0; j < args[i].length; j++) { + result.push(args[i][j]) + } + } else result.push(args[i]) + } + return result + }, every: createArrayIterativeMethod('every'), filter: createArrayIterativeMethod('filter', true), reduce: { @@ -752,16 +767,16 @@ Object.keys(defaultMethods).forEach((item) => { defaultMethods['<'].compile = function (data, buildState) { if (!Array.isArray(data)) return false if (data.length < 2) return false - let res = buildState.compile`(${data[0]} < ${data[1]})` - for (let i = 2; i < data.length; i++) res = buildState.compile`(${res} && ${data[i - 1]} < ${data[i]})` + let res = buildState.compile`(${data[0]} < (prev = ${data[1]}))` + for (let i = 2; i < data.length; i++) res = buildState.compile`(${res} && prev < ${data[i]})` return res } // @ts-ignore Allow custom attribute defaultMethods['<='].compile = function (data, buildState) { if (!Array.isArray(data)) return false if (data.length < 2) return false - let res = buildState.compile`(${data[0]} <= ${data[1]})` - for (let i = 2; i < data.length; i++) res = buildState.compile`(${res} && ${data[i - 1]} <= ${data[i]})` + let res = buildState.compile`(${data[0]} <= (prev = ${data[1]}))` + for (let i = 2; i < data.length; i++) res = buildState.compile`(${res} && prev <= ${data[i]})` return res } // @ts-ignore Allow custom attribute @@ -782,32 +797,32 @@ defaultMethods.max.compile = function (data, buildState) { defaultMethods['>'].compile = function (data, buildState) { if (!Array.isArray(data)) return false if (data.length < 2) return false - let res = buildState.compile`(${data[0]} > ${data[1]})` - for (let i = 2; i < data.length; i++) res = buildState.compile`(${res} && ${data[i - 1]} > ${data[i]})` + let res = buildState.compile`(${data[0]} > (prev = ${data[1]}))` + for (let i = 2; i < data.length; i++) res = buildState.compile`(${res} && prev > ${data[i]})` return res } // @ts-ignore Allow custom attribute defaultMethods['>='].compile = function (data, buildState) { if (!Array.isArray(data)) return false if (data.length < 2) return false - let res = buildState.compile`(${data[0]} >= ${data[1]})` - for (let i = 2; i < data.length; i++) res = buildState.compile`(${res} && ${data[i - 1]} >= ${data[i]})` + let res = buildState.compile`(${data[0]} >= (prev = ${data[1]}))` + for (let i = 2; i < data.length; i++) res = buildState.compile`(${res} && prev >= ${data[i]})` return res } // @ts-ignore Allow custom attribute defaultMethods['=='].compile = function (data, buildState) { if (!Array.isArray(data)) return false if (data.length < 2) return false - let res = buildState.compile`(${data[0]} == ${data[1]})` - for (let i = 2; i < data.length; i++) res = buildState.compile`(${res} && ${data[i - 1]} == ${data[i]})` + let res = buildState.compile`(${data[0]} == (prev = ${data[1]}))` + for (let i = 2; i < data.length; i++) res = buildState.compile`(${res} && prev == ${data[i]})` return res } // @ts-ignore Allow custom attribute defaultMethods['!='].compile = function (data, buildState) { if (!Array.isArray(data)) return false if (data.length < 2) return false - let res = buildState.compile`(${data[0]} != ${data[1]})` - for (let i = 2; i < data.length; i++) res = buildState.compile`(${res} && ${data[i - 1]} != ${data[i]})` + let res = buildState.compile`(${data[0]} != (prev = ${data[1]}))` + for (let i = 2; i < data.length; i++) res = buildState.compile`(${res} && prev != ${data[i]})` return res } // @ts-ignore Allow custom attribute diff --git a/suites/chained.json b/suites/chained.json index b0c95dd..891c3ea 100644 --- a/suites/chained.json +++ b/suites/chained.json @@ -58,5 +58,11 @@ }, "result": 149212, "description": "Max with Logic Chaining (Complex)" + }, + { + "description": "Addition Chained w/ Merge", + "rule": { "+": { "merge": [{ "val": "x" }, { "val": "y" }] }}, + "result": 6, + "data": { "x": [1, 2], "y": 3 } } ] \ No newline at end of file diff --git a/suites/divide.json b/suites/divide.json new file mode 100644 index 0000000..3685034 --- /dev/null +++ b/suites/divide.json @@ -0,0 +1,150 @@ +[ + "# Collection of Divide Operator Tests", + { + "description": "Divide", + "rule": { "/": [4, 2] }, + "result": 2, + "data": null + }, + { + "description": "Divide to Decimal", + "rule": { "/": [2, 4] }, + "result": 0.5, + "data": null, + "decimal": true + }, + { + "description": "Divide with Multiple Operands", + "rule": { "/": [8, 2, 2] }, + "result": 2, + "data": null + }, + { + "description": "Divide with Multiple Operands (2)", + "rule": { "/": [2, 2, 1] }, + "result": 1, + "data": null + }, + { + "description": "Divide with Negative Numbers", + "rule": { "/": [-1, 2] }, + "result": -0.5, + "data": null, + "decimal": true + }, + { + "description": "Divide with Strings", + "rule": { "/": ["8", "2", "2"] }, + "result": 2, + "data": null + }, + { + "description": "Divide with Booleans", + "rule": { "/": [false, true] }, + "result": 0, + "data": null + }, + { + "description": "Divide with Multiple Value Types", + "rule": { "/": ["8", true, 2] }, + "result": 4, + "data": null + }, + { + "description": "Divide with Multiple Value Types (2)", + "rule": { "/": ["1", 1] }, + "result": 1, + "data": null + }, + { + "description": "Divide with Single Operand (Number)", + "rule": { "/": [1] }, + "result": 1, + "data": null + }, + { + "description": "Divide with Single Operand, Direct (Number)", + "rule": { "/": 1 }, + "result": 1, + "data": null + }, + { + "description": "Divide with Single Operand, Direct (0)", + "rule": { "/": 0 }, + "result": 0, + "data": null + }, + { + "description": "Divide Operator with Single Operand (Number)", + "rule": { "/": [1] }, + "result": 1, + "data": null + }, + { + "description": "Divide Operator with Single Operand (Negative Number)", + "rule": { "/": [-1] }, + "result": -1, + "data": null + }, + { + "description": "Divide Operator with Single Operand, Direct (Number)", + "rule": { "/": 1 }, + "result": 1, + "data": null + }, + { + "description": "Divide Operator with Single Operand, Direct (0)", + "rule": { "/": 0 }, + "result": 0, + "data": null + }, + { + "description": "Divide Operator with Single Operand (String)", + "rule": { "/": ["1"] }, + "result": 1, + "data": null + }, + { + "description": "Divide Operator with Single Operand, Direct (Negative Number String)", + "rule": { "/": "-1" }, + "result": -1, + "data": null + }, + + { + "description": "Divide Operator with Single Operand, Direct (String 0)", + "rule": { "/": "0" }, + "result": 0, + "data": null + }, + { + "description": "Divide Operator with Single Operand, Direct (true)", + "rule": { "/": true }, + "result": 1, + "data": null + }, + { + "description": "Divide Operator with Single Operand, Direct (false)", + "rule": { "/": false }, + "result": 0, + "data": null + }, + { + "description": "Divide Operator with Single Operand, Direct (Empty String)", + "rule": { "/": "" }, + "result": 0, + "data": null + }, + { + "description": "Divide Operator with a Single Operand, Direct (null)", + "rule": { "/": null }, + "result": 0, + "data": null + }, + { + "description": "Divide with val", + "rule": { "/": [{ "val": "x" }, { "val": "y" }] }, + "data": { "x": 8, "y": 2 }, + "result": 4 + } +] \ No newline at end of file diff --git a/suites/minus.json b/suites/minus.json new file mode 100644 index 0000000..480a8af --- /dev/null +++ b/suites/minus.json @@ -0,0 +1,118 @@ +[ + "# Collection of Minus Operator Tests", + { + "description": "Subtraction", + "rule": { "-": [1, 2] }, + "result": -1, + "data": null + }, + { + "description": "Subtraction (2)", + "rule": { "-": [5, 12] }, + "result": -7, + "data": null + }, + { + "description": "Subtraction with Multiple Operands", + "rule": { "-": [1, 2, 3, 4] }, + "result": -8, + "data": null + }, + { + "description": "Subtraction with Negative Numbers", + "rule": { "-": [-1, 0, 5] }, + "result": -6, + "data": null + }, + { + "description": "Subtraction with Strings", + "rule": { "-": ["1", "2", "3"] }, + "result": -4, + "data": null + }, + { + "description": "Subtraction with Booleans", + "rule": { "-": [true, false, true] }, + "result": 0, + "data": null + }, + { + "description": "Subtraction with Multiple Value Types", + "rule": { "-": [1, "2", 3, "4", "", true, false, null] }, + "result": -9, + "data": null + }, + { + "description": "Minus Operator with Single Operand (Number)", + "rule": { "-": [1] }, + "result": -1, + "data": null + }, + { + "description": "Minus Operator with Single Operand (Negative Number)", + "rule": { "-": [-1] }, + "result": 1, + "data": null + }, + { + "description": "Minus Operator with Single Operand, Direct (Number)", + "rule": { "-": 1 }, + "result": -1, + "data": null + }, + { + "description": "Minus Operator with Single Operand, Direct (0)", + "rule": { "-": 0 }, + "result": 0, + "data": null + }, + { + "description": "Minus Operator with Single Operand (String)", + "rule": { "-": ["1"] }, + "result": -1, + "data": null + }, + { + "description": "Minus Operator with Single Operand, Direct (Negative Number String)", + "rule": { "-": "-1" }, + "result": 1, + "data": null + }, + + { + "description": "Minus Operator with Single Operand, Direct (String 0)", + "rule": { "-": "0" }, + "result": 0, + "data": null + }, + { + "description": "Minus Operator with Single Operand, Direct (true)", + "rule": { "-": true }, + "result": -1, + "data": null + }, + { + "description": "Minus Operator with Single Operand, Direct (false)", + "rule": { "-": false }, + "result": 0, + "data": null + }, + { + "description": "Minus Operator with Single Operand, Direct (Empty String)", + "rule": { "-": "" }, + "result": 0, + "data": null + }, + { + "description": "Minus Operator with a Single Operand, Direct (null)", + "rule": { "-": null }, + "result": 0, + "data": null + }, + { + "description": "Subtraction with val", + "rule": { "-": [{ "val": "x" }, { "val": "y" }] }, + "data": { "x": 1, "y": 2 }, + "result": -1 + } +] \ No newline at end of file diff --git a/suites/modulo.json b/suites/modulo.json new file mode 100644 index 0000000..45e75ec --- /dev/null +++ b/suites/modulo.json @@ -0,0 +1,161 @@ +[ + "# Collection of Modulo Operator Tests", + { + "description": "Modulo", + "rule": { "%": [4, 2] }, + "result": 0, + "data": null + }, + { + "description": "Modulo (2)", + "rule": { "%": [2, 2] }, + "result": 0, + "data": null + }, + { + "description": "Modulo (3)", + "rule": { "%": [3, 2] }, + "result": 1, + "data": null + }, + { + "description": "Modulo with a Decimal Operand", + "rule": { "%": [1, 0.5] }, + "result": 0, + "data": null, + "decimal": true + }, + { + "description": "Modulo with Multiple Operands", + "rule": { "%": [8, 6, 3] }, + "result": 2, + "data": null + }, + { + "description": "Modulo with Multiple Operands (2)", + "rule": { "%": [2, 2, 1] }, + "result": 0, + "data": null + }, + { + "description": "Modulo with Negative Numbers", + "rule": { "%": [-1, 2] }, + "result": -1, + "data": null + }, + { + "description": "Modulo with Strings", + "rule": { "%": ["8", "2"] }, + "result": 0, + "data": null + }, + { + "description": "Modulo with Booleans", + "rule": { "%": [false, true] }, + "result": 0, + "data": null + }, + { + "description": "Modulo with Multiple Value Types", + "rule": { "%": ["8", 3, true] }, + "result": 0, + "data": null + }, + { + "description": "Modulo with Multiple Value Types (2)", + "rule": { "%": ["1", 1] }, + "result": 0, + "data": null + }, + { + "description": "Modulo with Single Operand (Number)", + "rule": { "%": [1] }, + "result": 1, + "data": null + }, + { + "description": "Modulo with Single Operand, Direct (Number)", + "rule": { "%": 1 }, + "result": 1, + "data": null + }, + { + "description": "Modulo with Single Operand, Direct (0)", + "rule": { "%": 0 }, + "result": 0, + "data": null + }, + { + "description": "Modulo Operator with Single Operand (Number)", + "rule": { "%": [1] }, + "result": 1, + "data": null + }, + { + "description": "Modulo Operator with Single Operand (Negative Number)", + "rule": { "%": [-1] }, + "result": -1, + "data": null + }, + { + "description": "Modulo Operator with Single Operand, Direct (Number)", + "rule": { "%": 1 }, + "result": 1, + "data": null + }, + { + "description": "Modulo Operator with Single Operand, Direct (0)", + "rule": { "%": 0 }, + "result": 0, + "data": null + }, + { + "description": "Modulo Operator with Single Operand (String)", + "rule": { "%": ["1"] }, + "result": 1, + "data": null + }, + { + "description": "Modulo Operator with Single Operand, Direct (Negative Number String)", + "rule": { "%": "-1" }, + "result": -1, + "data": null + }, + + { + "description": "Modulo Operator with Single Operand, Direct (String 0)", + "rule": { "%": "0" }, + "result": 0, + "data": null + }, + { + "description": "Modulo Operator with Single Operand, Direct (true)", + "rule": { "%": true }, + "result": 1, + "data": null + }, + { + "description": "Modulo Operator with Single Operand, Direct (false)", + "rule": { "%": false }, + "result": 0, + "data": null + }, + { + "description": "Modulo Operator with Single Operand, Direct (Empty String)", + "rule": { "%": "" }, + "result": 0, + "data": null + }, + { + "description": "Modulo Operator with a Single Operand, Direct (null)", + "rule": { "%": null }, + "result": 0, + "data": null + }, + { + "description": "Modulo with val", + "rule": { "%": [{ "val": "x" }, { "val": "y" }] }, + "data": { "x": 11, "y": 6 }, + "result": 5 + } +] \ No newline at end of file diff --git a/suites/multiply.json b/suites/multiply.json new file mode 100644 index 0000000..4e8e829 --- /dev/null +++ b/suites/multiply.json @@ -0,0 +1,148 @@ +[ + "# Collection of Multiply Operator Tests", + { + "description": "Multiply", + "rule": { "*": [3, 2] }, + "result": 6, + "data": null + }, + { + "description": "Multiply with Multiple Operands", + "rule": { "*": [5, 10, 2] }, + "result": 100, + "data": null + }, + { + "description": "Multiply with Multiple Operands (2)", + "rule": { "*": [2, 2, 2] }, + "result": 8, + "data": null + }, + { + "description": "Multiply with Negative Numbers", + "rule": { "*": [-1, 2, 5] }, + "result": -10, + "data": null + }, + { + "description": "Multiply with Strings", + "rule": { "*": ["1", "2", "3"] }, + "result": 6, + "data": null + }, + { + "description": "Multiply with Booleans", + "rule": { "*": [true, false, true] }, + "result": 0, + "data": null + }, + { + "description": "Multiply with Multiple Value Types", + "rule": { "*": [1, "2", 3, "4", true] }, + "result": 24, + "data": null + }, + { + "description": "Multiply with Multiple Value Types (2)", + "rule": { "*": [1, "1"] }, + "result": 1, + "data": null + }, + { + "description": "Multiply with Multiple Value Types (3)", + "rule": { "*": ["1", null] }, + "result": 0, + "data": null + }, + { + "description": "Multiply with Single Operand (Number)", + "rule": { "*": [1] }, + "result": 1, + "data": null + }, + { + "description": "Multiply with Single Operand, Direct (Number)", + "rule": { "*": 1 }, + "result": 1, + "data": null + }, + { + "description": "Multiply with Single Operand, Direct (0)", + "rule": { "*": 0 }, + "result": 0, + "data": null + }, + { + "description": "Multiply Operator with Single Operand (Number)", + "rule": { "*": [1] }, + "result": 1, + "data": null + }, + { + "description": "Multiply Operator with Single Operand (Negative Number)", + "rule": { "*": [-1] }, + "result": -1, + "data": null + }, + { + "description": "Multiply Operator with Single Operand, Direct (Number)", + "rule": { "*": 1 }, + "result": 1, + "data": null + }, + { + "description": "Multiply Operator with Single Operand, Direct (0)", + "rule": { "*": 0 }, + "result": 0, + "data": null + }, + { + "description": "Multiply Operator with Single Operand (String)", + "rule": { "*": ["1"] }, + "result": 1, + "data": null + }, + { + "description": "Multiply Operator with Single Operand, Direct (Negative Number String)", + "rule": { "*": "-1" }, + "result": -1, + "data": null + }, + + { + "description": "Multiply Operator with Single Operand, Direct (String 0)", + "rule": { "*": "0" }, + "result": 0, + "data": null + }, + { + "description": "Multiply Operator with Single Operand, Direct (true)", + "rule": { "*": true }, + "result": 1, + "data": null + }, + { + "description": "Multiply Operator with Single Operand, Direct (false)", + "rule": { "*": false }, + "result": 0, + "data": null + }, + { + "description": "Multiply Operator with Single Operand, Direct (Empty String)", + "rule": { "*": "" }, + "result": 0, + "data": null + }, + { + "description": "Multiply Operator with a Single Operand, Direct (null)", + "rule": { "*": null }, + "result": 0, + "data": null + }, + { + "description": "Multiply with val", + "rule": { "*": [{ "val": "x" }, { "val": "y" }] }, + "data": { "x": 8, "y": 2 }, + "result": 16 + } +] \ No newline at end of file diff --git a/suites/plus.json b/suites/plus.json new file mode 100644 index 0000000..82aa130 --- /dev/null +++ b/suites/plus.json @@ -0,0 +1,144 @@ +[ + "# Collection of Plus Operator Tests", + { + "description": "Addition", + "rule": { "+": [1, 2] }, + "result": 3, + "data": null + }, + { + "description": "Addition (2)", + "rule": { "+": [5, 12] }, + "result": 17, + "data": null + }, + { + "description": "Addition with Multiple Operands", + "rule": { "+": [1, 2, 3, 4] }, + "result": 10, + "data": null + }, + { + "description": "Addition with Negative Numbers", + "rule": { "+": [-1, 0, 5] }, + "result": 4, + "data": null + }, + { + "description": "Addition with Strings", + "rule": { "+": ["1", "2", "3"] }, + "result": 6, + "data": null + }, + { + "description": "Addition with Booleans", + "rule": { "+": [true, false, true] }, + "result": 2, + "data": null + }, + { + "description": "Addition with Multiple Value Types", + "rule": { "+": [1, "2", 3, "4", "", true, false, null] }, + "result": 11, + "data": null + }, + { + "description": "Plus Operator with Single Operand (Number)", + "rule": { "+": [1] }, + "result": 1, + "data": null + }, + { + "description": "Plus Operator with Single Operand (Negative Number)", + "rule": { "+": [-1] }, + "result": -1, + "data": null + }, + { + "description": "Plus Operator with Single Operand, Direct (Number)", + "rule": { "+": 1 }, + "result": 1, + "data": null + }, + { + "description": "Plus Operator with Single Operand, Direct (0)", + "rule": { "+": 0 }, + "result": 0, + "data": null + }, + { + "description": "Plus Operator with Single Operand (String)", + "rule": { "+": ["1"] }, + "result": 1, + "data": null + }, + { + "description": "Plus Operator with Single Operand, Direct (Negative Number String)", + "rule": { "+": "-1" }, + "result": -1, + "data": null + }, + { + "description": "Plus Operator with Single Operand, Direct (String Decimal)", + "rule": { "+": "1.5" }, + "result": 1.5, + "data": null, + "decimal": true + }, + { + "description": "Plus Operator with Single Operand, Direct (String Negative Decimal)", + "rule": { "+": "-1.5" }, + "result": -1.5, + "data": null, + "decimal": true + }, + { + "description": "Plus Operator with Single Operand, Direct (String 0.5)", + "rule": { "+": "0.5" }, + "result": 0.5, + "data": null, + "decimal": true + }, + { + "description": "Plus Operator with Single Operand, Direct (String 1e2)", + "rule": { "+": "1e2" }, + "result": 100, + "data": null + }, + { + "description": "Plus Operator with Single Operand, Direct (String 0)", + "rule": { "+": "0" }, + "result": 0, + "data": null + }, + { + "description": "Plus Operator with Single Operand, Direct (true)", + "rule": { "+": true }, + "result": 1, + "data": null + }, + { + "description": "Plus Operator with Single Operand, Direct (false)", + "rule": { "+": false }, + "result": 0, + "data": null + }, + { + "description": "Plus Operator with Single Operand, Direct (Empty String)", + "rule": { "+": "" }, + "result": 0, + "data": null + }, + { + "description": "Plus Operator with a Single Operand, Direct (null)", + "rule": { "+": null }, + "result": 0, + "data": null + }, + { + "description": "Addition with val", + "rule": { "+": [{ "val": "x" }, { "val": "y" }] }, + "data": { "x": 1, "y": 2 }, + "result": 3 + } +] \ No newline at end of file