# 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: client/marketing.spec.ts >> Marketing & Public Pages >> TC-C-01: Homepage loads correctly
- Location: tests/e2e/client/marketing.spec.ts:4:3

# Error details

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

Locator: getByRole('heading', { name: /Three steps/i }).first()
Expected: visible
Timeout: 10000ms
Error: element(s) not found

Call log:
  - Expect "toBeVisible" with timeout 10000ms
  - waiting for getByRole('heading', { name: /Three steps/i }).first()

```

```yaml
- banner:
  - link "Pax Psychology":
    - /url: /
    - text: Pax Psychology.
  - navigation:
    - link "How it works":
      - /url: /#how
    - link "Who we help":
      - /url: /#who
    - link "Find a psychologist":
      - /url: /psychologists
    - link "Journal":
      - /url: /journal
  - link "Sign in":
    - /url: /auth/login
  - link "Book a session":
    - /url: /onboarding
- main:
  - text: 500 This one really is on us Error 500 · Something broke
  - heading "Something broke on our end." [level=1]
  - paragraph: That's on us, not you. We've already been pinged about it and someone's onto it. Give it a minute, then have another go.
  - button "Try again"
  - link "Back to home":
    - /url: /
  - paragraph: Still stuck?
  - link "Check service status":
    - /url: /contact
  - link "Tell us what happened":
    - /url: /contact
- contentinfo:
  - paragraph:
    - strong: If you're not safe right now
    - text: ", please call Lifeline on"
    - strong: 13 11 14
    - text: or
    - strong: "000"
    - text: . Pax Psychology isn't a crisis service; your psychologist can help with the rest, just not this minute.
  - text: Pax Psychology.
  - paragraph: Life happens. It's good to talk about it.
  - heading "For you" [level=5]
  - list:
    - listitem:
      - link "How it works":
        - /url: /#how
    - listitem:
      - link "Find a psychologist":
        - /url: /psychologists
    - listitem:
      - link "Pricing & rebates":
        - /url: /faqs
    - listitem:
      - link "FAQ":
        - /url: /faqs
  - heading "For psychologists" [level=5]
  - list:
    - listitem:
      - link "Join Pax Psychology":
        - /url: /for-psychs
    - listitem:
      - link "How we vet":
        - /url: /for-psychs
    - listitem:
      - link "Practitioner portal":
        - /url: /dashboard
  - heading "Pax Psychology" [level=5]
  - list:
    - listitem:
      - link "About":
        - /url: /our-story
    - listitem:
      - link "Journal":
        - /url: /journal
    - listitem:
      - link "For business":
        - /url: /for-business
    - listitem:
      - link "Privacy":
        - /url: /privacy-policy
    - listitem:
      - link "Contact":
        - /url: /contact
  - text: © 2026 Pax Psychology Pty Ltd · Naarm / Melbourne Made with care on unceded land.
- heading "Are cookies alright with you?" [level=2]
- paragraph:
  - text: We're all about vulnerability. So, we're letting you know that we store info about how our visitors use our website for improvements. Review our
  - link "privacy policy":
    - /url: /privacy-policy
  - text: and click accept below.
