test: intercept the MV3 service worker's network in the e2e harness
All checks were successful
check / check (push) Successful in 43s
All checks were successful
check / check (push) Successful in 43s
ctx.route() does not see requests made by the background service worker unless Playwright is run with PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1, so the phishing blocklist fetch that src/background/index.js issues at worker startup was reaching raw.githubusercontent.com on the real internet on every run. phishingDomains.js swallows fetch failures, so nothing surfaced it, and the raw.githubusercontent.com stub in tests/e2e/network.js was unreachable code that made the gap look covered. script/test-e2e now sets the flag, with a comment recording what to do if a future Playwright drops it. The flag being experimental is not taken on trust: launch() waits for the worker's own startup request to arrive in the route handler and refuses to run the suite if it never does, so escaping traffic fails the run instead of passing unnoticed. Chrome is additionally started with --host-resolver-rules=MAP * ~NOTFOUND, so anything that does slip past interception cannot reach a real host. Also: errors and unstubbed requests recorded during launch are attributed to the first test rather than discarded, a suite that registers no tests now fails instead of exiting 0, a failure after the browser is up tears the context down instead of hanging the process, E2E_TRACE_NETWORK=1 prints every routed request tagged [sw] or [page], and the dead exports in harness.js and network.js are gone.
This commit is contained in:
@@ -116,15 +116,28 @@ test("transaction detail renders an ERC-20 transfer (#151)", async (env) => {
|
||||
// ---------------------------------------------------------------- runner
|
||||
|
||||
async function main() {
|
||||
// A suite that runs nothing must never report success. If a refactor
|
||||
// drops the registrations above, or a require() of this file stops
|
||||
// reaching them, the only honest outcome is a red run — reporting
|
||||
// "0/0 passed" and exiting 0 is the same vacuous-check failure this
|
||||
// whole harness exists to prevent.
|
||||
if (tests.length === 0) {
|
||||
console.log("1..0");
|
||||
console.log("# FAILED: the e2e suite registered no tests");
|
||||
process.exitCode = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
const routeOpts = { seedTokenTransfer: false };
|
||||
|
||||
let session;
|
||||
try {
|
||||
session = await launch(routeOpts);
|
||||
} catch (e) {
|
||||
// Never skip and report success: a browser we cannot start is a
|
||||
// failure of the suite, not an absent one.
|
||||
console.error("e2e: could not start the browser: " + e.message);
|
||||
// Never skip and report success: a browser we cannot start, or
|
||||
// one whose network interception is not in force, is a failure of
|
||||
// the suite, not an absent one.
|
||||
console.error("e2e: cannot run the suite: " + e.message);
|
||||
process.exitCode = 1;
|
||||
return;
|
||||
}
|
||||
@@ -141,9 +154,13 @@ async function main() {
|
||||
|
||||
let failed = 0;
|
||||
let n = 0;
|
||||
// Starts at zero rather than at the current mark on purpose: errors
|
||||
// and escaping requests recorded during launch — before any test ran,
|
||||
// which is when the background worker does its startup fetches — are
|
||||
// attributed to the first test instead of being discarded.
|
||||
let mark = 0;
|
||||
for (const t of tests) {
|
||||
n += 1;
|
||||
const mark = session.errors.mark();
|
||||
let failure = null;
|
||||
try {
|
||||
await withTimeout(t.fn(env), t.name);
|
||||
@@ -155,6 +172,7 @@ async function main() {
|
||||
// provoked it, whether or not its assertions passed. This is the
|
||||
// mechanism that caught #150.
|
||||
const newErrors = session.errors.since(mark);
|
||||
mark = session.errors.mark();
|
||||
if (!failure && newErrors.length > 0) {
|
||||
failure = "uncaught browser errors during this test";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user