diff --git a/docs/plans/2026-03-29-fix-cross-origin-iframe-screenshot-test-plan.md b/docs/plans/2026-03-29-fix-cross-origin-iframe-screenshot-test-plan.md new file mode 100644 index 00000000..942401a9 --- /dev/null +++ b/docs/plans/2026-03-29-fix-cross-origin-iframe-screenshot-test-plan.md @@ -0,0 +1,211 @@ +# Test Plan: Fix Cross-Origin Iframe Screenshot + +**Implementation plan:** `docs/plans/2026-03-29-fix-cross-origin-iframe-screenshot.md` + +**Testing strategy (approved):** Strip iframe-blocking headers from proxy responses so proxied localhost content renders in browser pane iframes and the MCP screenshot tool captures real content instead of placeholders. + +**Strategy reconciliation notes:** +- The approved strategy names a Playwright e2e test as highest priority. The project has Playwright infrastructure in `test/e2e-browser/` with a running `TestServer` that boots a real Freshell instance. The existing `browser-pane.spec.ts` already exercises browser pane creation and URL loading. A new Playwright test can load a localhost URL through the proxy, then use the MCP agent API `screenshot-view` CLI command (or the `requestUiScreenshot` harness method) to verify the screenshot contains image content rather than a placeholder. This test exercises the entire fix end-to-end: proxy strips headers, iframe renders, screenshot captures real content. +- The implementation plan omits the Playwright e2e test entirely, covering only Vitest unit tests. This test plan adds it as test 1. +- The implementation plan omits the MCP instructions update verification. This test plan adds it as test 7 (a simple Grep-based assertion on the instructions text). +- The implementation plan's proxy-router unit tests and ui-screenshot unit test align with strategy items 2-4 and are included here as tests 3-6. +- No strategy changes requiring user approval: all tests use existing harnesses and infrastructure. + +--- + +## Harness requirements + +No new harnesses need to be built. All tests use existing infrastructure: + +1. **Playwright E2E harness** (`test/e2e-browser/helpers/fixtures.ts`): Boots a real Freshell production server via `TestServer`, provides `freshellPage` fixture with auth + WebSocket, `harness` for Redux state inspection, and `terminal` helper. The server includes the proxy router, so proxied URLs work out of the box. + +2. **Vitest + supertest** (`test/unit/server/proxy-router.test.ts`): Existing test file boots a target express server on an ephemeral port and sends requests through the proxy router via supertest. New tests add routes to the existing `targetApp` that return iframe-blocking headers. + +3. **Vitest + jsdom** (`test/unit/client/ui-screenshot.test.ts`): Existing test file mocks `html2canvas` and tests `captureUiScreenshot` with synthetic DOM. Same-origin iframes in jsdom allow `contentDocument` access, so proxy-URL iframe tests work without browser-level header stripping. + +--- + +## Test plan + +### Test 1: Browser pane screenshot captures proxied localhost content as image, not placeholder + +- **Name:** Screenshot of browser pane with proxied localhost URL produces image content, not a cross-origin placeholder +- **Type:** scenario +- **Disposition:** new +- **Harness:** Playwright E2E (`test/e2e-browser/specs/browser-pane-screenshot.spec.ts`) +- **Preconditions:** + - Freshell test server is running (production build, via `TestServer` fixture) + - A static HTTP server running on an ephemeral localhost port inside the test, serving a page with known canary text (e.g., `