open-design/e2e/lib/timeouts.ts
Patrick A 32fd5286b5
chore(e2e): improve test framework quality (#2305)
* chore(e2e): improve test framework quality

- Add lib/timeouts.ts with CI-scaled short/medium/long/xlong constants
- Add lib/playwright/mock-factory.ts to centralise standard localStorage,
  /api/agents, and /api/app-config mock setup; migrate critical-smoke and
  workspace-keyboard-flows to use applyStandardMocks()
- Delete empty lib/shared.ts placeholder
- Replace waitFor({ state: 'detached' }).catch(() => {}) with
  waitFor({ state: 'hidden' }) in all UI tests; 'hidden' resolves
  immediately when the element was never in the DOM, eliminating the
  silent error-swallowing catch
- Remove redundant .catch(() => false) from all isVisible() call sites
  since isVisible() never throws in Playwright
- Convert .waitFor().then(() => true).catch(() => false) guards in
  openDesignFile() to explicit try/catch blocks for clarity
- Simplify sendPrompt() in app.test.ts: replace the 3-attempt manual
  retry loop with a single fill + pressSequentially fallback; the core
  workaround for contenteditable unreliability is preserved but the
  loop structure is gone

* fix(e2e): guard routeMockAgents to GET only

routeMockAgents was intercepting all HTTP methods and returning the mock
fixture, silently swallowing any agent mutation requests. Mirror the
GET-only guard from routeAppConfig so writes fall through to the daemon.

* fix(e2e): address code review findings

- sendPrompt() in app.test.ts, workspace-keyboard-flows.test.ts,
  app-restoration.test.ts: drop fill() (unreliable on contenteditable,
  inputValue() always returns '' for them) and go straight to
  pressSequentially(), which types key-by-key and is authoritative
- Import T from timeouts.ts in app.test.ts and use T.short for the
  input/button waits, making the timeouts module non-dead

* fix(e2e): resolve adversarial review findings

- Revert sendPrompt to fill(): chat-composer-input is a textarea, not
  contenteditable; fill() is atomic and ~60x faster than pressSequentially
- Use T.medium in all waitForLoadingToClear calls: CI workers scale this
  to 20s automatically via the CI env var, eliminating cold-runner flakes
- Add T import to 6 files that needed it for T.medium
- Fix openDesignFile try/catch scope in app-manual-edit: previously the
  catch block only caught waitFor but click/expect errors were also swallowed;
  now only waitFor is inside try, real interaction failures propagate
- Fix regex escaping: .replace('.', '\\.') -> .replace(/\./g, '\\.') in
  app-manual-edit and app-design-files to handle multi-dot filenames
- Migrate entry-chrome-flows.test.ts to applyStandardMocks: it had the
  identical 3-call setup pattern as the factory but was not migrated
- Add GET method guard to project-management-flows app-config route handler,
  matching the pattern used by every other route handler in the suite
- Remove no-op 'as const' from timeouts.ts: Math.ceil returns number,
  not a literal, so the assertion had no effect
- Update e2e/AGENTS.md: remove deleted lib/shared.ts entry, document
  lib/timeouts.ts and lib/playwright/mock-factory.ts

* fix(e2e): scope openDesignFile try/catch to waitFor only

Move click and expect(preview).toBeVisible() outside the catch block so
that a regression in either open path (tab-click or file-list fallback)
fails loudly instead of being silently absorbed. The try now wraps only
the fileTabButton.waitFor existence probe; the subsequent click and final
assertion are unconditional.

---------

Co-authored-by: Patrick A <186436799+eefynet@users.noreply.github.com>
Co-authored-by: Patrick A <259201958+eefynet@users.noreply.github.com>
2026-05-23 00:24:32 +08:00

9 lines
267 B
TypeScript

// CI machines are slower; scale all waits proportionally.
const scale = process.env.CI ? 2.0 : 1.0;
export const T = {
short: Math.ceil(3_000 * scale),
medium: Math.ceil(10_000 * scale),
long: Math.ceil(30_000 * scale),
xlong: Math.ceil(60_000 * scale),
};