- button "Accept"
- button "Cancel"
- alert
```

# Test source

```ts
  1   | import { test, expect } from "@playwright/test";
  2   | 
  3   | test.describe("Marketing & Public Pages", () => {
  4   |   test("TC-C-01: Homepage loads correctly", async ({ page }) => {
  5   |     await page.goto("/");
  6   | 
  7   |     // How it works section (kit: "Three steps. No waiting rooms.")
  8   |     await expect(
  9   |       page.getByRole("heading", { name: /Three steps/i }).first(),
> 10  |     ).toBeVisible({ timeout: 10000 });
      |       ^ Error: expect(locator).toBeVisible() failed
  11  | 
  12  |     // Who we help section (kit: "Mostly grown-ups figuring it out.")
  13  |     await expect(
  14  |       page.getByRole("heading", { name: /Mostly grown-ups/i }).first(),
  15  |     ).toBeVisible();
  16  | 
  17  |     // Footer has privacy link
  18  |     await expect(
  19  |       page.getByRole("contentinfo").getByRole("link", { name: /privacy/i }),
  20  |     ).toBeVisible();
  21  |   });
  22  | 
  23  |   test("TC-C-01: Homepage mobile responsiveness", async ({ page }) => {
  24  |     await page.setViewportSize({ width: 375, height: 812 });
  25  |     await page.goto("/");
  26  |     await expect(page.locator("body")).toBeVisible();
  27  |   });
  28  | 
  29  |   test("TC-C-02: Our Story page", async ({ page }) => {
  30  |     await page.goto("/our-story");
  31  | 
  32  |     await expect(
  33  |       page
  34  |         .getByRole("heading", { name: /How Pax Psychology started/i })
  35  |         .first(),
  36  |     ).toBeVisible({ timeout: 10000 });
  37  |     await expect(
  38  |       page.getByText(/one in finance, one in psychology/i).first(),
  39  |     ).toBeVisible();
  40  |   });
  41  | 
  42  |   test("TC-C-03: For Business page", async ({ page }) => {
  43  |     await page.goto("/for-business");
  44  | 
  45  |     await expect(
  46  |       page
  47  |         .getByRole("heading", {
  48  |           name: /Look after the people who look after the work/i,
  49  |         })
  50  |         .first(),
  51  |     ).toBeVisible({ timeout: 10000 });
  52  |   });
  53  | 
  54  |   test("TC-C-04: Contact page form loads and accepts input", async ({
  55  |     page,
  56  |   }) => {
  57  |     await page.goto("/contact");
  58  | 
  59  |     // Dismiss cookie banner if present
  60  |     const cookieAccept = page.getByRole("button", { name: /accept/i }).first();
  61  |     if (await cookieAccept.isVisible({ timeout: 2000 }).catch(() => false)) {
  62  |       await cookieAccept.click();
  63  |     }
  64  | 
  65  |     // Verify contact form is visible
  66  |     await expect(
  67  |       page.getByRole("heading", { name: /contact us/i }).first(),
  68  |     ).toBeVisible({ timeout: 10000 });
  69  | 
  70  |     // Fill in the form using placeholders
  71  |     await page.getByPlaceholder(/name/i).first().fill("Test User");
  72  |     await page.getByPlaceholder(/email/i).first().fill("testuser@example.com");
  73  |     await page.getByPlaceholder(/phone/i).first().fill("0412 345 678");
  74  |     await page
  75  |       .getByPlaceholder(/message/i)
  76  |       .first()
  77  |       .fill("Staging test.");
  78  | 
  79  |     // Submit button exists. It stays disabled until the Turnstile CAPTCHA is
  80  |     // solved (when configured), so only click when it's enabled.
  81  |     const submitBtn = page.getByRole("button", { name: /submit/i }).first();
  82  |     await expect(submitBtn).toBeVisible();
  83  |     if (await submitBtn.isEnabled()) {
  84  |       await submitBtn.click();
  85  |       // Verify success message or that the form is still present
  86  |       await expect(
  87  |         page
  88  |           .getByText(/thanks|thank you/i)
  89  |           .first()
  90  |           .or(submitBtn),
  91  |       ).toBeVisible({ timeout: 10000 });
  92  |     }
  93  |   });
  94  | 
  95  |   test("TC-C-05: Privacy Policy and Terms of Use pages", async ({ page }) => {
  96  |     await page.goto("/privacy-policy");
  97  |     await expect(
  98  |       page.getByRole("heading", { name: /privacy policy/i }).first(),
  99  |     ).toBeVisible({ timeout: 10000 });
  100 | 
  101 |     await page.goto("/terms-of-use");
  102 |     await expect(
  103 |       page.getByRole("heading", { name: /terms/i }).first(),
  104 |     ).toBeVisible({ timeout: 10000 });
  105 |   });
  106 | 
  107 |   test("TC-C-06: Newsletter signup from the journal strip", async ({
  108 |     page,
  109 |   }) => {
  110 |     // The newsletter form moved off the footer to the dark strip on /journal
```