Skip to content

Commit e08bd3a

Browse files
committed
Account for 'not' condition in Conditions class
1 parent 813281b commit e08bd3a

File tree

2 files changed

+56
-10
lines changed

2 files changed

+56
-10
lines changed

src/condition.js

+18-10
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,17 @@ export default class Condition {
1010
Object.assign(this, properties)
1111
if (booleanOperator) {
1212
const subConditions = properties[booleanOperator]
13-
if (!(Array.isArray(subConditions))) {
14-
throw new Error(`"${booleanOperator}" must be an array`)
15-
}
13+
const subConditionsIsArray = Array.isArray(subConditions)
14+
if (booleanOperator !== 'not' && !subConditionsIsArray) throw new Error(`"${booleanOperator}" must be an array`)
15+
if (booleanOperator === 'not' && subConditionsIsArray) throw new Error(`"${booleanOperator}" cannot be an array`)
1616
this.operator = booleanOperator
1717
// boolean conditions always have a priority; default 1
1818
this.priority = parseInt(properties.priority, 10) || 1
19-
this[booleanOperator] = subConditions.map((c) => {
20-
return new Condition(c)
21-
})
19+
if (subConditionsIsArray) {
20+
this[booleanOperator] = subConditions.map((c) => new Condition(c))
21+
} else {
22+
this[booleanOperator] = new Condition(subConditions)
23+
}
2224
} else {
2325
if (!Object.prototype.hasOwnProperty.call(properties, 'fact')) throw new Error('Condition: constructor "fact" property required')
2426
if (!Object.prototype.hasOwnProperty.call(properties, 'operator')) throw new Error('Condition: constructor "operator" property required')
@@ -44,7 +46,11 @@ export default class Condition {
4446
}
4547
const oper = Condition.booleanOperator(this)
4648
if (oper) {
47-
props[oper] = this[oper].map((c) => c.toJSON(stringify))
49+
if (Array.isArray(this[oper])) {
50+
props[oper] = this[oper].map((c) => c.toJSON(false))
51+
} else {
52+
props[oper] = this[oper].toJSON(false)
53+
}
4854
} else {
4955
props.operator = this.operator
5056
props.value = this.value
@@ -110,27 +116,29 @@ export default class Condition {
110116
/**
111117
* Returns the boolean operator for the condition
112118
* If the condition is not a boolean condition, the result will be 'undefined'
113-
* @return {string 'all' or 'any'}
119+
* @return {string 'all', 'any', or 'not'}
114120
*/
115121
static booleanOperator (condition) {
116122
if (Object.prototype.hasOwnProperty.call(condition, 'any')) {
117123
return 'any'
118124
} else if (Object.prototype.hasOwnProperty.call(condition, 'all')) {
119125
return 'all'
126+
} else if (Object.prototype.hasOwnProperty.call(condition, 'not')) {
127+
return 'not'
120128
}
121129
}
122130

123131
/**
124132
* Returns the condition's boolean operator
125133
* Instance version of Condition.isBooleanOperator
126-
* @returns {string,undefined} - 'any', 'all', or undefined (if not a boolean condition)
134+
* @returns {string,undefined} - 'any', 'all', 'not' or undefined (if not a boolean condition)
127135
*/
128136
booleanOperator () {
129137
return Condition.booleanOperator(this)
130138
}
131139

132140
/**
133-
* Whether the operator is boolean ('all', 'any')
141+
* Whether the operator is boolean ('all', 'any', 'not')
134142
* @returns {Boolean}
135143
*/
136144
isBooleanOperator () {

test/condition.test.js

+38
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,26 @@ describe('Condition', () => {
5656
const json = condition.toJSON()
5757
expect(json).to.equal('{"operator":"equal","value":{"fact":"weight","params":{"unit":"lbs"},"path":".value"},"fact":"age"}')
5858
})
59+
60+
it('converts "not" conditions', () => {
61+
const properties = {
62+
not: {
63+
...factories.condition({
64+
fact: 'age',
65+
value: {
66+
fact: 'weight',
67+
params: {
68+
unit: 'lbs'
69+
},
70+
path: '.value'
71+
}
72+
})
73+
}
74+
}
75+
const condition = new Condition(properties)
76+
const json = condition.toJSON()
77+
expect(json).to.equal('{"priority":1,"not":{"operator":"equal","value":{"fact":"weight","params":{"unit":"lbs"},"path":".value"},"fact":"age"}}')
78+
})
5979
})
6080

6181
describe('evaluate', () => {
@@ -267,6 +287,24 @@ describe('Condition', () => {
267287
conditions.all = { foo: true }
268288
expect(() => new Condition(conditions)).to.throw(/"all" must be an array/)
269289
})
290+
291+
it('throws if is an array and condition is "not"', () => {
292+
const conditions = {
293+
not: [{ foo: true }]
294+
}
295+
expect(() => new Condition(conditions)).to.throw(/"not" cannot be an array/)
296+
})
297+
298+
it('does not throw if is not an array and condition is "not"', () => {
299+
const conditions = {
300+
not: {
301+
fact: 'foo',
302+
operator: 'equal',
303+
value: 'bar'
304+
}
305+
}
306+
expect(() => new Condition(conditions)).to.not.throw()
307+
})
270308
})
271309

272310
describe('atomic facts', () => {

0 commit comments

Comments
 (0)