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
Conversation
There was a problem hiding this comment.
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 targetede2e:*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 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)); |
Member
Author
There was a problem hiding this comment.
Caught — the Math.min flipped the intent. Fixed in 7849554: split into two independent guarantees that must both hold:
expect(recordedWidth).toBeGreaterThanOrEqual(50)— the bar's 50 px clamp floorexpect(recordedWidth).toBeGreaterThan(startWidth)— proves the drag actually grew the width; a regression that pinned width tostartWidthwould now fail loudly
Local Chromium run: still green (562ms).
663dd8f to
7849554
Compare
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>
86e6494 to
6993010
Compare
2 tasks
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.
playwright.config.tswith engine-specific
testIgnorelists for Phase 1 specs that rely on Chromium-onlybehaviour (triple-click select-paragraph, host #search/#replace toolbar
driver). New
pnpm e2e:chromium/:firefox/:webkitaliases.ci-e2e.yml) installs all three browsers viaplaywright install --with-deps chromium firefox webkit.tests/typing/ime.spec.ts) — CJK candidate flowdriven 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.tscover the composeHandler branches directly).
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.
tests/editing/clipboard.spec.ts) — replacethe
test.fixmewith syntheticClipboardEvent+ populatedDataTransfer. Chromium-only — Firefox nullsclipboardDataonsynthetic 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 slocal; CI target ~4-6 min including bundled browser install).
pnpm exec eslint e2eclean.pnpm lint:typesclean (turbo).pnpm e2e:chromium,pnpm e2e:firefox,pnpm e2e:webkitall pass their respective subsets.
--with-depssuccessfully (verified via the updated workflow step).
Skipped-test ledger
inline/format-toolbar.spec.tsinline/shortcuts.spec.tsediting/search-replace.spec.tsediting/clipboard.spec.ts(4 new specs)clipboardDataon synthetic ClipboardEventstyping/ime.spec.ts(3 specs)All carryovers are tracked in
e2e/BACKLOG.mdPhase 3.🤖 Generated with Claude Code