@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.
Files changed (134) hide show
  1. package/dist/cjs/index.cjs +2396 -0
  2. package/dist/cjs/index.cjs.map +1 -0
  3. package/dist/index.legacy-esm.js +2276 -0
  4. package/dist/index.mjs +2276 -0
  5. package/dist/index.mjs.map +1 -0
  6. package/package.json +38 -0
  7. package/src/core/base-builder/__tests__/fluent-builder-base.test.ts +2423 -0
  8. package/src/core/base-builder/__tests__/fluent-partial.test.ts +179 -0
  9. package/src/core/base-builder/__tests__/id-generator.test.ts +658 -0
  10. package/src/core/base-builder/__tests__/registry.test.ts +534 -0
  11. package/src/core/base-builder/__tests__/resolution-mixed-arrays.test.ts +319 -0
  12. package/src/core/base-builder/__tests__/resolution-pipeline.test.ts +416 -0
  13. package/src/core/base-builder/__tests__/resolution-switches.test.ts +468 -0
  14. package/src/core/base-builder/__tests__/resolution-templates.test.ts +255 -0
  15. package/src/core/base-builder/__tests__/switch.test.ts +815 -0
  16. package/src/core/base-builder/__tests__/template.test.ts +596 -0
  17. package/src/core/base-builder/__tests__/value-extraction.test.ts +200 -0
  18. package/src/core/base-builder/__tests__/value-storage.test.ts +459 -0
  19. package/src/core/base-builder/conditional/index.ts +64 -0
  20. package/src/core/base-builder/context.ts +152 -0
  21. package/src/core/base-builder/errors.ts +69 -0
  22. package/src/core/base-builder/fluent-builder-base.ts +308 -0
  23. package/src/core/base-builder/guards.ts +137 -0
  24. package/src/core/base-builder/id/generator.ts +290 -0
  25. package/src/core/base-builder/id/registry.ts +152 -0
  26. package/src/core/base-builder/index.ts +72 -0
  27. package/src/core/base-builder/resolution/path-resolver.ts +116 -0
  28. package/src/core/base-builder/resolution/pipeline.ts +103 -0
  29. package/src/core/base-builder/resolution/steps/__tests__/nested-asset-wrappers.test.ts +206 -0
  30. package/src/core/base-builder/resolution/steps/asset-id.ts +77 -0
  31. package/src/core/base-builder/resolution/steps/asset-wrappers.ts +64 -0
  32. package/src/core/base-builder/resolution/steps/builders.ts +84 -0
  33. package/src/core/base-builder/resolution/steps/mixed-arrays.ts +95 -0
  34. package/src/core/base-builder/resolution/steps/nested-asset-wrappers.ts +124 -0
  35. package/src/core/base-builder/resolution/steps/static-values.ts +35 -0
  36. package/src/core/base-builder/resolution/steps/switches.ts +71 -0
  37. package/src/core/base-builder/resolution/steps/templates.ts +40 -0
  38. package/src/core/base-builder/resolution/value-resolver.ts +333 -0
  39. package/src/core/base-builder/storage/auxiliary-storage.ts +82 -0
  40. package/src/core/base-builder/storage/value-storage.ts +282 -0
  41. package/src/core/base-builder/types.ts +266 -0
  42. package/src/core/base-builder/utils.ts +10 -0
  43. package/src/core/flow/__tests__/index.test.ts +292 -0
  44. package/src/core/flow/index.ts +118 -0
  45. package/src/core/index.ts +8 -0
  46. package/src/core/mocks/generated/action.builder.ts +92 -0
  47. package/src/core/mocks/generated/choice-item.builder.ts +120 -0
  48. package/src/core/mocks/generated/choice.builder.ts +134 -0
  49. package/src/core/mocks/generated/collection.builder.ts +93 -0
  50. package/src/core/mocks/generated/field-collection.builder.ts +86 -0
  51. package/src/core/mocks/generated/index.ts +10 -0
  52. package/src/core/mocks/generated/info.builder.ts +64 -0
  53. package/src/core/mocks/generated/input.builder.ts +63 -0
  54. package/src/core/mocks/generated/overview-collection.builder.ts +65 -0
  55. package/src/core/mocks/generated/splash-collection.builder.ts +93 -0
  56. package/src/core/mocks/generated/text.builder.ts +47 -0
  57. package/src/core/mocks/index.ts +1 -0
  58. package/src/core/mocks/types/action.ts +92 -0
  59. package/src/core/mocks/types/choice.ts +129 -0
  60. package/src/core/mocks/types/collection.ts +140 -0
  61. package/src/core/mocks/types/info.ts +7 -0
  62. package/src/core/mocks/types/input.ts +7 -0
  63. package/src/core/mocks/types/text.ts +5 -0
  64. package/src/core/schema/__tests__/index.test.ts +127 -0
  65. package/src/core/schema/index.ts +195 -0
  66. package/src/core/schema/types.ts +7 -0
  67. package/src/core/switch/__tests__/index.test.ts +156 -0
  68. package/src/core/switch/index.ts +81 -0
  69. package/src/core/tagged-template/README.md +448 -0
  70. package/src/core/tagged-template/__tests__/extract-bindings-from-schema.test.ts +207 -0
  71. package/src/core/tagged-template/__tests__/index.test.ts +190 -0
  72. package/src/core/tagged-template/__tests__/schema-std-integration.test.ts +580 -0
  73. package/src/core/tagged-template/binding.ts +95 -0
  74. package/src/core/tagged-template/expression.ts +92 -0
  75. package/src/core/tagged-template/extract-bindings-from-schema.ts +120 -0
  76. package/src/core/tagged-template/index.ts +5 -0
  77. package/src/core/tagged-template/std.ts +472 -0
  78. package/src/core/tagged-template/types.ts +123 -0
  79. package/src/core/template/__tests__/index.test.ts +380 -0
  80. package/src/core/template/index.ts +196 -0
  81. package/src/core/utils/index.ts +160 -0
  82. package/src/fp/README.md +411 -0
  83. package/src/fp/__tests__/index.test.ts +1178 -0
  84. package/src/fp/index.ts +386 -0
  85. package/src/gen/common.ts +15 -0
  86. package/src/index.ts +5 -0
  87. package/src/types.ts +203 -0
  88. package/types/core/base-builder/conditional/index.d.ts +21 -0
  89. package/types/core/base-builder/context.d.ts +39 -0
  90. package/types/core/base-builder/errors.d.ts +45 -0
  91. package/types/core/base-builder/fluent-builder-base.d.ts +147 -0
  92. package/types/core/base-builder/guards.d.ts +58 -0
  93. package/types/core/base-builder/id/generator.d.ts +69 -0
  94. package/types/core/base-builder/id/registry.d.ts +93 -0
  95. package/types/core/base-builder/index.d.ts +9 -0
  96. package/types/core/base-builder/resolution/path-resolver.d.ts +15 -0
  97. package/types/core/base-builder/resolution/pipeline.d.ts +27 -0
  98. package/types/core/base-builder/resolution/steps/asset-id.d.ts +14 -0
  99. package/types/core/base-builder/resolution/steps/asset-wrappers.d.ts +14 -0
  100. package/types/core/base-builder/resolution/steps/builders.d.ts +14 -0
  101. package/types/core/base-builder/resolution/steps/mixed-arrays.d.ts +14 -0
  102. package/types/core/base-builder/resolution/steps/nested-asset-wrappers.d.ts +14 -0
  103. package/types/core/base-builder/resolution/steps/static-values.d.ts +14 -0
  104. package/types/core/base-builder/resolution/steps/switches.d.ts +15 -0
  105. package/types/core/base-builder/resolution/steps/templates.d.ts +14 -0
  106. package/types/core/base-builder/resolution/value-resolver.d.ts +62 -0
  107. package/types/core/base-builder/storage/auxiliary-storage.d.ts +50 -0
  108. package/types/core/base-builder/storage/value-storage.d.ts +82 -0
  109. package/types/core/base-builder/types.d.ts +183 -0
  110. package/types/core/base-builder/utils.d.ts +2 -0
  111. package/types/core/flow/index.d.ts +23 -0
  112. package/types/core/index.d.ts +8 -0
  113. package/types/core/mocks/index.d.ts +2 -0
  114. package/types/core/mocks/types/action.d.ts +58 -0
  115. package/types/core/mocks/types/choice.d.ts +95 -0
  116. package/types/core/mocks/types/collection.d.ts +102 -0
  117. package/types/core/mocks/types/info.d.ts +7 -0
  118. package/types/core/mocks/types/input.d.ts +7 -0
  119. package/types/core/mocks/types/text.d.ts +5 -0
  120. package/types/core/schema/index.d.ts +34 -0
  121. package/types/core/schema/types.d.ts +5 -0
  122. package/types/core/switch/index.d.ts +21 -0
  123. package/types/core/tagged-template/binding.d.ts +19 -0
  124. package/types/core/tagged-template/expression.d.ts +11 -0
  125. package/types/core/tagged-template/extract-bindings-from-schema.d.ts +7 -0
  126. package/types/core/tagged-template/index.d.ts +6 -0
  127. package/types/core/tagged-template/std.d.ts +174 -0
  128. package/types/core/tagged-template/types.d.ts +69 -0
  129. package/types/core/template/index.d.ts +97 -0
  130. package/types/core/utils/index.d.ts +47 -0
  131. package/types/fp/index.d.ts +149 -0
  132. package/types/gen/common.d.ts +6 -0
  133. package/types/index.d.ts +3 -0
  134. package/types/types.d.ts +163 -0
@@ -0,0 +1,468 @@
1
+ import { describe, test, expect, beforeEach, vi } from "vitest";
2
+ import type { BaseBuildContext, SwitchMetadata } from "../types";
3
+ import { StorageKeys } from "../types";
4
+ import { AuxiliaryStorage } from "../storage/auxiliary-storage";
5
+ import { resolveSwitches } from "../resolution/steps/switches";
6
+
7
+ // Mock setValueAtPath for path resolution testing
8
+ vi.mock("../resolution/path-resolver", () => ({
9
+ setValueAtPath: vi.fn((result, path, value) => {
10
+ if (path.length === 1) {
11
+ result[String(path[0])] = value;
12
+ } else if (path.length === 2) {
13
+ const key = String(path[0]);
14
+ if (!result[key]) result[key] = [];
15
+ (result[key] as unknown[])[path[1] as number] = value;
16
+ }
17
+ }),
18
+ }));
19
+
20
+ import { setValueAtPath } from "../resolution/path-resolver";
21
+
22
+ describe("resolveSwitches - Case Index Tracking", () => {
23
+ let auxiliaryStorage: AuxiliaryStorage;
24
+ let arrayProperties: ReadonlySet<string>;
25
+
26
+ beforeEach(() => {
27
+ vi.clearAllMocks();
28
+ auxiliaryStorage = new AuxiliaryStorage();
29
+ arrayProperties = new Set(["values"]);
30
+ });
31
+
32
+ test("starts global case index at 0", () => {
33
+ let capturedCaseIndex: number | undefined;
34
+
35
+ const switchFn = vi.fn((_ctx: BaseBuildContext, caseIndex: number) => {
36
+ capturedCaseIndex = caseIndex;
37
+ return {
38
+ staticSwitch: [{ case: true, asset: { id: "test-1", type: "text" } }],
39
+ };
40
+ });
41
+
42
+ const switches: SwitchMetadata<BaseBuildContext>[] = [
43
+ { path: ["value"], switchFn },
44
+ ];
45
+ auxiliaryStorage.set(StorageKeys.SWITCHES, switches);
46
+
47
+ const result: Record<string, unknown> = {};
48
+ const context: BaseBuildContext = { parentId: "test" };
49
+
50
+ resolveSwitches(auxiliaryStorage, result, context, arrayProperties);
51
+
52
+ expect(capturedCaseIndex).toBe(0);
53
+ });
54
+
55
+ test("increments by number of cases in first switch", () => {
56
+ const capturedCaseIndices: number[] = [];
57
+
58
+ const firstSwitchFn = vi.fn((_ctx: BaseBuildContext, caseIndex: number) => {
59
+ capturedCaseIndices.push(caseIndex);
60
+ return {
61
+ staticSwitch: [
62
+ { case: "cond1", asset: { id: "test-1", type: "text" } },
63
+ { case: "cond2", asset: { id: "test-2", type: "text" } },
64
+ { case: true, asset: { id: "test-3", type: "text" } },
65
+ ],
66
+ };
67
+ });
68
+
69
+ const secondSwitchFn = vi.fn(
70
+ (_ctx: BaseBuildContext, caseIndex: number) => {
71
+ capturedCaseIndices.push(caseIndex);
72
+ return {
73
+ staticSwitch: [{ case: true, asset: { id: "test-4", type: "text" } }],
74
+ };
75
+ },
76
+ );
77
+
78
+ const switches: SwitchMetadata<BaseBuildContext>[] = [
79
+ { path: ["value"], switchFn: firstSwitchFn },
80
+ { path: ["label"], switchFn: secondSwitchFn },
81
+ ];
82
+ auxiliaryStorage.set(StorageKeys.SWITCHES, switches);
83
+
84
+ const result: Record<string, unknown> = {};
85
+ const context: BaseBuildContext = { parentId: "test" };
86
+
87
+ resolveSwitches(auxiliaryStorage, result, context, arrayProperties);
88
+
89
+ expect(capturedCaseIndices).toEqual([0, 3]); // Second switch starts at index 3
90
+ });
91
+
92
+ test("correctly offsets second switch case indices", () => {
93
+ const capturedCaseIndices: number[] = [];
94
+
95
+ const createSwitchFn =
96
+ (numCases: number) => (_ctx: BaseBuildContext, caseIndex: number) => {
97
+ capturedCaseIndices.push(caseIndex);
98
+ return {
99
+ staticSwitch: Array(numCases)
100
+ .fill(null)
101
+ .map((_, i) => ({
102
+ case: i === numCases - 1 ? true : `cond${i}`,
103
+ asset: { id: `test-${i}`, type: "text" },
104
+ })),
105
+ };
106
+ };
107
+
108
+ const switches: SwitchMetadata<BaseBuildContext>[] = [
109
+ { path: ["value"], switchFn: createSwitchFn(2) },
110
+ { path: ["label"], switchFn: createSwitchFn(3) },
111
+ { path: ["title"], switchFn: createSwitchFn(1) },
112
+ ];
113
+ auxiliaryStorage.set(StorageKeys.SWITCHES, switches);
114
+
115
+ const result: Record<string, unknown> = {};
116
+ const context: BaseBuildContext = { parentId: "test" };
117
+
118
+ resolveSwitches(auxiliaryStorage, result, context, arrayProperties);
119
+
120
+ // First: 0, Second: 0+2=2, Third: 2+3=5
121
+ expect(capturedCaseIndices).toEqual([0, 2, 5]);
122
+ });
123
+
124
+ test("handles switches with varying case counts", () => {
125
+ const capturedCaseIndices: number[] = [];
126
+
127
+ // Switch with 5 cases
128
+ const largeSwitchFn = vi.fn((_ctx: BaseBuildContext, caseIndex: number) => {
129
+ capturedCaseIndices.push(caseIndex);
130
+ return {
131
+ staticSwitch: [
132
+ { case: "c1", asset: { id: "1" } },
133
+ { case: "c2", asset: { id: "2" } },
134
+ { case: "c3", asset: { id: "3" } },
135
+ { case: "c4", asset: { id: "4" } },
136
+ { case: true, asset: { id: "5" } },
137
+ ],
138
+ };
139
+ });
140
+
141
+ // Switch with 1 case
142
+ const smallSwitchFn = vi.fn((_ctx: BaseBuildContext, caseIndex: number) => {
143
+ capturedCaseIndices.push(caseIndex);
144
+ return {
145
+ dynamicSwitch: [{ case: true, asset: { id: "6" } }],
146
+ };
147
+ });
148
+
149
+ const switches: SwitchMetadata<BaseBuildContext>[] = [
150
+ { path: ["large"], switchFn: largeSwitchFn },
151
+ { path: ["small"], switchFn: smallSwitchFn },
152
+ ];
153
+ auxiliaryStorage.set(StorageKeys.SWITCHES, switches);
154
+
155
+ const result: Record<string, unknown> = {};
156
+ const context: BaseBuildContext = { parentId: "test" };
157
+
158
+ resolveSwitches(auxiliaryStorage, result, context, arrayProperties);
159
+
160
+ expect(capturedCaseIndices).toEqual([0, 5]);
161
+ });
162
+ });
163
+
164
+ describe("resolveSwitches - Array Property Wrapping", () => {
165
+ let auxiliaryStorage: AuxiliaryStorage;
166
+
167
+ beforeEach(() => {
168
+ vi.clearAllMocks();
169
+ auxiliaryStorage = new AuxiliaryStorage();
170
+ });
171
+
172
+ test("wraps switch result in array for array properties", () => {
173
+ const arrayProperties = new Set(["values"]);
174
+
175
+ const switchFn = vi.fn(() => ({
176
+ staticSwitch: [{ case: true, asset: { id: "test", type: "text" } }],
177
+ }));
178
+
179
+ const switches: SwitchMetadata<BaseBuildContext>[] = [
180
+ { path: ["values"], switchFn },
181
+ ];
182
+ auxiliaryStorage.set(StorageKeys.SWITCHES, switches);
183
+
184
+ const result: Record<string, unknown> = {};
185
+ const context: BaseBuildContext = { parentId: "test" };
186
+
187
+ resolveSwitches(auxiliaryStorage, result, context, arrayProperties);
188
+
189
+ // Should wrap in array when path.length === 1 and property is array type
190
+ expect(setValueAtPath).toHaveBeenCalledWith(
191
+ result,
192
+ ["values"],
193
+ [{ staticSwitch: [{ case: true, asset: { id: "test", type: "text" } }] }],
194
+ );
195
+ });
196
+
197
+ test("does not wrap for non-array properties", () => {
198
+ const arrayProperties = new Set(["values"]);
199
+
200
+ const switchFn = vi.fn(() => ({
201
+ staticSwitch: [{ case: true, asset: { id: "test", type: "text" } }],
202
+ }));
203
+
204
+ const switches: SwitchMetadata<BaseBuildContext>[] = [
205
+ { path: ["label"], switchFn },
206
+ ];
207
+ auxiliaryStorage.set(StorageKeys.SWITCHES, switches);
208
+
209
+ const result: Record<string, unknown> = {};
210
+ const context: BaseBuildContext = { parentId: "test" };
211
+
212
+ resolveSwitches(auxiliaryStorage, result, context, arrayProperties);
213
+
214
+ // Should NOT wrap because 'label' is not in arrayProperties
215
+ expect(setValueAtPath).toHaveBeenCalledWith(result, ["label"], {
216
+ staticSwitch: [{ case: true, asset: { id: "test", type: "text" } }],
217
+ });
218
+ });
219
+
220
+ test("does not wrap when path length > 1", () => {
221
+ const arrayProperties = new Set(["values"]);
222
+
223
+ const switchFn = vi.fn(() => ({
224
+ staticSwitch: [{ case: true, asset: { id: "test", type: "text" } }],
225
+ }));
226
+
227
+ const switches: SwitchMetadata<BaseBuildContext>[] = [
228
+ { path: ["values", 0], switchFn },
229
+ ];
230
+ auxiliaryStorage.set(StorageKeys.SWITCHES, switches);
231
+
232
+ const result: Record<string, unknown> = { values: [] };
233
+ const context: BaseBuildContext = { parentId: "test" };
234
+
235
+ resolveSwitches(auxiliaryStorage, result, context, arrayProperties);
236
+
237
+ // Should NOT wrap because path.length > 1 (specific element)
238
+ expect(setValueAtPath).toHaveBeenCalledWith(result, ["values", 0], {
239
+ staticSwitch: [{ case: true, asset: { id: "test", type: "text" } }],
240
+ });
241
+ });
242
+ });
243
+
244
+ describe("resolveSwitches - Path Resolution", () => {
245
+ let auxiliaryStorage: AuxiliaryStorage;
246
+ let arrayProperties: ReadonlySet<string>;
247
+
248
+ beforeEach(() => {
249
+ vi.clearAllMocks();
250
+ auxiliaryStorage = new AuxiliaryStorage();
251
+ arrayProperties = new Set();
252
+ });
253
+
254
+ test("sets value at single-segment path", () => {
255
+ const switchFn = vi.fn(() => ({
256
+ staticSwitch: [{ case: true, asset: { id: "test" } }],
257
+ }));
258
+
259
+ const switches: SwitchMetadata<BaseBuildContext>[] = [
260
+ { path: ["value"], switchFn },
261
+ ];
262
+ auxiliaryStorage.set(StorageKeys.SWITCHES, switches);
263
+
264
+ const result: Record<string, unknown> = {};
265
+ const context: BaseBuildContext = { parentId: "test" };
266
+
267
+ resolveSwitches(auxiliaryStorage, result, context, arrayProperties);
268
+
269
+ expect(setValueAtPath).toHaveBeenCalledWith(
270
+ result,
271
+ ["value"],
272
+ expect.objectContaining({ staticSwitch: expect.any(Array) }),
273
+ );
274
+ });
275
+
276
+ test("sets value at multi-segment path", () => {
277
+ const switchFn = vi.fn(() => ({
278
+ staticSwitch: [{ case: true, asset: { id: "test" } }],
279
+ }));
280
+
281
+ const switches: SwitchMetadata<BaseBuildContext>[] = [
282
+ { path: ["nested", "deep"], switchFn },
283
+ ];
284
+ auxiliaryStorage.set(StorageKeys.SWITCHES, switches);
285
+
286
+ const result: Record<string, unknown> = {};
287
+ const context: BaseBuildContext = { parentId: "test" };
288
+
289
+ resolveSwitches(auxiliaryStorage, result, context, arrayProperties);
290
+
291
+ expect(setValueAtPath).toHaveBeenCalledWith(
292
+ result,
293
+ ["nested", "deep"],
294
+ expect.objectContaining({ staticSwitch: expect.any(Array) }),
295
+ );
296
+ });
297
+ });
298
+
299
+ describe("resolveSwitches - Edge Cases", () => {
300
+ let auxiliaryStorage: AuxiliaryStorage;
301
+ let arrayProperties: ReadonlySet<string>;
302
+
303
+ beforeEach(() => {
304
+ vi.clearAllMocks();
305
+ auxiliaryStorage = new AuxiliaryStorage();
306
+ arrayProperties = new Set();
307
+ });
308
+
309
+ test("returns early when no switches in storage", () => {
310
+ // Don't set any switches
311
+ const result: Record<string, unknown> = { existingValue: "test" };
312
+ const context: BaseBuildContext = { parentId: "test" };
313
+
314
+ resolveSwitches(auxiliaryStorage, result, context, arrayProperties);
315
+
316
+ // Result should be unchanged
317
+ expect(result).toEqual({ existingValue: "test" });
318
+ expect(setValueAtPath).not.toHaveBeenCalled();
319
+ });
320
+
321
+ test("returns early when empty switches array in storage", () => {
322
+ auxiliaryStorage.set(StorageKeys.SWITCHES, []);
323
+
324
+ const result: Record<string, unknown> = { existingValue: "test" };
325
+ const context: BaseBuildContext = { parentId: "test" };
326
+
327
+ resolveSwitches(auxiliaryStorage, result, context, arrayProperties);
328
+
329
+ expect(result).toEqual({ existingValue: "test" });
330
+ expect(setValueAtPath).not.toHaveBeenCalled();
331
+ });
332
+
333
+ test("returns early when no context provided", () => {
334
+ const switchFn = vi.fn(() => ({
335
+ staticSwitch: [{ case: true, asset: { id: "test" } }],
336
+ }));
337
+
338
+ const switches: SwitchMetadata<BaseBuildContext>[] = [
339
+ { path: ["value"], switchFn },
340
+ ];
341
+ auxiliaryStorage.set(StorageKeys.SWITCHES, switches);
342
+
343
+ const result: Record<string, unknown> = {};
344
+
345
+ resolveSwitches(auxiliaryStorage, result, undefined, arrayProperties);
346
+
347
+ expect(switchFn).not.toHaveBeenCalled();
348
+ expect(setValueAtPath).not.toHaveBeenCalled();
349
+ });
350
+
351
+ test("handles dynamicSwitch correctly", () => {
352
+ const capturedCaseIndex: number[] = [];
353
+
354
+ const firstSwitchFn = vi.fn((_ctx: BaseBuildContext, caseIndex: number) => {
355
+ capturedCaseIndex.push(caseIndex);
356
+ return {
357
+ dynamicSwitch: [
358
+ { case: "cond", asset: { id: "1" } },
359
+ { case: true, asset: { id: "2" } },
360
+ ],
361
+ };
362
+ });
363
+
364
+ const secondSwitchFn = vi.fn(
365
+ (_ctx: BaseBuildContext, caseIndex: number) => {
366
+ capturedCaseIndex.push(caseIndex);
367
+ return {
368
+ staticSwitch: [{ case: true, asset: { id: "3" } }],
369
+ };
370
+ },
371
+ );
372
+
373
+ const switches: SwitchMetadata<BaseBuildContext>[] = [
374
+ { path: ["first"], switchFn: firstSwitchFn },
375
+ { path: ["second"], switchFn: secondSwitchFn },
376
+ ];
377
+ auxiliaryStorage.set(StorageKeys.SWITCHES, switches);
378
+
379
+ const result: Record<string, unknown> = {};
380
+ const context: BaseBuildContext = { parentId: "test" };
381
+
382
+ resolveSwitches(auxiliaryStorage, result, context, arrayProperties);
383
+
384
+ // First has 2 cases (dynamicSwitch), second starts at index 2
385
+ expect(capturedCaseIndex).toEqual([0, 2]);
386
+ });
387
+ });
388
+
389
+ describe("resolveSwitches - Context Creation", () => {
390
+ let auxiliaryStorage: AuxiliaryStorage;
391
+ let arrayProperties: ReadonlySet<string>;
392
+
393
+ beforeEach(() => {
394
+ vi.clearAllMocks();
395
+ auxiliaryStorage = new AuxiliaryStorage();
396
+ arrayProperties = new Set();
397
+ });
398
+
399
+ test("creates switch context with property name in parentId", () => {
400
+ let capturedContext: BaseBuildContext | undefined;
401
+
402
+ const switchFn = vi.fn((ctx: BaseBuildContext) => {
403
+ capturedContext = ctx;
404
+ return { staticSwitch: [{ case: true, asset: { id: "test" } }] };
405
+ });
406
+
407
+ const switches: SwitchMetadata<BaseBuildContext>[] = [
408
+ { path: ["label"], switchFn },
409
+ ];
410
+ auxiliaryStorage.set(StorageKeys.SWITCHES, switches);
411
+
412
+ const result: Record<string, unknown> = {};
413
+ const context: BaseBuildContext = { parentId: "parent" };
414
+
415
+ resolveSwitches(auxiliaryStorage, result, context, arrayProperties);
416
+
417
+ expect(capturedContext).toBeDefined();
418
+ expect(capturedContext?.parentId).toBe("parent-label");
419
+ expect(capturedContext?.branch).toBeUndefined();
420
+ });
421
+
422
+ test("handles context without parentId", () => {
423
+ let capturedContext: BaseBuildContext | undefined;
424
+
425
+ const switchFn = vi.fn((ctx: BaseBuildContext) => {
426
+ capturedContext = ctx;
427
+ return { staticSwitch: [{ case: true, asset: { id: "test" } }] };
428
+ });
429
+
430
+ const switches: SwitchMetadata<BaseBuildContext>[] = [
431
+ { path: ["label"], switchFn },
432
+ ];
433
+ auxiliaryStorage.set(StorageKeys.SWITCHES, switches);
434
+
435
+ const result: Record<string, unknown> = {};
436
+ const context: BaseBuildContext = { parentId: undefined };
437
+
438
+ resolveSwitches(auxiliaryStorage, result, context, arrayProperties);
439
+
440
+ expect(capturedContext).toBeDefined();
441
+ expect(capturedContext?.parentId).toBe("label");
442
+ });
443
+
444
+ test("clears branch from switch context", () => {
445
+ let capturedContext: BaseBuildContext | undefined;
446
+
447
+ const switchFn = vi.fn((ctx: BaseBuildContext) => {
448
+ capturedContext = ctx;
449
+ return { staticSwitch: [{ case: true, asset: { id: "test" } }] };
450
+ });
451
+
452
+ const switches: SwitchMetadata<BaseBuildContext>[] = [
453
+ { path: ["value"], switchFn },
454
+ ];
455
+ auxiliaryStorage.set(StorageKeys.SWITCHES, switches);
456
+
457
+ const result: Record<string, unknown> = {};
458
+ const context: BaseBuildContext = {
459
+ parentId: "parent",
460
+ branch: { type: "slot", name: "test" },
461
+ };
462
+
463
+ resolveSwitches(auxiliaryStorage, result, context, arrayProperties);
464
+
465
+ expect(capturedContext).toBeDefined();
466
+ expect(capturedContext?.branch).toBeUndefined();
467
+ });
468
+ });