zebflow 0.11.14

Reactive web automation platform — pipelines, templates, and real-time collaboration in a single binary.
Documentation
# Zebflow UI smoke tests

Browser tests for the Studio. They cover the one thing `cargo test` cannot:
that a page **works**, not merely that its template **compiles**.

The Rust suites stay authoritative for everything reachable by `curl` —
`tests/platform` is faster and already covers the HTTP API, the office
protocol, and pipeline execution. Nothing here should duplicate them.

## Running

```bash
cd e2e
npm install
npx playwright install chromium   # once
npm test
```

The suite talks to a dev server on `http://localhost:10610`. If one is already
running it is adopted as-is; if the port is free, `dev.sh` is started for you
and shut down afterwards. Override the target with `ZEBFLOW_BASE_URL`.

Credentials default to `superadmin` / `admin123` and can be overridden with
`ZEBFLOW_OWNER` and `ZEBFLOW_PASSWORD`.

## What is covered

- `specs/studio-pages.spec.ts` — every Studio surface renders, carries its own
  title, and logs no console error or uncaught exception. Plus settings tab
  navigation, asserted on the resulting URL.
- `specs/project-lifecycle.spec.ts` — the path a new user walks: create a
  project, confirm the scaffold is a flat repository with the samples and **no
  scaffolded folders**, confirm a sample pipeline 404s until activated and
  answers afterwards, then confirm the sample page renders with `globals.css`
  applied and its counter hydrates.
- `specs/db-sekejap.spec.ts` — the Sekejap management pages on a connection
  the spec creates in a throwaway project: tables, query, schema, graph, mart
  and maintenance each draw real content; a table created in the UI takes a
  row added in the grid; a query shows its rows; the relations graph draws the
  edge and selects it.

- `specs/editor-extensions.spec.ts` — the composable editor in a throwaway
  project with `shared/editor/extensions/`: type, insert a figure (upload,
  caption, credit in its panel), mention through `@` against a picker route,
  cite from the slash menu's search box, save the JSON; the view page renders
  it on the server and the browser renders the same bytes; a hostile stored
  document renders with nothing that runs.

- `specs/editor-components.spec.ts` — an extension drawn by Zeb React
  components: in the editor the node is its `editComponent` (a node view)
  and its own select changes it through `update`; on the page it is its
  `component`, the server's bytes equal the browser's `renderDocumentHtml`,
  and the page hydrates it (its click handler runs).

- `specs/editor-html.spec.ts` — stored document HTML: the editor saves a
  document with a figure and a Potoru story, and its `renderDocumentHtml`
  beside the JSON, in a table; a page shows the stored HTML with
  `<DocumentHtml>` — the server's bytes are what the editor rendered, the
  player hydrates and plays — and a tampered row runs nothing.

The lifecycle spec creates a real project and deletes it in `afterAll`, so a
failed run leaves nothing behind.

## The one rule that matters

**Never assert that a click succeeded — assert the state it should produce.**

Zebflow renders on the server and hydrates after. A click that lands before the
handler is attached is swallowed with no error at all, and Playwright still
reports the click as successful. `clickUntil()` in `fixtures.ts` exists for
this: it retries the click until the observed state changes, so a slow compile
is not mistaken for a dead button, and a genuinely dead button still fails.

This is not hypothetical. It cost real debugging time: a wedged browser session
once reported successful clicks while delivering zero DOM events, which looked
exactly like broken hydration until a known-good control page proved otherwise.

## Keeping it honest

If you add a spec, break one of its assertions on purpose once and watch it
fail. A test that has never failed has not been shown to test anything.