Skip to content

Commit

Permalink
feat: update wpt usage
Browse files Browse the repository at this point in the history
Co-authored-by: Craig Morten <[email protected]>
  • Loading branch information
jlp-craigmorten and cmorten committed Mar 31, 2024
1 parent c8468cd commit d06ebe2
Show file tree
Hide file tree
Showing 17 changed files with 180,159 additions and 99,545 deletions.
336 changes: 174 additions & 162 deletions README.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@
"jest-junit": "^16.0.0",
"js-yaml": "^4.1.0",
"jsdom": "^20.0.0",
"minimatch": "^9.0.0",
"mocha": "^10.0.0",
"minimatch": "^9.0.3",
"mocha": "^10.3.0",
"mocha-sugar-free": "^1.4.0",
"prettier": "^3.0.0",
"q": "^1.5.1",
Expand Down
321 changes: 162 additions & 159 deletions tests/cypress/integration/web-platform-test.cy.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion tests/wpt
Submodule wpt updated 19543 files
4 changes: 2 additions & 2 deletions tests/wpt-jsdom/ATTAcomm.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ class ATTAcomm {

if (matcher === "property") {
if (name === namePropertyName[implementation]) {
const actual = computeAccessibleName(element);
const actual = computeAccessibleName(element) ?? "";
if (equality === "is") {
assert_equals(actual, expected);
continue;
}
} else if (name === descriptionPropertyName[implementation]) {
const actual = computeAccessibleDescription(element);
const actual = computeAccessibleDescription(element) ?? "";
if (equality === "is") {
assert_equals(actual, expected);
continue;
Expand Down
2 changes: 1 addition & 1 deletion tests/wpt-jsdom/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
See https://github.com/jsdom/jsdom/blob/67eb73efc22d85b2aa3c7b0237be58ac5129b584/test/README.md#L1
See https://github.com/jsdom/jsdom/blob/2f8a730/test/README.md
234 changes: 200 additions & 34 deletions tests/wpt-jsdom/run-single-wpt.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,31 @@ const { specify } = require("mocha-sugar-free");
const { inBrowserContext } = require("./util.js");
const { JSDOM, VirtualConsole } = require("jsdom");
const ResourceLoader = require("jsdom/lib/jsdom/browser/resources/resource-loader");
const { resolveReason } = require("./utils.js");
const {
computeAccessibleName,
computeAccessibleDescription,
getRole,
} = require("../../dist/");

const reporterPathname = "/resources/testharnessreport.js";
const testdriverPathname = "/resources/testdriver.js";
const ATTAcommPathname = "/wai-aria/scripts/ATTAcomm.js";

const unexpectedPassingTestMessage = `
Hey, did you fix a bug? This test used to be failing, but during
this run there were no errors. If you have fixed the issue covered
by this test, you can edit the "to-run.yaml" file and remove the line
containing this test. Thanks!
`;

module.exports = (urlPrefixFactory) => {
if (inBrowserContext()) {
return () => {
// TODO: browser support for running WPT
};
}

return (testPath, title = testPath, expectFail) => {
return (testPath, title = testPath, expectFail = false) => {
specify({
title,
expectPromise: true,
Expand All @@ -42,13 +52,23 @@ class CustomResourceLoader extends ResourceLoader {
fetch(urlString, options) {
const url = new URL(urlString);

if (url.pathname === reporterPathname) {
if (url.pathname === ATTAcommPathname) {
const filePath = path.resolve(__dirname, "./ATTAcomm.js");

return super.fetch(`file://${filePath}`, options);
} else if (url.pathname === testdriverPathname) {
const filePath = path.resolve(__dirname, "./testdriver.js");

return super.fetch(`file://${filePath}`, options);
} else if (url.pathname.startsWith("/resources/testdriver")) {
return Promise.resolve(Buffer.from("", "utf-8"));
} else if (url.pathname === reporterPathname) {
return Promise.resolve(Buffer.from("window.shimTest();", "utf-8"));
} else if (url.pathname.startsWith("/resources/")) {
// When running to-upstream tests, the server doesn't have a /resources/ directory.
// So, always go to the one in ./tests.
// So, always go to the one in ../wpt.
// The path replacement accounts for a rewrite performed by the WPT server:
// https://github.com/w3c/web-platform-tests/blob/master/tools/serve/serve.py#L271
// https://github.com/web-platform-tests/wpt/blob/master/tools/serve/serve.py#L271
const filePath = path
.resolve(__dirname, "../wpt" + url.pathname)
.replace(
Expand All @@ -57,18 +77,42 @@ class CustomResourceLoader extends ResourceLoader {
);

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

return super.fetch(urlString, options);
}
}

function formatFailedTest(test) {
switch (test.status) {
case test.PASS:
return `Unexpected passing test: ${JSON.stringify(
test.name,
)}${unexpectedPassingTestMessage}`;
case test.FAIL:
case test.PRECONDITION_FAILED:
return `Failed in ${JSON.stringify(test.name)}:\n${test.message}\n\n${
test.stack
}`;
case test.TIMEOUT:
return `Timeout in ${JSON.stringify(test.name)}:\n${test.message}\n\n${
test.stack
}`;
case test.NOTRUN:
return `Uncompleted test ${JSON.stringify(test.name)}:\n${
test.message
}\n\n${test.stack}`;
default:
throw new RangeError(
`Unexpected test status: ${test.status} (test: ${JSON.stringify(
test.name,
)})`,
);
}
}

function createJSDOM(urlPrefix, testPath, expectFail) {
const unhandledExceptions = [];
const doneErrors = [];

let allowUnhandledExceptions = false;

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

window.computeAccessibleName = computeAccessibleName;
window.computeAccessibleDescription = computeAccessibleDescription;
window.getRole = getRole;

window.shimTest = () => {
const oldSetup = window.setup;
window.setup = () => {
// noop, otherwise failing tests just slowly timeout
window.setup = (options) => {
if (options.allow_uncaught_exception) {
allowUnhandledExceptions = true;
}
oldSetup(options);
};

window.add_result_callback((test) => {
if (test.status === 1) {
errors.push(
`Failed in "${test.name}": \n${test.message}\n\n${test.stack}`,
// Overriding assert_throws_js and friends in order to allow us to throw exceptions from another realm. See
// https://github.com/jsdom/jsdom/issues/2727 for more information.

function assertThrowsJSImpl(
constructor,
func,
description,
assertionType,
) {
try {
func.call(this);
window.assert_true(
false,
`${assertionType}: ${description}: ${func} did not throw`,
);
} else if (test.status === 2) {
errors.push(
`Timeout in "${test.name}": \n${test.message}\n\n${test.stack}`,
} catch (e) {
if (e instanceof window.AssertionError) {
throw e;
}

// Basic sanity-checks on the thrown exception.
window.assert_true(
typeof e === "object",
`${assertionType}: ${description}: ${func} threw ${e} with type ${typeof e}, not an object`,
);
} else if (test.status === 3) {
errors.push(
`Uncompleted test "${test.name}": \n${test.message}\n\n${test.stack}`,

window.assert_true(
e !== null,
`${assertionType}: ${description}: ${func} threw null, not an object`,
);

// Basic sanity-check on the passed-in constructor
window.assert_true(
typeof constructor === "function",
`${assertionType}: ${description}: ${constructor} is not a constructor`,
);
let obj = constructor;
while (obj) {
if (typeof obj === "function" && obj.name === "Error") {
break;
}
obj = Object.getPrototypeOf(obj);
}
window.assert_true(
obj !== null && obj !== undefined,
`${assertionType}: ${description}: ${constructor} is not an Error subtype`,
);

// And checking that our exception is reasonable
window.assert_equals(
e.name,
constructor.name,
`${assertionType}: ${description}: ${func} threw ${e} (${e.name}) ` +
`expected instance of ${constructor.name}`,
);
}
}

// eslint-disable-next-line camelcase
window.assert_throws_js = (constructor, func, description) => {
assertThrowsJSImpl(
constructor,
func,
description,
"assert_throws_js",
);
};
// eslint-disable-next-line camelcase
window.promise_rejects_js = (test, expected, promise, description) => {
return promise
.then(test.unreached_func("Should have rejected: " + description))
.catch((e) => {
assertThrowsJSImpl(
expected,
() => {
throw e;
},
description,
"promise_reject_js",
);
});
};

window.add_result_callback((test) => {
if (
test.status === test.FAIL ||
test.status === test.TIMEOUT ||
test.status === test.NOTRUN
) {
errors.push(formatFailedTest(test));
}
});

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

if (harnessStatus.status === 2) {
let harnessFail = false;
if (harnessStatus.status === harnessStatus.ERROR) {
harnessFail = true;
errors.push(
new Error(
`test harness should not error: ${testPath}\n${harnessStatus.message}`,
),
);
} else if (harnessStatus.status === harnessStatus.TIMEOUT) {
harnessFail = true;
errors.push(
new Error(`test harness should not timeout: ${testPath}`),
);
}

errors.push(...doneErrors);
errors.push(...unhandledExceptions);

if (
typeof expectFail === "object" &&
(harnessFail || unhandledExceptions.length)
) {
expectFail = false;
}

if (errors.length === 0 && expectFail) {
reject(
new Error(`
Hey, did you fix a bug? This test used to be failing, but during
this run there were no errors. If you have fixed the issue covered
by this test, you can edit the "to-run.yaml" file and remove the line
containing this test. Thanks!
`),
);
} else if (errors.length === 1 && !expectFail) {
reject(new Error(unexpectedPassingTestMessage));
} else if (
errors.length === 1 &&
(tests.length === 1 || harnessFail) &&
!expectFail
) {
reject(new Error(errors[0]));
} else if (errors.length && !expectFail) {
reject(
new Error(
`${errors.length} errors in test:\n\n${errors.join("\n")}`,
`${errors.length}/${
tests.length
} errors in test:\n\n${errors.join("\n\n")}`,
),
);
} else {
} else if (typeof expectFail !== "object") {
resolve();
} else {
const unexpectedErrors = [];
for (const test of tests) {
const data = expectFail[test.name];
const reason = data && data[0];

const innerExpectFail = resolveReason(reason) === "expect-fail";
if (
innerExpectFail
? test.status === test.PASS
: test.status !== test.PASS
) {
unexpectedErrors.push(formatFailedTest(test));
}
}

if (unexpectedErrors.length) {
reject(
new Error(
`${unexpectedErrors.length}/${
tests.length
} errors in test:\n\n${unexpectedErrors.join("\n\n")}`,
),
);
} else {
resolve();
}
}
});
};
Expand Down
Loading

0 comments on commit d06ebe2

Please sign in to comment.