wyreframe 0.1.0 → 0.1.5

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 (58) hide show
  1. package/LICENSE +692 -0
  2. package/README.md +65 -5
  3. package/package.json +8 -7
  4. package/src/index.ts +425 -0
  5. package/src/renderer/Renderer.gen.tsx +49 -0
  6. package/src/renderer/Renderer.mjs +41 -1
  7. package/src/renderer/Renderer.res +78 -0
  8. package/src/parser/Core/__tests__/Bounds_test.mjs +0 -326
  9. package/src/parser/Core/__tests__/Bounds_test.res +0 -412
  10. package/src/parser/Core/__tests__/Grid_test.mjs +0 -322
  11. package/src/parser/Core/__tests__/Grid_test.res +0 -319
  12. package/src/parser/Core/__tests__/Types_test.mjs +0 -614
  13. package/src/parser/Core/__tests__/Types_test.res +0 -650
  14. package/src/parser/Detector/__tests__/BoxTracer_test.mjs +0 -70
  15. package/src/parser/Detector/__tests__/BoxTracer_test.res +0 -92
  16. package/src/parser/Detector/__tests__/HierarchyBuilder_test.mjs +0 -489
  17. package/src/parser/Detector/__tests__/HierarchyBuilder_test.res +0 -849
  18. package/src/parser/Detector/__tests__/ShapeDetector_test.mjs +0 -377
  19. package/src/parser/Detector/__tests__/ShapeDetector_test.res +0 -563
  20. package/src/parser/Interactions/__tests__/InteractionMerger_test.mjs +0 -576
  21. package/src/parser/Interactions/__tests__/InteractionMerger_test.res +0 -646
  22. package/src/parser/Scanner/__tests__/Grid_manual.mjs +0 -214
  23. package/src/parser/Scanner/__tests__/Grid_manual.res +0 -141
  24. package/src/parser/Semantic/Elements/__tests__/ButtonParser_test.mjs +0 -189
  25. package/src/parser/Semantic/Elements/__tests__/ButtonParser_test.res +0 -257
  26. package/src/parser/Semantic/Elements/__tests__/CheckboxParser_test.mjs +0 -202
  27. package/src/parser/Semantic/Elements/__tests__/CheckboxParser_test.res +0 -250
  28. package/src/parser/Semantic/Elements/__tests__/CodeTextParser_manual.mjs +0 -293
  29. package/src/parser/Semantic/Elements/__tests__/CodeTextParser_manual.res +0 -134
  30. package/src/parser/Semantic/Elements/__tests__/InputParser_test.mjs +0 -253
  31. package/src/parser/Semantic/Elements/__tests__/InputParser_test.res +0 -304
  32. package/src/parser/Semantic/Elements/__tests__/LinkParser_test.mjs +0 -289
  33. package/src/parser/Semantic/Elements/__tests__/LinkParser_test.res +0 -402
  34. package/src/parser/Semantic/Elements/__tests__/TextParser_test.mjs +0 -149
  35. package/src/parser/Semantic/Elements/__tests__/TextParser_test.res +0 -167
  36. package/src/parser/Semantic/__tests__/ASTBuilder_test.mjs +0 -187
  37. package/src/parser/Semantic/__tests__/ASTBuilder_test.res +0 -192
  38. package/src/parser/Semantic/__tests__/ParserRegistry_test.mjs +0 -154
  39. package/src/parser/Semantic/__tests__/ParserRegistry_test.res +0 -191
  40. package/src/parser/Semantic/__tests__/SemanticParser_integration_test.mjs +0 -768
  41. package/src/parser/Semantic/__tests__/SemanticParser_integration_test.res +0 -1069
  42. package/src/parser/Semantic/__tests__/SemanticParser_manual.mjs +0 -1329
  43. package/src/parser/Semantic/__tests__/SemanticParser_manual.res +0 -544
  44. package/src/parser/__tests__/GridScanner_integration.test.mjs +0 -632
  45. package/src/parser/__tests__/GridScanner_integration.test.res +0 -816
  46. package/src/parser/__tests__/Performance.test.mjs +0 -244
  47. package/src/parser/__tests__/Performance.test.res +0 -371
  48. package/src/parser/__tests__/PerformanceFixtures.mjs +0 -200
  49. package/src/parser/__tests__/PerformanceFixtures.res +0 -284
  50. package/src/parser/__tests__/WyreframeParser_integration.test.mjs +0 -770
  51. package/src/parser/__tests__/WyreframeParser_integration.test.res +0 -1008
  52. package/src/parser/__tests__/fixtures/alignment-test.txt +0 -9
  53. package/src/parser/__tests__/fixtures/all-elements.txt +0 -16
  54. package/src/parser/__tests__/fixtures/login-scene.txt +0 -17
  55. package/src/parser/__tests__/fixtures/multi-scene.txt +0 -25
  56. package/src/parser/__tests__/fixtures/nested-boxes.txt +0 -15
  57. package/src/parser/__tests__/fixtures/simple-box.txt +0 -5
  58. package/src/parser/__tests__/fixtures/with-dividers.txt +0 -14
