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.
- package/README.md +2 -2
- package/{bin/buildContracts-S22V7AGV.js → dist/buildContracts-FT6KWUJN.js} +3 -3
- package/dist/{chunk-XERMSYEH.js → chunk-FZ7GMIJB.js} +0 -21
- package/{bin/chunk-NI3MQCAS.js → dist/chunk-GJGUY643.js} +2 -2
- package/{bin → dist}/cli.cjs +30 -67
- package/{bin → dist}/cli.js +4 -4
- package/dist/{configLoader-DWHOHXHL.js → configLoader-Q7N5XV4P.js} +2 -2
- package/{bin/configLoader-UJZHQBYS.js → dist/configLoader-REHK3S3Q.js} +1 -1
- package/{bin/contractTestRunnerPlaywright-QDXSK3FE.js → dist/contractTestRunnerPlaywright-DIXP5DQ3.js} +5 -20
- package/dist/{contractTestRunnerPlaywright-WNWQYSXZ.js → contractTestRunnerPlaywright-EWAWQVHT.js} +5 -20
- package/dist/index.cjs +164 -122
- package/dist/index.d.cts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +155 -71
- package/dist/src/{Types.d-yGC2bBaB.d.ts → Types.d-DYfYR3Vc.d.cts} +1 -1
- package/dist/src/{Types.d-yGC2bBaB.d.cts → Types.d-DYfYR3Vc.d.ts} +1 -1
- package/dist/src/accordion/index.d.cts +1 -1
- package/dist/src/accordion/index.d.ts +1 -1
- package/dist/src/block/index.d.cts +1 -1
- package/dist/src/block/index.d.ts +1 -1
- package/dist/src/checkbox/index.d.cts +1 -1
- package/dist/src/checkbox/index.d.ts +1 -1
- package/dist/src/combobox/index.d.cts +1 -1
- package/dist/src/combobox/index.d.ts +1 -1
- package/dist/src/menu/index.d.cts +1 -1
- package/dist/src/menu/index.d.ts +1 -1
- package/dist/src/radio/index.d.cts +1 -1
- package/dist/src/radio/index.d.ts +1 -1
- package/dist/src/tabs/index.d.cts +1 -1
- package/dist/src/tabs/index.d.ts +1 -1
- package/dist/src/toggle/index.d.cts +1 -1
- package/dist/src/toggle/index.d.ts +1 -1
- package/dist/src/utils/test/{chunk-XERMSYEH.js → chunk-FZ7GMIJB.js} +1 -21
- package/dist/src/utils/test/{configLoader-SHJSRG2A.js → configLoader-NA7IBCS3.js} +2 -2
- package/dist/src/utils/test/{contractTestRunnerPlaywright-Z2AHXSNM.js → contractTestRunnerPlaywright-CIZOXYRW.js} +5 -19
- package/dist/src/utils/test/dsl/index.cjs +139 -60
- package/dist/src/utils/test/dsl/index.d.cts +3 -0
- package/dist/src/utils/test/dsl/index.d.ts +3 -0
- package/dist/src/utils/test/dsl/index.js +139 -60
- package/dist/src/utils/test/index.cjs +19 -55
- package/dist/src/utils/test/index.js +16 -10
- package/{bin/test-O3J4ZPQR.js → dist/test-HBPCSYH5.js} +16 -11
- package/package.json +5 -7
- package/bin/AccordionComponentStrategy-4ZEIQ2V6.js +0 -42
- package/bin/ComboboxComponentStrategy-OGRVZXAF.js +0 -64
- package/bin/MenuComponentStrategy-JAMTCSNF.js +0 -81
- package/bin/TabsComponentStrategy-3SQURPMX.js +0 -29
- package/bin/chunk-I2KLQ2HA.js +0 -22
- package/bin/chunk-PK5L2SAF.js +0 -17
- package/bin/chunk-XERMSYEH.js +0 -363
- package/dist/src/utils/test/aria-contracts/accordion/accordion.contract.json +0 -290
- package/dist/src/utils/test/aria-contracts/combobox/combobox.listbox.contract.json +0 -463
- package/dist/src/utils/test/aria-contracts/menu/menu.contract.json +0 -562
- package/dist/src/utils/test/aria-contracts/tabs/tabs.contract.json +0 -361
- /package/{bin → dist}/audit-RM6TCZ5C.js +0 -0
- /package/{bin → dist}/badgeHelper-JOWO6RQG.js +0 -0
- /package/{bin → dist}/chunk-JJEPLK7L.js +0 -0
- /package/{bin → dist}/cli.d.cts +0 -0
- /package/{bin → dist}/cli.d.ts +0 -0
- /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:
|
|
7
|
-
|
|
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:
|
|
11
|
-
|
|
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:
|
|
15
|
-
|
|
16
|
-
|
|
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:
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
{
|
|
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
|
-
{
|
|
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
|
-
{
|
|
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
|
-
{
|
|
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
|
|
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
|
|
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
|
|
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(
|
|
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(...
|
|
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
|
-
|
|
288
|
-
|
|
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:
|
|
5
|
-
|
|
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:
|
|
9
|
-
|
|
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:
|
|
13
|
-
|
|
14
|
-
|
|
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:
|
|
19
|
-
|
|
20
|
-
|
|
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
|
-
{
|
|
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
|
-
{
|
|
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
|
-
{
|
|
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
|
-
{
|
|
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
|
|
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
|
|
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
|
|
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(
|
|
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(...
|
|
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
|
-
|
|
286
|
-
|
|
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 = [
|