# Instructions

- Following Playwright test failed.
- Explain why, be concise, respect Playwright best practices.
- Provide a snippet of code with the fix, if possible.

# Test info

- Name: e2e-qa-chat-security.spec.ts >> AI-016 friendly error on chat failure is not implemented
- Location: test/process-test/e2e-qa-chat-security.spec.ts:78:5

# Error details

```
Error: expect(locator).toBeVisible() failed

Locator: getByText(/try again|error|something went wrong/i)
Expected: visible
Timeout: 5000ms
Error: element(s) not found

Call log:
  - Expect "toBeVisible" with timeout 5000ms
  - waiting for getByText(/try again|error|something went wrong/i)

```

```yaml
- banner:
  - paragraph: Mortgage protection
  - paragraph: Chat stays open · steps 0–8 · licensed agent after 8
  - text: Profile
  - button "Toggle profile" [pressed]
  - text: Progress
  - button "Toggle progress" [pressed]
- complementary:
  - heading "Progress (0–8)" [level=2]
  - list:
    - listitem: 0. Lead intake
    - listitem: 1. Lock intent
    - listitem: 2. Demographics & loan facts
    - listitem: 3. Build + tobacco
    - listitem: 4. Disease interview
    - listitem: 5. Spouse / income
    - listitem: 6. Soft decision
    - listitem: 7. Carrier shortlist
    - listitem: 8. Hand off to licensed agent
  - paragraph: Lead intake
  - paragraph: "Goal / exit: Contactable person + state"
  - paragraph: "Missing: name_or_phone, state"
- text: Hi — I can help with U.S. mortgage protection (life insurance that can pay off or cover a home loan). What’s your name, and which U.S. state is the mortgage in?
- textbox "Chat message":
  - /placeholder: Type a message…
- button "Send"
- complementary:
  - heading "Applicant profile" [level=2]
  - heading "Mortgage" [level=3]
  - text: O loan_balance — O loan_term_years — O coverage_on_whom — O co_borrower_flag — O property_state —
  - heading "Demographics" [level=3]
  - text: R name We’ll ask this next. O phone — O age / DOB — O sex — R state We’ll ask this next.
  - heading "BMI" [level=3]
  - text: O height_ft_in — O weight_lb — O bmi_computed —
  - heading "Tobacco" [level=3]
  - text: O tobacco_products —
  - heading "Diseases" [level=3]
  - text: O none / complete — O heart — O diabetes — O cancer — O kidney — O lung — O disabled — O impairments —
  - heading "Household" [level=3]
  - text: O spouse_age_sex — O spouse_annual_income — O beneficiary —
  - heading "Income" [level=3]
  - text: O annual_income — O decision — O carriers —
- alert
```

# Test source

```ts
  1  | import { expect, test } from "@playwright/test";
  2  | import { createCase, sendChat, sendUi, waitForChatReady } from "./helpers";
  3  | 
  4  | test("AI-001 AI-003 chat loads and input is usable", async ({ page }) => {
  5  |   await waitForChatReady(page);
  6  |   const box = page.getByLabel("Chat message");
  7  |   await expect(box).toBeEnabled();
  8  |   await box.click();
  9  |   await box.fill("Hi");
  10 |   await expect(box).toHaveValue("Hi");
  11 | });
  12 | 
  13 | test("AI-004 Send Hi gets a reply and stays on lead intake", async ({ page }) => {
  14 |   await waitForChatReady(page);
  15 |   await sendUi(page, "Hi");
  16 |   await expect(page.getByText("Hi", { exact: true }).first()).toBeVisible();
  17 |   await expect(page.getByTestId("process-current")).toHaveText("Lead intake");
  18 | });
  19 | 
  20 | test("AI-005 Enter submits the chat form", async ({ page }) => {
  21 |   await waitForChatReady(page);
  22 |   const box = page.getByLabel("Chat message");
  23 |   await box.fill("My name is John Smith");
  24 |   await box.focus();
  25 |   await Promise.all([
  26 |     page.waitForResponse(
  27 |       (r) => r.url().includes("/api/mortgage/chat") && r.request().method() === "POST",
  28 |       { timeout: 45_000 }
  29 |     ),
  30 |     page.locator("form").evaluate((form) => (form as HTMLFormElement).requestSubmit()),
  31 |   ]);
  32 |   await expect(page.getByText("John Smith", { exact: true })).toBeVisible();
  33 | });
  34 | 
  35 | test("AI-006 AI-007 empty and whitespace are not submitted", async ({ page }) => {
  36 |   await waitForChatReady(page);
  37 |   const users = page.locator("div.ml-8");
  38 |   await expect(users).toHaveCount(0);
  39 |   await page.getByRole("button", { name: "Send" }).click();
  40 |   await expect(users).toHaveCount(0);
  41 |   await page.getByLabel("Chat message").fill("   ");
  42 |   await page.getByRole("button", { name: "Send" }).click();
  43 |   await expect(users).toHaveCount(0);
  44 | });
  45 | 
  46 | test("AI-009 special characters do not crash chat", async ({ page }) => {
  47 |   await waitForChatReady(page);
  48 |   await sendUi(page, "!@#$%^&*()");
  49 |   await expect(page.getByText("!@#$%^&*()")).toBeVisible();
  50 |   await expect(page.getByLabel("Chat message")).toBeEnabled();
  51 | });
  52 | 
  53 | test("AI-013 single Send shows the user message once", async ({ page }) => {
  54 |   await waitForChatReady(page);
  55 |   await sendUi(page, "My name is Pat Lee");
  56 |   await expect(page.getByText("Pat Lee").first()).toBeVisible();
  57 | });
  58 | 
  59 | test("AI-056 new session does not inherit other case profile", async ({ request, page }) => {
  60 |   const a = await createCase(request);
  61 |   await sendChat(request, a.caseId, "My name is Alice Park");
  62 |   const b = await createCase(request);
  63 |   expect(b.profile.name).toBeFalsy();
  64 |   await page.goto(`/mortgage?case=${b.caseId}`);
  65 |   await expect(page.getByTestId("process-current")).toHaveText("Lead intake");
  66 |   await expect(page.getByText("Alice Park")).toHaveCount(0);
  67 | });
  68 | 
  69 | test("AI-296 script tag renders as text not alert", async ({ page }) => {
  70 |   await waitForChatReady(page);
  71 |   page.on("dialog", () => {
  72 |     throw new Error("XSS dialog must not appear");
  73 |   });
  74 |   await sendUi(page, "<script>alert(1)</script>");
  75 |   await expect(page.getByText("<script>alert(1)</script>")).toBeVisible();
  76 | });
  77 | 
  78 | test("AI-016 friendly error on chat failure is not implemented", async ({ page }) => {
  79 |   test.fail(true, "ChatPane send() has try/finally and no catch / user error UI");
  80 |   await waitForChatReady(page);
  81 |   await page.route("**/api/mortgage/chat", (route) => route.abort());
  82 |   await page.getByLabel("Chat message").fill("Hi");
  83 |   await page.getByRole("button", { name: "Send" }).click();
> 84 |   await expect(page.getByText(/try again|error|something went wrong/i)).toBeVisible({ timeout: 5_000 });
     |                                                                         ^ Error: expect(locator).toBeVisible() failed
  85 | });
  86 | 
```