@media-quest/engine 0.0.1 → 0.0.3

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.
Files changed (65) hide show
  1. package/dist/public-api.d.mts +543 -0
  2. package/dist/public-api.d.ts +543 -0
  3. package/dist/public-api.js +2187 -0
  4. package/dist/public-api.mjs +2150 -0
  5. package/package.json +10 -3
  6. package/src/Delement/AudioContainer.ts +169 -0
  7. package/src/Delement/DAuto-play.ts +36 -0
  8. package/src/Delement/DElement.ts +263 -0
  9. package/src/Delement/DImg.ts +78 -0
  10. package/src/Delement/DStyle-utils.ts +616 -0
  11. package/src/Delement/DStyle.ts +165 -0
  12. package/src/Delement/DText.ts +29 -0
  13. package/src/Delement/Ddiv.ts +38 -0
  14. package/src/Delement/VideoContainer.ts +199 -0
  15. package/src/Delement/css.spec.ts +36 -0
  16. package/src/Delement/css.ts +46 -0
  17. package/src/commands/DCommand.ts +62 -0
  18. package/src/commands/DCommandBus.ts +60 -0
  19. package/src/common/DMaybe.ts +46 -0
  20. package/src/common/DTimestamp.ts +20 -0
  21. package/src/common/DTmestamp.spec.ts +11 -0
  22. package/src/common/result.ts +41 -0
  23. package/src/dto/AnimationDto.ts +4 -0
  24. package/src/dto/DElement.dto.ts +50 -0
  25. package/src/dto/SchemaDto.ts +65 -0
  26. package/src/engine/DPage.ts +55 -0
  27. package/src/engine/SchemaEngine.ts +210 -0
  28. package/src/engine/element-factory.ts +52 -0
  29. package/src/engine/scale.spec.ts +38 -0
  30. package/src/engine/scale.ts +70 -0
  31. package/src/event-handlers/DEventHandler.ts +29 -0
  32. package/src/events/DEvents.ts +94 -0
  33. package/src/events/event-bus.spec.ts +21 -0
  34. package/src/events/event-bus.ts +81 -0
  35. package/src/kladd/context-menu-manager.ts +56 -0
  36. package/src/player/dplayer.spec.ts +108 -0
  37. package/src/player/dplayer.ts +70 -0
  38. package/src/player/history-que.spec.ts +45 -0
  39. package/src/player/history-que.ts +38 -0
  40. package/src/player/next-que.spec.ts +108 -0
  41. package/src/player/next-que.ts +93 -0
  42. package/src/public-api.ts +18 -5
  43. package/src/rules/__test__/complex-condition.spec.ts +15 -0
  44. package/src/rules/__test__/conditon.spec.ts +124 -0
  45. package/src/rules/__test__/numeric-condition.spec.ts +84 -0
  46. package/src/rules/__test__/rule-engine.spec.ts +354 -0
  47. package/src/rules/__test__/rule-evaluation.spec.ts +140 -0
  48. package/src/rules/__test__/string-condition.spec.ts +41 -0
  49. package/src/rules/condition.ts +191 -0
  50. package/src/rules/fact.ts +18 -0
  51. package/src/rules/rule-engine.ts +46 -0
  52. package/src/rules/rule.ts +40 -0
  53. package/src/services/DMedia-manager.spec.ts +27 -0
  54. package/src/services/DMedia-manager.ts +182 -0
  55. package/src/services/resource-provider.ts +33 -0
  56. package/src/services/sequence-manager.spec.ts +168 -0
  57. package/src/services/sequence-manager.ts +132 -0
  58. package/src/state/Dstate.spec.ts +7 -0
  59. package/src/state/Dstate.ts +105 -0
  60. package/src/state/boolean-property.ts +69 -0
  61. package/src/state/state-service.spec.ts +307 -0
  62. package/src/state/state-service.ts +251 -0
  63. package/src/state/state-testing-helpers.ts +59 -0
  64. package/src/utils/DUtil.ts +109 -0
  65. package/tsconfig.json +4 -3
