Files
Oleg Isonen 9a8ae2dc8f feat: Customize Form progress feedback (#6606)
Closes #6605

New Forms show editable feedback while Resource actions run. The
`formProgress` variable starts with `status: "idle"`, `loaded: 0`,
`total: 0`, and `files: []`. It becomes pending during submission, then
returns to idle. The existing `formState` still reports only initial,
success, or error.

The Progress container says “Submitting…” and adds measured
whole-request bytes when the total is known. Files include ID, field
name, name, size, and type. The browser cannot measure reliable per-file
transfer bytes in the single multipart request. The binding editor
suggests one example file to reveal those fields; the example never
enters the actual Form value. Saved Forms retain their existing bindings
and submission message.

## Checklist

- [x] Keep the existing Form outcome variable and add upload activity,
byte counts, and file details.
- [x] Show zero byte defaults on insertion, new submissions,
cancellation, and Preview reset without fake runtime files.
- [x] Suggest file fields in Form and Resource bindings while
evaluation, reset, rendering, and stored values use real data.
- [x] Preserve Builder Preview headers, authentication, response checks,
and cancellation.
- [x] Keep existing success/error feedback and saved-Form fallback.
- [x] Reset external progress when an active published Form unmounts.
- [x] Update Form, Variables, and MCP/CLI guides; clarify the older
screenshot and final-only simulation. Generated MCP docs check passes.
- [x] Audit Form and Variables docs against final progress behavior;
clarify the older Variables screenshot.
- [x] Cover lifecycle, transport, repeated submission, cancellation,
unmount, Preview, template, MCP binding/style, and editor completion
with focused tests.
- [x] Run relevant typechecks, lint, formatting, fixture generation, and
independent review.
- [x] Required CI checks pass on the latest commit.

## Verification

Local focused Form browser tests (25), Form template tests (12), Builder
Preview and Form context tests (14), and mounted editor example/reset
tests (6) pass. Builder, SDK React, SDK registry, and project-build
typechecks pass, as do lint, formatting, and fixture generation. The
fixture sync regenerated two unrelated linked-project site paths; those
outputs were restored before commit. Independent review found no
remaining issues. All latest-commit checks passed; E2E shard 9 passed on
a targeted rerun after its two Form tests also passed locally with 11
related tests.

This follow-up adds 162 net non-test lines, more than the initial
estimate. The extra code identifies the actual callback-bound variable
by ID, even when renamed, and gives autocomplete a separate example
scope so it cannot affect actual values. One provider covers Form fields
and Resource editors. No schema or package was added.

The existing Variables screenshot predates `formProgress`; its
explanatory text is current. The React Router fixture's built browser
client grew by 4 KiB on Linux CI (376 → 380 KiB), and its checked limit
matches that measured output. Multipart transfer remains one whole
request.

Browser submission supplies live progress. MCP can discover
`formProgress`, bind the Progress container, and style it; server
simulation reports final outcomes and does not measure browser uploads.
2026-10-26 14:38:12 +01:00
..

Builder E2E tests

Builder E2E workflows run with Playwright Test. The Playwright setup project waits for PostgREST, resets the disposable database, and warms the login route before Chromium runs the selected tests.

Run the suite

Use the full command for CI-like validation:

pnpm e2e:builder

The first run after migrations change applies the regular migration pipeline and writes an ignored schema cache under .cache/builder-e2e. Refresh it explicitly with:

pnpm e2e:builder:refresh-schema-cache

The regular E2E suite uses lightweight PostgreSQL containers. Verify that the complete migration chain also applies to the pinned Supabase PostgreSQL image with:

pnpm e2e:builder:check-supabase-migrations

Pass normal Playwright Test arguments after --. For example:

pnpm e2e:builder -- --grep "Builder can copy, duplicate, and delete a page"
pnpm e2e:builder -- 'apps/builder/e2e/tests/pages-actions.[shard-3].e2e.ts'
pnpm e2e:builder -- --debug --grep "Builder can copy"

A lightweight Playwright discovery pass validates the selection before Docker, database migrations, browser installation, or the Builder build starts. A filter that matches no tests therefore fails without starting the test environment.

Fast local reruns

Keep the E2E backend and Builder development server running to avoid rebuilding Builder and restarting Docker for each edit.

Terminal 1:

pnpm e2e:builder:dev:backend

Terminal 2:

pnpm dev

Terminal 3:

pnpm e2e:builder:dev -- --grep "Builder can copy, duplicate, and delete a page"

pnpm e2e:builder:dev defaults to E2E_BUILDER_URL=https://127.0.0.1:3000. Override it when the development server uses another port. Chromium maps wstd.dev and its project subdomains to loopback for local Builder URLs, so host-file changes are unnecessary.

The development backend uses E2E_DB_BOOTSTRAP=if-empty and keeps Docker containers running. The Playwright setup project still resets test data before each invocation.

Test organization

  • Put workflows in e2e/tests/*.e2e.ts and import test from e2e/test.ts.
  • Use Playwright's page fixture for the workflow under test. Playwright gives each test an isolated context and closes it automatically.
  • Use Playwright's context fixture when setup should share authentication with the workflow page.
  • Use withBrowserContext(browser, callback) for isolated setup or setup that runs in beforeAll. If cookies must survive from beforeAll into the tests, create an explicit context with newBrowserContext(browser) and close it in afterAll.
  • Use newIsolatedPage(browser) for identities that must not share cookies.
  • Keep tests in a file independent even though Playwright runs them in declaration order by default.

CI discovers isolated Playwright shards from filename tags. Each shard uses four workers, and files are assigned by measured CI duration to keep jobs near three to four minutes:

pages-actions.[shard-3].e2e.ts

Every E2E filename must contain at least one unique shard tag. CI derives its matrix from those tags, so adding or removing a shard does not require editing the workflow. Files with multiple tags are partitioned across those shards. All files selected by a shard must use the same set of tags. Rebalance by changing filename tags when measured job durations drift. Suites may opt into parallel mode only when every worker creates uniquely named setup data and the tests do not depend on each other's mutations.

Backend organization

Development, E2E, schema-cache, and Supabase compatibility commands share the backend definition in apps/builder/backend. compose.yaml defines the common services, and compose.<mode>.yaml defines only the differences for a named mode. Backend commands resolve these files by convention; callers do not pass Compose filenames.

The schema-cache fingerprint discovers migration sources and non-test backend files automatically. Adding a database image, initialization script, Compose override, or migration therefore invalidates the cache without updating a filename registry.

Failures

Failed shard jobs upload the Playwright HTML report, traces, screenshots, videos, and backend service logs.

When you need a completely clean backend locally:

E2E_SKIP_CLEANUP=false pnpm e2e:builder