Stabilize parallel E2E slices

This commit is contained in:
Jeppe Bundgaard
2026-06-15 16:17:45 +02:00
parent c88f5442ab
commit 53315bbb56
8 changed files with 32 additions and 16 deletions
+2 -2
View File
@@ -123,7 +123,7 @@ Default worker allocation:
```sh
PLAYWRIGHT_PARALLEL_WORKERS_CHROMIUM=2
PLAYWRIGHT_PARALLEL_WORKERS_FIREFOX=1
PLAYWRIGHT_PARALLEL_WORKERS_WEBKIT=2
PLAYWRIGHT_PARALLEL_WORKERS_WEBKIT=1
```
Optional overrides:
@@ -132,7 +132,7 @@ Optional overrides:
PLAYWRIGHT_PARALLEL_BASE_PORT=5191
PLAYWRIGHT_PARALLEL_WORKERS_CHROMIUM=2
PLAYWRIGHT_PARALLEL_WORKERS_FIREFOX=1
PLAYWRIGHT_PARALLEL_WORKERS_WEBKIT=2
PLAYWRIGHT_PARALLEL_WORKERS_WEBKIT=1
```
The runner fails fast if the combined worker count exceeds 5.
+1 -1
View File
@@ -28,7 +28,7 @@ const groups = [
{
name: "webkit",
projects: ["webkit-desktop", "webkit-tablet", "webkit-mobile"],
defaultWorkers: 2,
defaultWorkers: 1,
},
];
+1 -4
View File
@@ -26,6 +26,7 @@ const isBenignNavigationError = (error: unknown) => {
return (
message.includes("interrupted by another navigation") ||
message.includes("ERR_ABORTED") ||
message.includes("NS_BINDING_ABORTED") ||
message.includes("Frame load interrupted")
);
};
@@ -38,10 +39,6 @@ function fulfillJson(route: Route, body: unknown, status = 200) {
});
}
function getErrorMessage(error: unknown) {
return error instanceof Error ? error.message : String(error);
}
async function hasConnectivityIssue(page: Page) {
return page
.getByText(CONNECTIVITY_ISSUE_PATTERN)
+21 -6
View File
@@ -57,6 +57,20 @@ async function prepareInvoiceDistributionPage(page, overrides = {}) {
await primeSuperuserSession(page);
}
async function gotoInvoiceDistribution(page, url) {
for (let attempt = 0; attempt < 2; attempt += 1) {
try {
await page.goto(url);
return;
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
if (attempt > 0 || !message.includes("WebKit encountered an internal error")) {
throw error;
}
}
}
}
test.describe("Invoice distribution smoke", () => {
test("@smoke @pr overview loads and quick-open month action works", async ({ page }) => {
const componentWarnings = [];
@@ -68,7 +82,7 @@ test.describe("Invoice distribution smoke", () => {
});
await prepareInvoiceDistributionPage(page);
await page.goto("/superuser/invoices?activeTab=distribution");
await gotoInvoiceDistribution(page, "/superuser/invoices?activeTab=distribution");
await expect(page.getByTestId("distribution-overview-page")).toBeVisible({ timeout: 15_000 });
await expect(page.locator('[data-testid="distribution-overview-page"] h2').first()).toBeVisible();
@@ -95,7 +109,8 @@ test.describe("Invoice distribution smoke", () => {
test("@smoke monthly tabs keep URL query-state in sync", async ({ page }) => {
await prepareInvoiceDistributionPage(page);
await page.goto(
await gotoInvoiceDistribution(
page,
"/superuser/invoices/distribution/2026/3/customers?customerSearch=acme&customerSource=fixed_pricing&customerDepartment=Copenhagen&compareMode=line_by_line"
);
@@ -118,7 +133,7 @@ test.describe("Invoice distribution smoke", () => {
test("@smoke compare flow shows progress and mismatch-first results", async ({ page }) => {
await prepareInvoiceDistributionPage(page);
await page.goto("/superuser/invoices/distribution/2026/3/compare?compareMode=line_by_line");
await gotoInvoiceDistribution(page, "/superuser/invoices/distribution/2026/3/compare?compareMode=line_by_line");
await page.getByTestId("distribution-compare-submit").click();
const compareTable = page.getByTestId("distribution-compare-table");
@@ -139,7 +154,7 @@ test.describe("Invoice distribution smoke", () => {
test("@smoke mobile layout sanity keeps primary controls visible", async ({ page }) => {
await prepareInvoiceDistributionPage(page);
await page.goto("/superuser/invoices/distribution/2026/3/overview");
await gotoInvoiceDistribution(page, "/superuser/invoices/distribution/2026/3/overview");
await expect(page.getByTestId("distribution-month-toolbar")).toBeVisible();
await expect(page.getByTestId("distribution-month-prev")).toBeVisible();
@@ -155,12 +170,12 @@ test.describe("Invoice distribution smoke", () => {
invoiceDistributionForceCompareFallback: true,
});
await page.goto("/superuser/invoices?activeTab=distribution");
await gotoInvoiceDistribution(page, "/superuser/invoices?activeTab=distribution");
await expect(page.locator(".message.is-warning").filter({ hasText: /v2/i }).first()).toBeVisible({
timeout: 15_000,
});
await page.goto("/superuser/invoices/distribution/2026/3/compare?compareMode=line_by_line");
await gotoInvoiceDistribution(page, "/superuser/invoices/distribution/2026/3/compare?compareMode=line_by_line");
await expect(page.locator(".message.is-warning").filter({ hasText: /v2/i }).first()).toBeVisible({
timeout: 15_000,
});
+1 -1
View File
@@ -87,7 +87,7 @@ test("non-default release channel keeps the regular frontend and dynamic API run
expect(page.url()).toContain("/shared/passkey-safe-link");
expect(page.url()).not.toContain("api-v2.truckwash.io");
expect(runtimeRequests).toHaveLength(1);
await expect.poll(() => runtimeRequests.length).toBe(1);
const runtimeRequestUrl = new URL(runtimeRequests[0]);
expect(["/api/release/runtime", "/master/api/release/runtime"]).toContain(runtimeRequestUrl.pathname);
expect(runtimeRequestUrl.pathname).not.toBe("/canary/api/release/runtime");
+1
View File
@@ -120,6 +120,7 @@ function isBenignNavigationError(error) {
return (
message.includes("interrupted by another navigation") ||
message.includes("ERR_ABORTED") ||
message.includes("NS_BINDING_ABORTED") ||
message.includes("Frame load interrupted")
);
}
+1
View File
@@ -48,6 +48,7 @@ function isBenignNavigationError(error) {
return (
message.includes("interrupted by another navigation") ||
message.includes("ERR_ABORTED") ||
message.includes("NS_BINDING_ABORTED") ||
message.includes("Frame load interrupted")
);
}
+4 -2
View File
@@ -28,6 +28,8 @@ test("[PAGES][User][/user/bookings] should display the title", async ({ page })
});
test("[BOOKINGS][User][Mobile] should keep booking overview cards within the viewport", async ({ page }) => {
const today = new Date().toISOString().split("T")[0];
await mockApi(page, {
authenticated: true,
sessionData: {
@@ -42,7 +44,7 @@ test("[BOOKINGS][User][Mobile] should keep booking overview cards within the vie
customer_number: 12345679,
customer_name: "Pleno Logistics ApS",
department: 12,
datetime: "2026-05-28 08:30:00",
datetime: `${today} 08:30:00`,
reg_1: "AB12345",
reg_2: "CD67890",
reference: "Lang intern reference der tidligere pressede kortet ud over kanten",
@@ -65,7 +67,7 @@ test("[BOOKINGS][User][Mobile] should keep booking overview cards within the vie
customer_number: 12345679,
customer_name: "Pleno Logistics ApS",
department: 1,
datetime: "2026-05-28 14:15:00",
datetime: `${today} 14:15:00`,
reg_1: "EF24680",
reg_2: "",
reference: "",