Skip to content
This repository was archived by the owner on May 29, 2026. It is now read-only.

test(e2e): Phase 2 — cross-browser matrix + drag/IME#239

Merged
Jocs merged 4 commits into
masterfrom
test/e2e-phase-2-cross-browser-and-drag
May 21, 2026
Merged

test(e2e): Phase 2 — cross-browser matrix + drag/IME#239
Jocs merged 4 commits into
masterfrom
test/e2e-phase-2-cross-browser-and-drag

Conversation

@Jocs
Copy link
Copy Markdown
Member

@Jocs Jocs commented May 21, 2026

Summary

Phase 2 of the E2E roadmap. Brings the suite from Chromium-only / 54 passed
to a full Chromium + Firefox + WebKit matrix at 169 passed, 11 skipped.

  • Cross-browser projects unlocked in playwright.config.ts with engine-
    specific testIgnore lists for Phase 1 specs that rely on Chromium-only
    behaviour (triple-click select-paragraph, host #search/#replace toolbar
    driver). New pnpm e2e:chromium / :firefox / :webkit aliases.
  • CI (ci-e2e.yml) installs all three browsers via
    playwright install --with-deps chromium firefox webkit.
  • IME composition (tests/typing/ime.spec.ts) — CJK candidate flow
    driven through dispatched CompositionEvent + InputEvent(isComposing)
    bursts; covers paragraph, list-item, and non-empty table-cell contexts.
    Skipped on WebKit (synthetic IME unreliable under parallel-matrix load;
    unit tests in packages/core/src/block/base/__tests__/autoPair.spec.ts
    cover the composeHandler branches directly).
  • Drag plugins (tests/drag/) — TableDragBar column reorder,
    ParagraphFrontButton block reorder, ImageResizeBar handle drag. The
    table drag bar is a reorder tool, not a resize tool — the original
    BACKLOG framing ("assert column meta width changed") was based on a
    misreading; cells don't carry a width meta.
  • Real HTML clipboard (tests/editing/clipboard.spec.ts) — replace
    the test.fixme with synthetic ClipboardEvent + populated
    DataTransfer. Chromium-only — Firefox nulls clipboardData on
    synthetic ClipboardEvents (bug 1456493) and WebKit denies the
    permission headless. Tracked in BACKLOG Phase 3.

Test plan

  • pnpm e2e — 169 passed, 11 skipped across all three engines (~30 s
    local; CI target ~4-6 min including bundled browser install).
  • pnpm exec eslint e2e clean.
  • pnpm lint:types clean (turbo).
  • Targeted runs: pnpm e2e:chromium, pnpm e2e:firefox, pnpm e2e:webkit
    all pass their respective subsets.
  • CI Linux runner installs all three browsers with --with-deps
    successfully (verified via the updated workflow step).

Skipped-test ledger

Engine Spec Reason
Firefox + WebKit inline/format-toolbar.spec.ts triple-click select-paragraph (Chromium-only behaviour)
Firefox + WebKit inline/shortcuts.spec.ts same as above
Firefox + WebKit editing/search-replace.spec.ts host toolbar driver swallows mid-flight selection changes
Firefox + WebKit editing/clipboard.spec.ts (4 new specs) engines null clipboardData on synthetic ClipboardEvents
WebKit typing/ime.spec.ts (3 specs) synthetic CompositionEvent unreliable under parallel matrix

All carryovers are tracked in e2e/BACKLOG.md Phase 3.

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings May 21, 2026 03:56
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Expands the muya-e2e Playwright suite from Chromium-only to a Chromium + Firefox + WebKit project matrix, adding Phase 2 coverage for IME composition, drag/reorder/resize plugins, and synthetic HTML clipboard paste; updates CI and docs accordingly.

Changes:

  • Enable Firefox and WebKit projects in e2e/playwright.config.ts, add per-engine ignore lists, and add targeted e2e:* scripts.
  • Add new E2E specs for IME composition, table column reorder, paragraph reorder, image resize, and real-HTML clipboard paste (Chromium-only where required).
  • Update CI to install all Playwright browsers and update host/docs/backlog for Phase 2.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
