Skip to content

fix(e2e): make the runtime-error tests able to fail, drop a save race - #240

Merged
nk-o merged 1 commit into
masterfrom
claude/toolkit-0.6
Aug 11, 2026
Merged

fix(e2e): make the runtime-error tests able to fail, drop a save race#240
nk-o merged 1 commit into
masterfrom
claude/toolkit-0.6

Conversation

@nk-o

@nk-o nk-o commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

Toolkit 0.6.0 plus the fixes that came out of profiling this suite. Two of these are tests that currently cannot fail — those matter more than the seconds.

The runtime-error tests never observe the errors they exist to catch

lottie-block.spec.js and gist-block.spec.js both do:

const frontendPage = await publishAndGetFrontendPage(page, editor);
const runtimeErrors = trackRuntimeErrors(frontendPage);   // ← too late

publishAndGetFrontendPage does newPage()goto(href). Playwright does not buffer console or pageerror for listeners attached afterwards, and goto resolves on load — which has already waited for the async plugin scripts to both load and execute (classes/class-assets.php:413-414). So an error thrown during script evaluation was emitted and dropped before the listener existed.

relevantErrors was therefore always [], and expect(relevantErrors).toEqual([]) always passed.

The lottie one is the regression test for the duplicate customElements.define('lottie-player', …) fix. As written it would not catch a reintroduction.

The helper now takes an onPageReady callback and hands the page over before navigating.

Heads up for review: these two assertions have never actually run. If either now goes red, that is a real finding, not a broken test — the whole point of the change is that they can fail again.

The typography save is a race it loses

setFontSetting slept 1000 ms for a save the settings page debounces by exactly 1000 ms (settings/pages/typography.js:28-31) and then fires without awaiting (:254-260). The sleep expired as the POST was going out, and the page fixture closes the page at teardown, discarding anything in flight.

When it lost, the symptom appeared in a different test — Check fonts available on backend and frontend — as a mismatch against EXPECTED_GOOGLE_FONTS_FAMILY. Classic intermittent-and-baffling.

It now waits on the POST itself. No time saved; the 1000 ms is in the product.

The gist counters were asserted without retry

await expect(mockStats.jsonRequests).toBeGreaterThan(0)mockStats is a plain object the route handlers mutate, so await on a non-thenable buys nothing and the check ran once. That is precisely why a flat 1 s sleep had to sit in front of it. expect.poll retries and ends as soon as the mock fires.

Both sleeps (editor and frontend) are gone. ~1.6 s.

Smaller

  • Two waitForLoadState('domcontentloaded') calls that ran after goto had resolved on load — strictly later, so no-ops.
  • The build step is gone from the lint job. lint:js is biome check, and the shared Biome config excludes **/build; lint:css globs the SCSS sources. Neither reads anything the build produces. 8–15 s per PR.
  • @nk-crew/plugin-toolkit0.6.0 (toolkit#2): no tracing on tests that pass, and reportSlowTests restored so the next run prints its own slowest files.

Lockfile touched surgically — four fields for that one package. npm install --package-lock-only re-resolves the whole tree and, on a sibling repo, dropped two optional peers while flipping ~60 entries to dev.

Sleeps deliberately kept

console-errors.spec.js:100 and the two in lottie-block.spec.js are settle windows for the absence of a future event. There is no signal for "no error is coming", so a sleep is the correct tool.

Flagged, not fixed

ghostkit_typography is never reset. wp-env's database survives env:stop, so from the second run onward every editor boot enqueues a real fonts.googleapis.com stylesheet inside the load gate — which is likely why console-errors.spec.js has to ignore /fonts\.gstatic\.com/i and /net::ERR_/i. Test 4 also silently depends on tests 1–3 having run, so --grep on it alone fails.

I did not fix it: the obvious reset via update_custom_typography merges rather than replaces (classes/class-rest.php:1834-1856), so {} lands as [], and getting it right needs a local run.

Also flagged: publishAndGetFrontendPage and trackRuntimeErrors are copy-pasted across three spec files, which is why this fix had to be applied twice. Worth a tests/e2e/utils/ directory like the sibling plugins have.

Not included

assets-loading.spec.js boots the editor and publishes six times to produce content REST could create (est. 15–30 s). Detection is content-driven, so it should be equivalent — but it would stop the markup round-tripping through the editor's parse/serialize, and that wants a local run first.

The lottie and gist frontend tests attach their console/pageerror
listeners to the page `publishAndGetFrontendPage` returns -- after it has
already navigated. Playwright does not buffer those events for listeners
attached later, and `goto` resolves on `load`, which has already waited
for the async plugin scripts to load and execute. So any error thrown
during script evaluation was emitted and dropped before the listener
existed, `relevantErrors` was always empty, and
`expect(relevantErrors).toEqual([])` could not fail.

The lottie one is the regression test for the duplicate
`customElements.define` fix; as written it would not catch a
reintroduction. The helper now takes an `onPageReady` callback and hands
the page over before navigating.

typography's `setFontSetting` slept 1000ms for a save the settings page
debounces by exactly 1000ms and then fires without awaiting -- so the
sleep expired as the request went out, and the `page` fixture closes the
page at teardown, discarding anything still in flight. Losing that race
showed up in a later test as a font mismatch. It now waits on the POST.

gist asserted on `mockStats`, a plain object its route handlers mutate,
with a bare `expect` -- no retry, which is why a flat 1s sleep had to sit
in front of it. `expect.poll` ends as soon as the mock fires.

Also drops two `waitForLoadState('domcontentloaded')` calls that ran after
`goto` had already resolved on `load`, and the build step from the lint
job: `lint:js` is `biome check`, whose shared config excludes `**/build`,
and `lint:css` globs the SCSS sources -- neither reads build output.

Picks up @nk-crew/plugin-toolkit 0.6.0.

Not fixed, flagged instead: `ghostkit_typography` is never reset, so from
the second run on every editor boot enqueues a real fonts.googleapis.com
stylesheet, and test 4 silently depends on tests 1-3 having run. The
obvious reset through update_custom_typography merges rather than
replaces, so it needs a local run to get right.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8dea5e0891

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

// is why a flat 1s sleep used to sit above this -- polling ends as soon
// as the mock has fired instead.
await expect.poll(() => mockStats.jsonRequests).toBeGreaterThan(0);
await expect.poll(() => mockStats.cssRequests).toBeGreaterThan(0);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Wait for the mocked stylesheet to finish loading

In the editor test, cssRequests is incremented before route.fulfill() completes, so this poll only proves that the stylesheet request started. The bundled gist-simple code inserts the mocked gist and can emit the errors under test from the stylesheet's later load callback; because the fixed delay was removed, runtimeErrors can be filtered before that callback runs, allowing asynchronous regressions to pass. Wait for the rendered mocked gist content (such as .gist-file) or another post-load signal before inspecting the error array.

Useful? React with 👍 / 👎.

@nk-o
nk-o merged commit adbddf3 into master Aug 11, 2026
7 checks passed
@nk-o
nk-o deleted the claude/toolkit-0.6 branch August 11, 2026 11:00
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