Skip to content

Commit b6a8976

Browse files
committed
Implement logic for evaluating not condition
1 parent 8485a04 commit b6a8976

File tree

1 file changed

+27
-7
lines changed

1 file changed

+27
-7
lines changed

src/rule.js

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ class Rule extends EventEmitter {
7070
* @param {object} conditions - conditions, root element must be a boolean operator
7171
*/
7272
setConditions (conditions) {
73-
if (!Object.prototype.hasOwnProperty.call(conditions, 'all') && !Object.prototype.hasOwnProperty.call(conditions, 'any')) {
74-
throw new Error('"conditions" root must contain a single instance of "all" or "any"')
73+
if (!Object.prototype.hasOwnProperty.call(conditions, 'all') && !Object.prototype.hasOwnProperty.call(conditions, 'any') && !Object.prototype.hasOwnProperty.call(conditions, 'not')) {
74+
throw new Error('"conditions" root must contain a single instance of "all", "any", or "not"')
7575
}
7676
this.conditions = new Condition(conditions)
7777
return this
@@ -193,10 +193,12 @@ class Rule extends EventEmitter {
193193
let comparisonPromise
194194
if (condition.operator === 'all') {
195195
comparisonPromise = all(subConditions)
196-
} else {
196+
} else if (condition.operator === 'any') {
197197
comparisonPromise = any(subConditions)
198+
} else {
199+
comparisonPromise = not(subConditions)
198200
}
199-
// for booleans, rule passing is determined by the all/any result
201+
// for booleans, rule passing is determined by the all/any/not result
200202
return comparisonPromise.then(comparisonValue => {
201203
const passes = comparisonValue === true
202204
condition.result = passes
@@ -230,19 +232,25 @@ class Rule extends EventEmitter {
230232
}
231233

232234
/**
233-
* Evaluates a set of conditions based on an 'all' or 'any' operator.
235+
* Evaluates a set of conditions based on an 'all', 'any', or 'not' operator.
234236
* First, orders the top level conditions based on priority
235237
* Iterates over each priority set, evaluating each condition
236238
* If any condition results in the rule to be guaranteed truthy or falsey,
237239
* it will short-circuit and not bother evaluating any additional rules
238240
* @param {Condition[]} conditions - conditions to be evaluated
239-
* @param {string('all'|'any')} operator
241+
* @param {string('all'|'any'|'not')} operator
240242
* @return {Promise(boolean)} rule evaluation result
241243
*/
242244
const prioritizeAndRun = (conditions, operator) => {
243245
if (conditions.length === 0) {
244246
return Promise.resolve(true)
245247
}
248+
if (conditions.length === 1) {
249+
// no prioritizing is necessary, just evaluate the single condition
250+
// 'all' and 'any' will give the same results with a single condition so no method is necessary
251+
// this also covers the 'not' case which should only ever have a single condition
252+
return evaluateCondition(conditions[0])
253+
}
246254
let method = Array.prototype.some
247255
if (operator === 'all') {
248256
method = Array.prototype.every
@@ -292,6 +300,15 @@ class Rule extends EventEmitter {
292300
return prioritizeAndRun(conditions, 'all')
293301
}
294302

303+
/**
304+
* Runs a 'not' boolean operator on a single condition
305+
* @param {Condition} condition to be evaluated
306+
* @return {Promise(boolean)} condition evaluation result
307+
*/
308+
const not = (condition) => {
309+
return prioritizeAndRun([condition], 'not').then(result => !result)
310+
}
311+
295312
/**
296313
* Emits based on rule evaluation result, and decorates ruleResult with 'result' property
297314
* @param {RuleResult} ruleResult
@@ -305,9 +322,12 @@ class Rule extends EventEmitter {
305322
if (ruleResult.conditions.any) {
306323
return any(ruleResult.conditions.any)
307324
.then(result => processResult(result))
308-
} else {
325+
} else if (ruleResult.conditions.all) {
309326
return all(ruleResult.conditions.all)
310327
.then(result => processResult(result))
328+
} else {
329+
return not(ruleResult.conditions.not)
330+
.then(result => processResult(result))
311331
}
312332
}
313333
}

0 commit comments

Comments
 (0)