@@ -1,646 +0,0 @@
1
- /**
2
- * InteractionMerger_test.res
3
- *
4
- * Unit tests for the InteractionMerger module.
5
- * Tests validation, error detection, and successful merging of interactions.
6
- */
7
-
8
- open Vitest
9
- open Types
10
- open InteractionMerger
11
-
12
- describe("InteractionMerger", t => {
13
- // ============================================================================
14
- // Test Fixtures
15
- // ============================================================================
16
-
17
- let makePosition = (row, col) => Position.make(row, col)
18
- let makeBounds = (top, left, bottom, right) => Bounds.make(~top, ~left, ~bottom, ~right)
19
-
20
- // Simple scene with button and input
21
- let simpleScene: scene = {
22
- id: "login",
23
- title: "Login",
24
- transition: "fade",
25
- device: Desktop,
26
- elements: [
27
- Button({
28
- id: "submit-btn",
29
- text: "Submit",
30
- position: makePosition(5, 10),
31
- align: Center,
32
- actions: [],
33
- }),
34
- Input({
35
- id: "email",
36
- placeholder: Some("Email"),
37
- position: makePosition(3, 10),
38
- }),
39
- ],
40
- }
41
-
42
- // Scene with nested boxes
43
- let nestedScene: scene = {
44
- id: "dashboard",
45
- title: "Dashboard",
46
- transition: "slide",
47
- device: Desktop,
48
- elements: [
49
- Box({
50
- name: Some("Container"),
51
- bounds: makeBounds(0, 0, 10, 20),
52
- children: [
53
- Button({
54
- id: "action-btn",
55
- text: "Action",
56
- position: makePosition(2, 5),
57
- align: Left,
58
- actions: [],
59
- }),
60
- Section({
61
- name: "settings",
62
- children: [
63
- Link({
64
- id: "settings-link",
65
- text: "Settings",
66
- position: makePosition(4, 5),
67
- align: Left,
68
- actions: [],
69
- }),
70
- ],
71
- }),
72
- ],
73
- }),
74
- ],
75
- }
76
-
77
- // Valid interactions for simple scene
78
- let validInteractions: array<sceneInteractions> = [
79
- {
80
- sceneId: "login",
81
- interactions: [
82
- {
83
- elementId: "submit-btn",
84
- properties: Js.Dict.fromArray([("variant", Js.Json.string("primary"))]),
85
- actions: [
86
- Goto({
87
- target: "dashboard",
88
- transition: "slide",
89
- condition: None,
90
- }),
91
- ],
92
- },
93
- {
94
- elementId: "email",
95
- properties: Dict.fromArray([("required", JSON.Encode.bool(true))]),
96
- actions: [],
97
- },
98
- ],
99
- },
100
- ]
101
-
102
- // ============================================================================
103
- // Element ID Collection Tests
104
- // ============================================================================
105
-
106
- describe("collectElementIds", t => {
107
- test("collects ID from Button element", t => {
108
- let button = Button({
109
- id: "test-btn",
110
- text: "Test",
111
- position: makePosition(0, 0),
112
- align: Left,
113
- actions: [],
114
- })
115
-
116
- let ids = collectElementIds(button)
117
-
118
- t->expect(ids->Belt.Set.String.has("test-btn"))->Expect.toBe(true)
119
- })
120
-
121
- test("collects ID from Input element", t => {
122
- let input = Input({
123
- id: "test-input",
124
- placeholder: None,
125
- position: makePosition(0, 0),
126
- })
127
-
128
- let ids = collectElementIds(input)
129
-
130
- t->expect(ids->Belt.Set.String.has("test-input"))->Expect.toBe(true)
131
- })
132
-
133
- test("collects ID from Link element", t => {
134
- let link = Link({
135
- id: "test-link",
136
- text: "Test Link",
137
- position: makePosition(0, 0),
138
- align: Left,
139
- actions: [],
140
- })
141
-
142
- let ids = collectElementIds(link)
143
-
144
- t->expect(ids->Belt.Set.String.has("test-link"))->Expect.toBe(true)
145
- })
146
-
147
- test("collects name from Section element", t => {
148
- let section = Section({
149
- name: "test-section",
150
- children: [],
151
- })
152
-
153
- let ids = collectElementIds(section)
154
-
155
- t->expect(ids->Belt.Set.String.has("test-section"))->Expect.toBe(true)
156
- })
157
-
158
- test("returns empty set for elements without IDs", t => {
159
- let checkbox = Checkbox({
160
- checked: true,
161
- label: "Test",
162
- position: makePosition(0, 0),
163
- })
164
-
165
- let ids = collectElementIds(checkbox)
166
-
167
- t->expect(ids->Belt.Set.String.size)->Expect.toBe(0)
168
- })
169
-
170
- test("recursively collects IDs from Box children", t => {
171
- let box = Box({
172
- name: Some("Container"),
173
- bounds: makeBounds(0, 0, 10, 10),
174
- children: [
175
- Button({
176
- id: "btn1",
177
- text: "Button 1",
178
- position: makePosition(2, 2),
179
- align: Left,
180
- actions: [],
181
- }),
182
- Button({
183
- id: "btn2",
184
- text: "Button 2",
185
- position: makePosition(4, 2),
186
- align: Left,
187
- actions: [],
188
- }),
189
- ],
190
- })
191
-
192
- let ids = collectElementIds(box)
193
-
194
- t->expect(ids->Belt.Set.String.has("btn1"))->Expect.toBe(true)
195
- t->expect(ids->Belt.Set.String.has("btn2"))->Expect.toBe(true)
196
- t->expect(ids->Belt.Set.String.size)->Expect.toBe(2)
197
- })
198
-
199
- test("recursively collects IDs from nested Boxes", t => {
200
- let box = Box({
201
- name: Some("Outer"),
202
- bounds: makeBounds(0, 0, 20, 20),
203
- children: [
204
- Box({
205
- name: Some("Inner"),
206
- bounds: makeBounds(2, 2, 18, 18),
207
- children: [
208
- Input({
209
- id: "nested-input",
210
- placeholder: None,
211
- position: makePosition(5, 5),
212
- }),
213
- ],
214
- }),
215
- ],
216
- })
217
-
218
- let ids = collectElementIds(box)
219
-
220
- t->expect(ids->Belt.Set.String.has("nested-input"))->Expect.toBe(true)
221
- })
222
-
223
- test("collects IDs from Row children", t => {
224
- let row = Row({
225
- children: [
226
- Button({
227
- id: "row-btn1",
228
- text: "Button 1",
229
- position: makePosition(0, 0),
230
- align: Left,
231
- actions: [],
232
- }),
233
- Button({
234
- id: "row-btn2",
235
- text: "Button 2",
236
- position: makePosition(0, 10),
237
- align: Left,
238
- actions: [],
239
- }),
240
- ],
241
- align: Center,
242
- })
243
-
244
- let ids = collectElementIds(row)
245
-
246
- t->expect(ids->Belt.Set.String.has("row-btn1"))->Expect.toBe(true)
247
- t->expect(ids->Belt.Set.String.has("row-btn2"))->Expect.toBe(true)
248
- })
249
-
250
- test("collects IDs from Section and its children", t => {
251
- let section = Section({
252
- name: "my-section",
253
- children: [
254
- Link({
255
- id: "section-link",
256
- text: "Link",
257
- position: makePosition(0, 0),
258
- align: Left,
259
- actions: [],
260
- }),
261
- ],
262
- })
263
-
264
- let ids = collectElementIds(section)
265
-
266
- t->expect(ids->Belt.Set.String.has("my-section"))->Expect.toBe(true)
267
- t->expect(ids->Belt.Set.String.has("section-link"))->Expect.toBe(true)
268
- })
269
- })
270
-
271
- describe("collectSceneElementIds", t => {
272
- test("collects all element IDs from scene", t => {
273
- let ids = collectSceneElementIds(simpleScene)
274
-
275
- t->expect(ids->Belt.Set.String.has("submit-btn"))->Expect.toBe(true)
276
- t->expect(ids->Belt.Set.String.has("email"))->Expect.toBe(true)
277
- t->expect(ids->Belt.Set.String.size)->Expect.toBe(2)
278
- })
279
-
280
- test("collects IDs from nested elements in scene", t => {
281
- let ids = collectSceneElementIds(nestedScene)
282
-
283
- t->expect(ids->Belt.Set.String.has("action-btn"))->Expect.toBe(true)
284
- t->expect(ids->Belt.Set.String.has("settings"))->Expect.toBe(true)
285
- t->expect(ids->Belt.Set.String.has("settings-link"))->Expect.toBe(true)
286
- t->expect(ids->Belt.Set.String.size)->Expect.toBe(3)
287
- })
288
- })
289
-
290
- describe("buildSceneElementMap", t => {
291
- test("builds map of scene IDs to element IDs", t => {
292
- let ast: ast = {
293
- scenes: [simpleScene, nestedScene],
294
- }
295
-
296
- let sceneMap = buildSceneElementMap(ast)
297
-
298
- t->expect(sceneMap->Belt.Map.String.size)->Expect.toBe(2)
299
-
300
- let loginIds = sceneMap->Belt.Map.String.get("login")
301
- t->expect(loginIds->Option.isSome)->Expect.toBe(true)
302
- loginIds->Option.forEach(ids => {
303
- t->expect(ids->Belt.Set.String.has("submit-btn"))->Expect.toBe(true)
304
- t->expect(ids->Belt.Set.String.has("email"))->Expect.toBe(true)
305
- })
306
-
307
- let dashboardIds = sceneMap->Belt.Map.String.get("dashboard")
308
- t->expect(dashboardIds->Option.isSome)->Expect.toBe(true)
309
- dashboardIds->Option.forEach(ids => {
310
- t->expect(ids->Belt.Set.String.has("action-btn"))->Expect.toBe(true)
311
- t->expect(ids->Belt.Set.String.has("settings-link"))->Expect.toBe(true)
312
- })
313
- })
314
- })
315
-
316
- // ============================================================================
317
- // Validation Tests
318
- // ============================================================================
319
-
320
- describe("validateInteractions", t => {
321
- test("returns no errors for valid interactions", t => {
322
- let ast: ast = {scenes: [simpleScene]}
323
- let sceneMap = buildSceneElementMap(ast)
324
-
325
- let errors = validateInteractions(validInteractions, sceneMap)
326
-
327
- t->expect(errors->Array.length)->Expect.toBe(0)
328
- })
329
-
330
- test("detects missing element", t => {
331
- let ast: ast = {scenes: [simpleScene]}
332
- let sceneMap = buildSceneElementMap(ast)
333
-
334
- let invalidInteractions = [
335
- {
336
- sceneId: "login",
337
- interactions: [
338
- {
339
- elementId: "nonexistent-btn",
340
- properties: Js.Dict.empty(),
341
- actions: [],
342
- },
343
- ],
344
- },
345
- ]
346
-
347
- let errors = validateInteractions(invalidInteractions, sceneMap)
348
-
349
- t->expect(errors->Array.length)->Expect.toBe(1)
350
- switch errors[0] {
351
- | Some(ElementNotFound({elementId})) => t->expect(elementId)->Expect.toBe("nonexistent-btn")
352
- | _ => t->expect(true)->Expect.toBe(false) // fail: Expected ElementNotFound error
353
- }
354
- })
355
-
356
- test("detects missing scene", t => {
357
- let ast: ast = {scenes: [simpleScene]}
358
- let sceneMap = buildSceneElementMap(ast)
359
-
360
- let invalidInteractions = [
361
- {
362
- sceneId: "nonexistent-scene",
363
- interactions: [
364
- {
365
- elementId: "some-btn",
366
- properties: Js.Dict.empty(),
367
- actions: [],
368
- },
369
- ],
370
- },
371
- ]
372
-
373
- let errors = validateInteractions(invalidInteractions, sceneMap)
374
-
375
- t->expect(errors->Array.length)->Expect.toBe(1)
376
- switch errors[0] {
377
- | Some(SceneNotFound({sceneId})) => t->expect(sceneId)->Expect.toBe("nonexistent-scene")
378
- | _ => t->expect(true)->Expect.toBe(false) // fail: Expected SceneNotFound error
379
- }
380
- })
381
-
382
- test("detects duplicate interaction for same element", t => {
383
- let ast: ast = {scenes: [simpleScene]}
384
- let sceneMap = buildSceneElementMap(ast)
385
-
386
- let duplicateInteractions = [
387
- {
388
- sceneId: "login",
389
- interactions: [
390
- {
391
- elementId: "submit-btn",
392
- properties: Js.Dict.empty(),
393
- actions: [],
394
- },
395
- {
396
- elementId: "submit-btn",
397
- properties: Js.Dict.empty(),
398
- actions: [],
399
- },
400
- ],
401
- },
402
- ]
403
-
404
- let errors = validateInteractions(duplicateInteractions, sceneMap)
405
-
406
- t->expect(errors->Array.length)->Expect.toBe(1)
407
- switch errors[0] {
408
- | Some(DuplicateInteraction({elementId})) => t->expect(elementId)->Expect.toBe("submit-btn")
409
- | _ => t->expect(true)->Expect.toBe(false) // fail: Expected DuplicateInteraction error
410
- }
411
- })
412
-
413
- test("reports multiple errors", t => {
414
- let ast: ast = {scenes: [simpleScene]}
415
- let sceneMap = buildSceneElementMap(ast)
416
-
417
- let multiErrorInteractions = [
418
- {
419
- sceneId: "login",
420
- interactions: [
421
- {
422
- elementId: "nonexistent1",
423
- properties: Js.Dict.empty(),
424
- actions: [],
425
- },
426
- {
427
- elementId: "nonexistent2",
428
- properties: Js.Dict.empty(),
429
- actions: [],
430
- },
431
- ],
432
- },
433
- ]
434
-
435
- let errors = validateInteractions(multiErrorInteractions, sceneMap)
436
-
437
- t->expect(errors->Array.length)->Expect.toBe(2)
438
- })
439
- })
440
-
441
- // ============================================================================
442
- // Merge Function Tests
443
- // ============================================================================
444
-
445
- describe("mergeInteractions", t => {
446
- test("successfully merges valid interactions", t => {
447
- let ast: ast = {scenes: [simpleScene]}
448
-
449
- let result = mergeInteractions(ast, validInteractions)
450
-
451
- t->expect(result->Result.isOk)->Expect.toBe(true)
452
- result->Result.forEach(mergedAst => {
453
- t->expect(mergedAst.scenes->Array.length)->Expect.toBe(1)
454
- })
455
- })
456
-
457
- test("returns error for invalid interactions (hard errors)", t => {
458
- let ast: ast = {scenes: [simpleScene]}
459
-
460
- // SceneNotFound is a hard error (unlike ElementNotFound which is soft)
461
- let invalidInteractions = [
462
- {
463
- sceneId: "nonexistent-scene", // This scene doesn't exist
464
- interactions: [
465
- {
466
- elementId: "some-btn",
467
- properties: Js.Dict.empty(),
468
- actions: [],
469
- },
470
- ],
471
- },
472
- ]
473
-
474
- let result = mergeInteractions(ast, invalidInteractions)
475
-
476
- t->expect(result->Result.isError)->Expect.toBe(true)
477
- switch result {
478
- | Error(errors) => t->expect(errors->Array.length)->Expect.Int.toBeGreaterThan(0)
479
- | Ok(_) => t->expect(true)->Expect.toBe(false) // fail: Expected error result
480
- }
481
- })
482
-
483
- test("preserves scene structure after merge", t => {
484
- let ast: ast = {scenes: [simpleScene]}
485
-
486
- let result = mergeInteractions(ast, validInteractions)
487
-
488
- result->Result.forEach(mergedAst => {
489
- t->expect(mergedAst.scenes[0]->Option.map(s => s.id))->Expect.toEqual(Some("login"))
490
- t->expect(mergedAst.scenes[0]->Option.map(s => s.title))->Expect.toEqual(Some("Login"))
491
- t->expect(mergedAst.scenes[0]->Option.map(s => s.elements->Array.length))->Expect.toEqual(Some(2))
492
- })
493
- })
494
-
495
- test("handles multiple scenes with interactions", t => {
496
- let ast: ast = {scenes: [simpleScene, nestedScene]}
497
-
498
- let multiSceneInteractions = [
499
- {
500
- sceneId: "login",
501
- interactions: [
502
- {
503
- elementId: "submit-btn",
504
- properties: Js.Dict.empty(),
505
- actions: [],
506
- },
507
- ],
508
- },
509
- {
510
- sceneId: "dashboard",
511
- interactions: [
512
- {
513
- elementId: "action-btn",
514
- properties: Js.Dict.empty(),
515
- actions: [],
516
- },
517
- ],
518
- },
519
- ]
520
-
521
- let result = mergeInteractions(ast, multiSceneInteractions)
522
-
523
- t->expect(result->Result.isOk)->Expect.toBe(true)
524
- result->Result.forEach(mergedAst => {
525
- t->expect(mergedAst.scenes->Array.length)->Expect.toBe(2)
526
- })
527
- })
528
-
529
- test("merges empty interactions successfully", t => {
530
- let ast: ast = {scenes: [simpleScene]}
531
-
532
- let result = mergeInteractions(ast, [])
533
-
534
- t->expect(result->Result.isOk)->Expect.toBe(true)
535
- })
536
- })
537
-
538
- // ============================================================================
539
- // Error Formatting Tests
540
- // ============================================================================
541
-
542
- describe("formatError", t => {
543
- test("formats ElementNotFound error", t => {
544
- let error = ElementNotFound({
545
- sceneId: "login",
546
- elementId: "missing-btn",
547
- position: None,
548
- })
549
-
550
- let message = formatError(error)
551
-
552
- t->expect(message)->Expect.String.toContain("missing-btn")
553
- t->expect(message)->Expect.String.toContain("login")
554
- })
555
-
556
- test("formats DuplicateInteraction error", t => {
557
- let error = DuplicateInteraction({
558
- sceneId: "login",
559
- elementId: "duplicate-btn",
560
- })
561
-
562
- let message = formatError(error)
563
-
564
- t->expect(message)->Expect.String.toContain("duplicate-btn")
565
- t->expect(message)->Expect.String.toContain("Duplicate")
566
- })
567
-
568
- test("formats SceneNotFound error", t => {
569
- let error = SceneNotFound({sceneId: "missing-scene"})
570
-
571
- let message = formatError(error)
572
-
573
- t->expect(message)->Expect.String.toContain("missing-scene")
574
- t->expect(message)->Expect.String.toContain("not found")
575
- })
576
- })
577
-
578
- describe("formatErrors", t => {
579
- test("formats multiple errors with newlines", t => {
580
- let errors = [
581
- ElementNotFound({
582
- sceneId: "login",
583
- elementId: "btn1",
584
- position: None,
585
- }),
586
- ElementNotFound({
587
- sceneId: "login",
588
- elementId: "btn2",
589
- position: None,
590
- }),
591
- ]
592
-
593
- let message = formatErrors(errors)
594
-
595
- t->expect(message)->Expect.String.toContain("btn1")
596
- t->expect(message)->Expect.String.toContain("btn2")
597
- t->expect(message)->Expect.String.toContain("\n")
598
- })
599
- })
600
-
601
- // ============================================================================
602
- // findInteractionForElement Tests
603
- // ============================================================================
604
-
605
- describe("findInteractionForElement", t => {
606
- test("finds interaction for element", t => {
607
- let sceneInteractions = Some({
608
- sceneId: "login",
609
- interactions: [
610
- {
611
- elementId: "test-btn",
612
- properties: Js.Dict.empty(),
613
- actions: [],
614
- },
615
- ],
616
- })
617
-
618
- let result = findInteractionForElement("test-btn", sceneInteractions)
619
-
620
- t->expect(result->Option.isSome)->Expect.toBe(true)
621
- })
622
-
623
- test("returns None when element not found", t => {
624
- let sceneInteractions = Some({
625
- sceneId: "login",
626
- interactions: [
627
- {
628
- elementId: "test-btn",
629
- properties: Js.Dict.empty(),
630
- actions: [],
631
- },
632
- ],
633
- })
634
-
635
- let result = findInteractionForElement("other-btn", sceneInteractions)
636
-
637
- t->expect(result->Option.isNone)->Expect.toBe(true)
638
- })
639
-
640
- test("returns None when no scene interactions", t => {
641
- let result = findInteractionForElement("test-btn", None)
642
-
643
- t->expect(result->Option.isNone)->Expect.toBe(true)
644
- })
645
- })
646
- })