Skip to content

test(e2e): Node suite on Endform against a production build - #4

Draft
ostenbom wants to merge 16 commits into
mainfrom
e2e/endform
Draft

ostenbom wants to merge 16 commits into
mainfrom
e2e/endform

Conversation

@ostenbom

Copy link
Copy Markdown

Experiment on this fork: run the Node E2E suite on Endform against a production build of the test site, from one CI job without sharding. Not intended for upstream in this form.

  • a5faf15ed runs the Playwright suite against a local production build (passes natively: 344 passed).
  • 2155adbf9 runs it on Endform: the server runs in the CI job, Endform proxies runner traffic back to it, and site-resetting specs run in a separate one-at-a-time suite run.

Concurrency is set by EMDASH_ENDFORM_CONCURRENCY (default 32 in the workflow).

🤖 Generated with Claude Code

ostenbom and others added 2 commits October 16, 2026 10:58
Prototype. EMDASH_E2E_BUILD=production makes global setup run `astro build`
on the Node fixture and serve dist/server/entry.mjs instead of `astro dev`.
The page and admin warm-ups are skipped, since a build has nothing to
compile on demand.

Production builds need an opt-in for the dev-only test hooks.
EMDASH_INSECURE_TEST_BYPASS, set to a fixed public value, enables
dev-bypass, dev-reset, captured dev emails, the console email provider and
the localhost registry allowances in a built site. It is a switch, not a
secret, and must not be set on a real deployment.

Fixes for differences that only show up in production builds:
- Set EMDASH_SITE_URL for the build and the server; production setup won't
  infer it, and image remotePatterns are derived from it at build time.
- Add sharp to the Node fixture so the built server can optimize images.
- Use manual i18n routing in the fixture so Astro's generated locale
  fallback routes don't shadow its [locale] pages.
- Install the registry fixture at server start, not only in astro.config.

Test fixes for problems a single-server run exposes:
- Look up sandbox hook events by key instead of scanning the first 100.
- Accept additional users in the sandbox boundaries users check.
- Keep media drags away from the viewport edge and re-measure the drop
  target, since dnd-kit auto-scroll moves it during the drag.
- Use an https image URL in the editor image panel test (production CSP).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Under Endform (ENDFORM=true), Playwright starts e2e/endform-server.ts as a
webServer on the CLI machine. It runs the normal global setup in
production-build mode and serves the server info on 127.0.0.1:4446. Endform
proxies loopback traffic from its remote runners back to the CLI, and an
auto fixture copies the server info into each runner's temp file, so the
tests themselves don't change.

Every test runs on its own runner. Specs that reset or wipe site-wide state
(setup wizard, passkey setup, redirect loop detection) move to an
`exclusive` project that runs as a second suite run, one test at a time.
EMDASH_ENDFORM_CONCURRENCY caps concurrent tests, since every admin load
pulls the uncompressed bundle through the CLI machine's network.

Test assets now resolve relative to the spec file instead of process.cwd(),
which is not the repository root on a runner.

The new Endform E2E workflow runs both suite runs in one job, without
sharding. Native Playwright runs are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

PR template validation failed

Please fix the following issues by editing your PR description:

See CONTRIBUTING.md for the full contribution policy.

@endform-dev

endform-dev Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Endform

Passed on 3c5288f

Suite Result Tests Duration
(repository root) Passed 7 passed 1m 3s

ostenbom and others added 14 commits October 16, 2026 11:53
- Send test assets to Endform runners: `e2e/fixtures/assets/**` matched
  no files, `e2e/fixtures/assets/*` does.
- Put a gzip proxy in front of the production-build server. Astro's
  standalone server doesn't compress, and every Endform test downloads the
  ~9 MB admin bundle through the CLI machine; gzip cuts that about 4x.
- Give tests their own data instead of sharing it with tests that now run
  at the same time:
  - content types: each lifecycle test creates its own collection through
    the API instead of relying on the previous test's fixed slug.
  - i18n: the Translate buttons test opens a post it created, not
    whichever post is first in the list.
  - visual editing: the two tests that save real edits work on a copy of
    the seeded image post, which other tests expect unchanged.
  - media library: crop uploads get unique bytes, since uploads are
    deduplicated by content hash; the featured image picker accepts any
    copy of test-image.png.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Compress only built assets in the gzip proxy, so pages and API responses
  keep the headers the server set (the outer middleware test checks
  Content-Length).
- Allowed domains: clean up only the domains each test created, instead of
  every e2e-test domain, which deleted other tests' domains.
- Menus: wait for the add-link form's own dialog to close. Toasts also have
  the dialog role, so waiting for any dialog waited for each toast to time
  out. Serve an empty menu list to the empty-state test.
- Visual editing: the image insert test works on its own copy of the
  seeded post, and the slash menu test no longer saves its typing to it.
- Run CI at concurrency 64.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tate

The gzip proxy re-compressed the 5.7 MB admin chunk on every request, which
saturated the CI machine at concurrency 64. Built assets are content-hashed,
so cache each compressed body for the life of the server.

The redirects empty-state test now serves an empty list, since other tests
create redirects at the same time.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…el tests

- Redirects CRUD: unique paths per test, act on the test's own row by its
  button label, and wait on the redirect form's dialog rather than any
  dialog (toasts have the dialog role too).
- Content CRUD: the update test edits a post it created instead of renaming
  the seeded "First Post" that other tests open.
- Comments: the spec deletes every comment before each test, so it runs in
  the exclusive suite run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…clusively

- The comment hooks test asks the test plugin for its event types; the
  events-list route pages through every event when given `types`, since a
  full parallel run records more than one page.
- Specs that delete every comment or redirect are tagged @comments and
  @redirects and limited to one test at a time per tag, so they run inside
  the parallel suite run. Only the specs that reset the whole site stay in
  the exclusive run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each loop detection test now works under its own path prefix and deletes
only the redirects it created, instead of deleting every redirect before
and after each test. Its redirects can't form loops with another test's,
so the @redirects concurrency group, which made it the slowest chain in
the Endform run, is gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Tests that stub saves can still flush typed edits when their page closes,
so the seeded image post can gain blocks during a parallel run. Copies now
keep only the blocks global setup created, so the image insert test starts
from the seeded structure.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Plugin editor extensions and the Block Kit saved-entry test edit posts
  of their own (new createPost fixture), instead of all editing the first
  seeded post and colliding on stale drafts.
- Widgets: the empty-state test serves an empty list instead of trying to
  delete every widget area.
- Search: tests that switch search on and off for a collection are tagged
  @search and run one at a time on Endform.
- Media library: the organize test follows its own upload by filename
  instead of the first image in the grid.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Visual editing copies rebuild the seeded paragraphs around the seeded
  image. Editor saves re-key blocks, so filtering by the seeded keys could
  drop the paragraphs.
- Media library: wait for the library to finish loading after searching
  and after opening a folder before measuring a folder name's direction.
- Search: only the three tests that switch search for the pages collection
  are tagged @search; the others only ever enable posts and can run in
  parallel.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both trash-and-restore tests find their post by title in the content list,
and both created "Trash Test Post", so running at the same time each saw
the other's row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The 404 tab test serves an empty 404 summary; other tests request
  missing pages at the same time.
- The dashboard inset test waits for metric values to load before
  measuring them.
- Concurrency 128 ran the parallel suite no faster than 64 (96s vs 100s)
  while slowing individual tests on the shared server, so CI goes back to
  64.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant