From 8ceab06456dfe3e3c9b5a83360f244aa22f0a331 Mon Sep 17 00:00:00 2001 From: Sykander <26931543+Sykander@users.noreply.github.com> Date: Thu, 17 Nov 2022 14:06:18 +0000 Subject: [PATCH 1/2] Feature/ Controlled Execution - Added `controlledExecution` option on `add_operation` function - Added unit tests `controlledExecution` --- logic.js | 9 ++++++++- tests/tests.js | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/logic.js b/logic.js index 2767087..bbd0d6a 100644 --- a/logic.js +++ b/logic.js @@ -37,6 +37,7 @@ http://ricostacruz.com/cheatsheets/umdjs.html } var jsonLogic = {}; + var runOperationAsControlled = {}; var operations = { "==": function(a, b) { return a == b; @@ -348,6 +349,8 @@ http://ricostacruz.com/cheatsheets/umdjs.html } } return false; // None were truthy + } else if (runOperationAsControlled[op]) { + return operations[op](values, data, jsonLogic); } // Everyone else gets immediate depth-first recursion @@ -404,12 +407,16 @@ http://ricostacruz.com/cheatsheets/umdjs.html return arrayUnique(collection); }; - jsonLogic.add_operation = function(name, code) { + jsonLogic.add_operation = function(name, code, options) { operations[name] = code; + + var controlledExecution = Boolean(options && options.controlledExecution); + runOperationAsControlled[name] = controlledExecution; }; jsonLogic.rm_operation = function(name) { delete operations[name]; + delete runOperationAsControlled[name]; }; jsonLogic.rule_like = function(rule, pattern) { diff --git a/tests/tests.js b/tests/tests.js index 96798f5..b387695 100644 --- a/tests/tests.js +++ b/tests/tests.js @@ -307,4 +307,49 @@ QUnit.module('basic', () => { jsonLogic.apply({"or": [{"push": [true]}, {"push": [true]}]}); assert.deepEqual(i, [true]); }); + + QUnit.test("Expanding functionality with add_operator - controlledExecution", function(assert) { + // assert that controlled execution doesn't do pre-evaluation + var customOp = function(values, data, jsonLogic) { + return jsonLogic.apply(values[0], data); + } + + jsonLogic.add_operation('customOp', customOp, { controlledExecution: true }); + + assert.deepEqual(jsonLogic.apply({ customOp: [{ "var": "" }, { "var": "test" }]}, { test: 123 }), { test: 123 }); + assert.deepEqual(jsonLogic.apply({ customOp: [{ "var": "test" }, { "var": "" }]}, { test: 123 }), 123); + + // assert that controlled execution custom operators can be removed as normal + jsonLogic.rm_operation('customOp'); + + assert.throws(() => jsonLogic.apply({ customOp: [] }), Error, "Unrecognized operation customOp"); + + // assert that controlled-execution custom operators have access to jsonLogic object + // and can run on external data + const externalData = { + specialReference: 'external reference' + }; + customOp = function(values, data, jsonLogic) { + return jsonLogic.apply(values[0], externalData); + } + + jsonLogic.add_operation('customOp', customOp, { controlledExecution: true }); + + assert.deepEqual(jsonLogic.apply({ customOp: [{ var: "specialReference" }] }, { specialReference: 'pre-evaluation value' }), 'external reference'); + + // assert that operators are added with normal functionality when options is omitted + jsonLogic.add_operation('customOp', customOp); + + assert.throws(() => jsonLogic.apply({ customOp: [{ var: "specialReference" }] }, { specialReference: 'pre-evaluation value' }), TypeError, "Cannot read property 'apply' of undefined"); + + // assert that adding a custom operator without controlled-execution still + // results in pre-evaluation + customOp = function(value) { + return value; + } + + jsonLogic.add_operation('customOp', customOp); + + assert.deepEqual(jsonLogic.apply({ customOp: [{ var: "specialReference" }] }, { specialReference: 'pre-evaluation value' }), 'pre-evaluation value'); + }); }); From 0653b36b2b15b6f89c701d2143091e31c0315233 Mon Sep 17 00:00:00 2001 From: Sykander <26931543+Sykander@users.noreply.github.com> Date: Thu, 17 Nov 2022 14:55:36 +0000 Subject: [PATCH 2/2] Feature/ Controlled Execution - Cleaned up first test case --- tests/tests.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/tests.js b/tests/tests.js index b387695..6d4e70e 100644 --- a/tests/tests.js +++ b/tests/tests.js @@ -310,14 +310,14 @@ QUnit.module('basic', () => { QUnit.test("Expanding functionality with add_operator - controlledExecution", function(assert) { // assert that controlled execution doesn't do pre-evaluation - var customOp = function(values, data, jsonLogic) { - return jsonLogic.apply(values[0], data); + var customOp = function(values) { + return values[0]; } jsonLogic.add_operation('customOp', customOp, { controlledExecution: true }); - assert.deepEqual(jsonLogic.apply({ customOp: [{ "var": "" }, { "var": "test" }]}, { test: 123 }), { test: 123 }); - assert.deepEqual(jsonLogic.apply({ customOp: [{ "var": "test" }, { "var": "" }]}, { test: 123 }), 123); + assert.deepEqual(jsonLogic.apply({ customOp: [{ "var": "" }, { "var": "test" }]}, { test: 123 }), { var: "" }); + assert.deepEqual(jsonLogic.apply({ customOp: [{ "var": "test" }, { "var": "" }]}, { test: 123 }), { var: "test" }); // assert that controlled execution custom operators can be removed as normal jsonLogic.rm_operation('customOp');