Repository navigation
Conversation
roncodes
added a commit
that referenced
this pull request
Aug 25, 2026
Also names what the workflow's existing `test -s coverage/lcov.info` step does and does not catch: it guards the crudest form of the missing-artifact case, but it checks lcov.info rather than coverage-final.json and only tests existence, so a stale artifact from a previous run passes it.
This was referenced Aug 25, 2026
roncodes
added a commit
that referenced
this pull request
Aug 25, 2026
The parallel option is not the fix. reportCoverage() only renames the output folder to coverage_<hex> and forces the json reporter, requiring a separate coverage-merge step; the browser-to-disk path is unchanged, so it would break the current setup without touching the cause. Ruled out by reading the source rather than spending the runs. Moving forceModulesToBeLoaded() from QUnit.done to QUnit.begin was the better hypothesis: on a filtered run almost nothing is loaded, so force-loading is a large synchronous burst that delays the POST, while full runs have already loaded nearly everything. That is the only theory so far that explains why fast runs fail and slow ones do not. It produced 0 artifacts in 3 runs and was reverted rather than committed unproven — though 0-of-3 against a ~22% baseline happens about half the time, so it is not disproven either. Retry with ten runs if anyone wants to settle it. Also recorded: QUnit 2.25 does await promises returned from done callbacks (runLoggingCallbacks builds a serial chain), so 'QUnit does not wait' is not the explanation. The next thing worth checking is whether the POST reaches the middleware at all on a failing run, which splits 'never sent' from 'sent, server died first'.
roncodes
added a commit
that referenced
this pull request
Aug 25, 2026
Instrumented the middleware's coverageHandler with four log points and ran the
fast filter three times on port 7399. A failing run produces ZERO probe lines:
the middleware is never entered. The successful run produced all four.
That eliminates every server-side explanation. It is not 'sent, and the write
died' — the request never arrives. The fault is in the browser, between
fetch('/write-coverage') being called and the request completing, which is also
why moving forceModulesToBeLoaded() changed nothing: the problem was never a
delay before the POST.
The surviving explanation fits the run-length asymmetry that made this look
random. QUnit 2.25 runs done callbacks as a serial promise chain in registration
order, and testem's adapter registers before tests/test-helper.js — so testem
learns the run ended and starts closing the browser while sendCoverage() is
still in flight. After 139 tests testem has nothing to serialize and the browser
dies in milliseconds; after 5130 tests, emitting the results buys the fetch
enough time to land.
Fix candidates recorded in order: keepalive:true on the existing fetch (one word,
same underlying mechanism), navigator.sendBeacon (built for delivery during
teardown; the response only feeds an on-screen badge), or registering the
coverage handler before testem's. Verify any of them the same way — ten fast
filtered runs against the ~22% baseline.
The probe lived in node_modules and has been restored; nothing of it is
committed.
roncodes
added a commit
that referenced
this pull request
Aug 25, 2026
…(DEFECTS #16) The cause, at last, and it is a known upstream bug rather than anything odd about this repo. sendCoverage() POSTs ~1.9 MB to /write-coverage — 401 instrumented files, because a per-file 100% gate needs forceModulesToBeLoaded() to evaluate everything so untested files stay in the denominator. In CI mode testem tears the browser down the moment QUnit reports the run finished, truncating the upload mid-body. raw-body aborts, coverageHandler is never reached, and nothing is written. That is why it looked like flakiness rather than a bug: it depends on how long the run took. After 139 tests testem has almost nothing to serialize and kills the browser in milliseconds; after 5130 tests, emitting the results buys the upload enough time to land. Measured 2 of 9 artifacts on fast filtered runs against 100% on full runs, with `BadRequestError: request aborted` correlating 1:1 with every failure. Testem.afterTests hands testem a callback it WAITS for, so the upload finishes before teardown. It does not fire under --server, hence the branch on config.APP.isRunningWithServerArgs. Upstream, all with the identical raw-body:245 stack: ember-cli-code-coverage#420 (Aug 2024), #421, testem#1577 Our measurements are added to #420. Measured: 2 of 2 fast filtered runs now produce an artifact with no abort. Full suite unchanged — 5130 pass, 0 fail, lint 0. Ruled out and recorded so nobody retries them: keepalive:true and sendBeacon (the Fetch spec caps both at 64 KiB, ~30x under our payload), and moving forceModulesToBeLoaded() to QUnit.begin (0 of 3, and against the guidance in the addon's own source, which says to call it after the suite). Also recorded a debugging trap: instrumenting coverageHandler shows nothing on a failing run, which reads as "the POST never arrived". It does arrive and dies inside bodyParser, before the handler. I drew the wrong conclusion from that and had to retract it; instrument in front of bodyParser, not behind it. The freshness gate from PR #163 stays. It is what made this failure loud instead of silent, and it is still the guard against reading a stale report. DEFECTS #18 opened: branch totals still vary by +/-1 between identical runs (5825 vs 5826 across three otherwise-identical full runs). Same class of gate blocker #4 was, culprit not yet located.
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 join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
No description provided.