aria-ease 6.14.0 → 7.0.0

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 (93) hide show
  1. package/dist/AccordionComponentStrategy-2SWMNUR6.js +1 -0
  2. package/dist/ComboboxComponentStrategy-YSYLR2U5.js +5 -0
  3. package/dist/MenuComponentStrategy-C22BZEBH.js +5 -0
  4. package/dist/RelativeTargetResolver-T4P25J2M.js +1 -0
  5. package/dist/TabsComponentStrategy-ADEEFJXM.js +1 -0
  6. package/dist/audit-APAPHXRO.js +9 -0
  7. package/dist/badgeHelper-IB5RTMAG.js +11 -0
  8. package/dist/badgeHelper-JSROP5ML.js +1 -0
  9. package/dist/buildContracts-T4XQZBDU.js +13 -0
  10. package/dist/chunk-52I3INNG.js +11 -0
  11. package/dist/chunk-APUMBDOT.js +1 -0
  12. package/dist/chunk-BHNO4ZI3.js +1 -0
  13. package/dist/chunk-CNU4N4AY.js +1 -0
  14. package/dist/chunk-SM6ZKEDR.js +1 -0
  15. package/dist/chunk-ZNQ5BXVJ.js +1 -0
  16. package/dist/cli.cjs +132 -3560
  17. package/dist/cli.js +19 -161
  18. package/dist/configLoader-ZEJVXLX7.js +1 -0
  19. package/dist/configLoader-ZXTSCIP6.js +1 -0
  20. package/dist/contractTestRunnerPlaywright-FOCQTM4L.js +46 -0
  21. package/dist/contractTestRunnerPlaywright-QPU6HZXG.js +46 -0
  22. package/dist/formatters-H3CPDLG5.js +87 -0
  23. package/dist/index.cjs +64 -5103
  24. package/dist/index.d.cts +4 -6
  25. package/dist/index.d.ts +4 -6
  26. package/dist/index.js +17 -2703
  27. package/dist/src/accordion/index.cjs +1 -183
  28. package/dist/src/accordion/index.js +1 -181
  29. package/dist/src/block/index.cjs +1 -124
  30. package/dist/src/block/index.js +1 -122
  31. package/dist/src/checkbox/index.cjs +1 -109
  32. package/dist/src/checkbox/index.js +1 -107
  33. package/dist/src/combobox/index.cjs +1 -265
  34. package/dist/src/combobox/index.js +1 -263
  35. package/dist/src/menu/index.cjs +1 -339
  36. package/dist/src/menu/index.js +1 -337
  37. package/dist/src/radio/index.cjs +1 -117
  38. package/dist/src/radio/index.js +1 -115
  39. package/dist/src/tabs/index.cjs +1 -265
  40. package/dist/src/tabs/index.js +1 -263
  41. package/dist/src/toggle/index.cjs +1 -119
  42. package/dist/src/toggle/index.js +1 -117
  43. package/dist/src/utils/test/AccordionComponentStrategy-X2GSQ5KT.js +1 -0
  44. package/dist/src/utils/test/ComboboxComponentStrategy-SICWLI27.js +5 -0
  45. package/dist/src/utils/test/MenuComponentStrategy-R4VPAHDE.js +5 -0
  46. package/dist/src/utils/test/RelativeTargetResolver-UQQMZHI6.js +1 -0
  47. package/dist/src/utils/test/TabsComponentStrategy-L2PYNEW6.js +1 -0
  48. package/dist/src/utils/test/badgeHelper-ER5ZOHWF.js +11 -0
  49. package/dist/src/utils/test/chunk-APUMBDOT.js +1 -0
  50. package/dist/src/utils/test/chunk-BHNO4ZI3.js +1 -0
  51. package/dist/src/utils/test/configLoader-NCYRL2O6.js +1 -0
  52. package/dist/src/utils/test/contractTestRunnerPlaywright-YZCMF64Q.js +46 -0
  53. package/dist/src/utils/test/dsl/index.cjs +1 -838
  54. package/dist/src/utils/test/dsl/index.d.cts +2 -4
  55. package/dist/src/utils/test/dsl/index.d.ts +2 -4
  56. package/dist/src/utils/test/dsl/index.js +1 -836
  57. package/dist/src/utils/test/index.cjs +64 -2672
  58. package/dist/src/utils/test/index.d.cts +2 -2
  59. package/dist/src/utils/test/index.d.ts +2 -2
  60. package/dist/src/utils/test/index.js +16 -340
  61. package/dist/test-VXSCSKV5.js +19 -0
  62. package/package.json +7 -9
  63. package/dist/AccordionComponentStrategy-4ZEIQ2V6.js +0 -42
  64. package/dist/ComboboxComponentStrategy-DU342VMB.js +0 -64
  65. package/dist/MenuComponentStrategy-VYCC2XOM.js +0 -81
  66. package/dist/RelativeTargetResolver-DJAITO6D.js +0 -7
  67. package/dist/TabsComponentStrategy-3SQURPMX.js +0 -29
  68. package/dist/audit-JYEPKLHR.js +0 -63
  69. package/dist/badgeHelper-JOWO6RQG.js +0 -15
  70. package/dist/badgeHelper-RDOMCC6E.js +0 -108
  71. package/dist/buildContracts-VIV6GM56.js +0 -437
  72. package/dist/chunk-4DU5Z5BR.js +0 -340
  73. package/dist/chunk-GJGUY643.js +0 -182
  74. package/dist/chunk-GLT43UVH.js +0 -43
  75. package/dist/chunk-I2KLQ2HA.js +0 -22
  76. package/dist/chunk-JJEPLK7L.js +0 -107
  77. package/dist/chunk-PK5L2SAF.js +0 -17
  78. package/dist/configLoader-Q7N5XV4P.js +0 -183
  79. package/dist/configLoader-REHK3S3Q.js +0 -7
  80. package/dist/contractTestRunnerPlaywright-B2HLZKKK.js +0 -1394
  81. package/dist/contractTestRunnerPlaywright-RWK52C7S.js +0 -1394
  82. package/dist/formatters-32KQIIYS.js +0 -183
  83. package/dist/src/utils/test/AccordionComponentStrategy-WRHZOEN6.js +0 -38
  84. package/dist/src/utils/test/ComboboxComponentStrategy-XKQ72RFD.js +0 -60
  85. package/dist/src/utils/test/MenuComponentStrategy-6XWU5KLW.js +0 -77
  86. package/dist/src/utils/test/RelativeTargetResolver-G2XDN2VV.js +0 -1
  87. package/dist/src/utils/test/TabsComponentStrategy-BKG53SEV.js +0 -26
  88. package/dist/src/utils/test/badgeHelper-HZKGOPB4.js +0 -102
  89. package/dist/src/utils/test/chunk-4DU5Z5BR.js +0 -332
  90. package/dist/src/utils/test/chunk-GLT43UVH.js +0 -41
  91. package/dist/src/utils/test/configLoader-NA7IBCS3.js +0 -181
  92. package/dist/src/utils/test/contractTestRunnerPlaywright-5FIGA5G4.js +0 -1372
  93. package/dist/test-WDBS5JWO.js +0 -358
