Files
webstudio/apps/builder/e2e
Oleg Isonen d579607ed8 feat: Add draft pages (#5885)
Closes https://github.com/webstudio-is/webstudio/issues/3036

## Summary

- add an optional page-level draft state with a presentation-only
`[Draft]` prefix in Builder
- add **Mark as draft** and **Stage for publish** actions to the Page
details header menu
- keep drafts editable, previewable, linkable, duplicable, and
path-reserving in Builder
- exclude drafts from generated routes, public page collections, sitemap
output, staging, and production builds
- expose draft state and usage guidance through the runtime API, HTTP
client, CLI docs, and MCP contracts

## Why

Pages need a way to remain unfinished inside Builder without being
included in the next site deployment. Draft is an exclusion flag, not a
separate revision or publishing workflow state.

## Behavior and fixes

- home and `/*` catch-all pages cannot be drafts
- draft pages must be staged before becoming the home page
- restricted features used only on draft pages no longer block
publishing the publishable site
- **Stage for publish** only clears draft state; it does not deploy the
site
- missing or explicit `false` draft state remains backward-compatible
and publishable

## Validation

- 5,179 package tests passed across SDK, migrations, project-build, CLI,
and Builder
- targeted Builder browser E2E passed for draft/stage actions,
persistence, home-page guidance, copy, duplicate, delete, and
generated-app build behavior
- all affected package typechecks passed
- lint and package-boundary checks passed
- generated runtime contracts and CLI docs are reproducible
- `git diff --check` passed
2026-07-16 00:56:54 +02:00
..
2026-07-12 11:27:58 +02:00
2026-07-16 00:56:54 +02:00
2026-07-12 11:27:58 +02:00
2026-07-12 11:27:58 +02:00
2026-07-12 11:27:58 +02:00
2026-07-12 11:27:58 +02:00
2026-07-12 11:27:58 +02:00
2026-07-12 11:27:58 +02:00
2026-07-12 11:27:58 +02:00

Builder e2e

Fast local reruns

Use the full command for CI-like validation:

pnpm e2e:builder

For local test authoring, keep the e2e backend and Builder dev server running and rerun only the matching test. This avoids rebuilding Builder and avoids restarting Docker for every edit.

Terminal 1:

pnpm e2e:builder:dev:backend

Terminal 2:

pnpm dev

Terminal 3:

E2E_TEST_FILTER="Builder can copy, duplicate, and delete a page" pnpm e2e:builder:dev

E2E_TEST_FILTER is a substring match against the test name. It is not a regular expression. If the filter matches no tests, the runner fails and prints the available test names before starting Docker or building Builder.

Use E2E_TEST_FILTERS for a newline-separated list of exact or substring matches. Each entry is matched against both the test name and <suite> › <test>.

E2E_TEST_FILTERS='Builder can insert through the engine bridge
Builder-created data variables and resources persist' pnpm e2e:builder

CI shards the full e2e suite by file name tags such as pages-actions.[shard-3].e2e.ts. Use E2E_TEST_SHARD=shard-3 to run one shard. The goal is to keep all coverage while preventing one long serial e2e command from hitting the command timeout.

When adding a new e2e file, include one shard tag in the filename:

my-workflow.[shard-1].e2e.ts
my-workflow.[shard-2].e2e.ts
my-workflow.[shard-3].e2e.ts

If one workflow file grows too slow, split it by scenario into files with the same base name and different shard tags:

large-workflow.[shard-1].e2e.ts
large-workflow.[shard-2].e2e.ts
large-workflow.[shard-3].e2e.ts

Choose the shard by current CI timing, not by feature ownership. Put new or expensive files into the fastest shard, and rebalance later by renaming files. CI retries a failed shard once because a single shard rerun is cheap enough to absorb occasional browser/backend flakes.

pnpm e2e:builder:dev defaults to E2E_BUILDER_URL=https://127.0.0.1:3000, so it runs against the already-running Vite dev server instead of building and serving the production bundle. Override E2E_BUILDER_URL when the dev server is running on another port. The E2E harness maps wstd.dev and project subdomains to loopback for Chromium when this URL is loopback, so focused local runs do not require machine-level host-file edits.

The dev backend uses E2E_DB_BOOTSTRAP=if-empty and keeps Docker containers running. The e2e runner still resets test data before each run.

When you need a clean backend:

E2E_SKIP_CLEANUP=false pnpm e2e:builder