e2e/tests/typing/ime.spec.ts Adds synthetic CompositionEvent/InputEvent-driven IME composition coverage (skips WebKit).
e2e/tests/helpers/selectors.ts Extends float selectors for paragraph front button inner element and image transformer handles.
e2e/tests/editing/clipboard.spec.ts Replaces fixme with Chromium-only synthetic DataTransfer clipboard paste assertions.
e2e/tests/drag/table-drag-bar.spec.ts Adds TableDragBar column reorder E2E tests and visibility polling logic.
e2e/tests/drag/paragraph-reorder.spec.ts Adds paragraph front-button drag reorder E2E test.
e2e/tests/drag/image-resize.spec.ts Adds ImageResizeBar handle-drag E2E test asserting width rewrite in markdown.
e2e/README.md Documents cross-browser matrix runs and browser installation expectations.
e2e/playwright.config.ts Enables Firefox/WebKit projects with engine-specific testIgnore.
e2e/package.json Adds e2e:chromium/firefox/webkit scripts and updates e2e:install to install all browsers.
e2e/host/main.ts Refactors Intl.Segmenter polyfill setup into an async helper with top-level await.
e2e/BACKLOG.md Marks Phase 2 as landed and updates counts / carryovers.
.github/workflows/ci-e2e.yml Installs chromium+firefox+webkit in CI before running the E2E suite.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread e2e/tests/drag/image-resize.spec.ts Outdated
Comment on lines +91 to +95
// Width should be at least roughly the original; with the +80 px
// drag it normally lands well above start, but engines render
// the natural width differently — assert ≥ startWidth (the bar
// clamps to a 50 px floor, so it can't shrink below that).
expect(recordedWidth).toBeGreaterThanOrEqual(Math.min(50, startWidth));
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caught — the Math.min flipped the intent. Fixed in 7849554: split into two independent guarantees that must both hold:

  1. expect(recordedWidth).toBeGreaterThanOrEqual(50) — the bar's 50 px clamp floor
  2. expect(recordedWidth).toBeGreaterThan(startWidth) — proves the drag actually grew the width; a regression that pinned width to startWidth would now fail loudly

Local Chromium run: still green (562ms).

@Jocs Jocs force-pushed the test/e2e-phase-2-cross-browser-and-drag branch from 663dd8f to 7849554 Compare May 21, 2026 04:05
Jocs and others added 4 commits May 21, 2026 12:36
Unlocks Firefox + WebKit and adds the input/drag/clipboard flows that
require either engine-specific event sequences or synthetic DataTransfer
plumbing.

Cross-browser matrix
- Uncomment firefox + webkit projects in playwright.config.ts; ship per-
  engine testIgnore lists for the Phase 1 specs that rely on Chromium-
  only behaviour (triple-click select-paragraph, host #search/#replace
  toolbar sequencing).
- e2e/package.json gains e2e:chromium / e2e:firefox / e2e:webkit
  aliases; e2e:install now downloads all three browsers.
- ci-e2e.yml installs all three with --with-deps.
- README documents the new matrix runner and per-engine flags.

IME composition (tests/typing/ime.spec.ts)
- Drive CJK candidate flow via dispatched CompositionEvent +
  InputEvent(isComposing) bursts; assert text only lands after
  compositionend. Covers paragraph, list-item, and non-empty table-cell
  parent contexts. Skipped on WebKit (synthetic IME unreliable under
  parallel matrix load).

Drag plugins (tests/drag/)
- table-drag-bar.spec.ts — hover just below a header cell, mousedown +
  300 ms hold + drag past next column + mouseup → assert getMarkdown()
  returns the columns in swapped order. Bar is a reorder tool, not a
  resize tool (cells carry no width meta — original BACKLOG framing was
  based on a misreading).
- paragraph-reorder.spec.ts — drag the front-button handle from
  paragraph A to a point below paragraph B → assert markdown order
  swapped.
- image-resize.spec.ts — click a block-aligned data-URI image
  (network-free), drag the right .bar handle 80 px → assert
  <img width="N"> lands in the markdown.

Real HTML clipboard (tests/editing/clipboard.spec.ts)
- Replace the test.fixme with synthetic ClipboardEvent + populated
  DataTransfer paste. Covers <b>foo</b> → **foo**, <a href> →
  [text](url), basic <table> → GFM table, and plain-text fallback.
  Chromium-only — Firefox nulls clipboardData on synthetic
  ClipboardEvents (bug 1456493) and WebKit denies the permission
  headless. The keyboard Cmd/Ctrl+V path doesn't help: headless
  Chromium has an empty OS clipboard so the keystroke fires with
  clipboardData: null. Tracked in BACKLOG Phase 3.