@@ -0,0 +1,93 @@
1
+ import { PageDto } from "../dto/SchemaDto";
2
+
3
+ export class NextQue {
4
+ private originalOrder: ReadonlyArray<string> = [];
5
+ private allPages: PageDto[] = [];
6
+ private excludedTags = new Set<string>();
7
+ private excludedByPageId = new Set<string>();
8
+ private remaining: PageDto[] = [];
9
+ constructor(pages: PageDto[] = []) {
10
+ this.resetQue(pages);
11
+ }
12
+
13
+ /**
14
+ * Will reset que with the new pages.
15
+ * @param pages
16
+ */
17
+ resetQue(pages: PageDto[]) {
18
+ this.allPages = [...pages];
19
+ this.remaining = [...pages];
20
+ this.excludedTags = new Set();
21
+ this.excludedByPageId = new Set();
22
+ this.originalOrder = this.allPages.map((p) => p.id);
23
+ }
24
+
25
+ pop(): PageDto | false {
26
+ const next = this.remaining.shift();
27
+ // TODO CLONE??
28
+ return next ?? false;
29
+ }
30
+
31
+ peek(): PageDto | false {
32
+ const next = this.remaining[0];
33
+ return next ?? false;
34
+ }
35
+
36
+ jumpToPageById(pageId: string): boolean {
37
+ const index = this.remaining.findIndex((p) => p.id === pageId);
38
+ if (index < 0) {
39
+ return false;
40
+ }
41
+ this.remaining = this.remaining.slice(index);
42
+ return true;
43
+ }
44
+
45
+ removeByTag(tag: string | string[]) {
46
+ if (Array.isArray(tag)) {
47
+ tag.forEach((tag) => {
48
+ this.excludedTags.add(tag);
49
+ });
50
+ } else {
51
+ this.excludedTags.add(tag);
52
+ }
53
+ this.filterRemaining();
54
+ }
55
+
56
+ /**
57
+ * Will not be included
58
+ * @param pages
59
+ */
60
+ insertAsNextByForce(pages: PageDto[]) {
61
+ this.remaining.unshift(...pages);
62
+ }
63
+
64
+ removeByPageId(pageId: string | string[]) {
65
+ if (Array.isArray(pageId)) {
66
+ pageId.forEach((id) => {
67
+ this.excludedByPageId.add(id);
68
+ });
69
+ } else {
70
+ this.excludedByPageId.add(pageId);
71
+ }
72
+ this.filterRemaining();
73
+ // this.excludedByPageId.add(pageId);
74
+ }
75
+
76
+ private filterRemaining() {
77
+ this.remaining = this.remaining.filter((p) => {
78
+ const tags = p.tags ?? [];
79
+ const isIncluededByTag = !tags.some((tag) => this.excludedTags.has(tag));
80
+ const isIncludedByPageId = !this.excludedByPageId.has(p.id);
81
+ return isIncludedByPageId && isIncluededByTag;
82
+ });
83
+ }
84
+ get isEmpty(): boolean {
85
+ return this.remaining.length === 0;
86
+ }
87
+ get size(): number {
88
+ return this.remaining.length;
89
+ }
90
+ get pageCount(): number {
91
+ return this.originalOrder.length;
92
+ }
93
+ }
package/src/public-api.ts CHANGED
@@ -1,5 +1,18 @@
1
- export const createEngine = () => {
2
- const engine = document.createElement("div");
3
- engine.innerText = "ENGINE";
4
- return engine;
5
- }
1
+ export { SchemaEngine } from "./engine/SchemaEngine";
2
+ export * from "./dto/SchemaDto";
3
+ export * from "./dto/AnimationDto";
4
+ export * from "./dto/DElement.dto";
5
+ export * from "./event-handlers/DEventHandler";
6
+ export * from "./commands/DCommand";
7
+ export * from "./events/DEvents";
8
+ export * from "./rules/rule";
9
+ export * from "./rules/fact";
10
+ export * from "./rules/rule-engine";
11
+ export * from "./rules/condition";
12
+ export * from "./state/boolean-property";
13
+ export * from "./state/Dstate";
14
+ export * from "./Delement/DStyle";
15
+ export * from "./Delement/DAuto-play";
16
+ export * from "./Delement/css";
17
+
18
+ export * from "./utils/DUtil";
@@ -0,0 +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
+ });
@@ -0,0 +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
+ });
@@ -0,0 +1,84 @@
1
+ import { Condition } from "../condition";
2
+ import { Fact } from "../fact";
3
+ const numFact = (n: number): [Fact.Numeric] => [
4
+ {
5
+ kind: "numeric-fact",
6
+ value: n,
7
+ label: "Label-for " + n,
8
+ referenceId: "test-fact",
9
+ referenceLabel: "test-fact-label",
10
+ },
11
+ ];
12
+ const eq0: Condition.Numeric = {
13
+ kind: "numeric-condition",
14
+ referenceId: "test-fact",
15
+ operator: "eq",
16
+ value: 0,
17
+ referenceLabel: "fact-label",
18
+ valueLabel: "value-label",
19
+ };
20
+
21
+ const notEq0: Condition.Numeric = {
22
+ ...eq0,
23
+ operator: "not-eq",
24
+ };
25
+
26
+ const lessThen0: Condition.Numeric = {
27
+ ...eq0,
28
+ operator: "less-then",
29
+ };
30
+
31
+ const greaterThen0: Condition.Numeric = {
32
+ ...eq0,
33
+ operator: "greater-then",
34
+ };
35
+ const greaterThen0Inclusive: Condition.Numeric = {
36
+ ...eq0,
37
+ operator: "greater-then-inclusive",
38
+ };
39
+
40
+ const lessThen0Inclusive: Condition.Numeric = {
41
+ ...eq0,
42
+ operator: "less-then-inclusive",
43
+ };
44
+
45
+ describe("Numeric conditions", () => {
46
+ // beforeEach(() => {});
47
+
48
+ it("eq works", () => {
49
+ const equals = Condition.evaluate(eq0, numFact(0));
50
+ const notEquals = Condition.evaluate(eq0, numFact(1));
51
+ expect(equals).toBe(true);
52
+ expect(notEquals).toBe(false);
53
+ });
54
+
55
+ it("not-eq works", () => {
56
+ expect(Condition.evaluate(notEq0, numFact(1))).toBe(true);
57
+ expect(Condition.evaluate(notEq0, numFact(-1))).toBe(true);
58
+ expect(Condition.evaluate(notEq0, numFact(0))).toBe(false);
59
+ });
60
+
61
+ it("less than works", () => {
62
+ expect(Condition.evaluate(lessThen0, numFact(-1))).toBe(true);
63
+ expect(Condition.evaluate(lessThen0, numFact(0))).toBe(false);
64
+ expect(Condition.evaluate(lessThen0, numFact(1))).toBe(false);
65
+ });
66
+
67
+ it("less than inclusive works", () => {
68
+ expect(Condition.evaluate(lessThen0Inclusive, numFact(-1))).toBe(true);
69
+ expect(Condition.evaluate(lessThen0Inclusive, numFact(0))).toBe(true);
70
+ expect(Condition.evaluate(lessThen0Inclusive, numFact(1))).toBe(false);
71
+ });
72
+
73
+ it("greater than works", () => {
74
+ expect(Condition.evaluate(greaterThen0, numFact(-1))).toBe(false);
75
+ expect(Condition.evaluate(greaterThen0, numFact(0))).toBe(false);
76
+ expect(Condition.evaluate(greaterThen0, numFact(1))).toBe(true);
77
+ });
78
+
79
+ it("greater than inclusive works", () => {
80
+ expect(Condition.evaluate(greaterThen0Inclusive, numFact(-1))).toBe(false);
81
+ expect(Condition.evaluate(greaterThen0Inclusive, numFact(0))).toBe(true);
82
+ expect(Condition.evaluate(greaterThen0Inclusive, numFact(1))).toBe(true);
83
+ });
84
+ });
@@ -0,0 +1,354 @@
1
+ import { RuleEngine } from "../rule-engine";
2
+ import { Rule } from "../rule";
3
+ import { Fact } from "../fact";
4
+ import { Condition } from "../condition";
5
+ import { PageQueCommand } from "../../commands/DCommand";
6
+
7
+ const excludeById = (ids: string[]): PageQueCommand => {
8
+ return {
9
+ kind: "PAGE_QUE_EXCLUDE_BY_PAGE_ID_COMMAND",
10
+ target: "PAGE_QUE",
11
+ targetId: "PAGE_QUE",
12
+ payload: { pageIds: ids },
13
+ };
14
+ };
15
+
16
+ const excludeByTag = (id: string): PageQueCommand => ({
17
+ kind: "PAGE_QUE_EXCLUDE_BY_TAG_COMMAND",
18
+ target: "PAGE_QUE",
19
+ targetId: "PAGE_QUE",
20
+ payload: { tagIds: [id] },
21
+ });
22
+
23
+ let engine = new RuleEngine();
24
+ // const x = 'x';
25
+ // const y = 'y';
26
+
27
+ const xIs = (value: number): Fact.Numeric => ({
28
+ referenceId: "x",
29
+ referenceLabel: "x-label",
30
+ label: "value-label x",
31
+ value,
32
+ kind: "numeric-fact",
33
+ });
34
+
35
+ const yIs = (value: number): Fact.Numeric => ({
36
+ kind: "numeric-fact",
37
+ referenceId: "y",
38
+ referenceLabel: "y-label",
39
+ label: "var-label y",
40
+ // valueLabel: 'value-label y',
41
+ value,
42
+ });
43
+
44
+ const xCondition = (operator: Condition.NumericOperator, value: number): Condition.Numeric => ({
45
+ kind: "numeric-condition",
46
+ referenceId: "x",
47
+ referenceLabel: "",
48
+ operator,
49
+ value,
50
+ valueLabel: "",
51
+ });
52
+
53
+ const trueIf_0_conditions: Condition.Numeric[] = [
54
+ xCondition("eq", 0),
55
+ xCondition("not-eq", 2),
56
+ xCondition("less-then", 1),
57
+ xCondition("less-then-inclusive", 0),
58
+ xCondition("greater-then", -1),
59
+ xCondition("greater-then-inclusive", 0),
60
+ ];
61
+
62
+ const falseIf_0_conditions: Condition.Numeric[] = [
63
+ xCondition("eq", 10),
64
+ xCondition("not-eq", 0),
65
+ xCondition("less-then", -5),
66
+ xCondition("less-then-inclusive", -1),
67
+ xCondition("greater-then", 0),
68
+ xCondition("greater-then-inclusive", 1),
69
+ ];
70
+
71
+ const trueIf_0_simple: Condition.Complex[] = [
72
+ {
73
+ kind: "complex-condition",
74
+ name: "test-name",
75
+ all: [...trueIf_0_conditions],
76
+ some: [...trueIf_0_conditions, ...falseIf_0_conditions],
77
+ },
78
+ ];
79
+
80
+ const falseIf_0_simple: Condition.Complex[] = [
81
+ {
82
+ kind: "complex-condition",
83
+ name: "test-name",
84
+ all: [...trueIf_0_conditions, ...falseIf_0_conditions],
85
+ some: [...falseIf_0_conditions],
86
+ },
87
+ ];
88
+
89
+ describe("Rule-engine spec", () => {
90
+ beforeEach(() => {
91
+ engine = new RuleEngine();
92
+ });
93
+
94
+ it("Empty rule => one error, no actions", () => {
95
+ const rule: Rule<any, any> = {
96
+ id: "id123",
97
+ description: "",
98
+ some: [],
99
+ all: [],
100
+ onFailure: [],
101
+ onSuccess: [],
102
+ };
103
+ const result = engine.solveAll([rule], []);
104
+ expect(result.matching.length).toBe(0);
105
+ expect(result.errors.length).toBe(1);
106
+ });
107
+
108
+ it("Empty facts => no actions, no errors.", () => {
109
+ const hideAs1 = excludeById(["as1"]);
110
+ const rule: Rule<any, any> = {
111
+ id: "id123",
112
+ description: "",
113
+ some: [],
114
+ all: [...trueIf_0_conditions],
115
+ onFailure: [],
116
+ onSuccess: [hideAs1],
117
+ };
118
+ const facts = [yIs(1)];
119
+ const rules = [rule];
120
+ // engine.addRule(rule);
121
+ // engine.addFact(yIs(1)); // X is now missing.
122
+ const result = engine.solveAll(rules, facts);
123
+
124
+ expect(result.matching.length).toBe(0);
125
+ expect(result.errors.length).toBe(0);
126
+ });
127
+
128
+ it("and-rule 0=0 true -> 2 Actions in ruleMatch", () => {
129
+ const rule: Rule<any, any> = {
130
+ id: "id123",
131
+ description: "",
132
+ some: [],
133
+ all: [...trueIf_0_conditions],
134
+ onFailure: [],
135
+ onSuccess: [excludeById(["as3", "as6"])],
136
+ };
137
+ const f1 = xIs(0);
138
+ const rules = [rule];
139
+ const result = engine.solveAll(rules, [f1]);
140
+ const firstMatch = result.matching[0];
141
+ expect(firstMatch.actionList.length).toBe(1);
142
+ expect(result.matching.length).toBe(1);
143
+ expect(result.errors.length).toBe(0);
144
+ });
145
+
146
+ it("and-rule 0=1 false", () => {
147
+ const facts = [xIs(1)];
148
+ const rule: Rule<any, any> = {
149
+ id: "id123",
150
+
151
+ description: "",
152
+ some: [],
153
+ all: [xCondition("eq", 0)],
154
+ onFailure: [],
155
+ onSuccess: [excludeById(["abx", "dfg"])],
156
+ };
157
+ expect(engine.solve(rule, facts)).toEqual(false);
158
+ const results = engine.solveAll([rule], facts);
159
+ expect(results.matching.length).toBe(0);
160
+ expect(results.errors.length).toBe(0);
161
+ });
162
+
163
+ it("One true some-rule gives true", () => {
164
+ const facts = [xIs(6)];
165
+ const rule: Rule<any, any> = {
166
+ id: "id123",
167
+ description: "",
168
+ some: [xCondition("eq", 6)],
169
+ all: [],
170
+ onFailure: [],
171
+ onSuccess: [excludeById(["abcf"])],
172
+ };
173
+ expect(engine.solve(rule, facts)).toBe(true);
174
+ const result = engine.solveAll([rule], facts);
175
+ expect(result.matching.length).toBe(1);
176
+ });
177
+
178
+ it("One false some-rule gives false", () => {
179
+ const facts = [xIs(6)];
180
+ const rule: Rule<any, any> = {
181
+ id: "id123",
182
+
183
+ description: "",
184
+ some: [xCondition("eq", 5)],
185
+ all: [],
186
+ onFailure: [],
187
+ onSuccess: [],
188
+ };
189
+ expect(engine.solve(rule, facts)).toBe(false);
190
+ });
191
+
192
+ it("All true all-rules, and one true some-rule -> true", () => {
193
+ const facts = [xIs(9)];
194
+ const rule: Rule<any, any> = {
195
+ id: "id123",
196
+
197
+ description: "",
198
+ some: [xCondition("eq", 5), xCondition("greater-then", 3)],
199
+ all: [xCondition("greater-then", 5), xCondition("eq", 9)],
200
+ onFailure: [],
201
+ onSuccess: [],
202
+ };
203
+ expect(engine.solve(rule, facts)).toBe(true);
204
+ });
205
+
206
+ it("Can solve complex rule [some-2 -> true]", () => {
207
+ const facts = [xIs(9)];
208
+ const rule: Rule<any, any> = {
209
+ id: "id123",
210
+
211
+ description: "",
212
+ some: [
213
+ {
214
+ kind: "complex-condition",
215
+ name: "test-name",
216
+ all: [],
217
+ some: [xCondition("eq", 5), xCondition("greater-then", 3)],
218
+ },
219
+ ],
220
+ all: [],
221
+ onFailure: [],
222
+ onSuccess: [excludeByTag("asdf")],
223
+ };
224
+ expect(engine.solve(rule, facts)).toBe(true);
225
+ const result = engine.solveAll([rule], facts);
226
+ expect(result.matching.length).toBe(1);
227
+ });
228
+ it("Can solve complex rule [some-1 -> false]", () => {
229
+ const facts = [xIs(0)];
230
+ const rule: Rule<any, any> = {
231
+ id: "id123",
232
+
233
+ description: "",
234
+ some: [
235
+ {
236
+ kind: "complex-condition",
237
+ name: "test-name",
238
+ all: [],
239
+ some: [xCondition("eq", 5)],
240
+ },
241
+ ],
242
+ all: [],
243
+ onFailure: [],
244
+ onSuccess: [excludeByTag("xbj")],
245
+ };
246
+ expect(engine.solve(rule, facts)).toBe(false);
247
+ const result = engine.solveAll([rule], facts);
248
+ expect(result.matching.length).toBe(0);
249
+ expect(result.errors.length).toBe(0);
250
+ });
251
+
252
+ it("Can solve complex rule [some-1-true -> true]", () => {
253
+ const facts = [xIs(0)];
254
+ const rule: Rule<any, any> = {
255
+ id: "id123",
256
+
257
+ description: "",
258
+ some: [
259
+ {
260
+ kind: "complex-condition",
261
+ name: "test-name",
262
+ all: [],
263
+ some: [xCondition("greater-then", -5)],
264
+ },
265
+ ],
266
+ all: [],
267
+ onFailure: [],
268
+ onSuccess: [],
269
+ };
270
+ expect(engine.solve(rule, facts)).toBe(true);
271
+ });
272
+
273
+ it("Empty some (nested) returns false (not valid condition)", () => {
274
+ const rule: Rule<any, any> = {
275
+ id: "id123",
276
+
277
+ description: "",
278
+ some: [
279
+ {
280
+ kind: "complex-condition",
281
+ name: "test-name",
282
+ all: [],
283
+ some: [],
284
+ },
285
+ ],
286
+ all: [],
287
+ onFailure: [],
288
+ onSuccess: [],
289
+ };
290
+ expect(engine.solve(rule, [])).toBe(false);
291
+ });
292
+
293
+ it("Empty complex -> false", () => {
294
+ const rule: Rule<any, any> = {
295
+ id: "id123",
296
+
297
+ description: "",
298
+ some: [],
299
+ all: [],
300
+ onFailure: [],
301
+ onSuccess: [],
302
+ };
303
+ expect(engine.solve(rule, [])).toBe(false);
304
+ });
305
+
306
+ it("Complex all 6 true conditions -> true", () => {
307
+ const facts = [xIs(0)];
308
+ const action = excludeById(["as1"]);
309
+ const rule: Rule<any, any> = {
310
+ id: "id123",
311
+
312
+ description: "",
313
+ some: [...falseIf_0_simple, ...trueIf_0_simple],
314
+ all: [...trueIf_0_conditions, ...trueIf_0_simple],
315
+ onFailure: [],
316
+ onSuccess: [action],
317
+ };
318
+ // CAN SOLVE
319
+ expect(engine.solve(rule, facts)).toBe(true);
320
+ // engine.addRule(rule);
321
+ // expect(engine.getRules().length).toBe(1);
322
+
323
+ // const lastAction = engine.actionState?.lastAction as HidePageAction;
324
+ // expect(lastAction?.pageId).toBe('as1');
325
+ });
326
+
327
+ it("True some, but false all -> true", () => {
328
+ const facts = [xIs(0)];
329
+ const rule: Rule<any, any> = {
330
+ id: "id123",
331
+
332
+ description: "",
333
+ some: [...falseIf_0_simple, ...trueIf_0_simple],
334
+ all: [...trueIf_0_conditions, ...trueIf_0_simple, ...falseIf_0_simple],
335
+ onFailure: [],
336
+ onSuccess: [],
337
+ };
338
+ expect(engine.solve(rule, facts)).toBe(false);
339
+ });
340
+
341
+ it("Empty some && true all -> true", () => {
342
+ const facts = [xIs(0)];
343
+ const rule: Rule<any, any> = {
344
+ id: "id123",
345
+
346
+ description: "",
347
+ some: [],
348
+ all: [...trueIf_0_conditions, ...trueIf_0_simple],
349
+ onFailure: [],
350
+ onSuccess: [],
351
+ };
352
+ expect(engine.solve(rule, facts)).toBe(true);
353
+ });
354
+ });