- Introduced `.prettierrc.json` to enforce consistent code formatting across the project. - Updated unit and e2e test files to address formatting issues, improve readability, and ensure alignment with the new Prettier configuration.
210 lines
6.6 KiB
TypeScript
210 lines
6.6 KiB
TypeScript
import { expect, test } from "@playwright/test";
|
|
import { loginAsUser } from "../fixtures/authHelpers";
|
|
import { createPosFixture, mockApi, seedAuthenticatedState } from "../support/network.js";
|
|
import { attachPageHealthGuards, expectBodyHasContent, expectOneVisible, settlePage } from "./helpers";
|
|
|
|
const LOCAL_PROD_BASE_URL = "http://127.0.0.1:4173";
|
|
const LOGIN_URL = /\/login(?:\?.*)?$/;
|
|
const POS_PERMISSIONS = [
|
|
"admin",
|
|
"department_access_12",
|
|
"edit_order_items",
|
|
"get_user",
|
|
"list_customer_notes",
|
|
"list_customer_attributes",
|
|
"get_custom_prices_other",
|
|
];
|
|
|
|
async function gotoHealthyRoute(page, path: string) {
|
|
await page.goto(path);
|
|
await settlePage(page);
|
|
await expectBodyHasContent(page);
|
|
await expect(page.locator("body")).not.toContainText(/404/i);
|
|
}
|
|
|
|
async function seedAuthenticatedRole(
|
|
page,
|
|
{
|
|
token,
|
|
permissions,
|
|
sessionData = {},
|
|
pos = undefined,
|
|
}: {
|
|
token: string;
|
|
permissions: string[];
|
|
sessionData?: Record<string, unknown>;
|
|
pos?: unknown;
|
|
}
|
|
) {
|
|
await mockApi(page, {
|
|
authenticated: true,
|
|
permissions,
|
|
sessionData,
|
|
pos,
|
|
});
|
|
await seedAuthenticatedState(page, token);
|
|
}
|
|
|
|
test.describe("Local production release gate", () => {
|
|
test.describe("PWA sanity", () => {
|
|
test.use({ serviceWorkers: "allow" });
|
|
|
|
test("PWA bootstrap registers on the production build", async ({ page }, testInfo) => {
|
|
test.skip(
|
|
!testInfo.project.name.startsWith("chromium"),
|
|
"Service worker registration is release-gated on Chromium where Playwright exposes stable registrations."
|
|
);
|
|
|
|
const guards = attachPageHealthGuards(page, LOCAL_PROD_BASE_URL);
|
|
|
|
await mockApi(page, { authenticated: false });
|
|
|
|
await gotoHealthyRoute(page, "/");
|
|
await expect(page.getByTestId("landing-title")).toContainText("Truck Wash");
|
|
|
|
await page.waitForFunction(
|
|
async () => {
|
|
const registrations = await navigator.serviceWorker.getRegistrations();
|
|
return registrations.some((registration) =>
|
|
Boolean(registration.active || registration.installing || registration.waiting)
|
|
);
|
|
},
|
|
undefined,
|
|
{ timeout: 20_000 }
|
|
);
|
|
|
|
await guards.expectHealthy();
|
|
guards.dispose();
|
|
});
|
|
});
|
|
|
|
test.describe("Mocked local-prod browser coverage", () => {
|
|
test.use({ serviceWorkers: "block" });
|
|
|
|
test("public shell routes render on the production build", async ({ page }) => {
|
|
const guards = attachPageHealthGuards(page, LOCAL_PROD_BASE_URL);
|
|
|
|
await mockApi(page, {
|
|
authenticated: false,
|
|
selfServe: true,
|
|
});
|
|
|
|
await gotoHealthyRoute(page, "/");
|
|
await expect(page.getByTestId("landing-title")).toContainText("Truck Wash");
|
|
|
|
const manifestHref = await page.locator('link[rel="manifest"]').first().getAttribute("href");
|
|
expect(manifestHref).toBeTruthy();
|
|
const manifestResponse = await page.request.get(new URL(manifestHref!, LOCAL_PROD_BASE_URL).toString());
|
|
expect(manifestResponse.ok()).toBeTruthy();
|
|
|
|
await page.reload();
|
|
await settlePage(page);
|
|
await expect(page.getByTestId("landing-title")).toBeVisible();
|
|
|
|
for (const path of ["/about-us", "/privacy-policy", "/guest/home", "/guest/book/wash"]) {
|
|
await gotoHealthyRoute(page, path);
|
|
}
|
|
|
|
await guards.expectHealthy();
|
|
guards.dispose();
|
|
});
|
|
|
|
test("auth routes render and protected routes redirect when unauthenticated", async ({ page }) => {
|
|
const guards = attachPageHealthGuards(page, LOCAL_PROD_BASE_URL);
|
|
|
|
await mockApi(page, {
|
|
authenticated: false,
|
|
selfServe: true,
|
|
});
|
|
|
|
await gotoHealthyRoute(page, "/login");
|
|
await expect(page.getByTestId("login-submit")).toBeVisible();
|
|
|
|
await gotoHealthyRoute(page, "/login/driver");
|
|
await expect(page.locator('button[id="subuser-login-button"]')).toBeVisible();
|
|
|
|
await gotoHealthyRoute(page, "/admin/login");
|
|
await expect(page.locator('button[id="operator_login_button"]')).toBeVisible();
|
|
|
|
for (const path of ["/user", "/admin/12/modules/pos", "/superuser"]) {
|
|
await page.goto(path);
|
|
await settlePage(page);
|
|
await expect(page).toHaveURL(LOGIN_URL);
|
|
await expect(page.getByTestId("login-submit")).toBeVisible();
|
|
}
|
|
|
|
await guards.expectHealthy();
|
|
guards.dispose();
|
|
});
|
|
|
|
test("seeded user flow reaches dashboard, profile, and bookings", async ({ page }) => {
|
|
const guards = attachPageHealthGuards(page, LOCAL_PROD_BASE_URL);
|
|
|
|
await mockApi(page, {
|
|
authenticated: true,
|
|
permissions: ["user"],
|
|
sessionData: {
|
|
display_name: "Release User",
|
|
},
|
|
});
|
|
|
|
await loginAsUser(page, {
|
|
customerNumber: "release-user",
|
|
password: "release-password",
|
|
twoFactorAuthentication: false,
|
|
});
|
|
|
|
await expect(page.locator("#book-wash-button")).toBeVisible();
|
|
await expect(page.locator("#download-invoices-button")).toBeVisible();
|
|
|
|
await gotoHealthyRoute(page, "/user/profile");
|
|
await expect(page.locator(".card-header").first()).toBeVisible();
|
|
|
|
await gotoHealthyRoute(page, "/user/bookings");
|
|
await expect(page.locator(".title").first()).toBeVisible();
|
|
|
|
await guards.expectHealthy();
|
|
guards.dispose();
|
|
});
|
|
|
|
test("seeded department admin flow renders the POS shell", async ({ page }) => {
|
|
const guards = attachPageHealthGuards(page, LOCAL_PROD_BASE_URL);
|
|
|
|
await seedAuthenticatedRole(page, {
|
|
token: "release-admin-token",
|
|
permissions: POS_PERMISSIONS,
|
|
sessionData: {
|
|
display_name: "Release Admin",
|
|
},
|
|
pos: createPosFixture(),
|
|
});
|
|
|
|
await gotoHealthyRoute(page, "/admin/12/modules/pos");
|
|
await expectOneVisible([page.getByTestId("pos-step-1"), page.getByTestId("pos-mobile-step-1-shell")]);
|
|
|
|
await guards.expectHealthy();
|
|
guards.dispose();
|
|
});
|
|
|
|
test("seeded superuser flow renders the vehicles page", async ({ page }) => {
|
|
const guards = attachPageHealthGuards(page, LOCAL_PROD_BASE_URL);
|
|
|
|
await seedAuthenticatedRole(page, {
|
|
token: "release-superuser-token",
|
|
permissions: ["superuser", "user"],
|
|
sessionData: {
|
|
display_name: "Release Superuser",
|
|
},
|
|
});
|
|
|
|
await gotoHealthyRoute(page, "/superuser/vehicles");
|
|
await expect(page.locator("h2.title").first()).toBeVisible();
|
|
await expect(page.locator("body")).toContainText(/registrerede/i);
|
|
await expect(page.locator("body")).not.toContainText(/Order ID is required/i);
|
|
|
|
await guards.expectHealthy();
|
|
guards.dispose();
|
|
});
|
|
});
|
|
});
|