From f43cad1902fe447c88e4d40ef58f8359d3b95f2f Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 10 Feb 2026 05:24:54 +0000 Subject: [PATCH] docs: add agent testing infrastructure documentation to AGENTS.md and CLAUDE.md Section 14 in AGENTS.md covers the full test harness API, mock relay HTTP endpoints, Playwright fixture usage, and data-testid selector reference. CLAUDE.md testing section updated with quick-start example. https://claude.ai/code/session_01XnrszNmdqrAGd8g8qhAn4G --- AGENTS.md | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ CLAUDE.md | 26 +++++++++++++ 2 files changed, 133 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index 529aa432..7c5aa755 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -301,6 +301,113 @@ Three automated lint checks protect the codebase from common growth problems. Th --- +## 14. Playwright Agent Testing Infrastructure + +bitvid includes a test harness and fixtures that let Playwright CLI agents programmatically log in, seed relay data, and inspect app state — no browser extensions or real relays required. + +### Activating Test Mode + +Add `?__test__=1` to the URL, or set `localStorage.__bitvidTestMode__ = "1"` via `addInitScript`. This installs `window.__bitvidTest__` on the page. + +### Overriding Relays + +Point the app at a local mock relay instead of production: + +``` +?__test__=1&__testRelays__=ws://127.0.0.1:8877 +``` + +Or set `localStorage.__bitvidTestRelays__` to a JSON array of relay URLs. + +### Test Harness API (`window.__bitvidTest__`) + +| Method | Returns | Purpose | +|--------|---------|---------| +| `loginWithNsec(hexKey)` | `Promise` (pubkey) | Programmatic login, bypasses the modal | +| `logout()` | `void` | Clear active signer | +| `getAppState()` | `{ isLoggedIn, activePubkey, relays, ... }` | Inspect current state | +| `getFeedItems()` | `Array<{ title, pubkey, dTag, hasUrl, hasMagnet }>` | Scrape video cards from DOM | +| `waitForFeedItems(n, ms)` | `Promise` | Wait for N cards to appear | +| `waitForSelector(sel, ms)` | `Promise` | Wait for a DOM element | +| `getRelayHealth()` | `{ relays, unreachable, backoff }` | Relay connection status | +| `applyRelayOverrides(urls)` | `boolean` | Redirect relay connections | +| `nostrClient` | `NostrClient` | Direct access for advanced use | + +### Mock Relay (`scripts/agent/simple-relay.mjs`) + +Start with `startRelay(port, { httpPort })`. Alongside the Nostr WebSocket protocol, exposes an HTTP API: + +| Endpoint | Method | Purpose | +|----------|--------|---------| +| `/seed` | `POST` | Inject signed events (single object or array) | +| `/events` | `GET` | List all stored events | +| `/events` | `DELETE` | Clear all events | +| `/health` | `GET` | Event count + connection count | + +Programmatic API: `relay.seedEvent(event)`, `relay.clearEvents()`, `relay.getEvents()`. + +### Playwright Fixture (`tests/e2e/helpers/bitvidTestFixture.ts`) + +Import `test` and `expect` from the fixture for tests that need the full stack: + +```typescript +import { test, expect } from "./helpers/bitvidTestFixture"; + +test("agent can seed and view videos", async ({ page, gotoApp, loginAs, seedEvent }) => { + await seedEvent({ title: "Test Video", url: "https://example.com/v.mp4" }); + await gotoApp(); + await loginAs(page); + // ... assertions +}); +``` + +**Available fixture values:** + +| Fixture | Type | Purpose | +|---------|------|---------| +| `relay` | Relay instance | Auto-started/stopped per test | +| `seedEvent(video)` | `(TestVideoEvent) => Promise` | Create a signed kind 30078 event and inject it | +| `seedRawEvent(event)` | `(any) => Promise` | Inject a pre-built event | +| `clearRelay()` | `() => Promise` | Wipe all relay events | +| `gotoApp(path?)` | `(string?) => Promise` | Navigate with test mode + relay overrides | +| `loginAs(page)` | `(Page) => Promise` | Login with deterministic test key | +| `testPubkey` | `string` | Hex pubkey of the test key | +| `relayUrl` | `string` | WebSocket URL of the mock relay | + +### `data-testid` Selectors + +Use these for stable element targeting: + +| Selector | Element | +|----------|---------| +| `[data-testid="login-button"]` | Header login button | +| `[data-testid="upload-button"]` | Header upload button (hidden until logged in) | +| `[data-testid="profile-button"]` | Header profile button (hidden until logged in) | +| `[data-testid="search-input"]` | Header search field | +| `[data-testid="login-modal"]` | Login modal container | +| `[data-testid="login-provider-button"]` | Login provider option buttons | +| `[data-testid="nsec-secret-input"]` | Private key textarea in nsec login | +| `[data-testid="nsec-submit"]` | Nsec login submit button | +| `[data-testid="upload-modal"]` | Upload modal container | +| `[data-testid="upload-title"]` | Video title input | +| `[data-testid="upload-url"]` | Video URL input | +| `[data-testid="upload-magnet"]` | Magnet link input | +| `[data-testid="upload-submit"]` | Publish button | +| `[data-testid="video-modal"]` | Video player modal | +| `[data-testid="video-card"]` | Individual video card in the feed | +| `[data-testid="video-list"]` | Video feed grid container | + +### Key Files + +| File | Purpose | +|------|---------| +| `js/testHarness.js` | Test harness module (installs `window.__bitvidTest__`) | +| `scripts/agent/simple-relay.mjs` | Mock relay with HTTP seeding API | +| `tests/e2e/helpers/bitvidTestFixture.ts` | Reusable Playwright fixture | +| `tests/e2e/agent-testability.spec.ts` | Infrastructure validation tests | + +--- + ## Next Please read these documents next. diff --git a/CLAUDE.md b/CLAUDE.md index eb3f8d22..2c3c9897 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -80,6 +80,9 @@ bitvid/ | `js/nostrEventSchemas.js` | **Source of truth** for all Nostr event schemas | | `js/constants.js` | Feature flags and runtime configuration | | `config/instance-config.js` | Deployment-specific settings | +| `js/testHarness.js` | Playwright test harness (`window.__bitvidTest__`) | +| `tests/e2e/helpers/bitvidTestFixture.ts` | Reusable Playwright fixture for agent testing | +| `scripts/agent/simple-relay.mjs` | Mock Nostr relay with HTTP seeding API | | `docs/nostr-event-schemas.md` | Event schema documentation | --- @@ -330,6 +333,29 @@ Failed visual tests store artifacts in `artifacts/test-results/`: View with: `./scripts/show-artifacts.sh` +### Agent E2E Testing (Playwright) + +bitvid includes a test harness for programmatic Playwright testing without browser extensions or real relays. See `AGENTS.md` Section 14 for the full reference. Quick start: + +```typescript +import { test, expect } from "./helpers/bitvidTestFixture"; + +test("my test", async ({ page, gotoApp, loginAs, seedEvent }) => { + await seedEvent({ title: "Test Video", url: "https://example.com/v.mp4" }); + await gotoApp(); + await loginAs(page); + // interact with the app using data-testid selectors + await expect(page.locator('[data-testid="upload-button"]')).toBeVisible(); +}); +``` + +Key capabilities: +- **Programmatic login**: `loginAs(page)` uses `window.__bitvidTest__.loginWithNsec()` — no modal interaction needed +- **Mock relay**: Each test gets an isolated in-memory relay with HTTP seeding +- **Relay override**: `?__test__=1&__testRelays__=ws://localhost:8877` redirects all connections +- **State inspection**: `window.__bitvidTest__.getAppState()` returns login status, relays, etc. +- **Stable selectors**: All key elements have `data-testid` attributes (see AGENTS.md Section 14) + --- ## Common Tasks