Skip to content

test(e2e): wait for Monaco to hold focus before pasting into it - #32

Merged
mindaugaskasp merged 2 commits into
mainfrom
fix/monaco-paste-focus-race
Aug 7, 2026
Merged

test(e2e): wait for Monaco to hold focus before pasting into it#32
mindaugaskasp merged 2 commits into
mainfrom
fix/monaco-paste-focus-race

Conversation

@mindaugaskasp

Copy link
Copy Markdown
Owner

snippet-image.spec.mjs failed on CI three times today and blocked the v0.4.15 release twice, always identically: the editor's first .view-line was still empty after the paste.

The race

webContents.paste() delivers to whatever holds focus at that moment. The spec clicked .editor and pasted immediately:

await editor.locator('.editor').click()
await app.evaluate(({ clipboard }, text) => clipboard.writeText(text), body)
await app.evaluate(({ BrowserWindow }) => …webContents.paste())
await expect(editor.locator('.view-line').first()).not.toHaveText('')   // ← empty

Under CI load Monaco has not finished wiring its hidden textarea.inputarea by the time the paste fires, so the paste lands nowhere. Locally the click always won the race — which is exactly why this only ever showed up on CI, and why re-running "fixed" it.

The fix

focusEditor() clicks and then waits for that textarea to be focused — the only signal that a paste will actually arrive. Shared in e2e/monaco.mjs rather than copied into both specs, because the second copy is what drifts.

Verification — red → green

  • The wait is load-bearing, not vacuous: with the click removed from focusEditor, the focus assertion fails. So it is genuinely waiting for something.
  • With it restored: snippet-image.spec.mjs + compare-snippets.spec.mjs, 12 tests, three consecutive clean runs (22.5s / 20.0s / 20.3s).

🤖 Generated with Claude Code

mindaugaskasp and others added 2 commits August 7, 2026 03:06
`snippet-image.spec.mjs` failed on CI three times and blocked the v0.4.15
release twice, always the same way: the editor's first `.view-line` was
still empty after the paste.

The cause is a race, not the editor. `webContents.paste()` delivers to
whatever holds focus AT THAT MOMENT, and the spec clicked `.editor` and
then pasted immediately. Under CI load Monaco has not finished wiring its
hidden `textarea.inputarea` by then, so the paste lands nowhere and the
editor stays empty. Locally the click always won the race, which is why
this only ever appeared on CI.

`focusEditor()` clicks and then waits for that textarea to be focused —
the only signal that a paste will actually arrive. Both call sites use it
(`snippet-image` and `compare-snippets`); it is shared rather than copied
because the second copy is what drifts.

Verified the wait is load-bearing rather than vacuous: with the click
removed the focus assertion fails, and with it restored the two specs
passed three consecutive runs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
compare-snippets.spec.mjs:45 already spends two 15s waits inside a 30s
budget, and the extra round trip tipped it over on CI. It has never been
observed flaking, so it goes back to the plain click and monaco.mjs says
why.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@mindaugaskasp
mindaugaskasp merged commit dd3f9db into main Aug 7, 2026
6 checks passed
@mindaugaskasp
mindaugaskasp deleted the fix/monaco-paste-focus-race branch August 7, 2026 00:23
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.

1 participant