Skip to content

Commit 0de909f

Browse files
author
Cache Hamm
committed
Merge branch 'next-major' into promisify-events
2 parents 2d72d78 + f1546c2 commit 0de909f

8 files changed

Lines changed: 1232 additions & 1883 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
* Private `rule.event` property renamed. Use `rule.getEvent()` to avoid breaking changes in the future.
44
* Engine and Rule events `on('success')`, `on('failure')`, and Rule callbacks `onSuccess` and `onFailure` now honor returned promises; any event handler that returns a promise will be waited upon to resolve before engine execution continues.
55

6+
#### 5.3.0 / 2020-12-02
7+
* Allow facts to have a value of `undefined`
8+
9+
#### 5.2.0 / 2020-11-31
10+
* No changes; published to correct an accidental publish of untagged alpha
11+
612
#### 5.0.4 / 2020-09-26
713
* Upgrade dependencies to latest
814

package-lock.json

Lines changed: 1185 additions & 1864 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
"lint:fix": "standard --fix --env mocha",
1212
"prepublishOnly": "npm run build",
1313
"build": "babel --stage 1 -d dist/ src/",
14-
"watch": "babel --watch --stage 1 -d dist/ src"
14+
"watch": "babel --watch --stage 1 -d dist/ src",
15+
"examples": "./test/support/example_runner.sh"
1516
},
1617
"repository": {
1718
"type": "git",

src/fact.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,6 @@ class Fact {
2626
}
2727

2828
if (!this.id) throw new Error('factId required')
29-
if (typeof this.value === 'undefined' && typeof this.calculationMethod === 'undefined') {
30-
throw new Error('facts must have a value or method')
31-
}
3229

3330
this.priority = parseInt(options.priority || 1, 10)
3431
this.options = Object.assign({}, defaultOptions, options)

test/condition.test.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,15 +66,14 @@ describe('Condition', () => {
6666
let condition
6767
let almanac
6868
function setup (options, factValue) {
69-
if (typeof factValue === 'undefined') factValue = 1
7069
const properties = Object.assign({}, conditionBase, options)
7170
condition = new Condition(properties)
7271
const fact = new Fact(conditionBase.fact, factValue)
7372
almanac = new Almanac(new Map([[fact.id, fact]]))
7473
}
7574

7675
context('validations', () => {
77-
beforeEach(() => setup())
76+
beforeEach(() => setup({}, 1))
7877
it('throws when missing an almanac', () => {
7978
return expect(condition.evaluate(undefined, operators)).to.be.rejectedWith('almanac required')
8079
})
@@ -94,6 +93,18 @@ describe('Condition', () => {
9493
expect((await condition.evaluate(almanac, operators, 5)).result).to.equal(false)
9594
})
9695

96+
it('evaluates "equal" to check for undefined', async () => {
97+
condition = new Condition({ fact: 'age', operator: 'equal', value: undefined })
98+
let fact = new Fact('age', undefined)
99+
almanac = new Almanac(new Map([[fact.id, fact]]))
100+
101+
expect((await condition.evaluate(almanac, operators)).result).to.equal(true)
102+
103+
fact = new Fact('age', 1)
104+
almanac = new Almanac(new Map([[fact.id, fact]]))
105+
expect((await condition.evaluate(almanac, operators)).result).to.equal(false)
106+
})
107+
97108
it('evaluates "notEqual"', async () => {
98109
setup({ operator: 'notEqual' }, 50)
99110
expect((await condition.evaluate(almanac, operators)).result).to.equal(false)

test/engine.test.js

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@
22

33
import sinon from 'sinon'
44
import engineFactory, { Fact, Rule, Operator } from '../src/index'
5+
import defaultOperators from '../src/engine-default-operators'
56

67
describe('Engine', () => {
8+
const operatorCount = defaultOperators.length
9+
710
let engine
811
let sandbox
912
before(() => {
@@ -31,7 +34,7 @@ describe('Engine', () => {
3134
it('initializes with the default state', () => {
3235
expect(engine.status).to.equal('READY')
3336
expect(engine.rules.length).to.equal(0)
34-
expect(engine.operators.size).to.equal(10)
37+
expect(engine.operators.size).to.equal(operatorCount)
3538
})
3639

3740
it('can be initialized with rules', () => {
@@ -119,37 +122,37 @@ describe('Engine', () => {
119122

120123
describe('addOperator()', () => {
121124
it('adds the operator', () => {
122-
expect(engine.operators.size).to.equal(10)
125+
expect(engine.operators.size).to.equal(operatorCount)
123126
engine.addOperator('startsWithLetter', (factValue, jsonValue) => {
124127
return factValue[0] === jsonValue
125128
})
126-
expect(engine.operators.size).to.equal(11)
129+
expect(engine.operators.size).to.equal(operatorCount + 1)
127130
expect(engine.operators.get('startsWithLetter')).to.exist()
128131
expect(engine.operators.get('startsWithLetter')).to.be.an.instanceof(Operator)
129132
})
130133

131134
it('accepts an operator instance', () => {
132-
expect(engine.operators.size).to.equal(10)
135+
expect(engine.operators.size).to.equal(operatorCount)
133136
const op = new Operator('my-operator', _ => true)
134137
engine.addOperator(op)
135-
expect(engine.operators.size).to.equal(11)
138+
expect(engine.operators.size).to.equal(operatorCount + 1)
136139
expect(engine.operators.get('my-operator')).to.equal(op)
137140
})
138141
})
139142

140143
describe('removeOperator()', () => {
141144
it('removes the operator', () => {
142-
expect(engine.operators.size).to.equal(10)
145+
expect(engine.operators.size).to.equal(operatorCount)
143146
engine.addOperator('startsWithLetter', (factValue, jsonValue) => {
144147
return factValue[0] === jsonValue
145148
})
146-
expect(engine.operators.size).to.equal(11)
149+
expect(engine.operators.size).to.equal(operatorCount + 1)
147150
engine.removeOperator('startsWithLetter')
148-
expect(engine.operators.size).to.equal(10)
151+
expect(engine.operators.size).to.equal(operatorCount)
149152
})
150153

151154
it('can only remove added operators', () => {
152-
expect(engine.operators.size).to.equal(10)
155+
expect(engine.operators.size).to.equal(operatorCount)
153156
const isRemoved = engine.removeOperator('nonExisting')
154157
expect(isRemoved).to.equal(false)
155158
})

test/fact.test.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,6 @@ describe('Fact', () => {
2929
it('throws if no id provided', () => {
3030
expect(subject).to.throw(/factId required/)
3131
})
32-
33-
it('throws if no definition provided', () => {
34-
expect(subject.bind(null, 'factId')).to.throw(/facts must have a value or method/)
35-
})
3632
})
3733
})
3834

test/support/example_runner.sh

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/bin/bash
2+
3+
#
4+
# npm links the examples directory to the local copy of json-rules-engine
5+
# and runs all examples. This can be used to test a release candidate version
6+
# against the examples as an extra compatiblity test
7+
#
8+
THIS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
9+
10+
cd $THIS_DIR/../.. # project root
11+
npm link
12+
cd $THIS_DIR/../../examples # examples directory
13+
npm link json-rules-engine
14+
for i in *.js; do node $i; done;

0 commit comments

Comments
 (0)