Result: 169 passed, 11 skipped across Chromium + Firefox + WebKit
(up from 54 passed + 1 fixme on Chromium-only). pnpm exec eslint e2e
clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot caught that `expect(recordedWidth).toBeGreaterThanOrEqual(Math.min(50, startWidth))` degrades to a trivial `>= 50` check when startWidth > 50 — a regression that pinned width to start would still pass.

Split into two independent guarantees:
  (1) recordedWidth >= 50 — the bar clamps to a 50 px floor
  (2) recordedWidth > startWidth — verifies the drag actually increased width (the "drag worked" assertion)

Test still green locally.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
CI's bundled Chromium-for-Testing fails 4/4 paste tests because the
synthetic `new ClipboardEvent('paste', { clipboardData: dt })` leaves
`event.clipboardData === null` on CfT — muya's pasteHandler sees null
and returns early, paragraph stays empty. The synthetic-dispatch
approach only worked locally because Playwright's `channel: 'chrome'`
fallback used Chrome stable, which is lenient about synthetic
ClipboardEvents; bundled Chromium follows the spec strictly.

Rewrote pasteClipboard / pastePlainClipboard helpers to use the
spec-compliant path:

1. `test.use({ permissions: ['clipboard-read', 'clipboard-write'] })`
   at describe level so navigator.clipboard.write succeeds without
   a user-gesture prompt.
2. `navigator.clipboard.write([new ClipboardItem({ 'text/html': ...,
   'text/plain': ... })])` writes to the real OS clipboard.
3. `muya.focus() + muya.domNode.focus()` (matches the autopair fix
   pattern) so DOM focus lands inside the contenteditable.
4. `page.keyboard.press('${meta}+v')` fires a trusted paste keystroke
   whose `event.clipboardData` is populated by the browser.

Firefox/WebKit still skip these tests (ClipboardItem text/html is
gated/unavailable in headless on those engines — Playwright
issue #13037 + Firefox pref) — tracked in BACKLOG Phase 3.

Local Chromium: 5/5 pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Last CI run failed all WebKit clipboard tests with
  Error: browserContext.newPage: Unknown permission: clipboard-write

WebKit doesn't recognise the `'clipboard-write'` permission name, and
`test.use({ permissions: [...] })` at describe level registers the
grant in the BrowserContext factory — it runs *before* the per-test
`test.skip(browserName !== 'chromium', …)` inside the test body, so
WebKit hits the unknown-permission throw before reaching skip.

Moved grantPermissions into a small helper called *after* the skip
check, so it's only reached on chromium where the names are valid.

Local Chromium: 5/5 still green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Jocs Jocs force-pushed the test/e2e-phase-2-cross-browser-and-drag branch from 86e6494 to 6993010 Compare May 21, 2026 04:36
@Jocs Jocs merged commit c7b2100 into master May 21, 2026
5 of 6 checks passed
@Jocs Jocs deleted the test/e2e-phase-2-cross-browser-and-drag branch May 21, 2026 04:37
Jocs added a commit that referenced this pull request May 21, 2026
* test(e2e): skip 10k-paragraph perf budget on webkit and firefox

The 60s budget added in #238 was calibrated against chromium (~20s
observed locally) before the cross-browser matrix landed in #239.
WebKit on ubuntu-latest against the Vite dev server consistently runs
108-120s; firefox 62-68s. Both blow the budget on every run, and the
3-attempt retry cycle has been pushing the e2e job past its 15min cap
(#240 was cancelled by the GHA timeout for this reason).

Skip the perf assertion on non-chromium browsers as a short-term fix
so PR CI can stay green. The longer-term plan, already documented in
the file header, is to move @Perf tests to a nightly schedule against
a production bundle.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(ci): exclude @Perf tests from PR-time e2e job

The per-browser skip added in the first iteration of this PR turned
out to be incomplete: chromium on GHA ubuntu-latest also overshoots
the 60s budget (~70s observed) once running against the Vite dev
server, not just the webkit ~115s and firefox ~65s seen in the prior
runs. All three browsers blow the budget; only the local M-class
macOS Chromium baseline (~20s) actually fits.

Switch to the project's already-documented plan (see file header):
exclude @perf-tagged tests from PR-time CI via --grep-invert. Future
@Perf tests automatically pick up the same treatment, and the test
file stays free of skip logic. The follow-up to move @Perf onto a
nightly schedule against a production bundle becomes a small
workflow addition rather than a rewrite.

Revert the per-browser test.skip in perf.spec.ts so the local
`pnpm e2e` invocation still runs the regression guard on all three
browsers.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants