Skip to content

feat(electron): add Playwright-driven e2e tests for the demo app#133

Open
Harriet-star-glitch wants to merge 1 commit into
floatboatai:mainfrom
Harriet-star-glitch:feat/electron-demo-e2e-tests
Open

feat(electron): add Playwright-driven e2e tests for the demo app#133
Harriet-star-glitch wants to merge 1 commit into
floatboatai:mainfrom
Harriet-star-glitch:feat/electron-demo-e2e-tests

Conversation

@Harriet-star-glitch

Copy link
Copy Markdown

Summary / 摘要

Adds a real end-to-end test layer (Roadmap #25) that drives the packaged electron-demo build via Playwright's _electron — real Chromium, real main process, real IPC — instead of jsdom.

Motivation / 背景与动机

  • Issue:
  • Roadmap (docs/ROADMAP.md): 完成笔试题 #25 End-to-end testing, P1, marked done in this PR. Row says "Needs OpenSpec: No", so no proposal opened.
  • OpenSpec change: none (test infra, exempted per CONTRIBUTING.md §3.1)

Changes / 变更内容

  • apps/electron-demo:
    • e2e/driver.ts: launchApp()/closeApp() helper. Resolves the electron binary via the electron package's own export (portable, no hardcoded paths) and strips ELECTRON_RUN_AS_NODE from the spawned env — some sandboxed/CI shells set it to stop a stray electron invocation from opening a GUI window, which would otherwise make the launch handshake silently time out.
    • e2e/smoke.e2e.test.ts: three golden-path scenarios — app launches to an empty editor, live-preview renders typed markdown (heading/bold/italic), and a GFM task checkbox toggles via a real DOM click.
    • vitest.e2e.config.ts + new test:e2e script: separate from the default pnpm test on purpose (needs a prior pnpm build + a display).
    • tsconfig.json: include e2e/**/*.ts so it's typechecked.
    • package.json: new playwright-core devDependency.
  • vitest.config.ts (root): excludes **/e2e/**. Without this the root pnpm test picked the new file up anyway (vitest's default include glob matches any *.test.ts regardless of the .e2e. infix) and ran it under jsdom with no built app — confirmed by actually running pnpm test before adding the exclude and watching it try (and fail the isolation goal, though the individual test happened to still pass).
  • docs/ROADMAP.md: 完成笔试题 #25 → done, documents how to run it and what's out of scope for this first pass.

Explicitly out of scope (flagging so it doesn't look like an oversight):

  • CI wiring (Roadmap feat(search): 增加整词匹配支持 #26, "missing e2e gate") — different roadmap item, kept separate per CONTRIBUTING.md "one PR, one concern".
  • Vault/file-IO e2e coverage — the vault flow goes through a real native OS file picker dialog (dialog.showOpenDialog), which Playwright can't drive directly; bypassing it needs its own design (e.g. a test-only IPC shortcut) rather than folding it into this PR.

Testing / 测试

  • pnpm test passes (515/515) — confirmed the e2e file does NOT run here after the vitest.config.ts exclude fix
  • pnpm typecheck passes repo-wide
  • pnpm build passes repo-wide
  • New e2e suite: pnpm --filter @floatboat/nexus-electron-demo build && pnpm --filter @floatboat/nexus-electron-demo test:e2e — 3/3 passing, run 4 times total (~3s each) with no flakiness observed
  • Manual UI check in electron-demo — n/a, this PR is the automated version of that manual check

Compliance / 合规自检

  • CLA signed — will sign if/when the bot prompts
  • AI disclosure: this PR's functional code is primarily AI-generated, same as my prior PR (feat(live-preview): add grip-handle drag reorder for list items #132) on this repo. I asked Claude (Anthropic's Claude Code) to pick the hardest of the roadmap items I'd surveyed and implement it end-to-end — the driver, the tests, the config isolation fix, and the roadmap update. I reviewed the diff, the actual test:e2e output across multiple runs, and the repo-wide pnpm test/typecheck/build results, and caught (and had it fix) one real bug along the way: the checkbox e2e assertion originally trusted a stale DOM reference after .click(), which the app's own decoration-keying behavior detaches. I have not independently rewritten the implementation myself. Disclosing this explicitly per GOVERNANCE.md §6.2 rather than checking "not AI-generated" — understand maintainers may decide this doesn't meet that bar.
  • New dependencies: playwright-core@^1.61.1 (devDependency, apps/electron-demo only) — Apache-2.0 license — needed to drive the packaged Electron app from outside its process; -core variant specifically because it doesn't bundle/download its own browser binaries, it drives the project's own already-installed Electron binary.
  • No build artifacts committed
  • No secrets committed

Checklist / 自检清单

  • Title follows Conventional Commits
  • Public API changes update package README — n/a, electron-demo is a private app, not a published package
  • Touched live-preview-table.ts — n/a, not touched in this PR
  • New capability / breaking change → OpenSpec — test infra is exempt per CONTRIBUTING.md §3.1 ("bug fixes, internal refactors, dependency bumps, test/doc additions" don't need a proposal); confirmed against the ROADMAP.md row's own "Needs OpenSpec: No"
  • Change aligns with project scope

Roadmap floatboatai#25 (End-to-end testing) — no OpenSpec required per the
roadmap row. Adds a real end-to-end layer that drives the *packaged*
electron-demo build (real Chromium, real main process, real IPC) via
playwright-core's `_electron`, catching the class of bug that never
shows up in the jsdom unit suite: production build wiring, preload
bridge exposure, real layout/paint, real mouse coordinates.

- apps/electron-demo/e2e/driver.ts: launchApp()/closeApp() helper.
  Resolves the electron binary via the `electron` package's own export
  (portable — no hardcoded paths) and strips ELECTRON_RUN_AS_NODE from
  the spawned env, since some sandboxed/CI shells set it to stop a
  stray `electron` invocation from opening a GUI window, which would
  otherwise make the launch handshake silently time out.
- apps/electron-demo/e2e/smoke.e2e.test.ts: three golden-path
  scenarios — app launches to an empty editor, live-preview renders
  typed markdown (heading/bold/italic), and a GFM task checkbox
  toggles via a real DOM click. The checkbox assertion re-queries the
  element after clicking rather than trusting the original reference:
  its click handler dispatches a CM6 change whose decoration key
  embeds the checked state, so CM6 replaces the <input> node
  synchronously and the original reference is left detached.
- apps/electron-demo/vitest.e2e.config.ts + new `test:e2e` script:
  separate from the default `pnpm test` on purpose — these need a
  prior `pnpm build` and a display, so keeping them in the default
  jsdom run would make the fast unit suite flaky in headless CI.
- vitest.config.ts: excludes `**/e2e/**` from the root config. Without
  this, the root `pnpm test` picked the new file up anyway (vitest's
  default include glob matches any `*.test.ts`, `.e2e.` infix or not)
  and ran it under jsdom with no built app — confirmed by running
  `pnpm test` before adding the exclude.
- docs/ROADMAP.md: floatboatai#25 marked done, documents how to run it and what's
  intentionally out of scope for this first pass (vault/file-IO e2e
  coverage — needs a way to bypass native OS file dialogs, which is
  its own piece of work).

CI wiring (roadmap floatboatai#26, "missing e2e gate") is intentionally not part
of this PR — different roadmap item, kept separate per "one PR, one
concern".

Verified: `pnpm --filter @floatboat/nexus-electron-demo build` then
`test:e2e` — 3/3 passing, stable across 3 consecutive runs (~3s each).
Full repo `pnpm test` (515/515), `pnpm typecheck`, and `pnpm build`
all pass unaffected.
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants