aria-ease 6.10.0 → 6.12.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 (60) hide show
  1. package/README.md +2 -2
  2. package/{bin/buildContracts-S22V7AGV.js → dist/buildContracts-FT6KWUJN.js} +3 -3
  3. package/dist/{chunk-XERMSYEH.js → chunk-FZ7GMIJB.js} +0 -21
  4. package/{bin/chunk-NI3MQCAS.js → dist/chunk-GJGUY643.js} +2 -2
  5. package/{bin → dist}/cli.cjs +30 -67
  6. package/{bin → dist}/cli.js +4 -4
  7. package/dist/{configLoader-DWHOHXHL.js → configLoader-Q7N5XV4P.js} +2 -2
  8. package/{bin/configLoader-UJZHQBYS.js → dist/configLoader-REHK3S3Q.js} +1 -1
  9. package/{bin/contractTestRunnerPlaywright-QDXSK3FE.js → dist/contractTestRunnerPlaywright-DIXP5DQ3.js} +5 -20
  10. package/dist/{contractTestRunnerPlaywright-WNWQYSXZ.js → contractTestRunnerPlaywright-EWAWQVHT.js} +5 -20
  11. package/dist/index.cjs +164 -122
  12. package/dist/index.d.cts +3 -0
  13. package/dist/index.d.ts +3 -0
  14. package/dist/index.js +155 -71
  15. package/dist/src/{Types.d-yGC2bBaB.d.ts → Types.d-DYfYR3Vc.d.cts} +1 -1
  16. package/dist/src/{Types.d-yGC2bBaB.d.cts → Types.d-DYfYR3Vc.d.ts} +1 -1
  17. package/dist/src/accordion/index.d.cts +1 -1
  18. package/dist/src/accordion/index.d.ts +1 -1
  19. package/dist/src/block/index.d.cts +1 -1
  20. package/dist/src/block/index.d.ts +1 -1
  21. package/dist/src/checkbox/index.d.cts +1 -1
  22. package/dist/src/checkbox/index.d.ts +1 -1
  23. package/dist/src/combobox/index.d.cts +1 -1
  24. package/dist/src/combobox/index.d.ts +1 -1
  25. package/dist/src/menu/index.d.cts +1 -1
  26. package/dist/src/menu/index.d.ts +1 -1
  27. package/dist/src/radio/index.d.cts +1 -1
  28. package/dist/src/radio/index.d.ts +1 -1
  29. package/dist/src/tabs/index.d.cts +1 -1
  30. package/dist/src/tabs/index.d.ts +1 -1
  31. package/dist/src/toggle/index.d.cts +1 -1
  32. package/dist/src/toggle/index.d.ts +1 -1
  33. package/dist/src/utils/test/{chunk-XERMSYEH.js → chunk-FZ7GMIJB.js} +1 -21
  34. package/dist/src/utils/test/{configLoader-SHJSRG2A.js → configLoader-NA7IBCS3.js} +2 -2
  35. package/dist/src/utils/test/{contractTestRunnerPlaywright-Z2AHXSNM.js → contractTestRunnerPlaywright-CIZOXYRW.js} +5 -19
  36. package/dist/src/utils/test/dsl/index.cjs +139 -60
  37. package/dist/src/utils/test/dsl/index.d.cts +3 -0
  38. package/dist/src/utils/test/dsl/index.d.ts +3 -0
  39. package/dist/src/utils/test/dsl/index.js +139 -60
  40. package/dist/src/utils/test/index.cjs +19 -55
  41. package/dist/src/utils/test/index.js +16 -10
  42. package/{bin/test-O3J4ZPQR.js → dist/test-HBPCSYH5.js} +16 -11
  43. package/package.json +5 -7
  44. package/bin/AccordionComponentStrategy-4ZEIQ2V6.js +0 -42
  45. package/bin/ComboboxComponentStrategy-OGRVZXAF.js +0 -64
  46. package/bin/MenuComponentStrategy-JAMTCSNF.js +0 -81
  47. package/bin/TabsComponentStrategy-3SQURPMX.js +0 -29
  48. package/bin/chunk-I2KLQ2HA.js +0 -22
  49. package/bin/chunk-PK5L2SAF.js +0 -17
  50. package/bin/chunk-XERMSYEH.js +0 -363
  51. package/dist/src/utils/test/aria-contracts/accordion/accordion.contract.json +0 -290
  52. package/dist/src/utils/test/aria-contracts/combobox/combobox.listbox.contract.json +0 -463
  53. package/dist/src/utils/test/aria-contracts/menu/menu.contract.json +0 -562
  54. package/dist/src/utils/test/aria-contracts/tabs/tabs.contract.json +0 -361
  55. /package/{bin → dist}/audit-RM6TCZ5C.js +0 -0
  56. /package/{bin → dist}/badgeHelper-JOWO6RQG.js +0 -0
  57. /package/{bin → dist}/chunk-JJEPLK7L.js +0 -0
  58. /package/{bin → dist}/cli.d.cts +0 -0
  59. /package/{bin → dist}/cli.d.ts +0 -0
  60. /package/{bin → dist}/formatters-32KQIIYS.js +0 -0
@@ -1,90 +1,141 @@
1
1
  'use strict';
2
2
 
3
3
  // src/utils/test/dsl/src/state-packs/comboboxStatePack.ts
4
+ function hasCapabilities(ctx, requiredCaps) {
5
+ return requiredCaps.some((cap) => ctx.capabilities.includes(cap));
6
+ }
7
+ function resolveSetup(setup, ctx) {
8
+ if (Array.isArray(setup) && setup.length && !setup[0].when) {
9
+ setup = [{ when: ["keyboard"], steps: () => setup }];
10
+ }
11
+ for (const strat of setup) {
12
+ if (hasCapabilities(ctx, strat.when)) {
13
+ return strat.steps(ctx);
14
+ }
15
+ }
16
+ throw new Error(
17
+ `No setup strategy matches capabilities: ${ctx.capabilities.join(", ")}`
18
+ );
19
+ }
4
20
  var COMBOBOX_STATES = {
5
21
  "listbox.open": {
6
- setup: openCombobox(),
7
- assertion: isComboboxOpen()
22
+ setup: [
23
+ {
24
+ when: ["keyboard", "textInput"],
25
+ steps: () => [
26
+ { type: "keypress", target: "input", key: "ArrowDown" }
27
+ ]
28
+ },
29
+ {
30
+ when: ["pointer"],
31
+ steps: () => [
32
+ { type: "click", target: "button" }
33
+ ]
34
+ }
35
+ ],
36
+ assertion: isComboboxOpen
8
37
  },
9
38
  "listbox.closed": {
10
- setup: closeCombobox(),
11
- assertion: isComboboxClosed()
39
+ setup: [
40
+ {
41
+ when: ["keyboard"],
42
+ steps: () => [
43
+ /* { type: "keypress", target: "input", key: "Escape" } */
44
+ ]
45
+ },
46
+ {
47
+ when: ["pointer"],
48
+ steps: () => [
49
+ /* { type: "click", target: "button" } */
50
+ ]
51
+ }
52
+ ],
53
+ assertion: isComboboxClosed
12
54
  },
13
55
  "input.focused": {
14
- setup: focusInput(),
15
- assertion: [
16
- ...isInputFocused()
17
- ]
56
+ setup: [
57
+ {
58
+ when: ["keyboard"],
59
+ steps: () => [
60
+ { type: "focus", target: "input" }
61
+ ]
62
+ }
63
+ ],
64
+ assertion: isInputFocused
18
65
  },
19
66
  "input.filled": {
20
- setup: fillInput(),
21
- assertion: [
22
- ...isInputFilled()
23
- ]
67
+ setup: [
68
+ {
69
+ when: ["keyboard", "textInput"],
70
+ steps: () => [
71
+ { type: "type", target: "input", value: "test" }
72
+ ]
73
+ }
74
+ ],
75
+ assertion: isInputFilled
24
76
  },
25
77
  "activeOption.first": {
26
78
  requires: ["listbox.open"],
27
79
  setup: [
28
- { type: "keypress", target: "input", key: "ArrowDown" }
80
+ {
81
+ when: ["keyboard"],
82
+ steps: () => [
83
+ { type: "keypress", target: "input", key: "ArrowDown" }
84
+ ]
85
+ }
29
86
  ],
30
- assertion: [
31
- ...isActiveDescendantNotEmpty()
32
- ]
87
+ assertion: isActiveDescendantNotEmpty
33
88
  },
34
89
  "activeOption.last": {
35
90
  requires: ["activeOption.first"],
36
91
  setup: [
37
- { type: "keypress", target: "input", key: "ArrowUp" }
92
+ {
93
+ when: ["keyboard"],
94
+ steps: () => [
95
+ { type: "keypress", target: "input", key: "ArrowUp" }
96
+ ]
97
+ }
38
98
  ],
39
- assertion: [
40
- ...isActiveDescendantNotEmpty()
41
- ]
99
+ assertion: isActiveDescendantNotEmpty
42
100
  },
43
101
  "selectedOption.first": {
44
102
  requires: ["listbox.open"],
45
103
  setup: [
46
- { type: "click", target: "relative", relativeTarget: "first" }
104
+ {
105
+ when: ["pointer"],
106
+ steps: () => [
107
+ { type: "click", target: "relative", relativeTarget: "first" }
108
+ ]
109
+ }
47
110
  ],
48
- assertion: [
49
- ...isAriaSelected("first")
50
- ]
111
+ assertion: () => isAriaSelected("first")
51
112
  },
52
113
  "selectedOption.last": {
53
114
  requires: ["listbox.open"],
54
115
  setup: [
55
- { type: "click", target: "relative", relativeTarget: "last" }
116
+ {
117
+ when: ["pointer"],
118
+ steps: () => [
119
+ { type: "click", target: "relative", relativeTarget: "last" }
120
+ ]
121
+ }
56
122
  ],
57
- assertion: [
58
- ...isAriaSelected("first")
59
- ]
123
+ assertion: () => isAriaSelected("last")
60
124
  }
61
125
  };
62
- function openCombobox() {
63
- return [
64
- { type: "keypress", target: "input", key: "ArrowDown" }
65
- ];
66
- }
67
- function closeCombobox() {
68
- return [
69
- { type: "keypress", target: "input", key: "Escape" }
70
- ];
71
- }
72
- function focusInput() {
73
- return [
74
- { type: "focus", target: "input" }
75
- ];
76
- }
77
- function fillInput() {
78
- return [
79
- { type: "type", target: "input", value: "test" }
80
- ];
81
- }
82
126
  function isComboboxOpen() {
83
127
  return [
84
128
  {
85
129
  target: "listbox",
86
130
  assertion: "toBeVisible",
87
131
  failureMessage: "Expected listbox to be visible"
132
+ },
133
+ {
134
+ target: "input",
135
+ assertion: "toHaveAttribute",
136
+ attribute: "aria-expanded",
137
+ expectedValue: "true",
138
+ failureMessage: "Expect combobox input to have aria-expanded='true'"
88
139
  }
89
140
  ];
90
141
  }
@@ -94,6 +145,13 @@ function isComboboxClosed() {
94
145
  target: "listbox",
95
146
  assertion: "notToBeVisible",
96
147
  failureMessage: "Expected listbox to be closed"
148
+ },
149
+ {
150
+ target: "input",
151
+ assertion: "toHaveAttribute",
152
+ attribute: "aria-expanded",
153
+ expectedValue: "false",
154
+ failureMessage: "Expect combobox input to have aria-expanded='false'"
97
155
  }
98
156
  ];
99
157
  }
@@ -116,7 +174,7 @@ function isAriaSelected(index) {
116
174
  assertion: "toHaveAttribute",
117
175
  attribute: "aria-selected",
118
176
  expectedValue: "true",
119
- failureMessage: `Expected aria-selected on ${index} option to be true`
177
+ failureMessage: `Expected ${index} option to have aria-selected='true'`
120
178
  }
121
179
  ];
122
180
  }
@@ -142,7 +200,7 @@ function isInputFilled() {
142
200
 
143
201
  // src/utils/test/dsl/src/contractBuilder.ts
144
202
  var STATE_PACKS = {
145
- "combobox.listbox": COMBOBOX_STATES
203
+ "combobox": COMBOBOX_STATES
146
204
  // Add more mappings as needed
147
205
  };
148
206
  var FluentContract = class {
@@ -176,11 +234,13 @@ var ContractBuilder = class {
176
234
  const api = {
177
235
  ariaReference: (from, attribute, to) => ({
178
236
  required: () => this.relationshipInvariants.push({ type: "aria-reference", from, attribute, to, level: "required" }),
179
- optional: () => this.relationshipInvariants.push({ type: "aria-reference", from, attribute, to, level: "optional" })
237
+ optional: () => this.relationshipInvariants.push({ type: "aria-reference", from, attribute, to, level: "optional" }),
238
+ recommended: () => this.relationshipInvariants.push({ type: "aria-reference", from, attribute, to, level: "recommended" })
180
239
  }),
181
240
  contains: (parent, child) => ({
182
241
  required: () => this.relationshipInvariants.push({ type: "contains", parent, child, level: "required" }),
183
- optional: () => this.relationshipInvariants.push({ type: "contains", parent, child, level: "optional" })
242
+ optional: () => this.relationshipInvariants.push({ type: "contains", parent, child, level: "optional" }),
243
+ recommended: () => this.relationshipInvariants.push({ type: "contains", parent, child, level: "recommended" })
184
244
  })
185
245
  };
186
246
  fn(api);
@@ -191,7 +251,8 @@ var ContractBuilder = class {
191
251
  target: (target) => ({
192
252
  has: (attribute, expectedValue) => ({
193
253
  required: () => this.staticAssertions.push({ target, attribute, expectedValue, failureMessage: "", level: "required" }),
194
- optional: () => this.staticAssertions.push({ target, attribute, expectedValue, failureMessage: "", level: "optional" })
254
+ optional: () => this.staticAssertions.push({ target, attribute, expectedValue, failureMessage: "", level: "optional" }),
255
+ recommended: () => this.staticAssertions.push({ target, attribute, expectedValue, failureMessage: "", level: "recommended" })
195
256
  })
196
257
  })
197
258
  };
@@ -262,7 +323,17 @@ var DynamicTestBuilder = class {
262
323
  return this.parent;
263
324
  }
264
325
  _finalize() {
265
- const resolveSetup = (stateName, visited = /* @__PURE__ */ new Set()) => {
326
+ const capabilityMap = {
327
+ keypress: "keyboard",
328
+ click: "pointer",
329
+ type: "textInput",
330
+ focus: "keyboard",
331
+ hover: "pointer"
332
+ // add more mappings as needed
333
+ };
334
+ const capability = capabilityMap[this._as || "keyboard"] || (this._as || "keyboard");
335
+ const ctx = { capabilities: [capability] };
336
+ const resolveAllSetups = (stateName, visited = /* @__PURE__ */ new Set()) => {
266
337
  if (visited.has(stateName)) return [];
267
338
  visited.add(stateName);
268
339
  const s = this.statePack[stateName];
@@ -270,22 +341,30 @@ var DynamicTestBuilder = class {
270
341
  let actions = [];
271
342
  if (Array.isArray(s.requires)) {
272
343
  for (const req of s.requires) {
273
- actions = actions.concat(resolveSetup(req, visited));
344
+ actions = actions.concat(resolveAllSetups(req, visited));
274
345
  }
275
346
  }
276
- if (s.setup) actions = actions.concat(s.setup);
347
+ if (s.setup) actions = actions.concat(resolveSetup(s.setup, ctx));
277
348
  return actions;
278
349
  };
279
350
  const setup = [];
280
351
  for (const state of this._given) {
281
- setup.push(...resolveSetup(state));
352
+ setup.push(...resolveAllSetups(state));
282
353
  }
283
354
  const assertions = [];
284
355
  for (const state of this._then) {
285
356
  const s = this.statePack[state];
286
- if (s && s.assertion) {
287
- if (Array.isArray(s.assertion)) assertions.push(...s.assertion);
288
- else assertions.push(s.assertion);
357
+ if (s && s.assertion !== void 0) {
358
+ let value = s.assertion;
359
+ if (typeof value === "function") {
360
+ try {
361
+ value = value();
362
+ } catch (e) {
363
+ throw new Error(`Error calling assertion function for state '${state}': ${e.message}`);
364
+ }
365
+ }
366
+ if (Array.isArray(value)) assertions.push(...value);
367
+ else assertions.push(value);
289
368
  }
290
369
  }
291
370
  const action = [
@@ -92,10 +92,12 @@ declare class ContractBuilder {
92
92
  ariaReference: (from: string, attribute: string, to: string) => {
93
93
  required: () => void;
94
94
  optional: () => void;
95
+ recommended: () => void;
95
96
  };
96
97
  contains: (parent: string, child: string) => {
97
98
  required: () => void;
98
99
  optional: () => void;
100
+ recommended: () => void;
99
101
  };
100
102
  }) => void): this;
101
103
  static(fn: (s: {
@@ -103,6 +105,7 @@ declare class ContractBuilder {
103
105
  has: (attribute: string, expectedValue: string) => {
104
106
  required: () => void;
105
107
  optional: () => void;
108
+ recommended: () => void;
106
109
  };
107
110
  };
108
111
  }) => void): this;
@@ -92,10 +92,12 @@ declare class ContractBuilder {
92
92
  ariaReference: (from: string, attribute: string, to: string) => {
93
93
  required: () => void;
94
94
  optional: () => void;
95
+ recommended: () => void;
95
96
  };
96
97
  contains: (parent: string, child: string) => {
97
98
  required: () => void;
98
99
  optional: () => void;
100
+ recommended: () => void;
99
101
  };
100
102
  }) => void): this;
101
103
  static(fn: (s: {
@@ -103,6 +105,7 @@ declare class ContractBuilder {
103
105
  has: (attribute: string, expectedValue: string) => {
104
106
  required: () => void;
105
107
  optional: () => void;
108
+ recommended: () => void;
106
109
  };
107
110
  };
108
111
  }) => void): this;
@@ -1,88 +1,139 @@
1
1
  // src/utils/test/dsl/src/state-packs/comboboxStatePack.ts
2
+ function hasCapabilities(ctx, requiredCaps) {
3
+ return requiredCaps.some((cap) => ctx.capabilities.includes(cap));
4
+ }
5
+ function resolveSetup(setup, ctx) {
6
+ if (Array.isArray(setup) && setup.length && !setup[0].when) {
7
+ setup = [{ when: ["keyboard"], steps: () => setup }];
8
+ }
9
+ for (const strat of setup) {
10
+ if (hasCapabilities(ctx, strat.when)) {
11
+ return strat.steps(ctx);
12
+ }
13
+ }
14
+ throw new Error(
15
+ `No setup strategy matches capabilities: ${ctx.capabilities.join(", ")}`
16
+ );
17
+ }
2
18
  var COMBOBOX_STATES = {
3
19
  "listbox.open": {
4
- setup: openCombobox(),
5
- assertion: isComboboxOpen()
20
+ setup: [
21
+ {
22
+ when: ["keyboard", "textInput"],
23
+ steps: () => [
24
+ { type: "keypress", target: "input", key: "ArrowDown" }
25
+ ]
26
+ },
27
+ {
28
+ when: ["pointer"],
29
+ steps: () => [
30
+ { type: "click", target: "button" }
31
+ ]
32
+ }
33
+ ],
34
+ assertion: isComboboxOpen
6
35
  },
7
36
  "listbox.closed": {
8
- setup: closeCombobox(),
9
- assertion: isComboboxClosed()
37
+ setup: [
38
+ {
39
+ when: ["keyboard"],
40
+ steps: () => [
41
+ /* { type: "keypress", target: "input", key: "Escape" } */
42
+ ]
43
+ },
44
+ {
45
+ when: ["pointer"],
46
+ steps: () => [
47
+ /* { type: "click", target: "button" } */
48
+ ]
49
+ }
50
+ ],
51
+ assertion: isComboboxClosed
10
52
  },
11
53
  "input.focused": {
12
- setup: focusInput(),
13
- assertion: [
14
- ...isInputFocused()
15
- ]
54
+ setup: [
55
+ {
56
+ when: ["keyboard"],
57
+ steps: () => [
58
+ { type: "focus", target: "input" }
59
+ ]
60
+ }
61
+ ],
62
+ assertion: isInputFocused
16
63
  },
17
64
  "input.filled": {
18
- setup: fillInput(),
19
- assertion: [
20
- ...isInputFilled()
21
- ]
65
+ setup: [
66
+ {
67
+ when: ["keyboard", "textInput"],
68
+ steps: () => [
69
+ { type: "type", target: "input", value: "test" }
70
+ ]
71
+ }
72
+ ],
73
+ assertion: isInputFilled
22
74
  },
23
75
  "activeOption.first": {
24
76
  requires: ["listbox.open"],
25
77
  setup: [
26
- { type: "keypress", target: "input", key: "ArrowDown" }
78
+ {
79
+ when: ["keyboard"],
80
+ steps: () => [
81
+ { type: "keypress", target: "input", key: "ArrowDown" }
82
+ ]
83
+ }
27
84
  ],
28
- assertion: [
29
- ...isActiveDescendantNotEmpty()
30
- ]
85
+ assertion: isActiveDescendantNotEmpty
31
86
  },
32
87
  "activeOption.last": {
33
88
  requires: ["activeOption.first"],
34
89
  setup: [
35
- { type: "keypress", target: "input", key: "ArrowUp" }
90
+ {
91
+ when: ["keyboard"],
92
+ steps: () => [
93
+ { type: "keypress", target: "input", key: "ArrowUp" }
94
+ ]
95
+ }
36
96
  ],
37
- assertion: [
38
- ...isActiveDescendantNotEmpty()
39
- ]
97
+ assertion: isActiveDescendantNotEmpty
40
98
  },
41
99
  "selectedOption.first": {
42
100
  requires: ["listbox.open"],
43
101
  setup: [
44
- { type: "click", target: "relative", relativeTarget: "first" }
102
+ {
103
+ when: ["pointer"],
104
+ steps: () => [
105
+ { type: "click", target: "relative", relativeTarget: "first" }
106
+ ]
107
+ }
45
108
  ],
46
- assertion: [
47
- ...isAriaSelected("first")
48
- ]
109
+ assertion: () => isAriaSelected("first")
49
110
  },
50
111
  "selectedOption.last": {
51
112
  requires: ["listbox.open"],
52
113
  setup: [
53
- { type: "click", target: "relative", relativeTarget: "last" }
114
+ {
115
+ when: ["pointer"],
116
+ steps: () => [
117
+ { type: "click", target: "relative", relativeTarget: "last" }
118
+ ]
119
+ }
54
120
  ],
55
- assertion: [
56
- ...isAriaSelected("first")
57
- ]
121
+ assertion: () => isAriaSelected("last")
58
122
  }
59
123
  };
60
- function openCombobox() {
61
- return [
62
- { type: "keypress", target: "input", key: "ArrowDown" }
63
- ];
64
- }
65
- function closeCombobox() {
66
- return [
67
- { type: "keypress", target: "input", key: "Escape" }
68
- ];
69
- }
70
- function focusInput() {
71
- return [
72
- { type: "focus", target: "input" }
73
- ];
74
- }
75
- function fillInput() {
76
- return [
77
- { type: "type", target: "input", value: "test" }
78
- ];
79
- }
80
124
  function isComboboxOpen() {
81
125
  return [
82
126
  {
83
127
  target: "listbox",
84
128
  assertion: "toBeVisible",
85
129
  failureMessage: "Expected listbox to be visible"
130
+ },
131
+ {
132
+ target: "input",
133
+ assertion: "toHaveAttribute",
134
+ attribute: "aria-expanded",
135
+ expectedValue: "true",
136
+ failureMessage: "Expect combobox input to have aria-expanded='true'"
86
137
  }
87
138
  ];
88
139
  }
@@ -92,6 +143,13 @@ function isComboboxClosed() {
92
143
  target: "listbox",
93
144
  assertion: "notToBeVisible",
94
145
  failureMessage: "Expected listbox to be closed"
146
+ },
147
+ {
148
+ target: "input",
149
+ assertion: "toHaveAttribute",
150
+ attribute: "aria-expanded",
151
+ expectedValue: "false",
152
+ failureMessage: "Expect combobox input to have aria-expanded='false'"
95
153
  }
96
154
  ];
97
155
  }
@@ -114,7 +172,7 @@ function isAriaSelected(index) {
114
172
  assertion: "toHaveAttribute",
115
173
  attribute: "aria-selected",
116
174
  expectedValue: "true",
117
- failureMessage: `Expected aria-selected on ${index} option to be true`
175
+ failureMessage: `Expected ${index} option to have aria-selected='true'`
118
176
  }
119
177
  ];
120
178
  }