@@ -1,836 +1 @@
1
- // src/utils/test/dsl/src/state-packs/combobox/comboboxStatePack.ts
2
- var COMBOBOX_STATES = {
3
- "popup.open": {
4
- setup: [
5
- {
6
- when: ["keyboard", "textInput"],
7
- steps: () => [
8
- { type: "keypress", target: "input", key: "ArrowDown" }
9
- ]
10
- },
11
- {
12
- when: ["pointer"],
13
- steps: () => [
14
- { type: "click", target: "button" }
15
- ]
16
- }
17
- ],
18
- assertion: isComboboxOpen
19
- },
20
- "popup.closed": {
21
- setup: [
22
- {
23
- when: ["keyboard"],
24
- steps: () => [
25
- /* { type: "keypress", target: "input", key: "Escape" } */
26
- ]
27
- },
28
- {
29
- when: ["pointer"],
30
- steps: () => [
31
- /* { type: "click", target: "button" } */
32
- ]
33
- }
34
- ],
35
- assertion: [...isComboboxClosed(), ...isActiveDescendantEmpty()]
36
- },
37
- "main.focused": {
38
- setup: [
39
- {
40
- when: ["keyboard"],
41
- steps: () => [
42
- { type: "focus", target: "main" }
43
- ]
44
- }
45
- ],
46
- assertion: isMainFocused
47
- },
48
- "main.notFocused": {
49
- setup: [
50
- {
51
- when: ["keyboard"],
52
- steps: () => [
53
- //what to do here?
54
- ]
55
- }
56
- ],
57
- assertion: isMainNotFocused
58
- },
59
- "input.filled": {
60
- setup: [
61
- {
62
- when: ["keyboard", "textInput"],
63
- steps: () => [
64
- { type: "type", target: "input", value: "test" }
65
- ]
66
- }
67
- ],
68
- assertion: isInputFilled
69
- },
70
- "input.notFilled": {
71
- setup: [
72
- {
73
- when: ["keyboard", "textInput"],
74
- steps: () => [
75
- { type: "type", target: "input", value: "" }
76
- ]
77
- }
78
- ],
79
- assertion: isInputNotFilled
80
- },
81
- "activeOption.first": {
82
- requires: ["popup.open"],
83
- setup: [
84
- {
85
- when: ["keyboard"],
86
- steps: () => [
87
- { type: "keypress", target: "input", key: "ArrowDown" }
88
- ]
89
- }
90
- ],
91
- assertion: isActiveDescendantFirst
92
- },
93
- "activeOption.last": {
94
- requires: ["activeOption.first"],
95
- setup: [
96
- {
97
- when: ["keyboard"],
98
- steps: () => [
99
- { type: "keypress", target: "input", key: "ArrowUp" }
100
- ]
101
- }
102
- ],
103
- assertion: isActiveDescendantLast
104
- },
105
- "activeDescendant.notEmpty": {
106
- requires: [],
107
- setup: [
108
- {
109
- when: ["keyboard"],
110
- steps: () => []
111
- }
112
- ],
113
- assertion: isActiveDescendantNotEmpty
114
- },
115
- "activeDescendant.Empty": {
116
- requires: [],
117
- setup: [
118
- {
119
- when: ["keyboard"],
120
- steps: () => []
121
- }
122
- ],
123
- assertion: isActiveDescendantEmpty
124
- },
125
- "selectedOption.first": {
126
- requires: ["popup.open"],
127
- setup: [
128
- {
129
- when: ["pointer"],
130
- steps: () => [
131
- { type: "click", target: "relative", relativeTarget: "first" }
132
- ]
133
- }
134
- ],
135
- assertion: () => isAriaSelected("first")
136
- },
137
- "selectedOption.last": {
138
- requires: ["popup.open"],
139
- setup: [
140
- {
141
- when: ["pointer"],
142
- steps: () => [
143
- { type: "click", target: "relative", relativeTarget: "last" }
144
- ]
145
- }
146
- ],
147
- assertion: () => isAriaSelected("last")
148
- }
149
- };
150
- function isComboboxOpen() {
151
- return [
152
- {
153
- target: "popup",
154
- assertion: "toBeVisible",
155
- failureMessage: "Expected popup to be visible"
156
- },
157
- {
158
- target: "main",
159
- assertion: "toHaveAttribute",
160
- attribute: "aria-expanded",
161
- expectedValue: "true",
162
- failureMessage: "Expect combobox main to have aria-expanded='true'."
163
- }
164
- ];
165
- }
166
- function isComboboxClosed() {
167
- return [
168
- {
169
- target: "popup",
170
- assertion: "notToBeVisible",
171
- failureMessage: "Expected popup to be closed"
172
- },
173
- {
174
- target: "main",
175
- assertion: "toHaveAttribute",
176
- attribute: "aria-expanded",
177
- expectedValue: "false",
178
- failureMessage: "Expect combobox main to have aria-expanded='false'."
179
- }
180
- ];
181
- }
182
- function isActiveDescendantFirst() {
183
- return [
184
- {
185
- target: "main",
186
- assertion: "toHaveAttribute",
187
- attribute: "aria-activedescendant",
188
- expectedValue: { ref: "relative", relativeTarget: "first", property: "id" },
189
- failureMessage: "Expected aria-activedescendant on main to match the id of the first option."
190
- }
191
- ];
192
- }
193
- function isActiveDescendantLast() {
194
- return [
195
- {
196
- target: "main",
197
- assertion: "toHaveAttribute",
198
- attribute: "aria-activedescendant",
199
- expectedValue: { ref: "relative", relativeTarget: "last", property: "id" },
200
- failureMessage: "Expected aria-activedescendant on main to match the id of the last option."
201
- }
202
- ];
203
- }
204
- function isActiveDescendantNotEmpty() {
205
- return [
206
- {
207
- target: "main",
208
- assertion: "toHaveAttribute",
209
- attribute: "aria-activedescendant",
210
- expectedValue: "!empty",
211
- failureMessage: "Expected aria-activedescendant on main to not be empty."
212
- }
213
- ];
214
- }
215
- function isActiveDescendantEmpty() {
216
- return [
217
- {
218
- target: "main",
219
- assertion: "toHaveAttribute",
220
- attribute: "aria-activedescendant",
221
- expectedValue: "",
222
- failureMessage: "Expected aria-activedescendant on main to be empty."
223
- }
224
- ];
225
- }
226
- function isAriaSelected(index) {
227
- return [
228
- {
229
- target: "relative",
230
- relativeTarget: index,
231
- assertion: "toHaveAttribute",
232
- attribute: "aria-selected",
233
- expectedValue: "true",
234
- failureMessage: `Expected ${index} option to have aria-selected='true'.`
235
- }
236
- ];
237
- }
238
- function isMainFocused() {
239
- return [
240
- {
241
- target: "main",
242
- assertion: "toHaveFocus",
243
- failureMessage: "Expected main to be focused."
244
- }
245
- ];
246
- }
247
- function isMainNotFocused() {
248
- return [
249
- {
250
- target: "main",
251
- assertion: "notToHaveFocus",
252
- failureMessage: "Expected main to not have focused."
253
- }
254
- ];
255
- }
256
- function isInputFilled() {
257
- return [
258
- {
259
- target: "input",
260
- assertion: "toHaveValue",
261
- expectedValue: "test",
262
- failureMessage: "Expected input to have the value 'test'."
263
- }
264
- ];
265
- }
266
- function isInputNotFilled() {
267
- return [
268
- {
269
- target: "input",
270
- assertion: "toHaveValue",
271
- expectedValue: "",
272
- failureMessage: "Expected input to have the value ''."
273
- }
274
- ];
275
- }
276
-
277
- // src/utils/test/dsl/src/state-packs/menu/menuStatePack.ts
278
- var MENU_STATES = {
279
- "popup.open": {
280
- setup: [
281
- {
282
- when: ["keyboard"],
283
- steps: () => [
284
- { type: "keypress", target: "main", key: "Enter" }
285
- ]
286
- },
287
- {
288
- when: ["pointer"],
289
- steps: () => [
290
- { type: "click", target: "main" }
291
- ]
292
- }
293
- ],
294
- assertion: isMenuPopupOpen
295
- },
296
- "popup.closed": {
297
- setup: [
298
- {
299
- when: ["keyboard"],
300
- steps: () => [
301
- // component resets after each test so popup is closed
302
- ]
303
- },
304
- {
305
- when: ["pointer"],
306
- steps: () => []
307
- }
308
- ],
309
- assertion: isMenuPopupClosed
310
- },
311
- "main.focused": {
312
- setup: [
313
- {
314
- when: ["keyboard"],
315
- steps: () => [
316
- { type: "focus", target: "main" }
317
- ]
318
- }
319
- ],
320
- assertion: isMainFocused2
321
- },
322
- "main.notFocused": {
323
- setup: [
324
- {
325
- when: ["keyboard"],
326
- steps: () => [
327
- //what to do here?
328
- ]
329
- }
330
- ],
331
- assertion: isMainNotFocused2
332
- },
333
- "activeItem.first": {
334
- requires: ["popup.open"],
335
- setup: [
336
- {
337
- when: ["keyboard"],
338
- steps: () => [
339
- // By default, the first item should be active when the menu opens, so no action is needed to set this state
340
- ]
341
- }
342
- ],
343
- assertion: isActiveItemFirst
344
- },
345
- "activeItem.last": {
346
- requires: ["popup.open"],
347
- setup: [
348
- {
349
- when: ["keyboard"],
350
- steps: () => [
351
- { type: "keypress", target: "main", key: "ArrowUp" }
352
- ]
353
- }
354
- ],
355
- assertion: isActiveItemLast
356
- },
357
- "submenu.open": {
358
- requires: ["popup.open"],
359
- setup: [
360
- {
361
- when: ["keyboard"],
362
- steps: () => [
363
- { type: "keypress", target: "submenuTrigger", key: "ArrowRight" }
364
- ]
365
- },
366
- {
367
- when: ["pointer"],
368
- steps: () => [
369
- { type: "click", target: "submenuTrigger" }
370
- ]
371
- }
372
- ],
373
- assertion: isSubmenuPopupOpen
374
- },
375
- "submenu.closed": {
376
- requires: ["submenu.open"],
377
- setup: [
378
- {
379
- when: ["keyboard"],
380
- steps: () => [
381
- { type: "keypress", target: "submenuTrigger", key: "ArrowLeft" }
382
- ]
383
- },
384
- {
385
- when: ["pointer"],
386
- steps: () => [
387
- { type: "click", target: "submenuTrigger" }
388
- ]
389
- }
390
- ],
391
- assertion: isSubmenuPopupClosed
392
- },
393
- "submenuTrigger.focused": {
394
- setup: [
395
- {
396
- when: ["keyboard"],
397
- steps: () => [
398
- { type: "focus", target: "submenuTrigger" }
399
- ]
400
- }
401
- ],
402
- assertion: isSubmenuTriggerFocused
403
- },
404
- "submenuTrigger.notFocused": {
405
- setup: [
406
- {
407
- when: ["keyboard"],
408
- steps: () => [
409
- //what to do here?
410
- ]
411
- }
412
- ],
413
- assertion: isSubmenuTriggerNotFocused
414
- },
415
- "submenuActiveItem.first": {
416
- requires: ["submenu.open"],
417
- setup: [
418
- {
419
- when: ["keyboard"],
420
- steps: () => [
421
- // By default, the first item should be active when the submenu opens, so no action is needed to set this state
422
- ]
423
- },
424
- {
425
- when: ["pointer"],
426
- steps: () => []
427
- }
428
- ],
429
- assertion: isSubmenuActiveItemFirst
430
- }
431
- };
432
- function isMenuPopupOpen() {
433
- return [
434
- {
435
- target: "popup",
436
- assertion: "toBeVisible",
437
- failureMessage: "Expected popup to be visible"
438
- },
439
- {
440
- target: "main",
441
- assertion: "toHaveAttribute",
442
- attribute: "aria-expanded",
443
- expectedValue: "true",
444
- failureMessage: "Expect menu main to have aria-expanded='true'."
445
- }
446
- ];
447
- }
448
- function isMenuPopupClosed() {
449
- return [
450
- {
451
- target: "popup",
452
- assertion: "notToBeVisible",
453
- failureMessage: "Expected popup to be closed"
454
- },
455
- {
456
- target: "main",
457
- assertion: "toHaveAttribute",
458
- attribute: "aria-expanded",
459
- expectedValue: "false",
460
- failureMessage: "Expect menu main to have aria-expanded='false'."
461
- }
462
- ];
463
- }
464
- function isMainFocused2() {
465
- return [
466
- {
467
- target: "main",
468
- assertion: "toHaveFocus",
469
- failureMessage: "Expected menu main to be focused."
470
- }
471
- ];
472
- }
473
- function isMainNotFocused2() {
474
- return [
475
- {
476
- target: "main",
477
- assertion: "notToHaveFocus",
478
- failureMessage: "Expected menu main to not have focused."
479
- }
480
- ];
481
- }
482
- function isActiveItemFirst() {
483
- return [
484
- {
485
- target: "relative",
486
- assertion: "toHaveFocus",
487
- expectedValue: "first",
488
- failureMessage: "First menu item should have focus."
489
- }
490
- ];
491
- }
492
- function isActiveItemLast() {
493
- return [
494
- {
495
- target: "relative",
496
- assertion: "toHaveFocus",
497
- expectedValue: "last",
498
- failureMessage: "Last menu item should have focus."
499
- }
500
- ];
501
- }
502
- function isSubmenuPopupOpen() {
503
- return [
504
- {
505
- target: "submenu",
506
- assertion: "toBeVisible",
507
- failureMessage: "Expected submenu to be visible"
508
- },
509
- {
510
- target: "submenuTrigger",
511
- assertion: "toHaveAttribute",
512
- attribute: "aria-expanded",
513
- expectedValue: "true",
514
- failureMessage: "Expect submenu trigger to have aria-expanded='true'."
515
- }
516
- ];
517
- }
518
- function isSubmenuPopupClosed() {
519
- return [
520
- {
521
- target: "submenu",
522
- assertion: "notToBeVisible",
523
- failureMessage: "Expected submenu to be closed"
524
- },
525
- {
526
- target: "submenuTrigger",
527
- assertion: "toHaveAttribute",
528
- attribute: "aria-expanded",
529
- expectedValue: "false",
530
- failureMessage: "Expect submenu trigger to have aria-expanded='false'."
531
- }
532
- ];
533
- }
534
- function isSubmenuTriggerFocused() {
535
- return [
536
- {
537
- target: "submenuTrigger",
538
- assertion: "toHaveFocus",
539
- failureMessage: "Expected submenu trigger to be focused."
540
- }
541
- ];
542
- }
543
- function isSubmenuTriggerNotFocused() {
544
- return [
545
- {
546
- target: "submenuTrigger",
547
- assertion: "notToHaveFocus",
548
- failureMessage: "Expected submenu trigger to not have focused."
549
- }
550
- ];
551
- }
552
- function isSubmenuActiveItemFirst() {
553
- return [
554
- {
555
- target: "submenuItems",
556
- assertion: "toHaveFocus",
557
- failureMessage: "First interactive item in the submenu should have focus after Right Arrow open the submenu."
558
- }
559
- ];
560
- }
561
-
562
- // src/utils/test/dsl/src/state-packs/Capability.ts
563
- function hasCapabilities(ctx, requiredCaps) {
564
- return requiredCaps.some((cap) => ctx.capabilities.includes(cap));
565
- }
566
- function resolveSetup(setup, ctx) {
567
- if (Array.isArray(setup) && setup.length && !setup[0].when) {
568
- setup = [{ when: ["keyboard"], steps: () => setup }];
569
- }
570
- for (const strat of setup) {
571
- if (hasCapabilities(ctx, strat.when)) {
572
- return strat.steps(ctx);
573
- }
574
- }
575
- throw new Error(
576
- `No setup strategy matches capabilities: ${ctx.capabilities.join(", ")}`
577
- );
578
- }
579
-
580
- // src/utils/test/dsl/src/contractBuilder.ts
581
- var STATE_PACKS = {
582
- "combobox": COMBOBOX_STATES,
583
- "menu": MENU_STATES
584
- // Add more mappings as needed
585
- };
586
- var FluentContract = class {
587
- constructor(jsonContract) {
588
- this.jsonContract = jsonContract;
589
- }
590
- toJSON() {
591
- return this.jsonContract;
592
- }
593
- };
594
- var ContractBuilder = class {
595
- constructor(componentName) {
596
- this.componentName = componentName;
597
- this.statePack = STATE_PACKS[componentName] || {};
598
- }
599
- metaValue = {};
600
- selectorsValue = {};
601
- relationshipInvariants = [];
602
- staticAssertions = [];
603
- dynamicTests = [];
604
- statePack;
605
- meta(meta) {
606
- this.metaValue = meta;
607
- return this;
608
- }
609
- selectors(selectors) {
610
- this.selectorsValue = selectors;
611
- return this;
612
- }
613
- relationships(fn) {
614
- const statePack = this.statePack;
615
- const ctx = { capabilities: ["keyboard"] };
616
- const resolveAllSetups = (stateName, visited = /* @__PURE__ */ new Set()) => {
617
- if (visited.has(stateName)) return [];
618
- visited.add(stateName);
619
- const s = statePack[stateName];
620
- if (!s) return [];
621
- let actions = [];
622
- if (Array.isArray(s.requires)) {
623
- for (const req of s.requires) {
624
- actions = actions.concat(resolveAllSetups(req, visited));
625
- }
626
- }
627
- if (s.setup) actions = actions.concat(resolveSetup(s.setup, ctx));
628
- return actions;
629
- };
630
- const api = {
631
- ariaReference: (from, attribute, to) => {
632
- return {
633
- requires: (state) => {
634
- const setupActions = resolveAllSetups(state, /* @__PURE__ */ new Set());
635
- return {
636
- required: () => this.relationshipInvariants.push({ type: "aria-reference", from, attribute, to, level: "required", setup: setupActions }),
637
- optional: () => this.relationshipInvariants.push({ type: "aria-reference", from, attribute, to, level: "optional", setup: setupActions }),
638
- recommended: () => this.relationshipInvariants.push({ type: "aria-reference", from, attribute, to, level: "recommended", setup: setupActions })
639
- };
640
- },
641
- required: () => this.relationshipInvariants.push({ type: "aria-reference", from, attribute, to, level: "required" }),
642
- optional: () => this.relationshipInvariants.push({ type: "aria-reference", from, attribute, to, level: "optional" }),
643
- recommended: () => this.relationshipInvariants.push({ type: "aria-reference", from, attribute, to, level: "recommended" })
644
- };
645
- },
646
- contains: (parent, child) => {
647
- return {
648
- requires: (state) => {
649
- const setupActions = resolveAllSetups(state, /* @__PURE__ */ new Set());
650
- return {
651
- required: () => this.relationshipInvariants.push({ type: "contains", parent, child, level: "required", setup: setupActions }),
652
- optional: () => this.relationshipInvariants.push({ type: "contains", parent, child, level: "optional", setup: setupActions }),
653
- recommended: () => this.relationshipInvariants.push({ type: "contains", parent, child, level: "recommended", setup: setupActions })
654
- };
655
- },
656
- required: () => this.relationshipInvariants.push({ type: "contains", parent, child, level: "required" }),
657
- optional: () => this.relationshipInvariants.push({ type: "contains", parent, child, level: "optional" }),
658
- recommended: () => this.relationshipInvariants.push({ type: "contains", parent, child, level: "recommended" })
659
- };
660
- }
661
- };
662
- fn(api);
663
- return this;
664
- }
665
- static(fn) {
666
- const api = {
667
- target: (target) => {
668
- return {
669
- requires: (state) => {
670
- const statePack = this.statePack;
671
- const ctx = { capabilities: ["keyboard"] };
672
- const resolveAllSetups = (stateName, visited = /* @__PURE__ */ new Set()) => {
673
- if (visited.has(stateName)) return [];
674
- visited.add(stateName);
675
- const s = statePack[stateName];
676
- if (!s) return [];
677
- let actions = [];
678
- if (Array.isArray(s.requires)) {
679
- for (const req of s.requires) {
680
- actions = actions.concat(resolveAllSetups(req, visited));
681
- }
682
- }
683
- if (s.setup) actions = actions.concat(resolveSetup(s.setup, ctx));
684
- return actions;
685
- };
686
- const setupActions = resolveAllSetups(state, /* @__PURE__ */ new Set());
687
- return {
688
- has: (attribute, expectedValue) => ({
689
- required: () => this.staticAssertions.push({ target, attribute, expectedValue, failureMessage: "", level: "required", setup: setupActions }),
690
- optional: () => this.staticAssertions.push({ target, attribute, expectedValue, failureMessage: "", level: "optional", setup: setupActions }),
691
- recommended: () => this.staticAssertions.push({ target, attribute, expectedValue, failureMessage: "", level: "recommended", setup: setupActions })
692
- })
693
- };
694
- },
695
- has: (attribute, expectedValue) => ({
696
- required: () => this.staticAssertions.push({ target, attribute, expectedValue, failureMessage: "", level: "required" }),
697
- optional: () => this.staticAssertions.push({ target, attribute, expectedValue, failureMessage: "", level: "optional" }),
698
- recommended: () => this.staticAssertions.push({ target, attribute, expectedValue, failureMessage: "", level: "recommended" })
699
- })
700
- };
701
- }
702
- };
703
- fn(api);
704
- return this;
705
- }
706
- when(event) {
707
- return new DynamicTestBuilder(this, this.statePack, event);
708
- }
709
- addDynamicTest(test) {
710
- this.dynamicTests.push(test);
711
- }
712
- build() {
713
- return {
714
- meta: this.metaValue,
715
- selectors: this.selectorsValue,
716
- relationships: this.relationshipInvariants.length ? this.relationshipInvariants : void 0,
717
- static: this.staticAssertions.length ? [{ assertions: this.staticAssertions }] : [],
718
- dynamic: this.dynamicTests
719
- };
720
- }
721
- };
722
- var DynamicTestBuilder = class {
723
- constructor(parent, statePack, event) {
724
- this.parent = parent;
725
- this.statePack = statePack;
726
- this.event = event;
727
- }
728
- _as;
729
- _on;
730
- _given = [];
731
- _then = [];
732
- _desc = "";
733
- _level = "required";
734
- as(actionType) {
735
- this._as = actionType;
736
- return this;
737
- }
738
- on(target) {
739
- this._on = target;
740
- return this;
741
- }
742
- given(states) {
743
- this._given = Array.isArray(states) ? states : [states];
744
- return this;
745
- }
746
- then(states) {
747
- this._then = Array.isArray(states) ? states : [states];
748
- return this;
749
- }
750
- describe(desc) {
751
- this._desc = desc;
752
- return this;
753
- }
754
- required() {
755
- this._level = "required";
756
- this._finalize();
757
- return this.parent;
758
- }
759
- optional() {
760
- this._level = "optional";
761
- this._finalize();
762
- return this.parent;
763
- }
764
- recommended() {
765
- this._level = "recommended";
766
- this._finalize();
767
- return this.parent;
768
- }
769
- _finalize() {
770
- const capabilityMap = {
771
- keypress: "keyboard",
772
- click: "pointer",
773
- type: "textInput",
774
- focus: "keyboard",
775
- hover: "pointer"
776
- // add more mappings as needed
777
- };
778
- const capability = capabilityMap[this._as || "keyboard"] || (this._as || "keyboard");
779
- const ctx = { capabilities: [capability] };
780
- const resolveAllSetups = (stateName, visited = /* @__PURE__ */ new Set()) => {
781
- if (visited.has(stateName)) return [];
782
- visited.add(stateName);
783
- const s = this.statePack[stateName];
784
- if (!s) return [];
785
- let actions = [];
786
- if (Array.isArray(s.requires)) {
787
- for (const req of s.requires) {
788
- actions = actions.concat(resolveAllSetups(req, visited));
789
- }
790
- }
791
- if (s.setup) actions = actions.concat(resolveSetup(s.setup, ctx));
792
- return actions;
793
- };
794
- const setup = [];
795
- for (const state of this._given) {
796
- setup.push(...resolveAllSetups(state));
797
- }
798
- const assertions = [];
799
- for (const state of this._then) {
800
- const s = this.statePack[state];
801
- if (s && s.assertion !== void 0) {
802
- let value = s.assertion;
803
- if (typeof value === "function") {
804
- try {
805
- value = value();
806
- } catch (e) {
807
- throw new Error(`Error calling assertion function for state '${state}': ${e.message}`);
808
- }
809
- }
810
- if (Array.isArray(value)) assertions.push(...value);
811
- else assertions.push(value);
812
- }
813
- }
814
- const action = [
815
- {
816
- type: this._as,
817
- target: this._on,
818
- key: this._as === "keypress" ? this.event : void 0
819
- }
820
- ];
821
- this.parent.addDynamicTest({
822
- description: this._desc || "",
823
- level: this._level,
824
- action,
825
- assertions,
826
- ...setup.length ? { setup } : {}
827
- });
828
- }
829
- };
830
- function createContract(componentName, define) {
831
- const builder = new ContractBuilder(componentName);
832
- define(builder);
833
- return new FluentContract(builder.build());
834
- }
835
-
836
- export { createContract };
1
+ var A={"popup.open":{setup:[{when:["keyboard","textInput"],steps:()=>[{type:"keypress",target:"input",key:"ArrowDown"}]},{when:["pointer"],steps:()=>[{type:"click",target:"button"}]}],assertion:w},"popup.closed":{setup:[{when:["keyboard"],steps:()=>[]},{when:["pointer"],steps:()=>[]}],assertion:[...M(),...f()]},"main.focused":{setup:[{when:["keyboard"],steps:()=>[{type:"focus",target:"main"}]}],assertion:E},"main.notFocused":{setup:[{when:["keyboard"],steps:()=>[]}],assertion:D},"input.filled":{setup:[{when:["keyboard","textInput"],steps:()=>[{type:"type",target:"input",value:"test"}]}],assertion:C},"input.notFilled":{setup:[{when:["keyboard","textInput"],steps:()=>[{type:"type",target:"input",value:""}]}],assertion:I},"activeOption.first":{requires:["popup.open"],setup:[{when:["keyboard"],steps:()=>[{type:"keypress",target:"input",key:"ArrowDown"}]}],assertion:q},"activeOption.last":{requires:["activeOption.first"],setup:[{when:["keyboard"],steps:()=>[{type:"keypress",target:"input",key:"ArrowUp"}]}],assertion:S},"activeDescendant.notEmpty":{requires:[],setup:[{when:["keyboard"],steps:()=>[]}],assertion:T},"activeDescendant.Empty":{requires:[],setup:[{when:["keyboard"],steps:()=>[]}],assertion:f},"selectedOption.first":{requires:["popup.open"],setup:[{when:["pointer"],steps:()=>[{type:"click",target:"relative",relativeTarget:"first"}]}],assertion:()=>b("first")},"selectedOption.last":{requires:["popup.open"],setup:[{when:["pointer"],steps:()=>[{type:"click",target:"relative",relativeTarget:"last"}]}],assertion:()=>b("last")}};function w(){return [{target:"popup",assertion:"toBeVisible",failureMessage:"Expected popup to be visible"},{target:"main",assertion:"toHaveAttribute",attribute:"aria-expanded",expectedValue:"true",failureMessage:"Expect combobox main to have aria-expanded='true'."}]}function M(){return [{target:"popup",assertion:"notToBeVisible",failureMessage:"Expected popup to be closed"},{target:"main",assertion:"toHaveAttribute",attribute:"aria-expanded",expectedValue:"false",failureMessage:"Expect combobox main to have aria-expanded='false'."}]}function q(){return [{target:"main",assertion:"toHaveAttribute",attribute:"aria-activedescendant",expectedValue:{ref:"relative",relativeTarget:"first",property:"id"},failureMessage:"Expected aria-activedescendant on main to match the id of the first option."}]}function S(){return [{target:"main",assertion:"toHaveAttribute",attribute:"aria-activedescendant",expectedValue:{ref:"relative",relativeTarget:"last",property:"id"},failureMessage:"Expected aria-activedescendant on main to match the id of the last option."}]}function T(){return [{target:"main",assertion:"toHaveAttribute",attribute:"aria-activedescendant",expectedValue:"!empty",failureMessage:"Expected aria-activedescendant on main to not be empty."}]}function f(){return [{target:"main",assertion:"toHaveAttribute",attribute:"aria-activedescendant",expectedValue:"",failureMessage:"Expected aria-activedescendant on main to be empty."}]}function b(a){return [{target:"relative",relativeTarget:a,assertion:"toHaveAttribute",attribute:"aria-selected",expectedValue:"true",failureMessage:`Expected ${a} option to have aria-selected='true'.`}]}function E(){return [{target:"main",assertion:"toHaveFocus",failureMessage:"Expected main to be focused."}]}function D(){return [{target:"main",assertion:"notToHaveFocus",failureMessage:"Expected main to not have focused."}]}function C(){return [{target:"input",assertion:"toHaveValue",expectedValue:"test",failureMessage:"Expected input to have the value 'test'."}]}function I(){return [{target:"input",assertion:"toHaveValue",expectedValue:"",failureMessage:"Expected input to have the value ''."}]}var x={"popup.open":{setup:[{when:["keyboard"],steps:()=>[{type:"keypress",target:"main",key:"Enter"}]},{when:["pointer"],steps:()=>[{type:"click",target:"main"}]}],assertion:V},"popup.closed":{setup:[{when:["keyboard"],steps:()=>[]},{when:["pointer"],steps:()=>[]}],assertion:_},"main.focused":{setup:[{when:["keyboard"],steps:()=>[{type:"focus",target:"main"}]}],assertion:F},"main.notFocused":{setup:[{when:["keyboard"],steps:()=>[]}],assertion:H},"activeItem.first":{requires:["popup.open"],setup:[{when:["keyboard"],steps:()=>[]}],assertion:P},"activeItem.last":{requires:["popup.open"],setup:[{when:["keyboard"],steps:()=>[{type:"keypress",target:"main",key:"ArrowUp"}]}],assertion:O},"submenu.open":{requires:["popup.open"],setup:[{when:["keyboard"],steps:()=>[{type:"keypress",target:"submenuTrigger",key:"ArrowRight"}]},{when:["pointer"],steps:()=>[{type:"click",target:"submenuTrigger"}]}],assertion:B},"submenu.closed":{requires:["submenu.open"],setup:[{when:["keyboard"],steps:()=>[{type:"keypress",target:"submenuTrigger",key:"ArrowLeft"}]},{when:["pointer"],steps:()=>[{type:"click",target:"submenuTrigger"}]}],assertion:R},"submenuTrigger.focused":{setup:[{when:["keyboard"],steps:()=>[{type:"focus",target:"submenuTrigger"}]}],assertion:L},"submenuTrigger.notFocused":{setup:[{when:["keyboard"],steps:()=>[]}],assertion:z},"submenuActiveItem.first":{requires:["submenu.open"],setup:[{when:["keyboard"],steps:()=>[]},{when:["pointer"],steps:()=>[]}],assertion:J}};function V(){return [{target:"popup",assertion:"toBeVisible",failureMessage:"Expected popup to be visible"},{target:"main",assertion:"toHaveAttribute",attribute:"aria-expanded",expectedValue:"true",failureMessage:"Expect menu main to have aria-expanded='true'."}]}function _(){return [{target:"popup",assertion:"notToBeVisible",failureMessage:"Expected popup to be closed"},{target:"main",assertion:"toHaveAttribute",attribute:"aria-expanded",expectedValue:"false",failureMessage:"Expect menu main to have aria-expanded='false'."}]}function F(){return [{target:"main",assertion:"toHaveFocus",failureMessage:"Expected menu main to be focused."}]}function H(){return [{target:"main",assertion:"notToHaveFocus",failureMessage:"Expected menu main to not have focused."}]}function P(){return [{target:"relative",assertion:"toHaveFocus",expectedValue:"first",failureMessage:"First menu item should have focus."}]}function O(){return [{target:"relative",assertion:"toHaveFocus",expectedValue:"last",failureMessage:"Last menu item should have focus."}]}function B(){return [{target:"submenu",assertion:"toBeVisible",failureMessage:"Expected submenu to be visible"},{target:"submenuTrigger",assertion:"toHaveAttribute",attribute:"aria-expanded",expectedValue:"true",failureMessage:"Expect submenu trigger to have aria-expanded='true'."}]}function R(){return [{target:"submenu",assertion:"notToBeVisible",failureMessage:"Expected submenu to be closed"},{target:"submenuTrigger",assertion:"toHaveAttribute",attribute:"aria-expanded",expectedValue:"false",failureMessage:"Expect submenu trigger to have aria-expanded='false'."}]}function L(){return [{target:"submenuTrigger",assertion:"toHaveFocus",failureMessage:"Expected submenu trigger to be focused."}]}function z(){return [{target:"submenuTrigger",assertion:"notToHaveFocus",failureMessage:"Expected submenu trigger to not have focused."}]}function J(){return [{target:"submenuItems",assertion:"toHaveFocus",failureMessage:"First interactive item in the submenu should have focus after Right Arrow open the submenu."}]}function N(a,e){return e.some(o=>a.capabilities.includes(o))}function v(a,e){Array.isArray(a)&&a.length&&!a[0].when&&(a=[{when:["keyboard"],steps:()=>a}]);for(let o of a)if(N(e,o.when))return o.steps(e);throw new Error(`No setup strategy matches capabilities: ${e.capabilities.join(", ")}`)}var U={combobox:A,menu:x},h=class{constructor(e){this.jsonContract=e;}toJSON(){return this.jsonContract}},y=class{constructor(e){this.componentName=e;this.statePack=U[e]||{};}metaValue={};selectorsValue={};relationshipInvariants=[];staticAssertions=[];dynamicTests=[];statePack;meta(e){return this.metaValue=e,this}selectors(e){return this.selectorsValue=e,this}relationships(e){let o=this.statePack,p={capabilities:["keyboard"]},c=(t,i=new Set)=>{if(i.has(t))return [];i.add(t);let s=o[t];if(!s)return [];let r=[];if(Array.isArray(s.requires))for(let n of s.requires)r=r.concat(c(n,i));return s.setup&&(r=r.concat(v(s.setup,p))),r};return e({ariaReference:(t,i,s)=>({requires:r=>{let n=c(r,new Set);return {required:()=>this.relationshipInvariants.push({type:"aria-reference",from:t,attribute:i,to:s,level:"required",setup:n}),optional:()=>this.relationshipInvariants.push({type:"aria-reference",from:t,attribute:i,to:s,level:"optional",setup:n}),recommended:()=>this.relationshipInvariants.push({type:"aria-reference",from:t,attribute:i,to:s,level:"recommended",setup:n})}},required:()=>this.relationshipInvariants.push({type:"aria-reference",from:t,attribute:i,to:s,level:"required"}),optional:()=>this.relationshipInvariants.push({type:"aria-reference",from:t,attribute:i,to:s,level:"optional"}),recommended:()=>this.relationshipInvariants.push({type:"aria-reference",from:t,attribute:i,to:s,level:"recommended"})}),contains:(t,i)=>({requires:s=>{let r=c(s,new Set);return {required:()=>this.relationshipInvariants.push({type:"contains",parent:t,child:i,level:"required",setup:r}),optional:()=>this.relationshipInvariants.push({type:"contains",parent:t,child:i,level:"optional",setup:r}),recommended:()=>this.relationshipInvariants.push({type:"contains",parent:t,child:i,level:"recommended",setup:r})}},required:()=>this.relationshipInvariants.push({type:"contains",parent:t,child:i,level:"required"}),optional:()=>this.relationshipInvariants.push({type:"contains",parent:t,child:i,level:"optional"}),recommended:()=>this.relationshipInvariants.push({type:"contains",parent:t,child:i,level:"recommended"})})}),this}static(e){return e({target:p=>{let c=t=>{let i=this.statePack,s={capabilities:["keyboard"]},r=(n,u=new Set)=>{if(u.has(n))return [];u.add(n);let d=i[n];if(!d)return [];let g=[];if(Array.isArray(d.requires))for(let k of d.requires)g=g.concat(r(k,u));return d.setup&&(g=g.concat(v(d.setup,s))),g};return r(t,new Set)},l=(t,i,s)=>({required:()=>this.staticAssertions.push({target:p,attribute:t,expectedValue:i,failureMessage:"",level:"required",setup:s}),optional:()=>this.staticAssertions.push({target:p,attribute:t,expectedValue:i,failureMessage:"",level:"optional",setup:s}),recommended:()=>this.staticAssertions.push({target:p,attribute:t,expectedValue:i,failureMessage:"",level:"recommended",setup:s})});return {has:(t,i)=>({...l(t,i),requires:r=>{let n=c(r);return l(t,i,n)}})}}}),this}when(e){return new m(this,this.statePack,e)}addDynamicTest(e){this.dynamicTests.push(e);}build(){return {meta:this.metaValue,selectors:this.selectorsValue,relationships:this.relationshipInvariants.length?this.relationshipInvariants:void 0,static:this.staticAssertions.length?[{assertions:this.staticAssertions}]:[],dynamic:this.dynamicTests}}},m=class{constructor(e,o,p){this.parent=e;this.statePack=o;this.event=p;}_as;_on;_given=[];_then=[];_desc="";_level="required";as(e){return this._as=e,this}on(e){return this._on=e,this}given(e){return this._given=Array.isArray(e)?e:[e],this}then(e){return this._then=Array.isArray(e)?e:[e],this}describe(e){return this._desc=e,this}required(){return this._level="required",this._finalize(),this.parent}optional(){return this._level="optional",this._finalize(),this.parent}recommended(){return this._level="recommended",this._finalize(),this.parent}_finalize(){let p={capabilities:[{keypress:"keyboard",click:"pointer",type:"textInput",focus:"keyboard",hover:"pointer"}[this._as||"keyboard"]||this._as||"keyboard"]},c=(s,r=new Set)=>{if(r.has(s))return [];r.add(s);let n=this.statePack[s];if(!n)return [];let u=[];if(Array.isArray(n.requires))for(let d of n.requires)u=u.concat(c(d,r));return n.setup&&(u=u.concat(v(n.setup,p))),u},l=[];for(let s of this._given)l.push(...c(s));let t=[];for(let s of this._then){let r=this.statePack[s];if(r&&r.assertion!==void 0){let n=r.assertion;if(typeof n=="function")try{n=n();}catch(u){throw new Error(`Error calling assertion function for state '${s}': ${u.message}`)}Array.isArray(n)?t.push(...n):t.push(n);}}let i=[{type:this._as,target:this._on,key:this._as==="keypress"?this.event:void 0}];this.parent.addDynamicTest({description:this._desc||"",level:this._level,action:i,assertions:t,...l.length?{setup:l}:{}});}};function Y(a,e){let o=new y(a);return e(o),new h(o.build())}export{Y as createContract};