Adds one comprehensive Playwright test that walks a fresh Operations Manager session through all 8 Demo Guide steps performing the real action at each one, then restores the environment. Writing it surfaced a real desktop layout bug: the Demo Guide's fixed side panel overlapped main content with no reflow, making the return form's "Review return" button unclickable while the guide was open at ordinary viewport widths. Fixed by reserving layout space via a guide-open class. Also adds mobile bottom-sheet, keyboard-reachability, and console-error checks.
104 lines
5.5 KiB
TypeScript
104 lines
5.5 KiB
TypeScript
import { expect, test, type APIRequestContext } from "@playwright/test";
|
|
|
|
async function resetDemoData(request: APIRequestContext) {
|
|
const login = await request.post("/api/v1/demo/login", { data: { role: "operations_manager" } });
|
|
expect(login.ok()).toBeTruthy();
|
|
const reset = await request.post("/api/v1/demo/reset");
|
|
expect(reset.ok()).toBeTruthy();
|
|
}
|
|
|
|
test.describe.configure({ mode: "serial" });
|
|
|
|
test("full guided demo walkthrough, start to finish, restoring the environment after", async ({
|
|
page,
|
|
request,
|
|
}) => {
|
|
await resetDemoData(request);
|
|
|
|
await test.step("start the guided demo from the login screen", async () => {
|
|
await page.goto("/login");
|
|
await page.getByRole("button", { name: "Start begeleide demo" }).click();
|
|
await expect(page).toHaveURL(/\/dashboard/);
|
|
await expect(page.getByRole("dialog", { name: "Gegidste demo" })).toBeVisible();
|
|
});
|
|
|
|
await test.step("step 1: understand the operational state", async () => {
|
|
await expect(page.getByRole("heading", { name: "1. Begrijp de operationele status" })).toBeVisible();
|
|
await expect(page.getByRole("heading", { name: "Fleet readiness" })).toBeVisible();
|
|
await page.getByRole("button", { name: "Volgende" }).click();
|
|
});
|
|
|
|
await test.step("step 2: open the booking needing attention", async () => {
|
|
await expect(page.getByRole("heading", { name: "2. Open een boeking" })).toBeVisible();
|
|
await page.getByRole("button", { name: "Ga naar deze stap" }).click();
|
|
await expect(page).toHaveURL(/\/bookings\/BK-DEMO-RETURN$/);
|
|
await page.getByRole("button", { name: "Volgende" }).click();
|
|
});
|
|
|
|
await test.step("step 3: process the return with the pre-filled odometer anomaly", async () => {
|
|
await expect(page.getByRole("heading", { name: "3. Verwerk een retour" })).toBeVisible();
|
|
await expect(page.getByText("Demonstratiescenario: afwijkende kilometerstand")).toBeVisible();
|
|
await page.getByRole("button", { name: "Review return" }).click();
|
|
await expect(page.getByText(/below.*canonical reading/)).toBeVisible();
|
|
await page.getByRole("button", { name: "Confirm return" }).click();
|
|
await expect(page.getByRole("heading", { name: "Return registered" })).toBeVisible();
|
|
await page.getByRole("button", { name: "Ga verder met de demo" }).click();
|
|
});
|
|
|
|
await test.step("step 4: handle the newly created data-quality issue", async () => {
|
|
await expect(page).toHaveURL(/\/data-quality$/);
|
|
await expect(page.getByRole("heading", { name: "4. Bekijk en behandel" })).toBeVisible();
|
|
const firstIssueLink = page.locator(".data-table tbody tr").first().locator("a");
|
|
await firstIssueLink.click();
|
|
await expect(page.getByText("What's wrong")).toBeVisible();
|
|
// The newest issue is the odometer regression this return just created.
|
|
await page.getByRole("radio", { name: /Retain canonical/ }).check();
|
|
await page.getByRole("button", { name: "Resolve issue" }).click();
|
|
await expect(page.getByText(/Issue .* resolved/)).toBeVisible();
|
|
await page.getByRole("button", { name: "Ga verder met de demo" }).click();
|
|
});
|
|
|
|
await test.step("step 5: review and merge the possible duplicate customer", async () => {
|
|
await expect(page).toHaveURL(/\/data-quality\/DQ-DEMO-DUPLICATE$/);
|
|
await expect(page.getByRole("heading", { name: "5. Beoordeel en behandel" })).toBeVisible();
|
|
await page.getByRole("button", { name: /^Merge into/ }).click();
|
|
await page.getByRole("button", { name: "Yes, merge" }).click();
|
|
await expect(page.getByText(/Issue .* resolved/)).toBeVisible();
|
|
await page.getByRole("button", { name: "Ga verder met de demo" }).click();
|
|
});
|
|
|
|
await test.step("step 6: ask the procedure assistant a question", async () => {
|
|
await expect(page).toHaveURL(/\/knowledge$/);
|
|
await expect(page.getByRole("heading", { name: "6. Stel een vraag" })).toBeVisible();
|
|
await page.getByRole("button", { name: "What must I do when a vehicle returns with damage?" }).click();
|
|
await expect(page.getByText("Grounded in cited procedures")).toBeVisible();
|
|
await page.getByRole("button", { name: "Volgende" }).click();
|
|
});
|
|
|
|
await test.step("step 7: check automation and the audit trail", async () => {
|
|
await expect(page.getByRole("heading", { name: "7. Controleer automatisering" })).toBeVisible();
|
|
await page.getByRole("button", { name: "Ga naar deze stap" }).click();
|
|
await expect(page).toHaveURL(/\/automation$/);
|
|
// Plain-language status only -- never the raw backend state string (e.g. "degraded").
|
|
await expect(page.locator(".integration-cards")).not.toContainText("degraded");
|
|
await expect(page.locator(".integration-cards")).not.toContainText("no_evidence");
|
|
await page.goto("/audit");
|
|
await expect(page.locator(".data-table tbody tr").first()).toBeVisible();
|
|
await page.getByRole("button", { name: /Demo-gids/ }).click();
|
|
await page.getByRole("button", { name: "Volgende" }).click();
|
|
});
|
|
|
|
await test.step("step 8: review what's real, simulated, or not yet connected", async () => {
|
|
await expect(page.getByRole("heading", { name: "8. Bekijk wat echt is" })).toBeVisible();
|
|
await page.getByRole("button", { name: "Ga naar deze stap" }).click();
|
|
await expect(page).toHaveURL(/\/about$/);
|
|
await expect(page.getByRole("heading", { name: "Wat MobilityOps wel en niet is" })).toBeVisible();
|
|
await expect(page.getByText("Demomodus", { exact: false }).first()).toBeVisible();
|
|
await expect(page.getByText("Niet gekoppeld").first()).toBeVisible();
|
|
});
|
|
|
|
await test.step("restore the environment", async () => {
|
|
await resetDemoData(request);
|
|
});
|
|
});
|