@@ -140,7 +198,7 @@ function isInputFilled() {
140
198
 
141
199
  // src/utils/test/dsl/src/contractBuilder.ts
142
200
  var STATE_PACKS = {
143
- "combobox.listbox": COMBOBOX_STATES
201
+ "combobox": COMBOBOX_STATES
144
202
  // Add more mappings as needed
145
203
  };
146
204
  var FluentContract = class {
@@ -174,11 +232,13 @@ var ContractBuilder = class {
174
232
  const api = {
175
233
  ariaReference: (from, attribute, to) => ({
176
234
  required: () => this.relationshipInvariants.push({ type: "aria-reference", from, attribute, to, level: "required" }),
177
- optional: () => this.relationshipInvariants.push({ type: "aria-reference", from, attribute, to, level: "optional" })
235
+ optional: () => this.relationshipInvariants.push({ type: "aria-reference", from, attribute, to, level: "optional" }),
236
+ recommended: () => this.relationshipInvariants.push({ type: "aria-reference", from, attribute, to, level: "recommended" })
178
237
  }),
179
238
  contains: (parent, child) => ({
180
239
  required: () => this.relationshipInvariants.push({ type: "contains", parent, child, level: "required" }),
181
- optional: () => this.relationshipInvariants.push({ type: "contains", parent, child, level: "optional" })
240
+ optional: () => this.relationshipInvariants.push({ type: "contains", parent, child, level: "optional" }),
241
+ recommended: () => this.relationshipInvariants.push({ type: "contains", parent, child, level: "recommended" })
182
242
  })
183
243
  };
184
244
  fn(api);
@@ -189,7 +249,8 @@ var ContractBuilder = class {
189
249
  target: (target) => ({
190
250
  has: (attribute, expectedValue) => ({
191
251
  required: () => this.staticAssertions.push({ target, attribute, expectedValue, failureMessage: "", level: "required" }),
192
- optional: () => this.staticAssertions.push({ target, attribute, expectedValue, failureMessage: "", level: "optional" })
252
+ optional: () => this.staticAssertions.push({ target, attribute, expectedValue, failureMessage: "", level: "optional" }),
253
+ recommended: () => this.staticAssertions.push({ target, attribute, expectedValue, failureMessage: "", level: "recommended" })
193
254
  })
194
255
  })
195
256
  };
@@ -260,7 +321,17 @@ var DynamicTestBuilder = class {
260
321
  return this.parent;
261
322
  }
262
323
  _finalize() {
263
- const resolveSetup = (stateName, visited = /* @__PURE__ */ new Set()) => {
324
+ const capabilityMap = {
325
+ keypress: "keyboard",
326
+ click: "pointer",
327
+ type: "textInput",
328
+ focus: "keyboard",
329
+ hover: "pointer"
330
+ // add more mappings as needed
331
+ };
332
+ const capability = capabilityMap[this._as || "keyboard"] || (this._as || "keyboard");
333
+ const ctx = { capabilities: [capability] };
334
+ const resolveAllSetups = (stateName, visited = /* @__PURE__ */ new Set()) => {
264
335
  if (visited.has(stateName)) return [];
265
336
  visited.add(stateName);
266
337
  const s = this.statePack[stateName];
@@ -268,22 +339,30 @@ var DynamicTestBuilder = class {
268
339
  let actions = [];
269
340
  if (Array.isArray(s.requires)) {
270
341
  for (const req of s.requires) {
271
- actions = actions.concat(resolveSetup(req, visited));
342
+ actions = actions.concat(resolveAllSetups(req, visited));
272
343
  }
273
344
  }
274
- if (s.setup) actions = actions.concat(s.setup);
345
+ if (s.setup) actions = actions.concat(resolveSetup(s.setup, ctx));
275
346
  return actions;
276
347
  };
277
348
  const setup = [];
278
349
  for (const state of this._given) {
279
- setup.push(...resolveSetup(state));
350
+ setup.push(...resolveAllSetups(state));
280
351
  }
281
352
  const assertions = [];
282
353
  for (const state of this._then) {
283
354
  const s = this.statePack[state];
284
- if (s && s.assertion) {
285
- if (Array.isArray(s.assertion)) assertions.push(...s.assertion);
286
- else assertions.push(s.assertion);
355
+ if (s && s.assertion !== void 0) {
356
+ let value = s.assertion;
357
+ if (typeof value === "function") {
358
+ try {
359
+ value = value();
360
+ } catch (e) {
361
+ throw new Error(`Error calling assertion function for state '${state}': ${e.message}`);
362
+ }
363
+ }
364
+ if (Array.isArray(value)) assertions.push(...value);
365
+ else assertions.push(value);
287
366
  }
288
367
  }
289
368
  const action = [