---
name: md-cursor-e2e
description: >
  Use when user invokes /md-cursor-e2e, asks to write new Playwright E2E tests,
  debug failing specs, or add test coverage for a Multideal feature. Also when
  tests are flaky and need cursor-agent to diagnose and fix.
---

# Multideal cursor-agent E2E

cursor-agent does all test work — writes, runs, debugs, fixes. Claude scopes task, reads output, judges correctness, re-instructs if needed.

**REQUIRED:** Read `md-verify` for auth patterns, selectors, hard-won lessons.

---

## cursor-agent invocation

**NEVER** `run_in_background: true` — Claude must read output to know when done.
Run foreground via `ctx_execute` (no timeout ceiling):

```
mcp__plugin_context-mode_context-mode__ctx_execute(
  language: "shell",
  code: `/home/user/Projects/multideal/.claude/skills/md-cursor-e2e/ca.sh --workspace /home/user/Projects/multideal/apps/web --trust "PROMPT" --task-slug "<task-slug>"`
)
```

- `--task-slug` is the test/feature identifier (e.g., "checkout-flow", "vendor-onboard") — appended to log filename for easy monitoring
- cursor-agent has full tool access: reads, writes files, runs shell commands

---

## Your role (Claude)

1. Scope task → write cursor-agent prompt
2. Run cursor-agent → read output
3. Verify: correct spec? Tests pass?
4. Tests failed or spec wrong → re-instruct cursor-agent with specific fix
5. Repeat until tests pass and behavior correct

Never write test code. Never run playwright.

---

## Phase 0 — Scope (Claude)

Before dispatching:
1. Read existing specs in `tests/e2e/` — check if area already covered
2. Decide localhost vs live: **default localhost** (no budget). Live only for deployed-specific behavior (live payments, CSP headers, Firebase OTP)
3. Identify auth role: customer / vendor / admin

---

## Phase 1 — Write + Run (cursor-agent)

Dispatch cursor-agent to write spec AND run it:

```
You are writing and running Playwright E2E tests for the Multideal project —
a Hebrew-first PWA marketplace. Your job: write the spec, then run it, then
report results.

## Workspace layout (relative to apps/web/)
- tests/e2e/            — all spec files
- tests/e2e/fixtures/   — auth-helper.ts, seed-live-upsert.ts
- tests/e2e/_utils/     — index.ts (shared helpers)
- tests/e2e/_live-guard.mjs — import at top of any spec hardcoding dev.multi.deal URLs
- playwright.config.ts        — localhost (default, no budget cost)
- playwright.live.config.ts   — dev.multi.deal (set ALLOW_LIVE_E2E=1)

## Auth — NEVER call /api/auth/login-email (WAF blocks in tests)
  import { injectUser1Session, injectVendorSession, injectAdminSession } from './fixtures/auth-helper';
  await injectUser1Session(context);   // customer
  await injectVendorSession(context);  // vendor
  await injectAdminSession(context);   // admin

## Hard rules for spec writing
- waitUntil: 'domcontentloaded' — networkidle hangs on CF Worker + PWA
- Selectors: role/label/data-testid — never CSS classes
- Never waitForTimeout — use waitForSelector or condition polls
- RTL app, he-IL locale, Asia/Jerusalem timezone
- Import from @playwright/test, not playwright
- Import paths relative to the spec file location

## After writing the spec, run it:
[LOCALHOST]  pnpm exec playwright test tests/e2e/<FILE>.spec.ts
[LIVE]       ALLOW_LIVE_E2E=1 pnpm exec playwright test tests/e2e/<FILE>.spec.ts --config=playwright.live.config.ts

## Task
<DESCRIBE FEATURE/ROUTE TO TEST AND WHICH AUTH ROLE>

## Report back
- The spec file path you created
- Full test output (pass/fail per test)
- Full error + stack for any failures
- Any assumptions you made
```

---

## Phase 2 — Verify (Claude)

Read cursor-agent output. Check:
- Tests pass? → done (unless behavior looks wrong)
- Tests fail? → Phase 3
- Spec missing coverage? → re-instruct Phase 1 with more specific task

---

## Phase 3 — Fix (cursor-agent)

Send cursor-agent back with failure:

```
You wrote a Playwright spec for Multideal that is now failing.

<paste Phase 1 context block>

## Spec file
tests/e2e/<FILE>.spec.ts

## Failure output
<paste full error + stack>

## Fix rules
- Read the source component or API route the test exercises before changing anything
- Prefer fixing the test (selector, timing, assertion) over app code
- If app code is genuinely broken, call it out explicitly — do NOT silently fix both
- After fixing, re-run the spec and report results

## Report back
- What was wrong
- What you changed (test vs app code)
- Full test output after fix
```

---

## Routing

| User says | Start at |
|-----------|----------|
| "write e2e for /vendor/settings" | Phase 0 → 1 |
| "fix failing e2e tests" | Phase 1 with existing spec + run instruction |
| "tests are flaky" | Phase 3 with flakiness description + spec path |
| "add coverage for checkout" | Phase 0 → 1 |

---

## Quick reference

| Thing | Path |
|-------|-------|
| Auth helper | `tests/e2e/fixtures/auth-helper.ts` |
| Live guard | `tests/e2e/_live-guard.mjs` |
| Run (local) | `pnpm exec playwright test <spec>` |
| Run (live) | `ALLOW_LIVE_E2E=1 pnpm exec playwright test <spec> --config=playwright.live.config.ts` |
| Regression baseline | `MODE=baseline bash tests/e2e/visual-regression/run.sh` |
| Regression compare | `bash tests/e2e/visual-regression/run.sh` |
| Baseline PNGs | `tests/e2e/visual-regression/visual-regression.spec.ts-snapshots/` |

## Regression Baseline

Before dispatching cursor-agent (or any agent) for UI changes, capture a visual baseline against `dev.multi.deal`:

```bash
cd apps/web
MODE=baseline bash tests/e2e/visual-regression/run.sh
```

After deploy, run compare to detect regressions (default `MODE=compare`):

```bash
cd apps/web
bash tests/e2e/visual-regression/run.sh
```

Baseline PNGs live in `tests/e2e/visual-regression/visual-regression.spec.ts-snapshots/` (Playwright `toHaveScreenshot`). On failure, actual/diff PNGs are in `test-results/`. Requires `ALLOW_LIVE_E2E=1` (set by `run.sh`).
## Learned Rules

### ctx-execute-language-shell | fired:1 | 2026-06-10
`ctx_execute(language:"bash", ...)` → wrong, rejected: enum has no "bash". Use `language:"shell"`.
Prevent: always pass `language:"shell"` when running ca.sh / any shell via ctx_execute (valid enum: javascript|typescript|python|shell|ruby|go|rust|php|perl|r|elixir|csharp).
