import { expect, test } from "@playwright/test"; import { loginAsOperator, loginAsUser } from "../fixtures/authHelpers"; import { attachPageHealthGuards, expectOneVisible, requiredEnv, settlePage } from "./helpers"; const requiredCredentialNames = [ "PLAYWRIGHT_BASE_URL", "PLAYWRIGHT_USER_CUSTOMER_NUMBER", "PLAYWRIGHT_USER_PASSWORD", "PLAYWRIGHT_OPERATOR_USER_ID", "PLAYWRIGHT_OPERATOR_PASSWORD", ]; const roleSmokeEnabled = requiredCredentialNames.every((name) => Boolean(process.env[name])); const requireLiveCredentials = process.env.PLAYWRIGHT_REQUIRE_LIVE_CREDENTIALS === "true"; function getLiveSettings() { return { baseURL: requiredEnv("PLAYWRIGHT_BASE_URL"), customerCredentials: { customerNumber: requiredEnv("PLAYWRIGHT_USER_CUSTOMER_NUMBER"), password: requiredEnv("PLAYWRIGHT_USER_PASSWORD"), otpSecret: process.env.PLAYWRIGHT_USER_OTP_SECRET || "", twoFactorAuthentication: Boolean(process.env.PLAYWRIGHT_USER_OTP_SECRET), }, operatorCredentials: { userId: requiredEnv("PLAYWRIGHT_OPERATOR_USER_ID"), password: requiredEnv("PLAYWRIGHT_OPERATOR_PASSWORD"), }, departmentId: Number.parseInt(process.env.PLAYWRIGHT_DEPARTMENT_ID || "12", 10), }; } test.describe.configure({ mode: "serial" }); test.describe("@role-live credentialed live smoke release gate", () => { test.skip( !roleSmokeEnabled && !requireLiveCredentials, "Set seeded live credentials to run credentialed role smoke tests." ); test.beforeAll(() => { if (!requireLiveCredentials || roleSmokeEnabled) { return; } const missing = requiredCredentialNames.filter((name) => !process.env[name]); throw new Error(`Missing required live credential environment variables: ${missing.join(", ")}`); }); test("customer login reaches dashboard, profile, and bookings", async ({ page }) => { const { baseURL, customerCredentials } = getLiveSettings(); const guards = attachPageHealthGuards(page, baseURL); await loginAsUser(page, customerCredentials); await expect(page.locator("#book-wash-button")).toBeVisible(); await expect(page.locator("#download-invoices-button")).toBeVisible(); await page.goto("/user/profile"); await settlePage(page); await expect(page).toHaveURL(/\/user\/profile(?:\?.*)?$/); await expect(page.locator(".card-header").first()).toBeVisible(); await page.goto("/user/bookings"); await settlePage(page); await expect(page).toHaveURL(/\/user\/bookings(?:\?.*)?$/); await expect(page.locator(".title").first()).toBeVisible(); await guards.expectHealthy(); guards.dispose(); }); test("operator login reaches the seeded department route", async ({ page }) => { const { baseURL, operatorCredentials, departmentId } = getLiveSettings(); const guards = attachPageHealthGuards(page, baseURL); await loginAsOperator(page, operatorCredentials); await page.goto(`/admin/${departmentId}/modules/pos`); await settlePage(page); await expect(page).toHaveURL(new RegExp(`/admin/${departmentId}/modules/pos(?:\\?.*)?$`)); await expectOneVisible([page.getByTestId("pos-step-1"), page.getByTestId("pos-mobile-step-1-shell")]); await guards.expectHealthy(); guards.dispose(); }); });