chore(deps): vitest 1 -> 4 as one coupled upgrade (supersedes #284, #288) - #298
Merged
Conversation
added 2 commits
August 21, 2026 07:22
… 6, coverage-v8 4) Combines dependabot #284 (vitest) and #288 (@vitest/coverage-v8). They cannot land separately: vitest 4.1.11 peers `@vitest/coverage-v8: 4.1.11` EXACTLY, so either PR alone produces a tree `npm ci` refuses. The peer chain drags in two more packages, so this is a four-package move: vitest ^1.6.1 -> ^4.1.11 @vitest/coverage-v8 ^1.6.1 -> ^4.1.11 (exact-pinned to vitest) vite ^5.4.0 -> ^7.3.6 (vitest 4 peers ^6 || ^7 || ^8) @vitejs/plugin-vue ^5.2.1 -> ^6.0.8 (needed for vite 7) vite 7, not vite 8, deliberately. vite 8.2.2 is the current latest, but this repo's `.npmrc` sets `min-release-age=2` — a supply-chain cooldown that makes the lockfile lag newly published versions ON PURPOSE. Pulling a package inside its cooldown window is how you get a lock that resolves differently in CI than locally. vite 7.3.6 is well outside it and satisfies vitest 4's peer range. Five tests failed, all the same latent race ------------------------------------------- Three in ManifestDiff.spec.js, one in PageDesignerHost.spec.js, one in ApplicationDetailHeader.spec.js. None is a vitest bug and none needed a production change — every one is a test seeding component state while that component's own mounted-hook fetch is still in flight. ManifestDiff is the clearest. The test mounts, then immediately does: await wrapper.setData({ fromBlob: sampleFrom, toBlob: sampleTo }) with a comment claiming this "skips the async fetch". It does not skip it, it RACES it. The mocked axios resolves `{from: null, to: null}`, and whichever settles second wins. Under vitest 1 setData won; under vitest 4 the fetch does, nulls `fromBlob` straight back out, and `diffParts` computes over two empty strings and returns []. Verified directly rather than guessed — a probe printed `fromBlob: null` immediately after an awaited setData, while `diffLines` itself was confirmed to be a working function returning correct hunks. PageDesignerHost is the same shape wearing different clothes: it arms `mockRejectedValueOnce` before the mount-time `load()` has settled, so the mount's own request eats the rejection and the explicit `load()` succeeds. ApplicationDetailHeader assigns `wrapper.vm.versions` while the mounted hook is still fetching and assigning that same field. Fixed by letting the mount settle first (`await flushPromises()` / `await flush(wrapper)`) before seeding, with a comment at each site saying what the ordering depends on. These tests were correct-by-accident for three major versions. before: 3 files failed, 5 tests failed, 1373 passed after: 141 files passed, 1378 tests passed The coverage baseline is recalibrated, and that number needs reading carefully ------------------------------------------------------------------------------- tests/.coverage-baseline.json vitest: 85.18 -> 64.72. This is NOT 20 points of lost coverage. The suite is identical — 1378 tests before and after. The instrument changed: coverage-v8 v1: src/App.vue = 235 lines (exactly its `wc -l`) coverage-v8 v4: src/App.vue = 24 lines across src/**: 59,333 -> 10,097 lines, over the same ~200 files v1 treated every physical line as coverable — blank lines, comments and Vue template markup included, nearly all of which score covered for free. v4 remaps through `ast-v8-to-istanbul` to executable lines only. 64.72% of real statements is a stricter bar than 89.63% of a file's line count, so the ratchet is being recalibrated, not relaxed. The baseline file carries a `_note` explaining this so nobody "restores" 85.18 — under v4 it is unreachable and meaningless. Flagging explicitly for review: this repo does NOT currently run the vitest ratchet in CI. `frontend-checks` is `["check:manifest", "test:l10n", "check:gitignore", "check:nc-floor", "format"]`, and `enable-coverage-guard: true` refers to the separate PHP clover guard (`.coverage-baseline` = 57.39). So no CI gate changes either way here — but leaving 85.18 in place would make the ratchet fail instantly the day someone wires it up, which is why it is corrected rather than left alone. Verified with the commands CI runs ---------------------------------- npm ci rc=0 npx vitest run 141/141 files, 1378/1378 tests npm run test:coverage rc=0 npm run test:coverage-ratchet rc=0 (holds at floor) npm run build rc=0 npm run lint rc=0 npm run stylelint rc=0 npx prettier --check rc=0 Closes #284 Closes #288
# Conflicts: # package-lock.json
Contributor
Quality Report — ConductionNL/openbuild @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| test-l10n | ✅ | ||||
| check-gitignore | ✅ | ||||
| check-nc-floor | ✅ | ||||
| format | ✅ | ||||
| composer | ✅ | ✅ 106/106 | |||
| npm | ✅ | ✅ 625/625 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ✅ | ||||
| Playwright | ✅ | ||||
| Hydra gates | ✅ |
Quality workflow — 2026-08-21 06:27 UTC
Download the full PDF report from the workflow artifacts.
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.
chore(deps): vitest 1 -> 4 as one coupled upgrade (vite 7, plugin-vue 6, coverage-v8 4)
Combines dependabot #284 (vitest) and #288 (@vitest/coverage-v8). They cannot
land separately: vitest 4.1.11 peers
@vitest/coverage-v8: 4.1.11EXACTLY, soeither PR alone produces a tree
npm cirefuses. The peer chain drags in twomore packages, so this is a four-package move:
vite 7, not vite 8, deliberately. vite 8.2.2 is the current latest, but this
repo's
.npmrcsetsmin-release-age=2— a supply-chain cooldown that makesthe lockfile lag newly published versions ON PURPOSE. Pulling a package inside
its cooldown window is how you get a lock that resolves differently in CI than
locally. vite 7.3.6 is well outside it and satisfies vitest 4's peer range.
Five tests failed, all the same latent race
Three in ManifestDiff.spec.js, one in PageDesignerHost.spec.js, one in
ApplicationDetailHeader.spec.js. None is a vitest bug and none needed a
production change — every one is a test seeding component state while that
component's own mounted-hook fetch is still in flight.
ManifestDiff is the clearest. The test mounts, then immediately does:
with a comment claiming this "skips the async fetch". It does not skip it, it
RACES it. The mocked axios resolves
{from: null, to: null}, and whicheversettles second wins. Under vitest 1 setData won; under vitest 4 the fetch does,
nulls
fromBlobstraight back out, anddiffPartscomputes over two emptystrings and returns []. Verified directly rather than guessed — a probe printed
fromBlob: nullimmediately after an awaited setData, whilediffLinesitselfwas confirmed to be a working function returning correct hunks.
PageDesignerHost is the same shape wearing different clothes: it arms
mockRejectedValueOncebefore the mount-timeload()has settled, so themount's own request eats the rejection and the explicit
load()succeeds.ApplicationDetailHeader assigns
wrapper.vm.versionswhile the mounted hook isstill fetching and assigning that same field.
Fixed by letting the mount settle first (
await flushPromises()/await flush(wrapper)) before seeding, with a comment at each site saying whatthe ordering depends on. These tests were correct-by-accident for three major
versions.
The coverage baseline is recalibrated, and that number needs reading carefully
tests/.coverage-baseline.json vitest: 85.18 -> 64.72.
This is NOT 20 points of lost coverage. The suite is identical — 1378 tests
before and after. The instrument changed:
v1 treated every physical line as coverable — blank lines, comments and Vue
template markup included, nearly all of which score covered for free. v4 remaps
through
ast-v8-to-istanbulto executable lines only. 64.72% of real statementsis a stricter bar than 89.63% of a file's line count, so the ratchet is being
recalibrated, not relaxed. The baseline file carries a
_noteexplaining thisso nobody "restores" 85.18 — under v4 it is unreachable and meaningless.
Flagging explicitly for review: this repo does NOT currently run the vitest
ratchet in CI.
frontend-checksis["check:manifest", "test:l10n", "check:gitignore", "check:nc-floor", "format"], andenable-coverage-guard: truerefers to the separate PHP clover guard (.coverage-baseline= 57.39).So no CI gate changes either way here — but leaving 85.18 in place would make
the ratchet fail instantly the day someone wires it up, which is why it is
corrected rather than left alone.
Verified with the commands CI runs
npm ci rc=0
npx vitest run 141/141 files, 1378/1378 tests
npm run test:coverage rc=0
npm run test:coverage-ratchet rc=0 (holds at floor)
npm run build rc=0
npm run lint rc=0
npm run stylelint rc=0
npx prettier --check rc=0
Closes #284
Closes #288