import { expect, test } from "@playwright/test"; import { captureBrowserFailures, gotoLiveView, loginWithPassword, projectEmail, } from "./helpers"; async function submitSupportRequest( page: import("@playwright/test").Page, requesterEmail: string, kind: "privacy_request" | "data_export", subject: string, details: string, ): Promise { await page.goto("/support"); await page.getByLabel("What do you need help with?").selectOption(kind); await expect(page.getByLabel("Contact email")).toHaveValue(requesterEmail); await expect(page.getByLabel("Contact email")).toHaveAttribute( "readonly", "", ); await page.getByLabel("Subject").fill(subject); await page.getByLabel("Describe the problem").fill(details); await page.getByRole("button", { name: "Send support request" }).click(); await expect(page).toHaveURL(/\/support\/received\?reference=SUP-/); await expect( page.getByRole("heading", { name: "Support request created" }), ).toBeVisible(); } test.skip( process.env.E2E_PRODUCTION_RUN_SCOPED !== "1", "This support intake and staff queue check requires the production run-scoped fixture", ); test("run-scoped support intake and legal fixture reach production staff", async ({ browser, }, testInfo) => { const runID = process.env.E2E_RUN_ID; const fixturePassword = process.env.E2E_FIXTURE_PASSWORD; const adminEmail = process.env.E2E_ADMIN_EMAIL ?? projectEmail("admin", testInfo.project.name); const requesterEmail = projectEmail("requester", testInfo.project.name); if (!runID || !fixturePassword) { throw new Error("E2E_RUN_ID and E2E_FIXTURE_PASSWORD are required"); } const supportSubject = `Production E2E support ${runID}`; const supportDetails = "Run-scoped read-only browser fixture for the production support queue."; const privacySubject = `Production E2E privacy ${runID}`; const dataExportSubject = `Production E2E data export ${runID}`; const accountDeletionSubject = "Delete my Who Need Help account"; const removalExplanation = "Run-scoped read-only browser fixture for the production legal review queue."; const takeItDownExplanation = "Run-scoped read-only browser fixture for the production TAKE IT DOWN queue."; const removalReference = `REM-E2E-${runID.toUpperCase()}`; const takeItDownReference = `REM-E2E-TID-${runID.toUpperCase()}`; const requester = await loginWithPassword( browser, requesterEmail, fixturePassword, ); const admin = await loginWithPassword(browser, adminEmail, fixturePassword); const assertRequesterClean = captureBrowserFailures(requester.page); const assertAdminClean = captureBrowserFailures(admin.page); await submitSupportRequest( requester.page, requesterEmail, "privacy_request", privacySubject, "Run-scoped production browser verification for the authenticated privacy-request intake.", ); await submitSupportRequest( requester.page, requesterEmail, "data_export", dataExportSubject, "Run-scoped production browser verification for the authenticated data-export intake.", ); await requester.page.goto("/account/delete"); await expect(requester.page.getByLabel("Account email")).toHaveValue( requesterEmail, ); await expect(requester.page.getByLabel("Account email")).toHaveAttribute( "readonly", "", ); await requester.page .getByLabel("Additional information") .fill( "Run-scoped production browser verification for the account-deletion support workflow.", ); await requester.page .getByRole("button", { name: "Request account deletion" }) .click(); await expect(requester.page).toHaveURL(/\/support\/received\?reference=SUP-/); await gotoLiveView(admin.page, "/support/operations?queue=support"); await admin.page .locator("#support-case-filters") .getByLabel("Search") .fill(requesterEmail); const supportRows = admin.page.locator("main tbody tr"); await expect(supportRows).toHaveCount(4); await expect(supportRows.filter({ hasText: privacySubject })).toHaveCount(1); await expect(supportRows.filter({ hasText: dataExportSubject })).toHaveCount( 1, ); await expect( supportRows.filter({ hasText: accountDeletionSubject }), ).toHaveCount(1); await admin.page .locator("#support-case-filters") .getByLabel("Search") .fill(supportSubject); const supportRow = admin.page .locator("main tbody tr") .filter({ hasText: supportSubject }); await expect(supportRow).toHaveCount(1); await supportRow.getByRole("link", { name: "Open" }).click(); await expect( admin.page.getByRole("heading", { name: supportSubject }), ).toBeVisible(); await expect( admin.page.getByText(supportDetails, { exact: true }), ).toBeVisible(); await gotoLiveView(admin.page, "/support/operations?queue=legal"); await admin.page .locator("#legal-case-filters") .getByLabel("Search") .fill(removalReference); const generalLegalRow = admin.page.locator("main tbody tr"); await expect(generalLegalRow).toHaveCount(1); await expect(generalLegalRow).toContainText("general"); await generalLegalRow.getByRole("link", { name: "Open" }).click(); await expect( admin.page.getByText(removalExplanation, { exact: true }), ).toBeVisible(); await gotoLiveView(admin.page, "/support/operations?queue=legal"); await admin.page .locator("#legal-case-filters") .getByLabel("Search") .fill(takeItDownReference); const takeItDownRow = admin.page.locator("main tbody tr"); await expect(takeItDownRow).toHaveCount(1); await expect(takeItDownRow).toContainText(/take it down/i); await expect(takeItDownRow).toContainText("urgent review"); await takeItDownRow.getByRole("link", { name: "Open" }).click(); await expect( admin.page.getByText(takeItDownExplanation, { exact: true }), ).toBeVisible(); assertRequesterClean(); assertAdminClean(); await requester.context.close(); await admin.context.close(); });