aria-ease 6.9.1 → 6.10.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 +3 -3
- package/bin/{buildContracts-GBOY7UXG.js → buildContracts-S22V7AGV.js} +28 -0
- package/bin/{chunk-LMSKLN5O.js → chunk-NI3MQCAS.js} +34 -0
- package/bin/cli.cjs +235 -20
- package/bin/cli.js +4 -4
- package/bin/{configLoader-Q6A4JLKW.js → configLoader-UJZHQBYS.js} +1 -1
- package/{dist/contractTestRunnerPlaywright-XBWJZMR3.js → bin/contractTestRunnerPlaywright-QDXSK3FE.js} +173 -20
- package/bin/{test-OND56UUL.js → test-O3J4ZPQR.js} +2 -2
- package/dist/{configLoader-WTGJAP4Z.js → configLoader-DWHOHXHL.js} +34 -0
- package/{bin/contractTestRunnerPlaywright-ZZNWDUYP.js → dist/contractTestRunnerPlaywright-WNWQYSXZ.js} +173 -20
- package/dist/index.cjs +492 -298
- package/dist/index.d.cts +53 -53
- package/dist/index.d.ts +53 -53
- package/dist/index.js +289 -282
- package/dist/src/{Types.d-DYfYR3Vc.d.cts → Types.d-yGC2bBaB.d.cts} +1 -1
- package/dist/src/{Types.d-DYfYR3Vc.d.ts → Types.d-yGC2bBaB.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.cjs +21 -7
- package/dist/src/combobox/index.d.cts +1 -1
- package/dist/src/combobox/index.d.ts +1 -1
- package/dist/src/combobox/index.js +21 -7
- 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/{configLoader-YE2CYGDG.js → configLoader-SHJSRG2A.js} +34 -0
- package/dist/src/utils/test/{contractTestRunnerPlaywright-LC5OAVXB.js → contractTestRunnerPlaywright-Z2AHXSNM.js} +173 -20
- package/dist/src/utils/test/dsl/index.cjs +263 -270
- package/dist/src/utils/test/dsl/index.d.cts +53 -53
- package/dist/src/utils/test/dsl/index.d.ts +53 -53
- package/dist/src/utils/test/dsl/index.js +263 -270
- package/dist/src/utils/test/index.cjs +207 -20
- package/dist/src/utils/test/index.js +2 -2
- package/package.json +1 -1
|
@@ -1,6 +1,150 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
// src/utils/test/dsl/
|
|
3
|
+
// src/utils/test/dsl/src/state-packs/comboboxStatePack.ts
|
|
4
|
+
var COMBOBOX_STATES = {
|
|
5
|
+
"listbox.open": {
|
|
6
|
+
setup: openCombobox(),
|
|
7
|
+
assertion: isComboboxOpen()
|
|
8
|
+
},
|
|
9
|
+
"listbox.closed": {
|
|
10
|
+
setup: closeCombobox(),
|
|
11
|
+
assertion: isComboboxClosed()
|
|
12
|
+
},
|
|
13
|
+
"input.focused": {
|
|
14
|
+
setup: focusInput(),
|
|
15
|
+
assertion: [
|
|
16
|
+
...isInputFocused()
|
|
17
|
+
]
|
|
18
|
+
},
|
|
19
|
+
"input.filled": {
|
|
20
|
+
setup: fillInput(),
|
|
21
|
+
assertion: [
|
|
22
|
+
...isInputFilled()
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
"activeOption.first": {
|
|
26
|
+
requires: ["listbox.open"],
|
|
27
|
+
setup: [
|
|
28
|
+
{ type: "keypress", target: "input", key: "ArrowDown" }
|
|
29
|
+
],
|
|
30
|
+
assertion: [
|
|
31
|
+
...isActiveDescendantNotEmpty()
|
|
32
|
+
]
|
|
33
|
+
},
|
|
34
|
+
"activeOption.last": {
|
|
35
|
+
requires: ["activeOption.first"],
|
|
36
|
+
setup: [
|
|
37
|
+
{ type: "keypress", target: "input", key: "ArrowUp" }
|
|
38
|
+
],
|
|
39
|
+
assertion: [
|
|
40
|
+
...isActiveDescendantNotEmpty()
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
"selectedOption.first": {
|
|
44
|
+
requires: ["listbox.open"],
|
|
45
|
+
setup: [
|
|
46
|
+
{ type: "click", target: "relative", relativeTarget: "first" }
|
|
47
|
+
],
|
|
48
|
+
assertion: [
|
|
49
|
+
...isAriaSelected("first")
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
"selectedOption.last": {
|
|
53
|
+
requires: ["listbox.open"],
|
|
54
|
+
setup: [
|
|
55
|
+
{ type: "click", target: "relative", relativeTarget: "last" }
|
|
56
|
+
],
|
|
57
|
+
assertion: [
|
|
58
|
+
...isAriaSelected("first")
|
|
59
|
+
]
|
|
60
|
+
}
|
|
61
|
+
};
|
|
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
|
+
function isComboboxOpen() {
|
|
83
|
+
return [
|
|
84
|
+
{
|
|
85
|
+
target: "listbox",
|
|
86
|
+
assertion: "toBeVisible",
|
|
87
|
+
failureMessage: "Expected listbox to be visible"
|
|
88
|
+
}
|
|
89
|
+
];
|
|
90
|
+
}
|
|
91
|
+
function isComboboxClosed() {
|
|
92
|
+
return [
|
|
93
|
+
{
|
|
94
|
+
target: "listbox",
|
|
95
|
+
assertion: "notToBeVisible",
|
|
96
|
+
failureMessage: "Expected listbox to be closed"
|
|
97
|
+
}
|
|
98
|
+
];
|
|
99
|
+
}
|
|
100
|
+
function isActiveDescendantNotEmpty() {
|
|
101
|
+
return [
|
|
102
|
+
{
|
|
103
|
+
target: "input",
|
|
104
|
+
assertion: "toHaveAttribute",
|
|
105
|
+
attribute: "aria-activedescendant",
|
|
106
|
+
expectedValue: "!empty",
|
|
107
|
+
failureMessage: "Expected aria-activedescendant to not be empty"
|
|
108
|
+
}
|
|
109
|
+
];
|
|
110
|
+
}
|
|
111
|
+
function isAriaSelected(index) {
|
|
112
|
+
return [
|
|
113
|
+
{
|
|
114
|
+
target: "relative",
|
|
115
|
+
relativeTarget: index,
|
|
116
|
+
assertion: "toHaveAttribute",
|
|
117
|
+
attribute: "aria-selected",
|
|
118
|
+
expectedValue: "true",
|
|
119
|
+
failureMessage: `Expected aria-selected on ${index} option to be true`
|
|
120
|
+
}
|
|
121
|
+
];
|
|
122
|
+
}
|
|
123
|
+
function isInputFocused() {
|
|
124
|
+
return [
|
|
125
|
+
{
|
|
126
|
+
target: "input",
|
|
127
|
+
assertion: "toHaveFocus",
|
|
128
|
+
failureMessage: "Expected input to be focused"
|
|
129
|
+
}
|
|
130
|
+
];
|
|
131
|
+
}
|
|
132
|
+
function isInputFilled() {
|
|
133
|
+
return [
|
|
134
|
+
{
|
|
135
|
+
target: "input",
|
|
136
|
+
assertion: "toHaveValue",
|
|
137
|
+
expectedValue: "test",
|
|
138
|
+
failureMessage: "Expected input to have the value 'test'"
|
|
139
|
+
}
|
|
140
|
+
];
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// src/utils/test/dsl/src/contractBuilder.ts
|
|
144
|
+
var STATE_PACKS = {
|
|
145
|
+
"combobox.listbox": COMBOBOX_STATES
|
|
146
|
+
// Add more mappings as needed
|
|
147
|
+
};
|
|
4
148
|
var FluentContract = class {
|
|
5
149
|
constructor(jsonContract) {
|
|
6
150
|
this.jsonContract = jsonContract;
|
|
@@ -9,306 +153,155 @@ var FluentContract = class {
|
|
|
9
153
|
return this.jsonContract;
|
|
10
154
|
}
|
|
11
155
|
};
|
|
12
|
-
var
|
|
13
|
-
constructor(
|
|
14
|
-
this.
|
|
15
|
-
this.
|
|
16
|
-
}
|
|
17
|
-
has(attribute, expectedValue) {
|
|
18
|
-
const create = (level) => {
|
|
19
|
-
this.sink.push({
|
|
20
|
-
target: this.targetName,
|
|
21
|
-
attribute,
|
|
22
|
-
expectedValue,
|
|
23
|
-
failureMessage: `Expected ${this.targetName} to have ${attribute}${expectedValue !== void 0 ? `=${expectedValue}` : ""}.`,
|
|
24
|
-
level
|
|
25
|
-
});
|
|
26
|
-
};
|
|
27
|
-
return {
|
|
28
|
-
required: () => create("required"),
|
|
29
|
-
recommended: () => create("recommended"),
|
|
30
|
-
optional: () => create("optional")
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
var StaticBuilder = class {
|
|
35
|
-
constructor(sink) {
|
|
36
|
-
this.sink = sink;
|
|
37
|
-
}
|
|
38
|
-
target(targetName) {
|
|
39
|
-
return new StaticTargetBuilder(targetName, this.sink);
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
var DynamicChain = class {
|
|
43
|
-
constructor(key, testsSink, selectors) {
|
|
44
|
-
this.key = key;
|
|
45
|
-
this.testsSink = testsSink;
|
|
46
|
-
this.selectors = selectors;
|
|
47
|
-
}
|
|
48
|
-
selectorTarget = "";
|
|
49
|
-
actions = [];
|
|
50
|
-
assertions = [];
|
|
51
|
-
explicitDescription = "";
|
|
52
|
-
on(target) {
|
|
53
|
-
this.selectorTarget = target;
|
|
54
|
-
this.actions.push({ type: "keypress", target, key: this.key });
|
|
55
|
-
return this;
|
|
56
|
-
}
|
|
57
|
-
describe(description) {
|
|
58
|
-
this.explicitDescription = description;
|
|
59
|
-
return this;
|
|
156
|
+
var ContractBuilder = class {
|
|
157
|
+
constructor(componentName) {
|
|
158
|
+
this.componentName = componentName;
|
|
159
|
+
this.statePack = STATE_PACKS[componentName] || {};
|
|
60
160
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
if (!this.selectors.relative && this.selectors[parsed.selectorKey]) {
|
|
71
|
-
this.selectors.relative = this.selectors[parsed.selectorKey];
|
|
72
|
-
}
|
|
73
|
-
this.assertions.push({
|
|
74
|
-
target: "relative",
|
|
75
|
-
assertion: "toHaveFocus",
|
|
76
|
-
relativeTarget: parsed.relativeTarget
|
|
77
|
-
});
|
|
78
|
-
} else {
|
|
79
|
-
this.assertions.push({
|
|
80
|
-
target: targetExpression,
|
|
81
|
-
assertion: "toHaveFocus"
|
|
82
|
-
});
|
|
83
|
-
}
|
|
161
|
+
metaValue = {};
|
|
162
|
+
selectorsValue = {};
|
|
163
|
+
relationshipInvariants = [];
|
|
164
|
+
staticAssertions = [];
|
|
165
|
+
dynamicTests = [];
|
|
166
|
+
statePack;
|
|
167
|
+
meta(meta) {
|
|
168
|
+
this.metaValue = meta;
|
|
84
169
|
return this;
|
|
85
170
|
}
|
|
86
|
-
|
|
87
|
-
this.
|
|
171
|
+
selectors(selectors) {
|
|
172
|
+
this.selectorsValue = selectors;
|
|
88
173
|
return this;
|
|
89
174
|
}
|
|
90
|
-
|
|
91
|
-
|
|
175
|
+
relationships(fn) {
|
|
176
|
+
const api = {
|
|
177
|
+
ariaReference: (from, attribute, to) => ({
|
|
178
|
+
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" })
|
|
180
|
+
}),
|
|
181
|
+
contains: (parent, child) => ({
|
|
182
|
+
required: () => this.relationshipInvariants.push({ type: "contains", parent, child, level: "required" }),
|
|
183
|
+
optional: () => this.relationshipInvariants.push({ type: "contains", parent, child, level: "optional" })
|
|
184
|
+
})
|
|
185
|
+
};
|
|
186
|
+
fn(api);
|
|
92
187
|
return this;
|
|
93
188
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
target
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
189
|
+
static(fn) {
|
|
190
|
+
const api = {
|
|
191
|
+
target: (target) => ({
|
|
192
|
+
has: (attribute, expectedValue) => ({
|
|
193
|
+
required: () => this.staticAssertions.push({ target, attribute, expectedValue, failureMessage: "", level: "required" }),
|
|
194
|
+
optional: () => this.staticAssertions.push({ target, attribute, expectedValue, failureMessage: "", level: "optional" })
|
|
195
|
+
})
|
|
196
|
+
})
|
|
197
|
+
};
|
|
198
|
+
fn(api);
|
|
101
199
|
return this;
|
|
102
200
|
}
|
|
103
|
-
|
|
104
|
-
this.
|
|
105
|
-
}
|
|
106
|
-
recommended() {
|
|
107
|
-
this.finalize("recommended");
|
|
201
|
+
when(event) {
|
|
202
|
+
return new DynamicTestBuilder(this, this.statePack, event);
|
|
108
203
|
}
|
|
109
|
-
|
|
110
|
-
this.
|
|
111
|
-
}
|
|
112
|
-
finalize(level) {
|
|
113
|
-
if (!this.selectorTarget) {
|
|
114
|
-
throw new Error("Dynamic contract chain requires .on(<selectorKey>) before level terminator.");
|
|
115
|
-
}
|
|
116
|
-
const description = this.explicitDescription || `Pressing ${this.key} on ${this.selectorTarget} satisfies expected behavior.`;
|
|
117
|
-
this.testsSink.push({
|
|
118
|
-
description,
|
|
119
|
-
level,
|
|
120
|
-
action: this.actions,
|
|
121
|
-
assertions: this.assertions.map((a) => ({ ...a, level }))
|
|
122
|
-
});
|
|
204
|
+
addDynamicTest(test) {
|
|
205
|
+
this.dynamicTests.push(test);
|
|
123
206
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
207
|
+
build() {
|
|
208
|
+
return {
|
|
209
|
+
meta: this.metaValue,
|
|
210
|
+
selectors: this.selectorsValue,
|
|
211
|
+
relationships: this.relationshipInvariants.length ? this.relationshipInvariants : void 0,
|
|
212
|
+
static: this.staticAssertions.length ? [{ assertions: this.staticAssertions }] : [],
|
|
213
|
+
dynamic: this.dynamicTests
|
|
214
|
+
};
|
|
130
215
|
}
|
|
131
216
|
};
|
|
132
|
-
var
|
|
133
|
-
constructor(
|
|
134
|
-
this.
|
|
217
|
+
var DynamicTestBuilder = class {
|
|
218
|
+
constructor(parent, statePack, event) {
|
|
219
|
+
this.parent = parent;
|
|
220
|
+
this.statePack = statePack;
|
|
221
|
+
this.event = event;
|
|
135
222
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
223
|
+
_as;
|
|
224
|
+
_on;
|
|
225
|
+
_given = [];
|
|
226
|
+
_then = [];
|
|
227
|
+
_desc = "";
|
|
228
|
+
_level = "required";
|
|
229
|
+
as(actionType) {
|
|
230
|
+
this._as = actionType;
|
|
143
231
|
return this;
|
|
144
232
|
}
|
|
145
|
-
|
|
146
|
-
this.
|
|
233
|
+
on(target) {
|
|
234
|
+
this._on = target;
|
|
147
235
|
return this;
|
|
148
236
|
}
|
|
149
|
-
|
|
150
|
-
this.
|
|
237
|
+
given(states) {
|
|
238
|
+
this._given = Array.isArray(states) ? states : [states];
|
|
151
239
|
return this;
|
|
152
240
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
ariaReference: (from, attribute, to) => {
|
|
156
|
-
const create = (level) => {
|
|
157
|
-
this.relationshipInvariants.push({
|
|
158
|
-
type: "aria-reference",
|
|
159
|
-
from,
|
|
160
|
-
attribute,
|
|
161
|
-
to,
|
|
162
|
-
level
|
|
163
|
-
});
|
|
164
|
-
};
|
|
165
|
-
return {
|
|
166
|
-
required: () => create("required"),
|
|
167
|
-
recommended: () => create("recommended"),
|
|
168
|
-
optional: () => create("optional")
|
|
169
|
-
};
|
|
170
|
-
},
|
|
171
|
-
contains: (parent, child) => {
|
|
172
|
-
const create = (level) => {
|
|
173
|
-
this.relationshipInvariants.push({
|
|
174
|
-
type: "contains",
|
|
175
|
-
parent,
|
|
176
|
-
child,
|
|
177
|
-
level
|
|
178
|
-
});
|
|
179
|
-
};
|
|
180
|
-
return {
|
|
181
|
-
required: () => create("required"),
|
|
182
|
-
recommended: () => create("recommended"),
|
|
183
|
-
optional: () => create("optional")
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
});
|
|
241
|
+
then(states) {
|
|
242
|
+
this._then = Array.isArray(states) ? states : [states];
|
|
187
243
|
return this;
|
|
188
244
|
}
|
|
189
|
-
|
|
190
|
-
|
|
245
|
+
describe(desc) {
|
|
246
|
+
this._desc = desc;
|
|
191
247
|
return this;
|
|
192
248
|
}
|
|
193
|
-
|
|
194
|
-
|
|
249
|
+
required() {
|
|
250
|
+
this._level = "required";
|
|
251
|
+
this._finalize();
|
|
252
|
+
return this.parent;
|
|
195
253
|
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
this.
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
if (
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
}
|
|
217
|
-
if (!selectorKeys.has(invariant.child)) {
|
|
218
|
-
errors.push(`${prefix}: "child" references unknown selector "${invariant.child}"`);
|
|
254
|
+
optional() {
|
|
255
|
+
this._level = "optional";
|
|
256
|
+
this._finalize();
|
|
257
|
+
return this.parent;
|
|
258
|
+
}
|
|
259
|
+
recommended() {
|
|
260
|
+
this._level = "recommended";
|
|
261
|
+
this._finalize();
|
|
262
|
+
return this.parent;
|
|
263
|
+
}
|
|
264
|
+
_finalize() {
|
|
265
|
+
const resolveSetup = (stateName, visited = /* @__PURE__ */ new Set()) => {
|
|
266
|
+
if (visited.has(stateName)) return [];
|
|
267
|
+
visited.add(stateName);
|
|
268
|
+
const s = this.statePack[stateName];
|
|
269
|
+
if (!s) return [];
|
|
270
|
+
let actions = [];
|
|
271
|
+
if (Array.isArray(s.requires)) {
|
|
272
|
+
for (const req of s.requires) {
|
|
273
|
+
actions = actions.concat(resolveSetup(req, visited));
|
|
219
274
|
}
|
|
220
275
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
...errors.map((error) => `- ${error}`),
|
|
228
|
-
`Available selectors: ${availableSelectorsMessage}`
|
|
229
|
-
].join("\n")
|
|
230
|
-
);
|
|
276
|
+
if (s.setup) actions = actions.concat(s.setup);
|
|
277
|
+
return actions;
|
|
278
|
+
};
|
|
279
|
+
const setup = [];
|
|
280
|
+
for (const state of this._given) {
|
|
281
|
+
setup.push(...resolveSetup(state));
|
|
231
282
|
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
if (!selectorKeys.has(assertion.target)) {
|
|
239
|
-
errors.push(`static.assertions[${index}]: target "${assertion.target}" is not defined in selectors`);
|
|
283
|
+
const assertions = [];
|
|
284
|
+
for (const state of this._then) {
|
|
285
|
+
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);
|
|
240
289
|
}
|
|
241
|
-
});
|
|
242
|
-
if (errors.length > 0) {
|
|
243
|
-
throw new Error(
|
|
244
|
-
[
|
|
245
|
-
`Contract static target validation failed for component "${this.componentName}".`,
|
|
246
|
-
...errors.map((error) => `- ${error}`),
|
|
247
|
-
`Available selectors: ${available}`
|
|
248
|
-
].join("\n")
|
|
249
|
-
);
|
|
250
290
|
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
if (!isValidActionTarget(action.target)) {
|
|
265
|
-
errors.push(
|
|
266
|
-
`dynamic[${testIndex}].action[${actionIndex}]: target "${action.target}" is not defined in selectors`
|
|
267
|
-
);
|
|
268
|
-
}
|
|
269
|
-
});
|
|
270
|
-
test.assertions.forEach((assertion, assertionIndex) => {
|
|
271
|
-
if (!isValidAssertionTarget(assertion.target)) {
|
|
272
|
-
errors.push(
|
|
273
|
-
`dynamic[${testIndex}].assertions[${assertionIndex}]: target "${assertion.target}" is not defined in selectors`
|
|
274
|
-
);
|
|
275
|
-
}
|
|
276
|
-
if (assertion.target === "relative" && !this.selectorsValue.relative) {
|
|
277
|
-
errors.push(
|
|
278
|
-
`dynamic[${testIndex}].assertions[${assertionIndex}]: target "relative" requires selectors.relative to be defined`
|
|
279
|
-
);
|
|
280
|
-
}
|
|
281
|
-
});
|
|
291
|
+
const action = [
|
|
292
|
+
{
|
|
293
|
+
type: this._as,
|
|
294
|
+
target: this._on,
|
|
295
|
+
key: this._as === "keypress" ? this.event : void 0
|
|
296
|
+
}
|
|
297
|
+
];
|
|
298
|
+
this.parent.addDynamicTest({
|
|
299
|
+
description: this._desc || "",
|
|
300
|
+
level: this._level,
|
|
301
|
+
action,
|
|
302
|
+
assertions,
|
|
303
|
+
...setup.length ? { setup } : {}
|
|
282
304
|
});
|
|
283
|
-
if (errors.length > 0) {
|
|
284
|
-
throw new Error(
|
|
285
|
-
[
|
|
286
|
-
`Contract dynamic target validation failed for component "${this.componentName}".`,
|
|
287
|
-
...errors.map((error) => `- ${error}`),
|
|
288
|
-
`Available selectors: ${available}`,
|
|
289
|
-
`Allowed special targets: document, relative`
|
|
290
|
-
].join("\n")
|
|
291
|
-
);
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
build() {
|
|
295
|
-
this.validateRelationshipInvariants();
|
|
296
|
-
this.validateStaticTargets();
|
|
297
|
-
this.validateDynamicTargets();
|
|
298
|
-
const fallbackId = this.metaValue.id || `aria-ease.contract.${this.componentName}`;
|
|
299
|
-
return {
|
|
300
|
-
meta: {
|
|
301
|
-
id: fallbackId,
|
|
302
|
-
version: this.metaValue.version || "1.0.0",
|
|
303
|
-
description: this.metaValue.description || `Fluent contract for ${this.componentName}`,
|
|
304
|
-
source: this.metaValue.source,
|
|
305
|
-
W3CName: this.metaValue.W3CName
|
|
306
|
-
},
|
|
307
|
-
selectors: this.selectorsValue,
|
|
308
|
-
relationships: this.relationshipInvariants,
|
|
309
|
-
static: [{ assertions: this.staticAssertions }],
|
|
310
|
-
dynamic: this.dynamicTests
|
|
311
|
-
};
|
|
312
305
|
}
|
|
313
306
|
};
|
|
314
307
|
function createContract(componentName, define) {
|