Silence the spurious vi.mock hoisting warnings - #24621
Conversation
|
Warning This pull request does not link an OpenProject work package. Please add a link to the work package in the description, or reference it in the |
There was a problem hiding this comment.
Pull request overview
This PR reduces noisy Vitest warning output caused by Angular’s unit-test bundling (esbuild wrapping specs in __commonJS), by converting top-level vi.mock usage to vi.doMock in affected frontend specs and adjusting imports/initialization order where needed so mocks still apply.
Changes:
- Replace
vi.mockwithvi.doMockacross several sortable-lists-related specs to avoid spurious hoisting warnings. - Remove reliance on
vi.hoisted()in the engine specs by using plain module-scope constants. - Restructure the two engine specs to lazily import
createSortableRootafter mocks are registered.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| frontend/src/stimulus/controllers/dynamic/sortable-lists/scrollable.controller.spec.ts | Switch auto-scroll mock to vi.doMock to avoid hoisting warnings. |
| frontend/src/stimulus/controllers/dynamic/sortable-lists/list.controller.spec.ts | Switch Pragmatic adapter mock to vi.doMock and document dynamic-import ordering. |
| frontend/src/stimulus/controllers/dynamic/sortable-lists/item.controller.spec.ts | Switch multiple Pragmatic mocks to vi.doMock to avoid hoisting warnings. |
| frontend/src/stimulus/controllers/dynamic/sortable-lists.controller.spec.ts | Switch Pragmatic mocks to vi.doMock and update rationale comment. |
| frontend/src/common/drag-and-drop/sortable-lists-engine.spec.ts | Replace vi.hoisted() with const state, move createSortableRoot to lazy import after doMock. |
| frontend/src/common/drag-and-drop/sortable-lists-engine.preview.spec.ts | Same as above for preview-offset assertions: const state + lazy import after doMock. |
Suppressed comments (2)
frontend/src/common/drag-and-drop/sortable-lists-engine.spec.ts:65
typeof createSortableRootFnrelies on a type-only import alias, which does not exist at runtime and typically fails TypeScript type-checking. Use the localCreateSortableRoottype (or atypeof import()query) for the lazy binding’s type instead.
let createSortableRoot:typeof createSortableRootFn;
frontend/src/common/drag-and-drop/sortable-lists-engine.preview.spec.ts:54
- After switching away from the
import typealias, update the lazy binding’s type to use theCreateSortableRootalias so this remains valid under TypeScript type-checking.
let createSortableRoot:typeof createSortableRootFn;
vi.mock hoisting warnings
c24f965 to
76bb224
Compare
e7a6126 to
f22e7c6
Compare
|
Warning Flaky specs
🤖 Ask Copilot to investigateCopy the prompt below into a new comment on this PR to delegate the investigation to GitHub Copilot. It will look into the flakiness and open a separate pull request with you as reviewer. |
f22e7c6 to
5a2889c
Compare
|
Warning Flaky specs
🤖 Ask Copilot to investigateCopy the prompt below into a new comment on this PR to delegate the investigation to GitHub Copilot. It will look into the flakiness and open a separate pull request with you as reviewer. |
5a2889c to
f1f3f93
Compare
The Angular unit-test builder bundles each spec into a __commonJS wrapper, so Vitest's hoist validator walks that wrapper instead of our source and reports top-level vi.mock calls as nested. Only mock, unmock and hoisted are hoist-checked, so vi.doMock sidesteps it. These specs already import the mocked packages and the controller under test lazily in beforeAll, which is the ordering doMock needs. A note above each call records that, since doMock's position above the imports no longer carries the guarantee vi.mock's hoisting gave it. The root spec also claimed it read back the combine, prevent-unhandled and drag-preview options. It never did; they keep the mounted item controller's side effects inert.
vi.doMock only affects later imports, so the statically imported createSortableRoot would have pulled in the real auto-scroll module first and the mock would have stopped applying silently. A type import plus a lazy binding restores the ordering in both engine specs, and drops vi.hoisted with it. The preview spec also loses the file-split rationale that cited a shared module registry, which isolate:true removed. The split itself stands: the sibling renders previews for real.
f1f3f93 to
a3f233c
Compare
|
Warning Flaky specs
🤖 Ask Copilot to investigateCopy the prompt below into a new comment on this PR to delegate the investigation to GitHub Copilot. It will look into the flakiness and open a separate pull request with you as reviewer. |
Ticket
No work package — frontend test-output hygiene, noticed while working on #AGILE-361.
Stacked on #24525 (
implementation/AGILE-361-batch-selection), with #24622 on top of this one.What are you trying to accomplish?
A full
npm run test -- --browsers chromiumrun passes, but buries that result in warning noise. This PR removes 15 of those warnings; the PR stacked on top removes ~43 more.The warnings look like this, once per mock:
They are false positives. Every one of those calls is already at the top level of its spec file.
The cause is the Angular unit-test builder. It esbuild-bundles each spec before Vitest sees it, wrapping the module body in a lazy CommonJS initialiser:
@vitest/mockervalidates hoisting by walkingast.bodyand deleting any hoisted node it finds there. Inside that wrapper the node is not a direct child ofProgram, so it survives the sweep and warns. No source-level placement can satisfy the check — the calls are already where the warning asks them to be.What approach did you choose and why?
vi.mock→vi.doMock.@vitest/mockerhoist-checks onlymock,unmockandhoisted;doMockis excluded, so the wrapper stops mattering. And becausedoMockis not hoisted,vi.hoisted()is no longer needed either — a plain module-scopeconstinitialises before the factory runs.Four of the six specs needed nothing but the keyword: they already hold
import typeat the top and pull both the mocked packages and the subject under test viaawait import(...)inbeforeAll, which is exactly the orderingdoMockrequires.The two engine specs did need restructuring. Both statically imported the value
createSortableRoot, which transitively imports the mocked@atlaskitmodule — underdoMockthat resolves before the mock registers, so the mock would silently stop applying. Both now use a type-only import plus a lazy binding.That failure mode is quiet, which is why both engine specs were falsification-tested rather than merely re-run: with the
vi.doMockblock commented out,sortable-lists-engine.spec.tsproduces 4 failures on itsliveRegistrations()assertions and…preview.spec.tsproduces 2 on itspreviewCallsassertions. A green run there would have meant the conversion was wrong.Why
doMockis safe againvi.doMockwas abandoned in these specs because spec files poisoned each other's module registry. That was a consequence of the builder'sisolate: falsedefault, which 797894c ("Isolate vitest spec files") fixed by settingisolate: trueinvitest-base.config.ts. The reason it was unsafe no longer holds, and the commit body says so, so this doesn't get reverted blind later.Three specs also carried comments still describing the pre-
isolate: trueworld; those are corrected here rather than left to contradict the code.Alternatives considered
Suppressing the warning was the obvious cheap option, and it does not work: the warning is emitted node-side during transform, before the
RUNbanner, so the existingonConsoleLoghook invitest-base.config.tsnever sees it. Silencing it would have meant a custom Vite plugin or patchingconsole— and the warning is slated to become a hard error in a future Vitest, so suppression would only defer the work.Worth reporting upstream separately:
@angular/build's unit-test builder wrapping each spec in__commonJSis what makes Vitest's hoist validator misfire, and that is fixable at source.Merge checklist
Verification
Full suite run three times on chromium, because
doMockhas a flake history here and one green run would not have shown an intermittent registry problem.Warning: A vi.count 0 / 0 / 0Remaining output is untouched and out of scope for this PR: the
stimulus-useuseDispatchdeprecation (10),NG0912(1), the Lit dev-mode banner (2), andError updating activities list(2) — the last of which is a spec deliberately exercising an error path and should stay.