Files
pleno-vue/tests/unit/playwright-full-slice-ownership.spec.js
T

160 lines
5.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { execFileSync } from "node:child_process";
import { readFileSync } from "node:fs";
import fs from "node:fs/promises";
import { readdirSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { afterEach, describe, expect, it } from "vitest";
import {
browserEngines,
classifyTest,
deviceClasses,
fullSuiteProjects,
getLegacyTestListPath,
getPrimaryTestListPath,
ownedFilesByRole,
parseListedTests,
requireMatchingTests,
roles,
titleRules,
writeTestList,
} from "../../scripts/run-playwright-full-slice.mjs";
const root = process.cwd();
const playwrightCliPath = join(root, "node_modules", "@playwright", "test", "cli.js");
const titleRuleFiles = new Set(titleRules.map((rule) => rule.file));
const e2eSpecFiles = readdirSync(join(root, "tests/e2e"))
.filter((file) => /\.spec\.(?:js|ts)$/u.test(file))
.sort();
const generatedTestListPaths = [];
const generatedTestListDirectories = [];
describe("Playwright full-slice ownership", () => {
afterEach(async () => {
await Promise.all(generatedTestListPaths.splice(0).map((filePath) => fs.rm(filePath, { force: true })));
await Promise.all(
generatedTestListDirectories.splice(0).map((directory) => fs.rm(directory, { recursive: true, force: true }))
);
delete process.env.PLAYWRIGHT_TEST_LIST_DIR;
});
it("keeps full-suite slices ordered by browser, device, then role", () => {
expect(browserEngines).toEqual(["chromium", "webkit", "firefox"]);
expect(deviceClasses).toEqual(["mobile", "desktop", "tablet"]);
expect(roles).toEqual(["superuser", "admin", "customer", "subuser"]);
expect(fullSuiteProjects).toEqual([
"chromium-mobile",
"chromium-desktop",
"chromium-tablet",
"webkit-mobile",
"webkit-desktop",
"webkit-tablet",
"firefox-mobile",
"firefox-desktop",
"firefox-tablet",
]);
});
it("assigns every top-level e2e spec to one role or a title rule", () => {
const directOwners = new Map();
for (const [role, files] of Object.entries(ownedFilesByRole)) {
for (const file of files) {
if (directOwners.has(file)) {
throw new Error(`${file} is owned by both ${directOwners.get(file)} and ${role}.`);
}
directOwners.set(file, role);
}
}
const coveredFiles = new Set([...directOwners.keys(), ...titleRuleFiles]);
const uncoveredFiles = e2eSpecFiles.filter((file) => !coveredFiles.has(file));
expect(uncoveredFiles).toEqual([]);
});
it("keeps shared and infrastructure specs in their intended shards", () => {
expect(ownedFilesByRole.admin).toEqual(expect.arrayContaining(["default-mobile-redirect.spec.ts"]));
expect(ownedFilesByRole.superuser).toEqual(
expect.arrayContaining([
"errorReports.spec.ts",
"failover-config.source.spec.ts",
"release-manager.spec.js",
"session-bootstrap.spec.ts",
"superuser-users.spec.ts",
])
);
expect(ownedFilesByRole.customer).toEqual(
expect.arrayContaining([
"guest-book-wash-mobile.spec.ts",
"i18n-v2-integrity.spec.ts",
"release-bootstrap.spec.js",
"release-channel-switched.spec.js",
"release-channel-unavailable.spec.js",
"release-update-widget.spec.js",
"session-release-runtime.spec.ts",
])
);
});
it("classifies every listed test before role filtering", () => {
const listOutput = execFileSync(
process.execPath,
[playwrightCliPath, "test", "--list", "--reporter=list", "--project=chromium-desktop"],
{
cwd: root,
encoding: "utf8",
maxBuffer: 64 * 1024 * 1024,
}
);
const classificationErrors = [];
for (const testEntry of parseListedTests(listOutput)) {
try {
classifyTest(testEntry);
} catch (error) {
classificationErrors.push(error.message);
}
}
expect(classificationErrors).toEqual([]);
}, 15_000);
it("writes project-role test lists and a legacy compatibility copy", async () => {
const testListDirectory = await fs.mkdtemp(join(tmpdir(), "playwright-test-lists-"));
process.env.PLAYWRIGHT_TEST_LIST_DIR = testListDirectory;
generatedTestListDirectories.push(testListDirectory);
const matchingTests = [
{
listLine: "[webkit-tablet] tests/e2e/admin-pos-orders.spec.ts:10:1 admin order list",
},
];
const primaryPath = getPrimaryTestListPath("webkit-tablet", "admin");
const legacyPath = getLegacyTestListPath("admin", "webkit-tablet");
generatedTestListPaths.push(primaryPath, legacyPath);
await expect(writeTestList("admin", "webkit-tablet", matchingTests)).resolves.toBe(primaryPath);
expect(readFileSync(primaryPath, "utf8")).toBe(`${matchingTests[0].listLine}\n`);
expect(readFileSync(legacyPath, "utf8")).toBe(`${matchingTests[0].listLine}\n`);
});
it("fails closed when a required project-role slice resolves zero tests", () => {
expect(() => requireMatchingTests("customer", "webkit-mobile", [])).toThrow(
"Full Playwright slice resolved zero customer tests for webkit-mobile."
);
expect(requireMatchingTests("customer", "webkit-mobile", [{ listLine: "one test" }])).toHaveLength(1);
});
});
describe("Playwright full-suite project order", () => {
it("keeps playwright.config projects ordered by browser engine and device class", () => {
const source = readFileSync(join(root, "playwright.config.ts"), "utf8");
const projectNames = [...source.matchAll(/buildProject\("([^"]+)"/gu)].map((match) => match[1]);
expect(projectNames).toEqual(fullSuiteProjects);
});
});