mirror of
https://github.com/block/buzz.git
synced 2026-10-31 22:41:12 +00:00
test(e2e): cover structural bootstrap control flow
Signed-off-by: Brother Darryl <146fb160a3266e6165bfa385f6048c975eda9e21cf65da097a0b5ea7952532a5@buzz.block.builderlab.xyz>
This commit is contained in:
@@ -1,67 +1,165 @@
|
||||
import assert from "node:assert/strict";
|
||||
import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import test from "node:test";
|
||||
|
||||
const projects = [
|
||||
["desktop", "../scripts/check-e2e-bootstrap.mjs"],
|
||||
["web", "../scripts/check-e2e-bootstrap.mjs"],
|
||||
];
|
||||
|
||||
const validDirect = `
|
||||
import { test, bootstrapE2ePage } from "../helpers/test";
|
||||
test("uses bootstrap", async ({ page }) => { await bootstrapE2ePage(page); });
|
||||
`;
|
||||
const validBeforeEach = `
|
||||
import { test, bootstrapE2ePage } from "../helpers/test";
|
||||
test.beforeEach(async ({ page }) => { await bootstrapE2ePage(page); });
|
||||
test("uses registered hook", async ({ page }) => { await page.title(); });
|
||||
`;
|
||||
const validBeforeNavigate = `
|
||||
import { test, bootstrapE2ePage } from "../helpers/test";
|
||||
test("draft seed", async ({ page }) => {
|
||||
await bootstrapE2ePage(page, { beforeNavigate: async () => page.addInitScript(() => {}) });
|
||||
});
|
||||
`;
|
||||
const imports = 'import { test, bootstrapE2ePage } from "../helpers/test";';
|
||||
const spec = (body) =>
|
||||
`${imports}\ntest("x", async ({ page }) => { ${body} });`;
|
||||
|
||||
for (const [project, checkerPath] of projects) {
|
||||
const { checkSource } = await import(checkerPath);
|
||||
const { checkSource, runCheck } = await import(checkerPath);
|
||||
const accepts = (source) => assert.equal(checkSource(source), undefined);
|
||||
const rejects = (source) => assert.notEqual(checkSource(source), undefined);
|
||||
|
||||
test(`${project}: accepts direct, hook, and beforeNavigate bootstrap patterns`, () => {
|
||||
for (const source of [validDirect, validBeforeEach, validBeforeNavigate]) {
|
||||
assert.equal(checkSource(source), undefined);
|
||||
}
|
||||
accepts(spec("await bootstrapE2ePage(page);"));
|
||||
accepts(
|
||||
`${imports}\ntest.beforeEach(async ({ page }) => { await bootstrapE2ePage(page); });\ntest("x", async ({ page }) => { await page.title(); });`,
|
||||
);
|
||||
accepts(
|
||||
spec(
|
||||
"await bootstrapE2ePage(page, { beforeNavigate: async () => page.addInitScript(() => {}) });",
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
test(`${project}: accepts module helpers and ratified containers`, () => {
|
||||
accepts(
|
||||
`${imports}\nasync function open(page) { return await bootstrapE2ePage(page); }\ntest("x", async ({ page }) => { const response = await open(page); void response; });`,
|
||||
);
|
||||
accepts(
|
||||
spec(
|
||||
"try { await bootstrapE2ePage(page); } finally { await page.title(); }",
|
||||
),
|
||||
);
|
||||
accepts(
|
||||
spec(
|
||||
"try { await page.title(); } finally { await bootstrapE2ePage(page); }",
|
||||
),
|
||||
);
|
||||
accepts(
|
||||
spec("for (const attempt of [0, 1]) { await bootstrapE2ePage(page); }"),
|
||||
);
|
||||
accepts(
|
||||
spec(
|
||||
"for (let attempt = 0; attempt < 2; attempt += 1) { await bootstrapE2ePage(page); }",
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
for (const [name, source] of [
|
||||
[
|
||||
".ts helper suffix",
|
||||
`import { test, bootstrapE2ePage } from "../helpers/test.ts"; test("x", async () => {});`,
|
||||
'import { test, bootstrapE2ePage } from "../helpers/test.ts"; test("x", async () => {});',
|
||||
],
|
||||
[
|
||||
"import alias",
|
||||
`import { test as e2eTest, bootstrapE2ePage } from "../helpers/test"; e2eTest("x", async () => { await bootstrapE2ePage(); });`,
|
||||
'import { test as e2eTest, bootstrapE2ePage } from "../helpers/test"; e2eTest("x", async () => { await bootstrapE2ePage(); });',
|
||||
],
|
||||
[
|
||||
"re-export",
|
||||
`import { test, bootstrapE2ePage } from "./reexport"; test("x", async () => { await bootstrapE2ePage(); });`,
|
||||
'import { test, bootstrapE2ePage } from "./reexport"; test("x", async () => { await bootstrapE2ePage(); });',
|
||||
],
|
||||
[
|
||||
"dynamic import",
|
||||
`const { test, bootstrapE2ePage } = await import("../helpers/test"); test("x", async () => { await bootstrapE2ePage(); });`,
|
||||
'const { test, bootstrapE2ePage } = await import("../helpers/test"); test("x", async () => { await bootstrapE2ePage(); });',
|
||||
],
|
||||
[
|
||||
"dead-code call",
|
||||
`import { test, bootstrapE2ePage } from "../helpers/test"; async function never(page) { await bootstrapE2ePage(page); } test("x", async () => {});`,
|
||||
`${imports}\nasync function never(page) { await bootstrapE2ePage(page); } test("x", async () => {});`,
|
||||
],
|
||||
[
|
||||
"comment",
|
||||
`import { test, bootstrapE2ePage } from "../helpers/test"; // await bootstrapE2ePage(page)\ntest("x", async () => {});`,
|
||||
`${imports}\n// await bootstrapE2ePage(page)\ntest("x", async () => {});`,
|
||||
],
|
||||
[
|
||||
"string",
|
||||
`import { test, bootstrapE2ePage } from "../helpers/test"; const hint = "await bootstrapE2ePage(page)"; test("x", async () => {});`,
|
||||
`${imports}\nconst hint = "await bootstrapE2ePage(page)"; test("x", async () => {});`,
|
||||
],
|
||||
[
|
||||
"mixed safe and unsafe tests",
|
||||
`${imports}\ntest("safe", async ({ page }) => { await bootstrapE2ePage(page); }); test("unsafe", async () => {});`,
|
||||
],
|
||||
["if-wrapped call", spec("if (true) { await bootstrapE2ePage(page); }")],
|
||||
[
|
||||
"catch-only call",
|
||||
spec(
|
||||
"try { await page.title(); } catch { await bootstrapE2ePage(page); }",
|
||||
),
|
||||
],
|
||||
[
|
||||
"zero-iteration false loop",
|
||||
spec("for (; false;) { await bootstrapE2ePage(page); }"),
|
||||
],
|
||||
[
|
||||
"zero-iteration empty iterable",
|
||||
spec("for (const value of []) { await bootstrapE2ePage(page); }"),
|
||||
],
|
||||
[
|
||||
"uncalled nested function",
|
||||
spec("async function setup() { await bootstrapE2ePage(page); }"),
|
||||
],
|
||||
[
|
||||
"unawaited helper",
|
||||
`${imports}\nasync function open(page) { await bootstrapE2ePage(page); }\ntest("x", async ({ page }) => { open(page); });`,
|
||||
],
|
||||
[
|
||||
"fake test.extend",
|
||||
`${imports}\ntest.extend("x", async ({ page }) => { await bootstrapE2ePage(page); });`,
|
||||
],
|
||||
[
|
||||
"misplaced describe hook",
|
||||
`${imports}\ntest.describe("inside", () => { test.beforeEach(async ({ page }) => { await bootstrapE2ePage(page); }); test("covered", async () => {}); }); test("outside", async () => {});`,
|
||||
],
|
||||
[
|
||||
"shadowed bootstrap",
|
||||
`${imports}\ntest("x", async ({ page }) => { const bootstrapE2ePage = async () => {}; await bootstrapE2ePage(page); });`,
|
||||
],
|
||||
]) {
|
||||
test(`${project}: rejects ${name}`, () => {
|
||||
assert.notEqual(checkSource(source), undefined);
|
||||
});
|
||||
test(`${project}: rejects ${name}`, () => rejects(source));
|
||||
}
|
||||
|
||||
test(`${project}: discovers nested specs with a canonical relative import`, () => {
|
||||
const root = fs.mkdtempSync(path.join(os.tmpdir(), "e2e-bootstrap-"));
|
||||
try {
|
||||
fs.mkdirSync(path.join(root, "tests/e2e/nested"), { recursive: true });
|
||||
fs.mkdirSync(path.join(root, "tests/helpers"), { recursive: true });
|
||||
fs.writeFileSync(
|
||||
path.join(root, "tests/helpers/test.ts"),
|
||||
"export {};\n",
|
||||
);
|
||||
fs.writeFileSync(
|
||||
path.join(root, "tests/e2e/nested/example.spec.ts"),
|
||||
'import { test, bootstrapE2ePage } from "../../helpers/test"; test("x", async ({ page }) => { await bootstrapE2ePage(page); });',
|
||||
);
|
||||
assert.deepEqual(runCheck(root), []);
|
||||
} finally {
|
||||
fs.rmSync(root, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for (const [project, checkerPath] of projects) {
|
||||
const { checkSource } = await import(checkerPath);
|
||||
test(`${project}: traverses canonical parameterized registration containers only`, () => {
|
||||
assert.equal(
|
||||
checkSource(`${imports}
|
||||
for (const name of ["one", "two"]) test(name, async ({ page }) => { await bootstrapE2ePage(page); });
|
||||
["three"].forEach((name) => test(name, async ({ page }) => { await bootstrapE2ePage(page); }));
|
||||
["four"].map((name) => test(name, async ({ page }) => { await bootstrapE2ePage(page); }));`),
|
||||
undefined,
|
||||
);
|
||||
assert.notEqual(
|
||||
checkSource(`${imports}
|
||||
function registerLater() { test("hidden", async ({ page }) => { await bootstrapE2ePage(page); }); }
|
||||
test("unsafe", async () => {});`),
|
||||
undefined,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user