@player-tools/fluent 0.12.1--canary.241.6077
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/dist/cjs/index.cjs +2396 -0
- package/dist/cjs/index.cjs.map +1 -0
- package/dist/index.legacy-esm.js +2276 -0
- package/dist/index.mjs +2276 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +38 -0
- package/src/core/base-builder/__tests__/fluent-builder-base.test.ts +2423 -0
- package/src/core/base-builder/__tests__/fluent-partial.test.ts +179 -0
- package/src/core/base-builder/__tests__/id-generator.test.ts +658 -0
- package/src/core/base-builder/__tests__/registry.test.ts +534 -0
- package/src/core/base-builder/__tests__/resolution-mixed-arrays.test.ts +319 -0
- package/src/core/base-builder/__tests__/resolution-pipeline.test.ts +416 -0
- package/src/core/base-builder/__tests__/resolution-switches.test.ts +468 -0
- package/src/core/base-builder/__tests__/resolution-templates.test.ts +255 -0
- package/src/core/base-builder/__tests__/switch.test.ts +815 -0
- package/src/core/base-builder/__tests__/template.test.ts +596 -0
- package/src/core/base-builder/__tests__/value-extraction.test.ts +200 -0
- package/src/core/base-builder/__tests__/value-storage.test.ts +459 -0
- package/src/core/base-builder/conditional/index.ts +64 -0
- package/src/core/base-builder/context.ts +152 -0
- package/src/core/base-builder/errors.ts +69 -0
- package/src/core/base-builder/fluent-builder-base.ts +308 -0
- package/src/core/base-builder/guards.ts +137 -0
- package/src/core/base-builder/id/generator.ts +290 -0
- package/src/core/base-builder/id/registry.ts +152 -0
- package/src/core/base-builder/index.ts +72 -0
- package/src/core/base-builder/resolution/path-resolver.ts +116 -0
- package/src/core/base-builder/resolution/pipeline.ts +103 -0
- package/src/core/base-builder/resolution/steps/__tests__/nested-asset-wrappers.test.ts +206 -0
- package/src/core/base-builder/resolution/steps/asset-id.ts +77 -0
- package/src/core/base-builder/resolution/steps/asset-wrappers.ts +64 -0
- package/src/core/base-builder/resolution/steps/builders.ts +84 -0
- package/src/core/base-builder/resolution/steps/mixed-arrays.ts +95 -0
- package/src/core/base-builder/resolution/steps/nested-asset-wrappers.ts +124 -0
- package/src/core/base-builder/resolution/steps/static-values.ts +35 -0
- package/src/core/base-builder/resolution/steps/switches.ts +71 -0
- package/src/core/base-builder/resolution/steps/templates.ts +40 -0
- package/src/core/base-builder/resolution/value-resolver.ts +333 -0
- package/src/core/base-builder/storage/auxiliary-storage.ts +82 -0
- package/src/core/base-builder/storage/value-storage.ts +282 -0
- package/src/core/base-builder/types.ts +266 -0
- package/src/core/base-builder/utils.ts +10 -0
- package/src/core/flow/__tests__/index.test.ts +292 -0
- package/src/core/flow/index.ts +118 -0
- package/src/core/index.ts +8 -0
- package/src/core/mocks/generated/action.builder.ts +92 -0
- package/src/core/mocks/generated/choice-item.builder.ts +120 -0
- package/src/core/mocks/generated/choice.builder.ts +134 -0
- package/src/core/mocks/generated/collection.builder.ts +93 -0
- package/src/core/mocks/generated/field-collection.builder.ts +86 -0
- package/src/core/mocks/generated/index.ts +10 -0
- package/src/core/mocks/generated/info.builder.ts +64 -0
- package/src/core/mocks/generated/input.builder.ts +63 -0
- package/src/core/mocks/generated/overview-collection.builder.ts +65 -0
- package/src/core/mocks/generated/splash-collection.builder.ts +93 -0
- package/src/core/mocks/generated/text.builder.ts +47 -0
- package/src/core/mocks/index.ts +1 -0
- package/src/core/mocks/types/action.ts +92 -0
- package/src/core/mocks/types/choice.ts +129 -0
- package/src/core/mocks/types/collection.ts +140 -0
- package/src/core/mocks/types/info.ts +7 -0
- package/src/core/mocks/types/input.ts +7 -0
- package/src/core/mocks/types/text.ts +5 -0
- package/src/core/schema/__tests__/index.test.ts +127 -0
- package/src/core/schema/index.ts +195 -0
- package/src/core/schema/types.ts +7 -0
- package/src/core/switch/__tests__/index.test.ts +156 -0
- package/src/core/switch/index.ts +81 -0
- package/src/core/tagged-template/README.md +448 -0
- package/src/core/tagged-template/__tests__/extract-bindings-from-schema.test.ts +207 -0
- package/src/core/tagged-template/__tests__/index.test.ts +190 -0
- package/src/core/tagged-template/__tests__/schema-std-integration.test.ts +580 -0
- package/src/core/tagged-template/binding.ts +95 -0
- package/src/core/tagged-template/expression.ts +92 -0
- package/src/core/tagged-template/extract-bindings-from-schema.ts +120 -0
- package/src/core/tagged-template/index.ts +5 -0
- package/src/core/tagged-template/std.ts +472 -0
- package/src/core/tagged-template/types.ts +123 -0
- package/src/core/template/__tests__/index.test.ts +380 -0
- package/src/core/template/index.ts +196 -0
- package/src/core/utils/index.ts +160 -0
- package/src/fp/README.md +411 -0
- package/src/fp/__tests__/index.test.ts +1178 -0
- package/src/fp/index.ts +386 -0
- package/src/gen/common.ts +15 -0
- package/src/index.ts +5 -0
- package/src/types.ts +203 -0
- package/types/core/base-builder/conditional/index.d.ts +21 -0
- package/types/core/base-builder/context.d.ts +39 -0
- package/types/core/base-builder/errors.d.ts +45 -0
- package/types/core/base-builder/fluent-builder-base.d.ts +147 -0
- package/types/core/base-builder/guards.d.ts +58 -0
- package/types/core/base-builder/id/generator.d.ts +69 -0
- package/types/core/base-builder/id/registry.d.ts +93 -0
- package/types/core/base-builder/index.d.ts +9 -0
- package/types/core/base-builder/resolution/path-resolver.d.ts +15 -0
- package/types/core/base-builder/resolution/pipeline.d.ts +27 -0
- package/types/core/base-builder/resolution/steps/asset-id.d.ts +14 -0
- package/types/core/base-builder/resolution/steps/asset-wrappers.d.ts +14 -0
- package/types/core/base-builder/resolution/steps/builders.d.ts +14 -0
- package/types/core/base-builder/resolution/steps/mixed-arrays.d.ts +14 -0
- package/types/core/base-builder/resolution/steps/nested-asset-wrappers.d.ts +14 -0
- package/types/core/base-builder/resolution/steps/static-values.d.ts +14 -0
- package/types/core/base-builder/resolution/steps/switches.d.ts +15 -0
- package/types/core/base-builder/resolution/steps/templates.d.ts +14 -0
- package/types/core/base-builder/resolution/value-resolver.d.ts +62 -0
- package/types/core/base-builder/storage/auxiliary-storage.d.ts +50 -0
- package/types/core/base-builder/storage/value-storage.d.ts +82 -0
- package/types/core/base-builder/types.d.ts +183 -0
- package/types/core/base-builder/utils.d.ts +2 -0
- package/types/core/flow/index.d.ts +23 -0
- package/types/core/index.d.ts +8 -0
- package/types/core/mocks/index.d.ts +2 -0
- package/types/core/mocks/types/action.d.ts +58 -0
- package/types/core/mocks/types/choice.d.ts +95 -0
- package/types/core/mocks/types/collection.d.ts +102 -0
- package/types/core/mocks/types/info.d.ts +7 -0
- package/types/core/mocks/types/input.d.ts +7 -0
- package/types/core/mocks/types/text.d.ts +5 -0
- package/types/core/schema/index.d.ts +34 -0
- package/types/core/schema/types.d.ts +5 -0
- package/types/core/switch/index.d.ts +21 -0
- package/types/core/tagged-template/binding.d.ts +19 -0
- package/types/core/tagged-template/expression.d.ts +11 -0
- package/types/core/tagged-template/extract-bindings-from-schema.d.ts +7 -0
- package/types/core/tagged-template/index.d.ts +6 -0
- package/types/core/tagged-template/std.d.ts +174 -0
- package/types/core/tagged-template/types.d.ts +69 -0
- package/types/core/template/index.d.ts +97 -0
- package/types/core/utils/index.d.ts +47 -0
- package/types/fp/index.d.ts +149 -0
- package/types/gen/common.d.ts +6 -0
- package/types/index.d.ts +3 -0
- package/types/types.d.ts +163 -0
|
@@ -0,0 +1,815 @@
|
|
|
1
|
+
import { describe, test, expect, beforeEach } from "vitest";
|
|
2
|
+
import { FluentBuilderBase } from "../fluent-builder-base";
|
|
3
|
+
import { BaseBuildContext, FluentBuilder } from "../types";
|
|
4
|
+
import { resetGlobalIdSet } from "../id/generator";
|
|
5
|
+
import { expression } from "../../tagged-template";
|
|
6
|
+
import type { Asset } from "@player-ui/types";
|
|
7
|
+
|
|
8
|
+
interface TestAsset extends Asset<"test"> {
|
|
9
|
+
value: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
class TestAssetBuilder
|
|
13
|
+
extends FluentBuilderBase<TestAsset>
|
|
14
|
+
implements FluentBuilder<TestAsset, BaseBuildContext>
|
|
15
|
+
{
|
|
16
|
+
constructor() {
|
|
17
|
+
super({ type: "test" });
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
value(v: string): this {
|
|
21
|
+
return this.set("value", v);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
id(v: string): this {
|
|
25
|
+
return this.set("id", v);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
build(context?: BaseBuildContext): TestAsset {
|
|
29
|
+
return this.buildWithDefaults({ type: "test", value: "" }, context);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
interface CollectionAsset extends Asset<"collection"> {
|
|
34
|
+
values?: Array<{ asset: Asset }>;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
class CollectionBuilder
|
|
38
|
+
extends FluentBuilderBase<CollectionAsset>
|
|
39
|
+
implements FluentBuilder<CollectionAsset, BaseBuildContext>
|
|
40
|
+
{
|
|
41
|
+
// Mark 'values' as an array property to test array wrapping logic
|
|
42
|
+
static __arrayProperties__ = new Set(["values"]);
|
|
43
|
+
|
|
44
|
+
constructor() {
|
|
45
|
+
super({ type: "collection" });
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
withValues(v: Array<FluentBuilder<Asset, BaseBuildContext> | Asset>): this {
|
|
49
|
+
return this.set("values", { asset: v });
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
id(v: string): this {
|
|
53
|
+
return this.set("id", v);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
build(context?: BaseBuildContext): CollectionAsset {
|
|
57
|
+
return this.buildWithDefaults({ type: "collection" }, context);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
describe("Switch Integration with FluentBuilderBase", () => {
|
|
62
|
+
beforeEach(() => {
|
|
63
|
+
resetGlobalIdSet();
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
describe("Basic switch() method", () => {
|
|
67
|
+
test("can add a switch to a builder using the switch() method", () => {
|
|
68
|
+
const builder = new TestAssetBuilder()
|
|
69
|
+
.value("original")
|
|
70
|
+
.switch(["value"], {
|
|
71
|
+
cases: [
|
|
72
|
+
{
|
|
73
|
+
case: expression`user.lang === 'es'`,
|
|
74
|
+
asset: new TestAssetBuilder().value("Hola"),
|
|
75
|
+
},
|
|
76
|
+
{ case: true, asset: new TestAssetBuilder().value("Hello") },
|
|
77
|
+
],
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
const result = builder.build({ parentId: "test" });
|
|
81
|
+
|
|
82
|
+
expect(result).toEqual({
|
|
83
|
+
id: "test-test",
|
|
84
|
+
type: "test",
|
|
85
|
+
value: {
|
|
86
|
+
staticSwitch: [
|
|
87
|
+
{
|
|
88
|
+
case: "@[user.lang === 'es']@",
|
|
89
|
+
asset: {
|
|
90
|
+
value: "Hola",
|
|
91
|
+
type: "test",
|
|
92
|
+
id: "test-test-value-staticSwitch-0-test",
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
case: true,
|
|
97
|
+
asset: {
|
|
98
|
+
value: "Hello",
|
|
99
|
+
type: "test",
|
|
100
|
+
id: "test-test-value-staticSwitch-1-test",
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
],
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
test("can add dynamic switch", () => {
|
|
109
|
+
const builder = new TestAssetBuilder()
|
|
110
|
+
.value("original")
|
|
111
|
+
.switch(["value"], {
|
|
112
|
+
cases: [{ case: true, asset: new TestAssetBuilder().value("Hi") }],
|
|
113
|
+
isDynamic: true,
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
const result = builder.build({ parentId: "test" });
|
|
117
|
+
|
|
118
|
+
expect(result).toEqual({
|
|
119
|
+
id: "test-test",
|
|
120
|
+
type: "test",
|
|
121
|
+
value: {
|
|
122
|
+
dynamicSwitch: [
|
|
123
|
+
{
|
|
124
|
+
case: true,
|
|
125
|
+
asset: {
|
|
126
|
+
value: "Hi",
|
|
127
|
+
type: "test",
|
|
128
|
+
id: "test-test-value-dynamicSwitch-0-test",
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
],
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
test("preserves existing asset id when provided", () => {
|
|
137
|
+
const builder = new TestAssetBuilder()
|
|
138
|
+
.value("original")
|
|
139
|
+
.switch(["value"], {
|
|
140
|
+
cases: [
|
|
141
|
+
{
|
|
142
|
+
case: true,
|
|
143
|
+
asset: new TestAssetBuilder().value("Hello").id("custom-id"),
|
|
144
|
+
},
|
|
145
|
+
],
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
const result = builder.build({ parentId: "test" });
|
|
149
|
+
|
|
150
|
+
expect(result.value).toEqual({
|
|
151
|
+
staticSwitch: [
|
|
152
|
+
{
|
|
153
|
+
case: true,
|
|
154
|
+
asset: {
|
|
155
|
+
value: "Hello",
|
|
156
|
+
type: "test",
|
|
157
|
+
id: "custom-id",
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
],
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
test("handles multiple cases with sequential indexing", () => {
|
|
165
|
+
const builder = new TestAssetBuilder()
|
|
166
|
+
.value("original")
|
|
167
|
+
.switch(["value"], {
|
|
168
|
+
cases: [
|
|
169
|
+
{
|
|
170
|
+
case: expression`name.first === 'John'`,
|
|
171
|
+
asset: new TestAssetBuilder().value("First"),
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
case: expression`name.first === 'Jane'`,
|
|
175
|
+
asset: new TestAssetBuilder().value("Second"),
|
|
176
|
+
},
|
|
177
|
+
{ case: true, asset: new TestAssetBuilder().value("Default") },
|
|
178
|
+
],
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
const result = builder.build({ parentId: "test" });
|
|
182
|
+
|
|
183
|
+
expect(result.value).toEqual({
|
|
184
|
+
staticSwitch: [
|
|
185
|
+
{
|
|
186
|
+
case: "@[name.first === 'John']@",
|
|
187
|
+
asset: {
|
|
188
|
+
value: "First",
|
|
189
|
+
type: "test",
|
|
190
|
+
id: "test-test-value-staticSwitch-0-test",
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
case: "@[name.first === 'Jane']@",
|
|
195
|
+
asset: {
|
|
196
|
+
value: "Second",
|
|
197
|
+
type: "test",
|
|
198
|
+
id: "test-test-value-staticSwitch-1-test",
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
case: true,
|
|
203
|
+
asset: {
|
|
204
|
+
value: "Default",
|
|
205
|
+
type: "test",
|
|
206
|
+
id: "test-test-value-staticSwitch-2-test",
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
],
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
describe("Switch with nested paths", () => {
|
|
215
|
+
test("can replace array element with switch", () => {
|
|
216
|
+
const builder = new CollectionBuilder()
|
|
217
|
+
.withValues([
|
|
218
|
+
new TestAssetBuilder().value("Item 1"),
|
|
219
|
+
new TestAssetBuilder().value("Item 2"),
|
|
220
|
+
new TestAssetBuilder().value("Item 3"),
|
|
221
|
+
])
|
|
222
|
+
.switch(["values", 1], {
|
|
223
|
+
cases: [
|
|
224
|
+
{
|
|
225
|
+
case: expression`user.isAdmin`,
|
|
226
|
+
asset: new TestAssetBuilder().value("Admin Item"),
|
|
227
|
+
},
|
|
228
|
+
{ case: true, asset: new TestAssetBuilder().value("Default") },
|
|
229
|
+
],
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
const result = builder.build({ parentId: "test" });
|
|
233
|
+
|
|
234
|
+
expect(result).toEqual({
|
|
235
|
+
id: "test-collection",
|
|
236
|
+
type: "collection",
|
|
237
|
+
values: [
|
|
238
|
+
{
|
|
239
|
+
asset: {
|
|
240
|
+
id: "test-collection-values-0-test",
|
|
241
|
+
type: "test",
|
|
242
|
+
value: "Item 1",
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
staticSwitch: [
|
|
247
|
+
{
|
|
248
|
+
case: "@[user.isAdmin]@",
|
|
249
|
+
asset: {
|
|
250
|
+
value: "Admin Item",
|
|
251
|
+
type: "test",
|
|
252
|
+
id: "test-collection-values-staticSwitch-0-test",
|
|
253
|
+
},
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
case: true,
|
|
257
|
+
asset: {
|
|
258
|
+
value: "Default",
|
|
259
|
+
type: "test",
|
|
260
|
+
id: "test-collection-values-staticSwitch-1-test",
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
],
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
asset: {
|
|
267
|
+
id: "test-collection-values-2-test",
|
|
268
|
+
type: "test",
|
|
269
|
+
value: "Item 3",
|
|
270
|
+
},
|
|
271
|
+
},
|
|
272
|
+
],
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
test("can add multiple switches at different array indices", () => {
|
|
277
|
+
const builder = new CollectionBuilder()
|
|
278
|
+
.withValues([
|
|
279
|
+
new TestAssetBuilder().value("Item 1"),
|
|
280
|
+
new TestAssetBuilder().value("Item 2"),
|
|
281
|
+
new TestAssetBuilder().value("Item 3"),
|
|
282
|
+
])
|
|
283
|
+
.switch(["values", 0], {
|
|
284
|
+
cases: [
|
|
285
|
+
{
|
|
286
|
+
case: expression`showSpecial`,
|
|
287
|
+
asset: new TestAssetBuilder().value("Special First"),
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
case: true,
|
|
291
|
+
asset: new TestAssetBuilder().value("Regular First"),
|
|
292
|
+
},
|
|
293
|
+
],
|
|
294
|
+
})
|
|
295
|
+
.switch(["values", 2], {
|
|
296
|
+
cases: [
|
|
297
|
+
{
|
|
298
|
+
case: expression`user.isPremium`,
|
|
299
|
+
asset: new TestAssetBuilder().value("Premium Last"),
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
case: true,
|
|
303
|
+
asset: new TestAssetBuilder().value("Standard Last"),
|
|
304
|
+
},
|
|
305
|
+
],
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
const result = builder.build({ parentId: "test" });
|
|
309
|
+
|
|
310
|
+
expect(result).toEqual({
|
|
311
|
+
id: "test-collection",
|
|
312
|
+
type: "collection",
|
|
313
|
+
values: [
|
|
314
|
+
{
|
|
315
|
+
staticSwitch: [
|
|
316
|
+
{
|
|
317
|
+
case: "@[showSpecial]@",
|
|
318
|
+
asset: {
|
|
319
|
+
value: "Special First",
|
|
320
|
+
type: "test",
|
|
321
|
+
id: "test-collection-values-staticSwitch-0-test",
|
|
322
|
+
},
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
case: true,
|
|
326
|
+
asset: {
|
|
327
|
+
value: "Regular First",
|
|
328
|
+
type: "test",
|
|
329
|
+
id: "test-collection-values-staticSwitch-1-test",
|
|
330
|
+
},
|
|
331
|
+
},
|
|
332
|
+
],
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
asset: {
|
|
336
|
+
id: "test-collection-values-1-test",
|
|
337
|
+
type: "test",
|
|
338
|
+
value: "Item 2",
|
|
339
|
+
},
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
staticSwitch: [
|
|
343
|
+
{
|
|
344
|
+
case: "@[user.isPremium]@",
|
|
345
|
+
asset: {
|
|
346
|
+
value: "Premium Last",
|
|
347
|
+
type: "test",
|
|
348
|
+
id: "test-collection-values-staticSwitch-2-test",
|
|
349
|
+
},
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
case: true,
|
|
353
|
+
asset: {
|
|
354
|
+
value: "Standard Last",
|
|
355
|
+
type: "test",
|
|
356
|
+
id: "test-collection-values-staticSwitch-3-test",
|
|
357
|
+
},
|
|
358
|
+
},
|
|
359
|
+
],
|
|
360
|
+
},
|
|
361
|
+
],
|
|
362
|
+
});
|
|
363
|
+
});
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
describe("Switch reusability", () => {
|
|
367
|
+
test("can reuse the same builder with different contexts", () => {
|
|
368
|
+
const builder = new TestAssetBuilder()
|
|
369
|
+
.value("original")
|
|
370
|
+
.switch(["value"], {
|
|
371
|
+
cases: [{ case: true, asset: new TestAssetBuilder().value("Hi") }],
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
const result1 = builder.build({ parentId: "test1" });
|
|
375
|
+
const result2 = builder.build({ parentId: "test2" });
|
|
376
|
+
|
|
377
|
+
expect(result1.id).toBe("test1-test");
|
|
378
|
+
expect(result2.id).toBe("test2-test");
|
|
379
|
+
|
|
380
|
+
const switch1: unknown = result1.value;
|
|
381
|
+
const switch2: unknown = result2.value;
|
|
382
|
+
|
|
383
|
+
expect(switch1).toHaveProperty("staticSwitch");
|
|
384
|
+
expect(switch2).toHaveProperty("staticSwitch");
|
|
385
|
+
|
|
386
|
+
if (
|
|
387
|
+
typeof switch1 === "object" &&
|
|
388
|
+
switch1 !== null &&
|
|
389
|
+
"staticSwitch" in switch1 &&
|
|
390
|
+
typeof switch2 === "object" &&
|
|
391
|
+
switch2 !== null &&
|
|
392
|
+
"staticSwitch" in switch2
|
|
393
|
+
) {
|
|
394
|
+
const staticSwitch1 = switch1.staticSwitch;
|
|
395
|
+
const staticSwitch2 = switch2.staticSwitch;
|
|
396
|
+
|
|
397
|
+
if (
|
|
398
|
+
Array.isArray(staticSwitch1) &&
|
|
399
|
+
Array.isArray(staticSwitch2) &&
|
|
400
|
+
staticSwitch1.length > 0 &&
|
|
401
|
+
staticSwitch2.length > 0
|
|
402
|
+
) {
|
|
403
|
+
const case1 = staticSwitch1[0];
|
|
404
|
+
const case2 = staticSwitch2[0];
|
|
405
|
+
|
|
406
|
+
if (typeof case1 === "object" && case1 !== null && "asset" in case1) {
|
|
407
|
+
const asset1 = case1.asset;
|
|
408
|
+
if (
|
|
409
|
+
typeof asset1 === "object" &&
|
|
410
|
+
asset1 !== null &&
|
|
411
|
+
"id" in asset1
|
|
412
|
+
) {
|
|
413
|
+
expect(asset1.id).toBe("test1-test-value-staticSwitch-0-test");
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
if (typeof case2 === "object" && case2 !== null && "asset" in case2) {
|
|
418
|
+
const asset2 = case2.asset;
|
|
419
|
+
if (
|
|
420
|
+
typeof asset2 === "object" &&
|
|
421
|
+
asset2 !== null &&
|
|
422
|
+
"id" in asset2
|
|
423
|
+
) {
|
|
424
|
+
expect(asset2.id).toBe("test2-test-value-staticSwitch-0-test");
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
});
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
describe("Switch with string case expressions", () => {
|
|
433
|
+
test("handles string case expressions", () => {
|
|
434
|
+
const builder = new TestAssetBuilder()
|
|
435
|
+
.value("original")
|
|
436
|
+
.switch(["value"], {
|
|
437
|
+
cases: [
|
|
438
|
+
{
|
|
439
|
+
case: "{{foo}} === 'bar'",
|
|
440
|
+
asset: new TestAssetBuilder().value("Match"),
|
|
441
|
+
},
|
|
442
|
+
{ case: true, asset: new TestAssetBuilder().value("No Match") },
|
|
443
|
+
],
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
const result = builder.build({ parentId: "test" });
|
|
447
|
+
|
|
448
|
+
expect(result.value).toEqual({
|
|
449
|
+
staticSwitch: [
|
|
450
|
+
{
|
|
451
|
+
case: "{{foo}} === 'bar'",
|
|
452
|
+
asset: {
|
|
453
|
+
value: "Match",
|
|
454
|
+
type: "test",
|
|
455
|
+
id: "test-test-value-staticSwitch-0-test",
|
|
456
|
+
},
|
|
457
|
+
},
|
|
458
|
+
{
|
|
459
|
+
case: true,
|
|
460
|
+
asset: {
|
|
461
|
+
value: "No Match",
|
|
462
|
+
type: "test",
|
|
463
|
+
id: "test-test-value-staticSwitch-1-test",
|
|
464
|
+
},
|
|
465
|
+
},
|
|
466
|
+
],
|
|
467
|
+
});
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
test("handles boolean case expressions", () => {
|
|
471
|
+
const builder = new TestAssetBuilder()
|
|
472
|
+
.value("original")
|
|
473
|
+
.switch(["value"], {
|
|
474
|
+
cases: [
|
|
475
|
+
{ case: false, asset: new TestAssetBuilder().value("False") },
|
|
476
|
+
{ case: true, asset: new TestAssetBuilder().value("True") },
|
|
477
|
+
],
|
|
478
|
+
});
|
|
479
|
+
|
|
480
|
+
const result = builder.build({ parentId: "test" });
|
|
481
|
+
|
|
482
|
+
expect(result.value).toEqual({
|
|
483
|
+
staticSwitch: [
|
|
484
|
+
{
|
|
485
|
+
case: false,
|
|
486
|
+
asset: {
|
|
487
|
+
value: "False",
|
|
488
|
+
type: "test",
|
|
489
|
+
id: "test-test-value-staticSwitch-0-test",
|
|
490
|
+
},
|
|
491
|
+
},
|
|
492
|
+
{
|
|
493
|
+
case: true,
|
|
494
|
+
asset: {
|
|
495
|
+
value: "True",
|
|
496
|
+
type: "test",
|
|
497
|
+
id: "test-test-value-staticSwitch-1-test",
|
|
498
|
+
},
|
|
499
|
+
},
|
|
500
|
+
],
|
|
501
|
+
});
|
|
502
|
+
});
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
describe("Switch array wrapping behavior (path.length check)", () => {
|
|
506
|
+
test("switches on entire array property should be wrapped in array", () => {
|
|
507
|
+
// When switching the entire 'values' array property (path.length === 1),
|
|
508
|
+
// the switch result should be wrapped in an array because 'values' is an array type
|
|
509
|
+
const builder = new CollectionBuilder().switch(["values"], {
|
|
510
|
+
cases: [
|
|
511
|
+
{
|
|
512
|
+
case: expression`user.isAdmin`,
|
|
513
|
+
asset: new TestAssetBuilder().value("Admin Only"),
|
|
514
|
+
},
|
|
515
|
+
{
|
|
516
|
+
case: true,
|
|
517
|
+
asset: new TestAssetBuilder().value("Default"),
|
|
518
|
+
},
|
|
519
|
+
],
|
|
520
|
+
});
|
|
521
|
+
|
|
522
|
+
const result = builder.build({ parentId: "test" });
|
|
523
|
+
|
|
524
|
+
// The switch should be wrapped in an array: [{ staticSwitch: [...] }]
|
|
525
|
+
expect(result.values).toBeInstanceOf(Array);
|
|
526
|
+
expect(result.values).toHaveLength(1);
|
|
527
|
+
expect(result.values?.[0]).toHaveProperty("staticSwitch");
|
|
528
|
+
expect(result.values?.[0]).toEqual({
|
|
529
|
+
staticSwitch: [
|
|
530
|
+
{
|
|
531
|
+
case: "@[user.isAdmin]@",
|
|
532
|
+
asset: {
|
|
533
|
+
value: "Admin Only",
|
|
534
|
+
type: "test",
|
|
535
|
+
id: "test-collection-values-staticSwitch-0-test",
|
|
536
|
+
},
|
|
537
|
+
},
|
|
538
|
+
{
|
|
539
|
+
case: true,
|
|
540
|
+
asset: {
|
|
541
|
+
value: "Default",
|
|
542
|
+
type: "test",
|
|
543
|
+
id: "test-collection-values-staticSwitch-1-test",
|
|
544
|
+
},
|
|
545
|
+
},
|
|
546
|
+
],
|
|
547
|
+
});
|
|
548
|
+
});
|
|
549
|
+
|
|
550
|
+
test("switches on specific array element should NOT be double-wrapped", () => {
|
|
551
|
+
// When switching a specific element in the array (path.length > 1),
|
|
552
|
+
// the switch result should NOT be wrapped in an additional array
|
|
553
|
+
const builder = new CollectionBuilder()
|
|
554
|
+
.withValues([
|
|
555
|
+
new TestAssetBuilder().value("Item 1"),
|
|
556
|
+
new TestAssetBuilder().value("Item 2"),
|
|
557
|
+
])
|
|
558
|
+
.switch(["values", 1], {
|
|
559
|
+
cases: [
|
|
560
|
+
{
|
|
561
|
+
case: expression`user.isAdmin`,
|
|
562
|
+
asset: new TestAssetBuilder().value("Admin Item"),
|
|
563
|
+
},
|
|
564
|
+
{
|
|
565
|
+
case: true,
|
|
566
|
+
asset: new TestAssetBuilder().value("Default"),
|
|
567
|
+
},
|
|
568
|
+
],
|
|
569
|
+
});
|
|
570
|
+
|
|
571
|
+
const result = builder.build({ parentId: "test" });
|
|
572
|
+
|
|
573
|
+
// The switch at index 1 should NOT be double-wrapped
|
|
574
|
+
// It should be: [{ asset: ... }, { staticSwitch: [...] }]
|
|
575
|
+
// NOT: [{ asset: ... }, [{ staticSwitch: [...] }]]
|
|
576
|
+
expect(result.values).toBeInstanceOf(Array);
|
|
577
|
+
expect(result.values).toHaveLength(2);
|
|
578
|
+
|
|
579
|
+
// First element should be the original asset
|
|
580
|
+
expect(result.values?.[0]).toEqual({
|
|
581
|
+
asset: {
|
|
582
|
+
id: "test-collection-values-0-test",
|
|
583
|
+
type: "test",
|
|
584
|
+
value: "Item 1",
|
|
585
|
+
},
|
|
586
|
+
});
|
|
587
|
+
|
|
588
|
+
// Second element should be the switch (NOT wrapped in an extra array)
|
|
589
|
+
expect(result.values?.[1]).toHaveProperty("staticSwitch");
|
|
590
|
+
expect(result.values?.[1]).not.toBeInstanceOf(Array);
|
|
591
|
+
expect(result.values?.[1]).toEqual({
|
|
592
|
+
staticSwitch: [
|
|
593
|
+
{
|
|
594
|
+
case: "@[user.isAdmin]@",
|
|
595
|
+
asset: {
|
|
596
|
+
value: "Admin Item",
|
|
597
|
+
type: "test",
|
|
598
|
+
id: "test-collection-values-staticSwitch-0-test",
|
|
599
|
+
},
|
|
600
|
+
},
|
|
601
|
+
{
|
|
602
|
+
case: true,
|
|
603
|
+
asset: {
|
|
604
|
+
value: "Default",
|
|
605
|
+
type: "test",
|
|
606
|
+
id: "test-collection-values-staticSwitch-1-test",
|
|
607
|
+
},
|
|
608
|
+
},
|
|
609
|
+
],
|
|
610
|
+
});
|
|
611
|
+
});
|
|
612
|
+
|
|
613
|
+
test("multiple switches on different array indices should all be unwrapped", () => {
|
|
614
|
+
// Verify that multiple switches at different array indices all avoid double-wrapping
|
|
615
|
+
const builder = new CollectionBuilder()
|
|
616
|
+
.withValues([
|
|
617
|
+
new TestAssetBuilder().value("Item 1"),
|
|
618
|
+
new TestAssetBuilder().value("Item 2"),
|
|
619
|
+
new TestAssetBuilder().value("Item 3"),
|
|
620
|
+
])
|
|
621
|
+
.switch(["values", 0], {
|
|
622
|
+
cases: [
|
|
623
|
+
{
|
|
624
|
+
case: expression`showFirst`,
|
|
625
|
+
asset: new TestAssetBuilder().value("First Switch"),
|
|
626
|
+
},
|
|
627
|
+
{
|
|
628
|
+
case: true,
|
|
629
|
+
asset: new TestAssetBuilder().value("First Default"),
|
|
630
|
+
},
|
|
631
|
+
],
|
|
632
|
+
})
|
|
633
|
+
.switch(["values", 2], {
|
|
634
|
+
cases: [
|
|
635
|
+
{
|
|
636
|
+
case: expression`showLast`,
|
|
637
|
+
asset: new TestAssetBuilder().value("Last Switch"),
|
|
638
|
+
},
|
|
639
|
+
{ case: true, asset: new TestAssetBuilder().value("Last Default") },
|
|
640
|
+
],
|
|
641
|
+
});
|
|
642
|
+
|
|
643
|
+
const result = builder.build({ parentId: "test" });
|
|
644
|
+
|
|
645
|
+
expect(result.values).toBeInstanceOf(Array);
|
|
646
|
+
expect(result.values).toHaveLength(3);
|
|
647
|
+
|
|
648
|
+
// All array elements should contain switches, not arrays of switches
|
|
649
|
+
expect(result.values?.[0]).toHaveProperty("staticSwitch");
|
|
650
|
+
expect(result.values?.[0]).not.toBeInstanceOf(Array);
|
|
651
|
+
|
|
652
|
+
expect(result.values?.[1]).toEqual({
|
|
653
|
+
asset: {
|
|
654
|
+
id: "test-collection-values-1-test",
|
|
655
|
+
type: "test",
|
|
656
|
+
value: "Item 2",
|
|
657
|
+
},
|
|
658
|
+
});
|
|
659
|
+
|
|
660
|
+
expect(result.values?.[2]).toHaveProperty("staticSwitch");
|
|
661
|
+
expect(result.values?.[2]).not.toBeInstanceOf(Array);
|
|
662
|
+
});
|
|
663
|
+
});
|
|
664
|
+
|
|
665
|
+
describe("Case Index Offsets", () => {
|
|
666
|
+
test("first switch cases start at index 0", () => {
|
|
667
|
+
const builder = new TestAssetBuilder()
|
|
668
|
+
.value("original")
|
|
669
|
+
.switch(["value"], {
|
|
670
|
+
cases: [
|
|
671
|
+
{
|
|
672
|
+
case: expression`cond1`,
|
|
673
|
+
asset: new TestAssetBuilder().value("First"),
|
|
674
|
+
},
|
|
675
|
+
{ case: true, asset: new TestAssetBuilder().value("Default") },
|
|
676
|
+
],
|
|
677
|
+
});
|
|
678
|
+
|
|
679
|
+
const result = builder.build({ parentId: "test" });
|
|
680
|
+
|
|
681
|
+
// Case indices appear in generated IDs as staticSwitch-N
|
|
682
|
+
expect(result.value).toHaveProperty("staticSwitch");
|
|
683
|
+
if (
|
|
684
|
+
typeof result.value === "object" &&
|
|
685
|
+
result.value !== null &&
|
|
686
|
+
"staticSwitch" in result.value &&
|
|
687
|
+
Array.isArray(result.value.staticSwitch)
|
|
688
|
+
) {
|
|
689
|
+
const cases = result.value.staticSwitch as Array<{
|
|
690
|
+
asset: { id: string };
|
|
691
|
+
}>;
|
|
692
|
+
expect(cases[0].asset.id).toContain("staticSwitch-0");
|
|
693
|
+
expect(cases[1].asset.id).toContain("staticSwitch-1");
|
|
694
|
+
}
|
|
695
|
+
});
|
|
696
|
+
|
|
697
|
+
test("second switch cases start after first switch", () => {
|
|
698
|
+
// When multiple switches exist on different properties,
|
|
699
|
+
// their case indices should be offset
|
|
700
|
+
const builder = new CollectionBuilder()
|
|
701
|
+
.withValues([new TestAssetBuilder().value("Item 1")])
|
|
702
|
+
.switch(["values", 0], {
|
|
703
|
+
cases: [
|
|
704
|
+
{
|
|
705
|
+
case: expression`cond1`,
|
|
706
|
+
asset: new TestAssetBuilder().value("First"),
|
|
707
|
+
},
|
|
708
|
+
{
|
|
709
|
+
case: expression`cond2`,
|
|
710
|
+
asset: new TestAssetBuilder().value("Second"),
|
|
711
|
+
},
|
|
712
|
+
{ case: true, asset: new TestAssetBuilder().value("Third") },
|
|
713
|
+
],
|
|
714
|
+
});
|
|
715
|
+
|
|
716
|
+
const result = builder.build({ parentId: "test" });
|
|
717
|
+
|
|
718
|
+
// With 3 cases in the first switch, indices 0-2 are used
|
|
719
|
+
if (
|
|
720
|
+
result.values &&
|
|
721
|
+
Array.isArray(result.values) &&
|
|
722
|
+
result.values[0] &&
|
|
723
|
+
typeof result.values[0] === "object" &&
|
|
724
|
+
"staticSwitch" in result.values[0] &&
|
|
725
|
+
Array.isArray(result.values[0].staticSwitch)
|
|
726
|
+
) {
|
|
727
|
+
const cases = result.values[0].staticSwitch as Array<{
|
|
728
|
+
asset: { id: string };
|
|
729
|
+
}>;
|
|
730
|
+
expect(cases).toHaveLength(3);
|
|
731
|
+
expect(cases[0].asset.id).toContain("staticSwitch-0");
|
|
732
|
+
expect(cases[1].asset.id).toContain("staticSwitch-1");
|
|
733
|
+
expect(cases[2].asset.id).toContain("staticSwitch-2");
|
|
734
|
+
}
|
|
735
|
+
});
|
|
736
|
+
|
|
737
|
+
test("case indices appear in generated IDs", () => {
|
|
738
|
+
const builder = new TestAssetBuilder()
|
|
739
|
+
.value("original")
|
|
740
|
+
.switch(["value"], {
|
|
741
|
+
cases: [
|
|
742
|
+
{ case: expression`a`, asset: new TestAssetBuilder().value("A") },
|
|
743
|
+
{ case: expression`b`, asset: new TestAssetBuilder().value("B") },
|
|
744
|
+
{ case: expression`c`, asset: new TestAssetBuilder().value("C") },
|
|
745
|
+
{ case: expression`d`, asset: new TestAssetBuilder().value("D") },
|
|
746
|
+
{ case: true, asset: new TestAssetBuilder().value("E") },
|
|
747
|
+
],
|
|
748
|
+
});
|
|
749
|
+
|
|
750
|
+
const result = builder.build({ parentId: "test" });
|
|
751
|
+
|
|
752
|
+
if (
|
|
753
|
+
typeof result.value === "object" &&
|
|
754
|
+
result.value !== null &&
|
|
755
|
+
"staticSwitch" in result.value &&
|
|
756
|
+
Array.isArray(result.value.staticSwitch)
|
|
757
|
+
) {
|
|
758
|
+
const cases = result.value.staticSwitch as Array<{
|
|
759
|
+
asset: { id: string };
|
|
760
|
+
}>;
|
|
761
|
+
expect(cases).toHaveLength(5);
|
|
762
|
+
expect(cases[0].asset.id).toBe("test-test-value-staticSwitch-0-test");
|
|
763
|
+
expect(cases[1].asset.id).toBe("test-test-value-staticSwitch-1-test");
|
|
764
|
+
expect(cases[2].asset.id).toBe("test-test-value-staticSwitch-2-test");
|
|
765
|
+
expect(cases[3].asset.id).toBe("test-test-value-staticSwitch-3-test");
|
|
766
|
+
expect(cases[4].asset.id).toBe("test-test-value-staticSwitch-4-test");
|
|
767
|
+
}
|
|
768
|
+
});
|
|
769
|
+
|
|
770
|
+
test("dynamic switch case indices follow same pattern", () => {
|
|
771
|
+
const builder = new TestAssetBuilder()
|
|
772
|
+
.value("original")
|
|
773
|
+
.switch(["value"], {
|
|
774
|
+
cases: [
|
|
775
|
+
{
|
|
776
|
+
case: expression`cond`,
|
|
777
|
+
asset: new TestAssetBuilder().value("A"),
|
|
778
|
+
},
|
|
779
|
+
{ case: true, asset: new TestAssetBuilder().value("B") },
|
|
780
|
+
],
|
|
781
|
+
isDynamic: true,
|
|
782
|
+
});
|
|
783
|
+
|
|
784
|
+
const result = builder.build({ parentId: "test" });
|
|
785
|
+
|
|
786
|
+
if (
|
|
787
|
+
typeof result.value === "object" &&
|
|
788
|
+
result.value !== null &&
|
|
789
|
+
"dynamicSwitch" in result.value &&
|
|
790
|
+
Array.isArray(result.value.dynamicSwitch)
|
|
791
|
+
) {
|
|
792
|
+
const cases = result.value.dynamicSwitch as Array<{
|
|
793
|
+
asset: { id: string };
|
|
794
|
+
}>;
|
|
795
|
+
expect(cases[0].asset.id).toBe("test-test-value-dynamicSwitch-0-test");
|
|
796
|
+
expect(cases[1].asset.id).toBe("test-test-value-dynamicSwitch-1-test");
|
|
797
|
+
}
|
|
798
|
+
});
|
|
799
|
+
});
|
|
800
|
+
|
|
801
|
+
describe("Array Property Handling", () => {
|
|
802
|
+
test("wraps result in array for array-type properties", () => {
|
|
803
|
+
// When switching an entire array property, result should be wrapped
|
|
804
|
+
const builder = new CollectionBuilder().switch(["values"], {
|
|
805
|
+
cases: [{ case: true, asset: new TestAssetBuilder().value("Test") }],
|
|
806
|
+
});
|
|
807
|
+
|
|
808
|
+
const result = builder.build({ parentId: "test" });
|
|
809
|
+
|
|
810
|
+
// values should be an array containing the switch result
|
|
811
|
+
expect(result.values).toBeInstanceOf(Array);
|
|
812
|
+
expect(result.values).toHaveLength(1);
|
|
813
|
+
});
|
|
814
|
+
});
|
|
815
|
+
});
|