Skip to content

The live e2e suite never runs in CI — 20+ specs are effectively manual, and that is how framework#3528 shipped #2835

Description

@os-zhuang

The gap

e2e/live/** holds 20+ Playwright specs covering the interaction-critical paths — row actions, action modals, master-detail, inline edit, conditional rules, form subforms, Studio designers. None of them run in CI. They need a real ObjectStack backend from a sibling checkout, and no CI job provides one:

  • playwright.config.ts (the only config CI runs, ci.yml → pnpm test:e2e --project=chromium) serves the console production build with no backend. testIgnore: ['**/live/**']. Its 4 specs assert blank-page / bootstrap health, and console-rendering.spec.ts:22-34 explicitly whitelists Failed to connect to ObjectStack server as benign noise.
  • playwright.live.config.ts / import-console / import-harness all require externally-started servers and are gated behind env flags. They only run when a human remembers.

So the specs exist, they pass, and they guard nothing on their own.

Why this is worth fixing now

framework#3528 is the concrete cost. A paused screen flow's dialog was torn down by its own host — an object-form step mounts lazily-loaded field widgets, and that suspension unwound to the host's route-level <Suspense>, which swapped the page for a fallback and remounted it, destroying the dialog and the run with it. Symptom: dialog closes, zero network requests, flow paused forever. It was reported as "Submit does nothing" and cost a full investigation to place.

Unit tests could not see it: they render the runner directly with an eagerly-imported body, so there is no suspension and no host to tear down. Only a real browser against a real backend reproduces it. #2833 added e2e/live/screen-flow.spec.ts covering the full trigger → screen → resume round trip — and it lands straight into the suite that CI never runs.

Proposed work

Give CI a backend and run e2e/live/** against it. Sketch:

  1. A job that boots an ObjectStack example app (the live specs target showcase_app) — container image, or npx objectstack dev against a published @objectstack/* with a file-backed sqlite db.
  2. Serve the console dev/preview build pointed at it; reuse e2e/live/global-setup.ts for auth (it already mints the session token and writes storageState).
  3. Run pnpm test:e2e:live. The specs are already fully env-parameterised (LIVE_APP_URL / LIVE_API_URL), so nothing needs rewriting — I ran the new screen-flow spec this way locally and it passed in ~10s wall clock.

Sequencing note: if a green CI is wanted before the whole suite is trustworthy, start with a small allowlist (screen-flow, action-modal, master-detail) and grow it, rather than switching all 20+ on at once and inheriting whatever flake exists.

One caveat found while mapping this: the dev-server job in ci.yml:283-307 ("Dev-server fixture build") is stale — there is no apps/dev-server in the tree and no @object-ui/dev-server in any package.json (apps/console/README.md:38-41 confirms it was removed). Don't build a fixture backend around that job; it needs deleting or rewriting either way.

Related

packages/plugin-dashboard/src/__tests__/DashboardRenderer.designMode.test.tsx is describe.skip'd with TODO(#ci-hang) since 2026-05-01 — a whole suite disabled to unblock main and never root-caused. Different mechanism, same outcome: coverage that exists on disk and protects nothing. Worth folding into the same push.

Acceptance

  • A CI job runs at least a subset of e2e/live/** against a real backend on every PR.
  • The screen-flow round trip is in that subset.
  • The stale dev-server job is removed or repointed.

Activity

  1. xuyushun441-sys commented on Aug 3, 2026

    @xuyushun441-sys
    Contributor

    维护者裁决(2026-08-03)

    批准 allowlist 起步方案:CI 起真后端,先跑 screen-flow / action-modal / master-detail 三个 spec,逐步扩量;同 PR 删除或重写 stale 的 dev-server job(ci.yml:283-307,对应 app 已不存在)。DashboardRenderer.designMode 的 describe.skip(TODO(#ci-hang))纳入同一波清理的范围核查。

    裁决理由记录:这是本批 18 条里「防 AI 写代码犯错」收益最高的一条——framework#3528 类缺陷(懒加载 suspension 拆宿主 dialog)只有真浏览器+真后端能复现,恰是单测够不着的盲区;20+ 个 spec 目前存在于磁盘、保护着零。

    排期:v17 发布后立即(以发布后的稳定 @objectstack/* 包为 CI 后端目标;纯 CI 增量,不占发版窗口)。摘 needs-user-decision,加 pm:queue。


    Generated by Claude Code


    Generated by Claude Code

  2. xuyushun441-sys commented on Aug 3, 2026

    @xuyushun441-sys
    Contributor

    排期提前(维护者 2026-08-03 追加裁决)—— 已认领,待 pin-bump 合并后派发

    会话 session_01NVPjPzmmAJ2Ngtvgg5MSRa。

    从「v17 发布后立即」提前至 rc.2 pin-bump 合并后立即。 原排期锚的是「发布后的稳定 @objectstack/* 包」作为 CI 后端目标——17.0.0-rc.2 今日已上 npm(dist-tag rc),这个前提已经满足:rc 是已发布的固定制品,装得到、可复现,正是 CI 后端需要的。等正式版只是多等,不多得。

    提前的额外红利

    CI 后端用已发布的 rc.2 起,等于每个 PR 都在跑一次 rc.2 × console 的集成冒烟。正式版发版前多一层网,而且抓的正好是单测够不着的那一类(e2e/live/** 覆盖的行操作、弹窗、主从、内联编辑、screen flow 全回路)。

    两条护栏(提前的代价必须被约束)

    1. 新 lane 先做 non-required check(informational,不阻塞合并)。objectstack#4850 有前科:spec 包一个测试超时把无关 PR 逐出了合并队列。新 CI lane 的 flake 风险必须先隔离在合并队列之外,稳定若干天后再议是否转必需。
    2. 按裁决的 allowlist 起步——screen-flow / action-modal / master-detail 三条,不要一次开 20+ 条把既有 flake 一并继承。

    裁决其余部分不变:同 PR 删除或重写 stale 的 dev-server job(ci.yml:283-307,对应 apps/dev-server 已不存在);DashboardRenderer.designMode 的 describe.skip(TODO(#ci-hang),2026-05-01 至今)纳入同一波范围核查。

    排在 pin-bump 之后的原因:后端起 rc.2、console 却仍 pin 着 rc.1 的话,测的是一个错配组合,绿也不说明问题。


    Generated by Claude Code


    Generated by Claude Code

  3. xuyushun441-sys commented on Aug 3, 2026

    @xuyushun441-sys
    Contributor

    开工认领确认:session session_01NVPjPzmmAJ2Ngtvgg5MSRa(与上方裁决同会话派发的开发 agent),分支 claude/issue-2835-live-e2e-ci。按追加裁决执行:non-required lane + allowlist(screen-flow / action-modal / master-detail)+ 同 PR 处理 stale dev-server job。


    Generated by Claude Code


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions