Skip to content

Demote non-browser e2e assertions to a fetch-based integration layer #777

Description

@vivek7405

Problem

Split off from #774 (which landed the config-level testing wins: parallel Node/Bun e2e jobs, the WebKit + Firefox browser matrix, and opt-in coverage). This issue covers the one heavy, separable item deliberately deferred from that PR because it is a large, careful refactor rather than a minimal one.

test/e2e/e2e.test.mjs (~144KB, ~119 test() blocks) drives everything through Puppeteer against the running blog, but a large share of those blocks assert only on the HTTP response, the SSR HTML string, response headers, or the importmap, none of which need a real browser. Each Puppeteer navigation is 10-50x slower than a fetch() against the same server, and the whole suite now runs twice (Node + Bun), so every demotable block is paid for four times over.

Design / approach

Add a fast fetch()-based node:test integration layer that spawns ONE blog server (reusing the e2e harness's existing spawn / freePort helpers) and asserts over plain fetch(), then move the non-browser blocks out of the Puppeteer file into it and delete them from the Puppeteer suite. Keep in Puppeteer only blocks that genuinely need a DOM: page.evaluate, navigation/hydration, client-router, slots, view transitions, streaming-into-DOM.

Clear demotion candidates already spotted in test/e2e/e2e.test.mjs (audit each, do not assume): import map includes all framework entries (~L195), modulepreload links are deduplicated (~L207), every modulepreload resolves (~L216), health endpoint responds (~L672), /api/posts GET returns an array (~L1286), POST /api/posts without auth is rejected (~L1293), 404 for unknown pathname serves text/html (~L1306), no CSRF cookie on a GET response (~L1337), dynamic route renders post title in <head> (~L1025), unknown slug hits notFound 404 (~L1043), dashboard middleware redirects (~L1055), metadata <title>/<meta> per route (~L1240).

Also fold in the cheap cleanup deferred from #774: extract the per-file hand-rolled const assert = { ok, equal, deepEqual, ... } block (duplicated across 45 browser .test.js files) into one shared test/browser-assert.js module the tests import. Superset of methods actually used: ok, equal, deepEqual, strictEqual, notStrictEqual, notEqual, match, isTrue, isFalse, isOk, isArray, doesNotThrow, throws. Match the existing inline semantics exactly (strict equality, JSON-stringify deepEqual) so it is a pure drop-in.

Implementation notes (for the implementing agent)

Acceptance criteria

  • A fetch-based integration test file covers the demoted assertions and runs under the fast node driver (no Puppeteer)
  • The migrated blocks are deleted from test/e2e/e2e.test.mjs; the Puppeteer suite retains only genuinely DOM-needing tests
  • One shared browser-assert module replaces the 45 inline const assert = {} blocks; browser suite stays green on Chromium/Firefox/WebKit
  • e2e wall-clock measurably drops vs the post-Improve testing architecture and cut e2e wall-clock time #774 baseline
  • agent-docs/testing.md updated

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

  • Status
    Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions