add uncommitted plans and CLAUDE.md
This commit is contained in:
parent
6b4cbdc152
commit
fb133f9cba
10 changed files with 5241 additions and 0 deletions
|
|
@ -0,0 +1,117 @@
|
|||
# Playwright Test Migration + WebAuthn E2E Tests
|
||||
|
||||
## Problem
|
||||
|
||||
The existing 7 E2E tests use a hand-rolled test runner (`helpers.js` with
|
||||
`run()`/`assert()`). This works but lacks structured reporting, retry logic,
|
||||
parallel execution, and proper lifecycle hooks.
|
||||
|
||||
Additionally, the WebAuthn (passkey) authentication flow has no E2E coverage.
|
||||
The existing tests acknowledge this gap -- `test_login.js` checks that the
|
||||
WebAuthn button exists but doesn't exercise the actual flow.
|
||||
|
||||
## Decision
|
||||
|
||||
Two-phase approach:
|
||||
|
||||
1. Migrate all existing E2E tests from the custom runner to `@playwright/test`
|
||||
2. Add comprehensive WebAuthn E2E tests using CDP virtual authenticators
|
||||
|
||||
## Phase 1: Migrate to @playwright/test
|
||||
|
||||
### Infrastructure
|
||||
|
||||
- Add `@playwright/test` to `package.json`
|
||||
- Create `playwright.config.js` with:
|
||||
- `baseURL` from `TARGET_URL` env var (default `http://localhost:8099`)
|
||||
- Chromium-only project (WebAuthn CDP requires Chromium)
|
||||
- `testDir` pointing to the e2e directory
|
||||
- `testMatch` for `*.spec.js` files
|
||||
- Update `run.sh` to call `npx playwright test` instead of looping over `test_*.js`
|
||||
|
||||
### Test conversion
|
||||
|
||||
Each `test_*.js` becomes `*.spec.js`:
|
||||
- `run(async (page, assert) => { ... })` becomes `test('...', async ({ page }) => { ... })`
|
||||
- `assert(condition, msg)` becomes `expect(condition).toBeTruthy()` or specific matchers
|
||||
- Shared setup moves to `test.beforeAll()` / `test.beforeEach()`
|
||||
- `TARGET_URL` usage replaced by Playwright's `baseURL` (use relative paths)
|
||||
|
||||
### What stays the same
|
||||
|
||||
- `run.sh` still starts the app, seeds data, runs tests, tears down
|
||||
- `setup_db.py` unchanged
|
||||
- Test logic/assertions are equivalent
|
||||
|
||||
### Files removed
|
||||
|
||||
- `helpers.js` -- replaced by Playwright Test's built-in fixtures and `expect`
|
||||
|
||||
## Phase 2: WebAuthn E2E tests
|
||||
|
||||
### Approach: CDP Virtual Authenticator + Route Interception
|
||||
|
||||
Chromium DevTools Protocol exposes `WebAuthn.addVirtualAuthenticator` which
|
||||
creates a software authenticator that the browser's WebAuthn API treats as real.
|
||||
This lets us test the full stack: button click -> `navigator.credentials` ->
|
||||
server round-trip -> redirect.
|
||||
|
||||
For error scenarios, we use Playwright's `page.route()` to intercept network
|
||||
requests and return error responses.
|
||||
|
||||
### Virtual authenticator configuration
|
||||
|
||||
```js
|
||||
const cdpSession = await page.context().newCDPSession(page);
|
||||
await cdpSession.send('WebAuthn.enable');
|
||||
const { authenticatorId } = await cdpSession.send('WebAuthn.addVirtualAuthenticator', {
|
||||
options: {
|
||||
protocol: 'ctap2',
|
||||
transport: 'internal',
|
||||
hasResidentKey: true,
|
||||
hasUserVerification: true,
|
||||
isUserVerified: true,
|
||||
automaticPresenceSimulation: true,
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Test scenarios
|
||||
|
||||
**Registration (from credentials page, requires active session):**
|
||||
- Register a passkey via the "Add security key" button
|
||||
- Verify the new passkey appears in the credential list
|
||||
- Verify registration uses resident key (discoverable credential)
|
||||
|
||||
**Authentication (usernameless login):**
|
||||
- Full round-trip: register passkey -> logout -> login via passkey button
|
||||
- No username needed -- browser's passkey picker selects the credential
|
||||
- Verify redirect to `/manage/credentials` after successful login
|
||||
- Verify session is established (can access protected pages)
|
||||
|
||||
**Deletion:**
|
||||
- Register passkey + have password, delete the passkey
|
||||
- Cannot delete last credential (only has passkey, no password)
|
||||
|
||||
**Error handling (route interception):**
|
||||
- Server error on authentication begin
|
||||
- Server error on authentication complete
|
||||
- Expired session (complete without prior begin)
|
||||
|
||||
### Test data
|
||||
|
||||
Extend `setup_db.py` to create a user for WebAuthn tests:
|
||||
- User with password credential (for logging in to register a passkey)
|
||||
- The test flow: login with password -> register passkey -> logout -> login with passkey
|
||||
|
||||
### Files changed/created
|
||||
|
||||
| File | Change |
|
||||
|------|--------|
|
||||
| `tests/e2e/package.json` | Add `@playwright/test` dependency |
|
||||
| `tests/e2e/playwright.config.js` | New: Playwright Test configuration |
|
||||
| `tests/e2e/run.sh` | Update to use `npx playwright test` |
|
||||
| `tests/e2e/helpers.js` | Remove (replaced by Playwright Test) |
|
||||
| `tests/e2e/test_*.js` -> `*.spec.js` | Migrate all 7 tests to Playwright Test syntax |
|
||||
| `tests/e2e/test_webauthn.spec.js` | New: WebAuthn E2E test suite |
|
||||
| `tests/e2e/setup_db.py` | Add WebAuthn test user fixture |
|
||||
Loading…
Add table
Add a link
Reference in a new issue