| Duration | ~55 min in the lesson + ~30 min homework |
| Prerequisites | Checkpoint lesson-8.3. |
| Checkpoint | lesson-8.4 |
What you will have
The project has Playwright end-to-end tests for the lead path and the admin login. They run against a safe local copy wired to a separate test database, pass on a clean run, and fail when the form is deliberately broken.
Video
The video for this lesson is not recorded yet.
Prompts used in this lesson
Part 4 — The test environment and the tests
Purpose: catch a broken lead form or admin login before visitors do. Write end-to-end tests with Playwright for the two paths that matter most. Context: Playwright is installed (playwright.config.ts, tests folder e2e/). I created a second Supabase project for tests and a file .env.e2e. Read .env.local for variable NAMES only and tell me which names .env.e2e must contain; I will fill in the values myself. Never print values from either file. Before writing code: read the current Playwright documentation for the webServer option, for authentication with a setup project and storage state, and for locators. Tell me which pages you read. Safe target (most important): 1. Tests run only against a local server that Playwright starts itself on port 3100 with the values from .env.e2e, and never reuse an already running server. 2. That server uses the test Supabase project. Apply all migrations in supabase/migrations/ to it and create the admin test user from the credentials in .env.e2e. 3. In the test environment these stay empty and the code must skip them without errors: email, Telegram, Meta Conversions API, Google Ads conversions, the Claude API key, the GTM container ID. Check each code path and tell me if any would still send something. 4. Turnstile uses Cloudflare's documented always-pass dummy keys. 5. A guard that stops the whole run before the first test if the base URL is not localhost, or if the Supabase URL equals the one in .env.local. 6. .env.e2e and Playwright's saved login state are in .gitignore. Tests: A. Lead path: open the landing page, fill the form with a unique test email, submit, arrive on /thank-you. Sign in to the admin, find that lead in /admin/leads, open its card, change its status to "contacted", and confirm the change appears in the status history. B. Admin login: signed out, /admin redirects to /admin/login; a wrong password shows an error and does not sign in; the right password opens the admin. Also: delete the example test; add npm scripts "test:e2e" and "test:e2e:ui"; add the commands and the rule "run test:e2e before pushing" to CLAUDE.md. Constraints: do not change application behaviour to make a test pass. If the rate limit or anything else in the app blocks the tests, stop and explain the options to me. Find elements by their labels and roles, the way a visitor would. Done when: you have run the tests three times in a row with all passing, shown me the output, and confirmed by a row count that the production database received nothing. Report anything you could not verify.
Part 5 — Break it on purpose
The end-to-end test for the lead path fails. The output is in the terminal and the report is in playwright-report/. Find the cause in the application and explain it to me in one sentence before changing anything. Fix the cause, not the test: do not edit files in e2e/, do not loosen an assertion, do not add retries or waits. Then run the full test suite and show me the result.
Do along
Work on your own project and pause the video where a step says so.
- Pause after Part 2. Check
node --versionagainst Playwright's supported versions. - Create a second Supabase project for tests. Create the admin test user's credentials (a new password).
- Pause after Part 3. Run
npm init playwright@latestwith the answers from Part 3, thennpx playwright testandnpx playwright show-report. - Pause after Part 4. Run the prompt from Part 4. When Claude lists the variable names, create
.env.e2eand fill in the test project's values yourself. If your form has different fields or your first pipeline stage afternewhas another name, say so in the prompt. - Watch the lead-path test in UI mode.
- Pause after Part 5. Break the form by hand (misspell one field name), run the tests, read the report.
- Use the fix prompt from Part 5. Check that the diff does not touch
e2e/. - After Part 6, run
npm run test:e2eonce more, then commit and tag with the commands under "Recap and next".
Check your work
- Run
npm run test:e2e. Expected: all tests pass. - Open your production CRM. Expected: no new test lead; no test email or Telegram message arrived.
- Misspell a form field name, run the tests. Expected: the lead-path test fails. Undo with
git restoreon that file; run again: pass.
Common problems
- The run stops at once with the guard's message →
.env.e2eholds production values or is incomplete → correct the values; this is the guard doing its job. - The form test fails at the Turnstile step → real Turnstile keys are in the test file → use Cloudflare's dummy always-pass keys from its testing page.
- A real email or Telegram message arrived during a test → a notification variable is set in
.env.e2eor the code ignores an empty value → stop, tell Claude which message arrived, have it fix the skip and prove it.
Homework
About 30 minutes, on your own, after the lesson. Lesson 8.5 does not depend on it.
- Learn what your tests see. Break two more things by hand, one at a time: one inside the form (for example the visible label of a field) and one elsewhere on the page (for example a headline or a footer link). Before each run, write down whether you expect a test to fail. Run
npm run test:e2e, then undo withgit restore. Deliverable: a heading "Tests: covered and not covered" indocs/architecture.mdwith, for each break, what you changed, your prediction and the result. Done when: both entries are written,git statusshows no leftover change from the drills, and the tests pass. - One more test of your own. Decide what, after the lead path, would cost your business most if it broke unnoticed: for example, the form showing an error when a required field is empty, or a campaign page under
/lp/loading with its form. Ask Claude for one test of it, with the constraints from the Part 4 prompt: local test environment only, no change to application behaviour, elements found by labels and roles. Then break that thing by hand and watch the new test fail. Done when: the whole suite passes three times in a row and the new test fails on your deliberate break. If you cannot get it reliably green, delete the new test file; a test that fails at random is worse than none.
Commit without a tag: git add -A, git commit -m "Homework 8.4: test coverage notes and one more test", git push.
Save your work
git add -A
git commit -m "Lesson 8.4: Playwright end-to-end tests for lead path and admin login"
git tag lesson-8.4
git push
git push --tags