# Lector Playwright QA — Execution Prompt for Conductor

**Pickup:** Read this file at the start of the session before doing anything else.  
**Spec:** `/home/node/.openclaw/workspace/lector-test-spec.md` — 80+ test cases across 11 sections.  
**Results:** Write to `/home/node/.openclaw/workspace/lector-qa-results.md` as you go.  
**Report back:** Post a summary comment to `rutgersguy/lector#15` when done.

---

## Environment

- **Target URL:** `https://lector.nerdbox.com`
- **Routing:** Hash-based via `wouter`. All client routes are `/#/login`, `/#/`, `/#/review`, `/#/analyze`, `/#/settings`. The server only has one HTML entry point — navigate with the hash.
- **Auth:** Google OAuth only in production. Email/password IS implemented — use that for all automated tests.
- **Admin account:** `broadnax@gmail.com` (Google OAuth — cannot be automated; run admin tests manually or skip)
- **Stripe:** Test mode. Card: `4242 4242 4242 4242`, any future expiry, any CVC.
- **Session cookies:** `Secure; HttpOnly; SameSite=Lax` — tests must run over HTTPS, not localhost.

---

## Playwright Setup

Playwright 1.58.2 + `@playwright/test` are installed in the workspace:

```
/home/node/.openclaw/workspace/node_modules/.bin/playwright
/home/node/.openclaw/workspace/node_modules/@playwright/test
```

Chromium binary: `/home/node/.cache/ms-playwright/chromium-1208/chrome-linux64/chrome`

**Create** `/home/node/.openclaw/workspace/playwright.config.ts` with this content:

```typescript
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  testDir: './tests/lector',
  timeout: 30000,
  retries: 1,
  reporter: [['list'], ['json', { outputFile: 'tests/lector/results.json' }]],
  use: {
    baseURL: 'https://lector.nerdbox.com',
    headless: true,
    launchOptions: {
      executablePath: '/home/node/.cache/ms-playwright/chromium-1208/chrome-linux64/chrome',
      args: ['--no-sandbox', '--disable-setuid-sandbox'],
    },
    screenshot: 'only-on-failure',
    video: 'off',
  },
  projects: [
    { name: 'chromium', use: { ...devices['Desktop Chrome'] } },
  ],
});
```

**Create** `/home/node/.openclaw/workspace/tests/lector/` directory for test files.

**Run command** (from `/home/node/.openclaw/workspace/`):

```bash
node node_modules/.bin/playwright test tests/lector/SECTION.spec.ts --config=playwright.config.ts
```

---

## Test Account Setup

Before running tests, create a fresh test account via the email/password signup flow:

- **Email:** `lector-qa-test@mailinator.com` (or generate `lector-test+<timestamp>@mailinator.com`)
- **Password:** `QaTest2026!`
- This account should be fresh (no prior data) for auth/onboarding tests
- For SRS/review tests, seed cards programmatically via the API first:
  ```bash
  # Login and get session cookie
  curl -s -c /tmp/qa-cookies.txt -X POST https://lector.nerdbox.com/api/auth/login \
    -H "Content-Type: application/json" \
    -d '{"email":"lector-qa-test@mailinator.com","password":"QaTest2026!"}'
  ```

---

## Execution Plan

Run section by section. Use `sessions_spawn` for each section to keep the main session lean:

```
sessions_spawn(task="Run Playwright tests for Section 1 (Auth) per /home/node/.openclaw/workspace/lector-playwright-execution.md", mode="run", runtime="subagent")
```

Collect pass/fail counts from each sub-agent and write them to `lector-qa-results.md`.

### Section order (happy path first):

| # | Section | File | Priority |
|---|---------|------|----------|
| 1 | Authentication & Account Management | `01-auth.spec.ts` | High |
| 2 | Today Tab — Passage & Reading | `02-today.spec.ts` | High |
| 3 | Review Tab — SRS | `03-review.spec.ts` | High |
| 4 | Parse/Analyze Tab | `04-parse.spec.ts` | High |
| 5 | Settings | `05-settings.spec.ts` | Medium |
| 6 | Navigation & Layout | `06-navigation.spec.ts` | Medium |
| 7 | Billing & Tier UI | `07-billing.spec.ts` | Medium |
| 8 | Error Handling & Edge Cases | `08-errors.spec.ts` | Low |
| 9 | Responsive Design | `09-responsive.spec.ts` | Low |
| 10 | Monetization (Stripe sandbox) | `10-monetization.spec.ts` | Low |
| 11 | Regression | `11-regression.spec.ts` | High |

---

## Key Implementation Notes

### Hash routing
All navigation must use hash routes:
```typescript
await page.goto('https://lector.nerdbox.com/#/login');
await page.goto('https://lector.nerdbox.com/#/review');
```
Do NOT use `page.goto('/login')` — the server serves a single HTML file, routing is client-side.

### Auth helper
Create a shared `auth.ts` fixture to avoid repeating login in every test:
```typescript
// tests/lector/helpers/auth.ts
import { Page } from '@playwright/test';

export async function loginWithEmail(page: Page, email: string, password: string) {
  await page.goto('https://lector.nerdbox.com/#/login');
  await page.getByRole('button', { name: /sign in with email/i }).click();
  await page.getByLabel(/email/i).fill(email);
  await page.getByLabel(/password/i).fill(password);
  await page.getByRole('button', { name: /sign in/i }).click();
  await page.waitForURL(/lector\.nerdbox\.com\/#\//);
}
```

### Google OAuth tests
Skip automated execution — Google blocks OAuth automation. Mark these as **MANUAL** in results with a note: "Requires human tester with Google account."

### Word click / gloss popup
The passage text words are likely `<span>` elements. Use:
```typescript
const words = page.locator('.passage-text span, [data-word]');
await words.first().click();
```
Inspect the actual DOM if selectors don't match — adapt to what's there.

### SRS card interaction
For Review tab tests, look for card front/back pattern:
```typescript
await page.getByRole('button', { name: /show answer/i }).click();
await page.getByRole('button', { name: /easy|good|hard|again/i }).first().click();
```

### Parse quota (10/day free tier)
The API test already confirmed this works at the API level. For UI:
```typescript
// After 10 parses, expect upgrade banner
await expect(page.locator('[data-testid="upgrade-banner"], .upgrade-banner')).toBeVisible();
```
If `data-testid` attributes aren't present, use text content selectors.

---

## Results Format

Write `lector-qa-results.md` as you go with this structure:

```markdown
# Lector QA Results — {DATE}

## Summary
| Section | Total | Pass | Fail | Skip | Notes |
|---------|-------|------|------|------|-------|
| 1. Auth | 8 | 7 | 1 | 0 | OAuth skipped (manual) |
...

## Failures

### [Section] — [Test Name]
**Expected:** ...
**Actual:** ...
**Screenshot:** (if taken)
**Fix needed:** ...

## Skipped / Manual
- Google OAuth (1.1.1, 1.1.2) — requires human tester
- ...
```

---

## After All Sections Complete

1. Tally totals in the summary table
2. For each failure, open a GitHub issue in `rutgersguy/lector` with the bug details
3. Post a summary comment to `rutgersguy/lector#15` with:
   - Pass/fail counts per section
   - Links to any new bug issues filed
   - Note any infrastructure gaps (missing `data-testid` attributes, etc.)

**GitHub API (use token from git remote):**
```bash
cd /home/node/.openclaw/workspace
TOKEN=$(git remote get-url origin | sed 's|https://||;s|@github.com.*||')
curl -s -X POST \
  -H "Authorization: token $TOKEN" \
  -H "Content-Type: application/json" \
  "https://api.github.com/repos/rutgersguy/lector/issues/15/comments" \
  -d "{\"body\": \"$(cat /tmp/qa-summary.md | python3 -c 'import sys,json; print(json.dumps(sys.stdin.read()))' | tr -d '\"')\"}"
```
