Skip to content

Commit d06ebe2

Browse files
feat: update wpt usage
Co-authored-by: Craig Morten <[email protected]>
1 parent c8468cd commit d06ebe2

17 files changed

+180159
-99545
lines changed

README.md

+174-162
Large diffs are not rendered by default.

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@
6464
"jest-junit": "^16.0.0",
6565
"js-yaml": "^4.1.0",
6666
"jsdom": "^20.0.0",
67-
"minimatch": "^9.0.0",
68-
"mocha": "^10.0.0",
67+
"minimatch": "^9.0.3",
68+
"mocha": "^10.3.0",
6969
"mocha-sugar-free": "^1.4.0",
7070
"prettier": "^3.0.0",
7171
"q": "^1.5.1",

tests/cypress/integration/web-platform-test.cy.js

+162-159
Large diffs are not rendered by default.

tests/wpt

Submodule wpt updated 19543 files

tests/wpt-jsdom/ATTAcomm.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ class ATTAcomm {
2525

2626
if (matcher === "property") {
2727
if (name === namePropertyName[implementation]) {
28-
const actual = computeAccessibleName(element);
28+
const actual = computeAccessibleName(element) ?? "";
2929
if (equality === "is") {
3030
assert_equals(actual, expected);
3131
continue;
3232
}
3333
} else if (name === descriptionPropertyName[implementation]) {
34-
const actual = computeAccessibleDescription(element);
34+
const actual = computeAccessibleDescription(element) ?? "";
3535
if (equality === "is") {
3636
assert_equals(actual, expected);
3737
continue;

tests/wpt-jsdom/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
See https://github.com/jsdom/jsdom/blob/67eb73efc22d85b2aa3c7b0237be58ac5129b584/test/README.md#L1
1+
See https://github.com/jsdom/jsdom/blob/2f8a730/test/README.md

tests/wpt-jsdom/run-single-wpt.js

+200-34
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,31 @@ const { specify } = require("mocha-sugar-free");
66
const { inBrowserContext } = require("./util.js");
77
const { JSDOM, VirtualConsole } = require("jsdom");
88
const ResourceLoader = require("jsdom/lib/jsdom/browser/resources/resource-loader");
9+
const { resolveReason } = require("./utils.js");
910
const {
1011
computeAccessibleName,
1112
computeAccessibleDescription,
13+
getRole,
1214
} = require("../../dist/");
1315

1416
const reporterPathname = "/resources/testharnessreport.js";
17+
const testdriverPathname = "/resources/testdriver.js";
18+
const ATTAcommPathname = "/wai-aria/scripts/ATTAcomm.js";
19+
20+
const unexpectedPassingTestMessage = `
21+
Hey, did you fix a bug? This test used to be failing, but during
22+
this run there were no errors. If you have fixed the issue covered
23+
by this test, you can edit the "to-run.yaml" file and remove the line
24+
containing this test. Thanks!
25+
`;
1526

1627
module.exports = (urlPrefixFactory) => {
1728
if (inBrowserContext()) {
1829
return () => {
1930
// TODO: browser support for running WPT
2031
};
2132
}
22-
23-
return (testPath, title = testPath, expectFail) => {
33+
return (testPath, title = testPath, expectFail = false) => {
2434
specify({
2535
title,
2636
expectPromise: true,
@@ -42,13 +52,23 @@ class CustomResourceLoader extends ResourceLoader {
4252
fetch(urlString, options) {
4353
const url = new URL(urlString);
4454

45-
if (url.pathname === reporterPathname) {
55+
if (url.pathname === ATTAcommPathname) {
56+
const filePath = path.resolve(__dirname, "./ATTAcomm.js");
57+
58+
return super.fetch(`file://${filePath}`, options);
59+
} else if (url.pathname === testdriverPathname) {
60+
const filePath = path.resolve(__dirname, "./testdriver.js");
61+
62+
return super.fetch(`file://${filePath}`, options);
63+
} else if (url.pathname.startsWith("/resources/testdriver")) {
64+
return Promise.resolve(Buffer.from("", "utf-8"));
65+
} else if (url.pathname === reporterPathname) {
4666
return Promise.resolve(Buffer.from("window.shimTest();", "utf-8"));
4767
} else if (url.pathname.startsWith("/resources/")) {
4868
// When running to-upstream tests, the server doesn't have a /resources/ directory.
49-
// So, always go to the one in ./tests.
69+
// So, always go to the one in ../wpt.
5070
// The path replacement accounts for a rewrite performed by the WPT server:
51-
// https://github.com/w3c/web-platform-tests/blob/master/tools/serve/serve.py#L271
71+
// https://github.com/web-platform-tests/wpt/blob/master/tools/serve/serve.py#L271
5272
const filePath = path
5373
.resolve(__dirname, "../wpt" + url.pathname)
5474
.replace(
@@ -57,18 +77,42 @@ class CustomResourceLoader extends ResourceLoader {
5777
);
5878

5979
return super.fetch(`file://${filePath}`, options);
60-
} else if (url.pathname === "/wai-aria/scripts/ATTAcomm.js") {
61-
const filePath = path.resolve(__dirname, "./ATTAcomm.js");
62-
return super.fetch(`file://${filePath}`, options);
6380
}
6481

6582
return super.fetch(urlString, options);
6683
}
6784
}
6885

86+
function formatFailedTest(test) {
87+
switch (test.status) {
88+
case test.PASS:
89+
return `Unexpected passing test: ${JSON.stringify(
90+
test.name,
91+
)}${unexpectedPassingTestMessage}`;
92+
case test.FAIL:
93+
case test.PRECONDITION_FAILED:
94+
return `Failed in ${JSON.stringify(test.name)}:\n${test.message}\n\n${
95+
test.stack
96+
}`;
97+
case test.TIMEOUT:
98+
return `Timeout in ${JSON.stringify(test.name)}:\n${test.message}\n\n${
99+
test.stack
100+
}`;
101+
case test.NOTRUN:
102+
return `Uncompleted test ${JSON.stringify(test.name)}:\n${
103+
test.message
104+
}\n\n${test.stack}`;
105+
default:
106+
throw new RangeError(
107+
`Unexpected test status: ${test.status} (test: ${JSON.stringify(
108+
test.name,
109+
)})`,
110+
);
111+
}
112+
}
113+
69114
function createJSDOM(urlPrefix, testPath, expectFail) {
70115
const unhandledExceptions = [];
71-
const doneErrors = [];
72116

73117
let allowUnhandledExceptions = false;
74118

@@ -102,27 +146,108 @@ function createJSDOM(urlPrefix, testPath, expectFail) {
102146

103147
window.computeAccessibleName = computeAccessibleName;
104148
window.computeAccessibleDescription = computeAccessibleDescription;
149+
window.getRole = getRole;
105150

106151
window.shimTest = () => {
107152
const oldSetup = window.setup;
108-
window.setup = () => {
109-
// noop, otherwise failing tests just slowly timeout
153+
window.setup = (options) => {
154+
if (options.allow_uncaught_exception) {
155+
allowUnhandledExceptions = true;
156+
}
157+
oldSetup(options);
110158
};
111159

112-
window.add_result_callback((test) => {
113-
if (test.status === 1) {
114-
errors.push(
115-
`Failed in "${test.name}": \n${test.message}\n\n${test.stack}`,
160+
// Overriding assert_throws_js and friends in order to allow us to throw exceptions from another realm. See
161+
// https://github.com/jsdom/jsdom/issues/2727 for more information.
162+
163+
function assertThrowsJSImpl(
164+
constructor,
165+
func,
166+
description,
167+
assertionType,
168+
) {
169+
try {
170+
func.call(this);
171+
window.assert_true(
172+
false,
173+
`${assertionType}: ${description}: ${func} did not throw`,
116174
);
117-
} else if (test.status === 2) {
118-
errors.push(
119-
`Timeout in "${test.name}": \n${test.message}\n\n${test.stack}`,
175+
} catch (e) {
176+
if (e instanceof window.AssertionError) {
177+
throw e;
178+
}
179+
180+
// Basic sanity-checks on the thrown exception.
181+
window.assert_true(
182+
typeof e === "object",
183+
`${assertionType}: ${description}: ${func} threw ${e} with type ${typeof e}, not an object`,
120184
);
121-
} else if (test.status === 3) {
122-
errors.push(
123-
`Uncompleted test "${test.name}": \n${test.message}\n\n${test.stack}`,
185+
186+
window.assert_true(
187+
e !== null,
188+
`${assertionType}: ${description}: ${func} threw null, not an object`,
189+
);
190+
191+
// Basic sanity-check on the passed-in constructor
192+
window.assert_true(
193+
typeof constructor === "function",
194+
`${assertionType}: ${description}: ${constructor} is not a constructor`,
195+
);
196+
let obj = constructor;
197+
while (obj) {
198+
if (typeof obj === "function" && obj.name === "Error") {
199+
break;
200+
}
201+
obj = Object.getPrototypeOf(obj);
202+
}
203+
window.assert_true(
204+
obj !== null && obj !== undefined,
205+
`${assertionType}: ${description}: ${constructor} is not an Error subtype`,
206+
);
207+
208+
// And checking that our exception is reasonable
209+
window.assert_equals(
210+
e.name,
211+
constructor.name,
212+
`${assertionType}: ${description}: ${func} threw ${e} (${e.name}) ` +
213+
`expected instance of ${constructor.name}`,
124214
);
125215
}
216+
}
217+
218+
// eslint-disable-next-line camelcase
219+
window.assert_throws_js = (constructor, func, description) => {
220+
assertThrowsJSImpl(
221+
constructor,
222+
func,
223+
description,
224+
"assert_throws_js",
225+
);
226+
};
227+
// eslint-disable-next-line camelcase
228+
window.promise_rejects_js = (test, expected, promise, description) => {
229+
return promise
230+
.then(test.unreached_func("Should have rejected: " + description))
231+
.catch((e) => {
232+
assertThrowsJSImpl(
233+
expected,
234+
() => {
235+
throw e;
236+
},
237+
description,
238+
"promise_reject_js",
239+
);
240+
});
241+
};
242+
243+
window.add_result_callback((test) => {
244+
if (
245+
test.status === test.FAIL ||
246+
test.status === test.TIMEOUT ||
247+
test.status === test.NOTRUN
248+
) {
249+
errors.push(formatFailedTest(test));
250+
}
126251
});
127252

128253
window.add_completion_callback((tests, harnessStatus) => {
@@ -131,34 +256,75 @@ function createJSDOM(urlPrefix, testPath, expectFail) {
131256
window.close();
132257
});
133258

134-
if (harnessStatus.status === 2) {
259+
let harnessFail = false;
260+
if (harnessStatus.status === harnessStatus.ERROR) {
261+
harnessFail = true;
262+
errors.push(
263+
new Error(
264+
`test harness should not error: ${testPath}\n${harnessStatus.message}`,
265+
),
266+
);
267+
} else if (harnessStatus.status === harnessStatus.TIMEOUT) {
268+
harnessFail = true;
135269
errors.push(
136270
new Error(`test harness should not timeout: ${testPath}`),
137271
);
138272
}
139273

140-
errors.push(...doneErrors);
141274
errors.push(...unhandledExceptions);
142275

276+
if (
277+
typeof expectFail === "object" &&
278+
(harnessFail || unhandledExceptions.length)
279+
) {
280+
expectFail = false;
281+
}
282+
143283
if (errors.length === 0 && expectFail) {
144-
reject(
145-
new Error(`
146-
Hey, did you fix a bug? This test used to be failing, but during
147-
this run there were no errors. If you have fixed the issue covered
148-
by this test, you can edit the "to-run.yaml" file and remove the line
149-
containing this test. Thanks!
150-
`),
151-
);
152-
} else if (errors.length === 1 && !expectFail) {
284+
reject(new Error(unexpectedPassingTestMessage));
285+
} else if (
286+
errors.length === 1 &&
287+
(tests.length === 1 || harnessFail) &&
288+
!expectFail
289+
) {
153290
reject(new Error(errors[0]));
154291
} else if (errors.length && !expectFail) {
155292
reject(
156293
new Error(
157-
`${errors.length} errors in test:\n\n${errors.join("\n")}`,
294+
`${errors.length}/${
295+
tests.length
296+
} errors in test:\n\n${errors.join("\n\n")}`,
158297
),
159298
);
160-
} else {
299+
} else if (typeof expectFail !== "object") {
161300
resolve();
301+
} else {
302+
const unexpectedErrors = [];
303+
for (const test of tests) {
304+
const data = expectFail[test.name];
305+
const reason = data && data[0];
306+
307+
const innerExpectFail = resolveReason(reason) === "expect-fail";
308+
if (
309+
innerExpectFail
310+
? test.status === test.PASS
311+
: test.status !== test.PASS
312+
) {
313+
unexpectedErrors.push(formatFailedTest(test));
314+
}
315+
}
316+
317+
if (unexpectedErrors.length) {
318+
reject(
319+
new Error(
320+
`${unexpectedErrors.length}/${
321+
tests.length
322+
} errors in test:\n\n${unexpectedErrors.join("\n\n")}`,
323+
),
324+
);
325+
} else {
326+
resolve();
327+
}
162328
}
163329
});
164330
};

0 commit comments

Comments
 (0)