Skip to content

Commit 6449c59

Browse files
committed
Fixing validation
1 parent 0ac40a4 commit 6449c59

File tree

3 files changed

+99
-30
lines changed

3 files changed

+99
-30
lines changed

src/validation.js

+6-7
Original file line numberDiff line numberDiff line change
@@ -32,23 +32,22 @@ export function predicatesFromRule(rule, schema) {
3232

3333
export function predicatesFromCondition(condition, schema) {
3434
return flatMap(Object.keys(condition), ref => {
35+
let refVal = condition[ref];
3536
if (ref === OR || ref === AND) {
36-
if (Array.isArray(condition[ref])) {
37-
return flatMap(condition[ref], w => predicatesFromRule(w, schema));
37+
if (Array.isArray(refVal)) {
38+
return flatMap(refVal, c => predicatesFromCondition(c, schema));
3839
} else {
39-
toError(
40-
`${ref} with ${JSON.stringify(condition[ref])} must be an Array`
41-
);
40+
toError(`${ref} with ${JSON.stringify(refVal)} must be an Array`);
4241
return [];
4342
}
4443
} else if (ref === NOT) {
45-
return predicatesFromCondition(condition[ref], schema);
44+
return predicatesFromCondition(refVal, schema);
4645
} else {
4746
// TODO disable validation of nested structures
4847
let isField = schema.properties[ref] !== undefined;
4948
let isArray = isField && schema.properties[ref].type === "array";
5049
if (isField && !isArray) {
51-
return predicatesFromRule(condition[ref], schema);
50+
return predicatesFromRule(refVal, schema);
5251
} else {
5352
return [];
5453
}

test/documentationExamples.test.js

+68-20
Original file line numberDiff line numberDiff line change
@@ -185,32 +185,80 @@ test("OR", () => {
185185
]);
186186
});
187187

188-
/**
189-
### Boolean operations on multi fields
188+
test("multi field default AND", () => {
189+
let rules = [
190+
{
191+
conditions: {
192+
age: { less: 70 },
193+
country: { is: "USA" },
194+
},
195+
event: EVENT,
196+
},
197+
];
190198

191-
To support cases, when action depends on more, than one field meeting criteria we introduced
192-
multi fields boolean operations.
199+
let engine = new Engine(rules, schema);
200+
expect.assertions(5);
193201

194-
#### Default AND operation
202+
return Promise.all([
203+
engine
204+
.run({ age: 16, country: "China" })
205+
.then(res => expect(res).toEqual([])),
206+
engine
207+
.run({ age: 16, country: "Mexico" })
208+
.then(res => expect(res).toEqual([])),
209+
engine
210+
.run({ age: 16, country: "USA" })
211+
.then(res => expect(res).toEqual([EVENT])),
212+
engine
213+
.run({ age: 69, country: "USA" })
214+
.then(res => expect(res).toEqual([EVENT])),
215+
engine
216+
.run({ age: 70, country: "USA" })
217+
.then(res => expect(res).toEqual([])),
218+
]);
219+
});
195220

196-
Let's say, when `age` is less than 70 and `country` is `USA` we want to `require` `bio`.
221+
test("multi field OR", () => {
222+
let rules = [
223+
{
224+
conditions: {
225+
or: [
226+
{
227+
age: { less: 70 },
228+
country: { is: "USA" },
229+
},
230+
{
231+
state: { is: "NY" },
232+
},
233+
],
234+
},
235+
event: EVENT,
236+
},
237+
];
197238

198-
```js
199-
let rules = [{
200-
conditions: {
201-
age: { less : 70 },
202-
country: { is: "USA" }
203-
},
204-
event: {
205-
type: "require",
206-
params: { fields: [ "bio" ]}
207-
}
208-
}]
209-
```
239+
let engine = new Engine(rules, schema);
240+
expect.assertions(5);
210241

211-
This is the way we can express this. By default each field is treated as a
212-
separate condition and all conditions must be meet.
242+
return Promise.all([
243+
engine
244+
.run({ age: 16, country: "China", state: "Beijing" })
245+
.then(res => expect(res).toEqual([])),
246+
engine
247+
.run({ age: 16, country: "China", state: "NY" })
248+
.then(res => expect(res).toEqual([EVENT])),
249+
engine
250+
.run({ age: 16, country: "USA" })
251+
.then(res => expect(res).toEqual([EVENT])),
252+
engine
253+
.run({ age: 80, state: "NY" })
254+
.then(res => expect(res).toEqual([EVENT])),
255+
engine
256+
.run({ age: 69, country: "USA" })
257+
.then(res => expect(res).toEqual([EVENT])),
258+
]);
259+
});
213260

261+
/**
214262
#### OR
215263
216264
In addition to previous rule we need `bio`, if `state` is `NY`.

test/validation.test.js

+25-3
Original file line numberDiff line numberDiff line change
@@ -209,13 +209,35 @@ test("valid field or", () => {
209209
expect(validateConditionFields(validFieldOr, defSchema)).toBeUndefined();
210210
});
211211

212-
test("extract predicates from when with or & and", () => {
213-
expect(predicatesFromCondition({ or: [{ is: 1 }, { less: 10 }] })).toEqual([
212+
test("extract predicates from rule when with or & and", () => {
213+
expect(predicatesFromRule({ or: [{ is: 1 }, { less: 10 }] })).toEqual([
214214
"is",
215215
"less",
216216
]);
217-
expect(predicatesFromCondition({ and: [{ is: 1 }, { less: 10 }] })).toEqual([
217+
expect(predicatesFromRule({ and: [{ is: 1 }, { less: 10 }] })).toEqual([
218218
"is",
219219
"less",
220220
]);
221221
});
222+
223+
test("extract predicates from condition when with or & and", () => {
224+
let schema = {
225+
properties: {
226+
age: { type: "integer" },
227+
grade: { type: "integer" },
228+
},
229+
};
230+
231+
expect(
232+
predicatesFromCondition(
233+
{ or: [{ age: { is: 1 } }, { grade: { less: 10 } }] },
234+
schema
235+
)
236+
).toEqual(["is", "less"]);
237+
expect(
238+
predicatesFromCondition(
239+
{ and: [{ age: { is: 1 } }, { grade: { less: 10 } }] },
240+
schema
241+
)
242+
).toEqual(["is", "less"]);
243+
});

0 commit comments

Comments
 (0)