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