@media-quest/engine 0.0.22 → 0.0.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/Delement/DElement.dto.ts +5 -5
- package/src/Delement/DElement.ts +88 -88
- package/src/Delement/DImg.ts +39 -39
- package/src/Delement/DStyle-utils.ts +616 -616
- package/src/Delement/DStyle.ts +165 -165
- package/src/Delement/DText.ts +13 -13
- package/src/Delement/Ddiv.ts +25 -25
- package/src/Delement/button-click-action.ts +35 -35
- package/src/Delement/css.spec.ts +36 -36
- package/src/Delement/css.ts +46 -46
- package/src/Delement/element-factory.ts +40 -40
- package/src/common/DMaybe.ts +46 -46
- package/src/common/DTimestamp.ts +20 -20
- package/src/common/DTmestamp.spec.ts +11 -11
- package/src/common/result.ts +41 -41
- package/src/engine/SchemaDto.ts +24 -24
- package/src/engine/SchemaEngine.ts +150 -150
- package/src/engine/SchemaResult.ts +10 -10
- package/src/engine/dplayer.spec.ts +91 -91
- package/src/engine/dplayer.ts +104 -104
- package/src/engine/history-que.spec.ts +67 -67
- package/src/engine/history-que.ts +17 -17
- package/src/engine/next-que.spec.ts +121 -121
- package/src/engine/next-que.ts +101 -101
- package/src/engine/page-que-ruleengine-action.ts +6 -6
- package/src/engine/scale.spec.ts +38 -38
- package/src/engine/scale.ts +70 -70
- package/src/events/mq-events.ts +63 -63
- package/src/page/Page.ts +182 -182
- package/src/page/media-player.ts +117 -117
- package/src/page/page-component.ts +113 -113
- package/src/page/page-result.ts +11 -11
- package/src/page/task-manager.ts +240 -240
- package/src/page/task-state.ts +55 -55
- package/src/page/task.ts +90 -90
- package/src/public-api.ts +26 -26
- package/src/rules/__test__/complex-condition.spec.ts +15 -15
- package/src/rules/__test__/conditon.spec.ts +124 -124
- package/src/rules/__test__/numeric-condition.spec.ts +84 -84
- package/src/rules/__test__/rule-engine.spec.ts +348 -348
- package/src/rules/__test__/rule-evaluation.spec.ts +140 -140
- package/src/rules/__test__/string-condition.spec.ts +41 -41
- package/src/rules/condition.ts +191 -191
- package/src/rules/fact.ts +18 -18
- package/src/rules/rule-engine.ts +45 -45
- package/src/rules/rule.ts +40 -40
- package/src/utils/DUtil.ts +116 -116
- package/src/utils/ID.spec.ts +39 -39
- package/src/utils/ID.ts +73 -73
- package/tsconfig.json +19 -19
package/src/page/task.ts
CHANGED
|
@@ -1,90 +1,90 @@
|
|
|
1
|
-
type BaseTask = {
|
|
2
|
-
readonly blockAudio: boolean;
|
|
3
|
-
readonly blockVideo: boolean;
|
|
4
|
-
readonly blockResponseButton: boolean;
|
|
5
|
-
readonly blockFormInput: boolean;
|
|
6
|
-
readonly priority:
|
|
7
|
-
| "run-if-idle"
|
|
8
|
-
| "follow-queue"
|
|
9
|
-
| "replace-all"
|
|
10
|
-
| "replace-current"
|
|
11
|
-
| "replace-queue"
|
|
12
|
-
| "prepend-to-queue"
|
|
13
|
-
| "append-to-queue";
|
|
14
|
-
};
|
|
15
|
-
export type DelayTask = BaseTask & {
|
|
16
|
-
readonly kind: "delay-task";
|
|
17
|
-
readonly duration: number;
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
export type PlayAudioTask = BaseTask & {
|
|
21
|
-
readonly kind: "play-audio-task";
|
|
22
|
-
readonly url: string;
|
|
23
|
-
readonly audioId: string;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export type PlayVideoTask = BaseTask & {
|
|
27
|
-
readonly kind: "play-video-task";
|
|
28
|
-
readonly url: string;
|
|
29
|
-
readonly videoId: string;
|
|
30
|
-
readonly loop?: boolean;
|
|
31
|
-
readonly startAt?: number;
|
|
32
|
-
readonly stopAt?: "end" | "start" | number;
|
|
33
|
-
readonly volume?: number;
|
|
34
|
-
};
|
|
35
|
-
const eq = (a: Task, b: Task) => {
|
|
36
|
-
if (!b) {
|
|
37
|
-
return false;
|
|
38
|
-
}
|
|
39
|
-
if (a.kind !== b.kind) {
|
|
40
|
-
return false;
|
|
41
|
-
}
|
|
42
|
-
if (a.kind === "delay-task" && b.kind === "delay-task") {
|
|
43
|
-
return a.duration === b.duration;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (a.kind === "play-audio-task" && b.kind === "play-audio-task") {
|
|
47
|
-
return a.url === b.url && a.audioId === b.audioId;
|
|
48
|
-
}
|
|
49
|
-
if (a.kind === "play-video-task" && b.kind === "play-video-task") {
|
|
50
|
-
return (
|
|
51
|
-
a.url === b.url &&
|
|
52
|
-
a.videoId === b.videoId &&
|
|
53
|
-
a.startAt === b.startAt &&
|
|
54
|
-
a.stopAt === b.stopAt &&
|
|
55
|
-
a.volume === b.volume
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
return false;
|
|
59
|
-
};
|
|
60
|
-
const deleteTaskList = (task: Task) => {
|
|
61
|
-
return task.priority === "replace-all" || task.priority === "replace-queue";
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
const shallRemoveCurrent = (task: Task) => {
|
|
65
|
-
return task.priority === "replace-current" || task.priority === "replace-all";
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
const notEq = (a: Task, b: Task) => !eq(a, b);
|
|
69
|
-
|
|
70
|
-
const is = (task: Task | undefined | false | null | {}): task is Task => {
|
|
71
|
-
if (!task) {
|
|
72
|
-
return false;
|
|
73
|
-
}
|
|
74
|
-
if (typeof task !== "object") {
|
|
75
|
-
return false;
|
|
76
|
-
}
|
|
77
|
-
if (Array.isArray(task)) {
|
|
78
|
-
return false;
|
|
79
|
-
}
|
|
80
|
-
return true;
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
export const Task = {
|
|
84
|
-
eq,
|
|
85
|
-
is,
|
|
86
|
-
notEq,
|
|
87
|
-
deleteTaskList,
|
|
88
|
-
shallRemoveCurrent,
|
|
89
|
-
};
|
|
90
|
-
export type Task = PlayVideoTask | PlayAudioTask | DelayTask;
|
|
1
|
+
type BaseTask = {
|
|
2
|
+
readonly blockAudio: boolean;
|
|
3
|
+
readonly blockVideo: boolean;
|
|
4
|
+
readonly blockResponseButton: boolean;
|
|
5
|
+
readonly blockFormInput: boolean;
|
|
6
|
+
readonly priority:
|
|
7
|
+
| "run-if-idle"
|
|
8
|
+
| "follow-queue"
|
|
9
|
+
| "replace-all"
|
|
10
|
+
| "replace-current"
|
|
11
|
+
| "replace-queue"
|
|
12
|
+
| "prepend-to-queue"
|
|
13
|
+
| "append-to-queue";
|
|
14
|
+
};
|
|
15
|
+
export type DelayTask = BaseTask & {
|
|
16
|
+
readonly kind: "delay-task";
|
|
17
|
+
readonly duration: number;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export type PlayAudioTask = BaseTask & {
|
|
21
|
+
readonly kind: "play-audio-task";
|
|
22
|
+
readonly url: string;
|
|
23
|
+
readonly audioId: string;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export type PlayVideoTask = BaseTask & {
|
|
27
|
+
readonly kind: "play-video-task";
|
|
28
|
+
readonly url: string;
|
|
29
|
+
readonly videoId: string;
|
|
30
|
+
readonly loop?: boolean;
|
|
31
|
+
readonly startAt?: number;
|
|
32
|
+
readonly stopAt?: "end" | "start" | number;
|
|
33
|
+
readonly volume?: number;
|
|
34
|
+
};
|
|
35
|
+
const eq = (a: Task, b: Task) => {
|
|
36
|
+
if (!b) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
if (a.kind !== b.kind) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
if (a.kind === "delay-task" && b.kind === "delay-task") {
|
|
43
|
+
return a.duration === b.duration;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (a.kind === "play-audio-task" && b.kind === "play-audio-task") {
|
|
47
|
+
return a.url === b.url && a.audioId === b.audioId;
|
|
48
|
+
}
|
|
49
|
+
if (a.kind === "play-video-task" && b.kind === "play-video-task") {
|
|
50
|
+
return (
|
|
51
|
+
a.url === b.url &&
|
|
52
|
+
a.videoId === b.videoId &&
|
|
53
|
+
a.startAt === b.startAt &&
|
|
54
|
+
a.stopAt === b.stopAt &&
|
|
55
|
+
a.volume === b.volume
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
return false;
|
|
59
|
+
};
|
|
60
|
+
const deleteTaskList = (task: Task) => {
|
|
61
|
+
return task.priority === "replace-all" || task.priority === "replace-queue";
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const shallRemoveCurrent = (task: Task) => {
|
|
65
|
+
return task.priority === "replace-current" || task.priority === "replace-all";
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const notEq = (a: Task, b: Task) => !eq(a, b);
|
|
69
|
+
|
|
70
|
+
const is = (task: Task | undefined | false | null | {}): task is Task => {
|
|
71
|
+
if (!task) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
if (typeof task !== "object") {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
if (Array.isArray(task)) {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
return true;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export const Task = {
|
|
84
|
+
eq,
|
|
85
|
+
is,
|
|
86
|
+
notEq,
|
|
87
|
+
deleteTaskList,
|
|
88
|
+
shallRemoveCurrent,
|
|
89
|
+
};
|
|
90
|
+
export type Task = PlayVideoTask | PlayAudioTask | DelayTask;
|
package/src/public-api.ts
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
export * from "./engine/SchemaResult";
|
|
2
|
-
export * from "./engine/SchemaEngine";
|
|
3
|
-
export * from "./engine/SchemaDto";
|
|
4
|
-
export * from "./engine/page-que-ruleengine-action";
|
|
5
|
-
export * from "./rules/rule";
|
|
6
|
-
export * from "./rules/fact";
|
|
7
|
-
export * from "./rules/rule-engine";
|
|
8
|
-
export * from "./rules/condition";
|
|
9
|
-
export * from "./utils/DUtil";
|
|
10
|
-
export * from "./utils/ID";
|
|
11
|
-
|
|
12
|
-
export * from "./events/mq-events";
|
|
13
|
-
|
|
14
|
-
export * from "./page/page-component";
|
|
15
|
-
|
|
16
|
-
// ELEMENTS
|
|
17
|
-
export * from "./Delement/css";
|
|
18
|
-
export * from "./Delement/DStyle";
|
|
19
|
-
export * from "./Delement/DImg";
|
|
20
|
-
export * from "./Delement/DText";
|
|
21
|
-
export * from "./Delement/Ddiv";
|
|
22
|
-
export * from "./Delement/button-click-action";
|
|
23
|
-
export * from "./Delement/DElement";
|
|
24
|
-
export * from "./Delement/DElement.dto";
|
|
25
|
-
export { PageDto } from "./page/Page";
|
|
26
|
-
export * from "./page/task";
|
|
1
|
+
export * from "./engine/SchemaResult";
|
|
2
|
+
export * from "./engine/SchemaEngine";
|
|
3
|
+
export * from "./engine/SchemaDto";
|
|
4
|
+
export * from "./engine/page-que-ruleengine-action";
|
|
5
|
+
export * from "./rules/rule";
|
|
6
|
+
export * from "./rules/fact";
|
|
7
|
+
export * from "./rules/rule-engine";
|
|
8
|
+
export * from "./rules/condition";
|
|
9
|
+
export * from "./utils/DUtil";
|
|
10
|
+
export * from "./utils/ID";
|
|
11
|
+
|
|
12
|
+
export * from "./events/mq-events";
|
|
13
|
+
|
|
14
|
+
export * from "./page/page-component";
|
|
15
|
+
|
|
16
|
+
// ELEMENTS
|
|
17
|
+
export * from "./Delement/css";
|
|
18
|
+
export * from "./Delement/DStyle";
|
|
19
|
+
export * from "./Delement/DImg";
|
|
20
|
+
export * from "./Delement/DText";
|
|
21
|
+
export * from "./Delement/Ddiv";
|
|
22
|
+
export * from "./Delement/button-click-action";
|
|
23
|
+
export * from "./Delement/DElement";
|
|
24
|
+
export * from "./Delement/DElement.dto";
|
|
25
|
+
export { PageDto } from "./page/Page";
|
|
26
|
+
export * from "./page/task";
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { Condition } from '../condition';
|
|
2
|
-
describe('Rule validations', () => {
|
|
3
|
-
// beforeEach(() => {
|
|
4
|
-
// });
|
|
5
|
-
|
|
6
|
-
it('isCondition -> true', () => {
|
|
7
|
-
const d: Condition.Complex = {
|
|
8
|
-
kind: 'complex-condition',
|
|
9
|
-
name: 'test-name',
|
|
10
|
-
all: [],
|
|
11
|
-
some: [],
|
|
12
|
-
};
|
|
13
|
-
expect(Condition.isEmpty(d)).toBe(true);
|
|
14
|
-
});
|
|
15
|
-
});
|
|
1
|
+
import { Condition } from '../condition';
|
|
2
|
+
describe('Rule validations', () => {
|
|
3
|
+
// beforeEach(() => {
|
|
4
|
+
// });
|
|
5
|
+
|
|
6
|
+
it('isCondition -> true', () => {
|
|
7
|
+
const d: Condition.Complex = {
|
|
8
|
+
kind: 'complex-condition',
|
|
9
|
+
name: 'test-name',
|
|
10
|
+
all: [],
|
|
11
|
+
some: [],
|
|
12
|
+
};
|
|
13
|
+
expect(Condition.isEmpty(d)).toBe(true);
|
|
14
|
+
});
|
|
15
|
+
});
|
|
@@ -1,124 +1,124 @@
|
|
|
1
|
-
import { Condition } from "../condition";
|
|
2
|
-
import { Fact } from "../fact";
|
|
3
|
-
|
|
4
|
-
const xEqCondition = (value: number): Condition.Numeric => {
|
|
5
|
-
const numericCondition: Condition.Numeric = {
|
|
6
|
-
kind: "numeric-condition",
|
|
7
|
-
value,
|
|
8
|
-
valueLabel: "value-label",
|
|
9
|
-
operator: "eq",
|
|
10
|
-
referenceId: "x",
|
|
11
|
-
referenceLabel: "fact-label",
|
|
12
|
-
};
|
|
13
|
-
return numericCondition;
|
|
14
|
-
};
|
|
15
|
-
const exq1: Fact.Numeric = {
|
|
16
|
-
label: "",
|
|
17
|
-
referenceId: "x",
|
|
18
|
-
referenceLabel: "x-label",
|
|
19
|
-
value: 1,
|
|
20
|
-
kind: "numeric-fact",
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
const exq2: Fact.Numeric = {
|
|
24
|
-
label: "",
|
|
25
|
-
referenceId: "x",
|
|
26
|
-
referenceLabel: "x-label",
|
|
27
|
-
value: 2,
|
|
28
|
-
kind: "numeric-fact",
|
|
29
|
-
};
|
|
30
|
-
const f = {
|
|
31
|
-
xeq1: exq1,
|
|
32
|
-
xeq2: exq2,
|
|
33
|
-
} as const;
|
|
34
|
-
const con = {
|
|
35
|
-
xeq1: xEqCondition(1),
|
|
36
|
-
xeq2: xEqCondition(2),
|
|
37
|
-
xeq3: xEqCondition(3),
|
|
38
|
-
} as const;
|
|
39
|
-
|
|
40
|
-
const complex = (all: Condition.Simple[], some: Condition.Simple[]): Condition.Complex => ({
|
|
41
|
-
kind: "complex-condition",
|
|
42
|
-
all,
|
|
43
|
-
some,
|
|
44
|
-
name: "test-name",
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
const validNumericCondition: Condition.Numeric = {
|
|
48
|
-
kind: "numeric-condition",
|
|
49
|
-
value: 1,
|
|
50
|
-
referenceId: "x",
|
|
51
|
-
referenceLabel: "fact-label",
|
|
52
|
-
valueLabel: "value-label",
|
|
53
|
-
operator: "not-eq",
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
const inValidFactId: Condition.Numeric = {
|
|
57
|
-
kind: "numeric-condition",
|
|
58
|
-
value: 1,
|
|
59
|
-
referenceId: "",
|
|
60
|
-
referenceLabel: "fact-label",
|
|
61
|
-
valueLabel: "value-label",
|
|
62
|
-
operator: "not-eq",
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
const undefinedCondition = undefined as unknown as Condition;
|
|
66
|
-
|
|
67
|
-
const validStringCondition: Condition.String = {
|
|
68
|
-
kind: "string-condition",
|
|
69
|
-
value: "hello",
|
|
70
|
-
referenceId: "asdf",
|
|
71
|
-
referenceLabel: "fact-label",
|
|
72
|
-
valueLabel: "value-label",
|
|
73
|
-
operator: "not-eq",
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
describe("Can pick all simple conditions from Complex.", () => {
|
|
77
|
-
const complex: Condition.Complex = {
|
|
78
|
-
kind: "complex-condition",
|
|
79
|
-
name: "test-condition",
|
|
80
|
-
all: [validStringCondition, validNumericCondition],
|
|
81
|
-
some: [inValidFactId, validNumericCondition, inValidFactId],
|
|
82
|
-
};
|
|
83
|
-
it("empty condition will always be false", () => {
|
|
84
|
-
expect(Condition.getAllSimpleConditions(complex).length).toBe(5);
|
|
85
|
-
expect(Condition.getAllSimpleConditions([complex, complex, validNumericCondition, inValidFactId]).length).toBe(
|
|
86
|
-
12
|
|
87
|
-
);
|
|
88
|
-
});
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
describe("condition validation", () => {
|
|
92
|
-
it("empty condition will always be false", () => {
|
|
93
|
-
expect(Condition.evaluate(complex([], []), [f.xeq1])).toBe(false);
|
|
94
|
-
});
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
describe("condition evaluation", () => {
|
|
98
|
-
it("If 1 in some is true -> true", () => {
|
|
99
|
-
const all: Condition.Simple[] = [];
|
|
100
|
-
const some: Condition.Simple[] = [con.xeq1, con.xeq3];
|
|
101
|
-
const facts: Fact[] = [f.xeq1];
|
|
102
|
-
expect(Condition.evaluate(complex(all, some), facts)).toBe(true);
|
|
103
|
-
});
|
|
104
|
-
it("If not all is true (empty some) -> false", () => {
|
|
105
|
-
const all: Condition.Simple[] = [con.xeq1, con.xeq3];
|
|
106
|
-
const some: Condition.Simple[] = [];
|
|
107
|
-
const facts: Fact[] = [f.xeq1];
|
|
108
|
-
expect(Condition.evaluate(complex(all, some), facts)).toBe(false);
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
it("If not all is true (non empty some) -> false", () => {
|
|
112
|
-
const all: Condition.Simple[] = [con.xeq1, con.xeq3];
|
|
113
|
-
const some: Condition.Simple[] = [con.xeq3];
|
|
114
|
-
const facts: Fact[] = [f.xeq1];
|
|
115
|
-
expect(Condition.evaluate(complex(all, some), facts)).toBe(false);
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
it("If not all is true (non empty some) -> false", () => {
|
|
119
|
-
const all: Condition.Simple[] = [con.xeq1, con.xeq3];
|
|
120
|
-
const some: Condition.Simple[] = [con.xeq3];
|
|
121
|
-
const facts: Fact[] = [f.xeq1];
|
|
122
|
-
expect(Condition.evaluate(complex(all, some), facts)).toBe(false);
|
|
123
|
-
});
|
|
124
|
-
});
|
|
1
|
+
import { Condition } from "../condition";
|
|
2
|
+
import { Fact } from "../fact";
|
|
3
|
+
|
|
4
|
+
const xEqCondition = (value: number): Condition.Numeric => {
|
|
5
|
+
const numericCondition: Condition.Numeric = {
|
|
6
|
+
kind: "numeric-condition",
|
|
7
|
+
value,
|
|
8
|
+
valueLabel: "value-label",
|
|
9
|
+
operator: "eq",
|
|
10
|
+
referenceId: "x",
|
|
11
|
+
referenceLabel: "fact-label",
|
|
12
|
+
};
|
|
13
|
+
return numericCondition;
|
|
14
|
+
};
|
|
15
|
+
const exq1: Fact.Numeric = {
|
|
16
|
+
label: "",
|
|
17
|
+
referenceId: "x",
|
|
18
|
+
referenceLabel: "x-label",
|
|
19
|
+
value: 1,
|
|
20
|
+
kind: "numeric-fact",
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const exq2: Fact.Numeric = {
|
|
24
|
+
label: "",
|
|
25
|
+
referenceId: "x",
|
|
26
|
+
referenceLabel: "x-label",
|
|
27
|
+
value: 2,
|
|
28
|
+
kind: "numeric-fact",
|
|
29
|
+
};
|
|
30
|
+
const f = {
|
|
31
|
+
xeq1: exq1,
|
|
32
|
+
xeq2: exq2,
|
|
33
|
+
} as const;
|
|
34
|
+
const con = {
|
|
35
|
+
xeq1: xEqCondition(1),
|
|
36
|
+
xeq2: xEqCondition(2),
|
|
37
|
+
xeq3: xEqCondition(3),
|
|
38
|
+
} as const;
|
|
39
|
+
|
|
40
|
+
const complex = (all: Condition.Simple[], some: Condition.Simple[]): Condition.Complex => ({
|
|
41
|
+
kind: "complex-condition",
|
|
42
|
+
all,
|
|
43
|
+
some,
|
|
44
|
+
name: "test-name",
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const validNumericCondition: Condition.Numeric = {
|
|
48
|
+
kind: "numeric-condition",
|
|
49
|
+
value: 1,
|
|
50
|
+
referenceId: "x",
|
|
51
|
+
referenceLabel: "fact-label",
|
|
52
|
+
valueLabel: "value-label",
|
|
53
|
+
operator: "not-eq",
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const inValidFactId: Condition.Numeric = {
|
|
57
|
+
kind: "numeric-condition",
|
|
58
|
+
value: 1,
|
|
59
|
+
referenceId: "",
|
|
60
|
+
referenceLabel: "fact-label",
|
|
61
|
+
valueLabel: "value-label",
|
|
62
|
+
operator: "not-eq",
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const undefinedCondition = undefined as unknown as Condition;
|
|
66
|
+
|
|
67
|
+
const validStringCondition: Condition.String = {
|
|
68
|
+
kind: "string-condition",
|
|
69
|
+
value: "hello",
|
|
70
|
+
referenceId: "asdf",
|
|
71
|
+
referenceLabel: "fact-label",
|
|
72
|
+
valueLabel: "value-label",
|
|
73
|
+
operator: "not-eq",
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
describe("Can pick all simple conditions from Complex.", () => {
|
|
77
|
+
const complex: Condition.Complex = {
|
|
78
|
+
kind: "complex-condition",
|
|
79
|
+
name: "test-condition",
|
|
80
|
+
all: [validStringCondition, validNumericCondition],
|
|
81
|
+
some: [inValidFactId, validNumericCondition, inValidFactId],
|
|
82
|
+
};
|
|
83
|
+
it("empty condition will always be false", () => {
|
|
84
|
+
expect(Condition.getAllSimpleConditions(complex).length).toBe(5);
|
|
85
|
+
expect(Condition.getAllSimpleConditions([complex, complex, validNumericCondition, inValidFactId]).length).toBe(
|
|
86
|
+
12
|
|
87
|
+
);
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
describe("condition validation", () => {
|
|
92
|
+
it("empty condition will always be false", () => {
|
|
93
|
+
expect(Condition.evaluate(complex([], []), [f.xeq1])).toBe(false);
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
describe("condition evaluation", () => {
|
|
98
|
+
it("If 1 in some is true -> true", () => {
|
|
99
|
+
const all: Condition.Simple[] = [];
|
|
100
|
+
const some: Condition.Simple[] = [con.xeq1, con.xeq3];
|
|
101
|
+
const facts: Fact[] = [f.xeq1];
|
|
102
|
+
expect(Condition.evaluate(complex(all, some), facts)).toBe(true);
|
|
103
|
+
});
|
|
104
|
+
it("If not all is true (empty some) -> false", () => {
|
|
105
|
+
const all: Condition.Simple[] = [con.xeq1, con.xeq3];
|
|
106
|
+
const some: Condition.Simple[] = [];
|
|
107
|
+
const facts: Fact[] = [f.xeq1];
|
|
108
|
+
expect(Condition.evaluate(complex(all, some), facts)).toBe(false);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it("If not all is true (non empty some) -> false", () => {
|
|
112
|
+
const all: Condition.Simple[] = [con.xeq1, con.xeq3];
|
|
113
|
+
const some: Condition.Simple[] = [con.xeq3];
|
|
114
|
+
const facts: Fact[] = [f.xeq1];
|
|
115
|
+
expect(Condition.evaluate(complex(all, some), facts)).toBe(false);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it("If not all is true (non empty some) -> false", () => {
|
|
119
|
+
const all: Condition.Simple[] = [con.xeq1, con.xeq3];
|
|
120
|
+
const some: Condition.Simple[] = [con.xeq3];
|
|
121
|
+
const facts: Fact[] = [f.xeq1];
|
|
122
|
+
expect(Condition.evaluate(complex(all, some), facts)).toBe(false);
|
|
123
|
+
});
|
|
124
|
+
});
|