Files
EpicNext-Cms/e2e/ui
openhands 9cc57cddfc feat(catalog): update the catalog live after an import, no page refresh
Organising imports, the Studio furni batch, the catalog totals and the
"import from a source" stats all used to need a full page reload, or at
best a router.refresh() that re-rendered the whole admin route, before
anything on screen reflected what the import had just written.

- live-catalog-merge.ts (new): pure tree and total arithmetic. Applies a
  delta of created pages, added offers and moved offers, recomputes depth
  for the touched subtree, bumps parent child counts and the item totals.
  Returns the input untouched when a delta is empty, so subscribers can
  bail out instead of re-rendering. Depth resolution tolerates a parent
  cycle in a dirty DB and still terminates, matching getTreeFlat.
- use-live-catalog.ts (new): one module-level store exposed through
  useSyncExternalStore, so every consumer shares a single instance without
  threading a provider through the admin layout. Deltas only apply to the
  "normal" catalog, so public and public_handlers trees stay separate.
  seedCatalogTotals() takes the first server value per mode and never
  overwrites it afterwards, so a later hard render cannot make the header
  totals jump backwards.
- actions/catalog.ts: organizeImportFurni now reports each group through
  the new OrganizedPageChange, carrying parentId, pageLayout, the icon,
  isNew and the per-source movedFrom counts, so the client can fold the
  result into the tree without reading the page back.
- organize-imports-dialog.tsx: drops useRouter and router.refresh(); the
  response is applied as a delta the moment the run finishes.
- studio-client.tsx: reads the tree from the store instead of freezing it
  with useState(initialTree), loads it on mount when empty, and refreshes
  it once a batch import settles. The batch is server-side and derives its
  import pages from furnidata, so that one path re-reads the tree via
  GET /api/admin/catalog/tree?mode=full rather than trusting the delta.
- studio/furni/page.tsx: stops calling getTreeFlat() and no longer passes
  initialTree; the store is the single source of truth for the rail.
- import-clone-client.tsx: tracks which items are already present, so
  present and clonable update per cloned row instead of only at the end.
- catalog-manager-dialog.tsx: seeds the totals once and renders the live
  values, so the header reflects an import that just ran.
- e2e/ui/fixtures/entry.tsx: drops the removed initialTree prop.
2026-09-29 15:34:36 +02:00
..

Isolated UI regression checks

Run pnpm test:ui after pnpm install --frozen-lockfile and pnpm exec playwright install chromium. The fixture server bundles real CMS components with local HTTP/server-action fixtures. It does not use the database or production credentials. Production smoke tests remain in the separate pnpm test:e2e command.

The suite covers accessible settings switches, news editor/preview, support-table filters, import history, attachment recovery and news/event recovery. Axe checks WCAG A/AA rules. The sandboxed preview cannot execute Axe; its accessible name and keyboard exit are checked separately. Automated checks do not replace a full accessibility audit.

Visual references are committed under __screenshots__/<platform>/<viewport>. Normal runs compare references and must not update them. For an intentional UI change, use pnpm test:ui:update, inspect every changed PNG and commit only accepted references. Keep the Playwright browser version aligned with the lockfile. Linux references must be captured on the Linux runner; Windows references are not interchangeable.

Fixtures contain synthetic data only. Do not add production requests, environment secrets, ignored local documents or database access to tests. CI retains test reports and failures as the ui-results artifact.