]> Piment Noir Git Repositories - e-mobility-charging-stations-simulator.git/commit
test(ui-web): mock useTheme/useSkin in SimulatorBar.test.ts to fix vitest 4.x teardow...
authorJérôme Benoit <jerome.benoit@piment-noir.org>
Thu, 4 Jun 2026 17:17:35 +0000 (19:17 +0200)
committerGitHub <noreply@github.com>
Thu, 4 Jun 2026 17:17:35 +0000 (19:17 +0200)
commit5790cab94b1b64c3f4e453860ce86436e69fff2f
tree1baee7c5312c0e26aef5fef844c7e49356798a06
parentc55e9e4bd48a548f26a720cda7ebbc9f1875babb
test(ui-web): mock useTheme/useSkin in SimulatorBar.test.ts to fix vitest 4.x teardown RPC leak (#1884)

* test(ui-web): mock useTheme/useSkin in SimulatorBar.test.ts to fix vitest 4.x teardown leak

The two final tests ('should call switchTheme/switchSkin when … select changes')
mounted SimulatorBar with the real useTheme/useSkin composables. Both code paths
schedule console.warn output AFTER the synchronous test body resolves:

1. validateTokenContract() (src/shared/tokens/contract.ts) wraps work in
   requestAnimationFrame and warns when CSS variables are missing. jsdom does
   not resolve --color-* CSS variables, so the contract check logs ~24 warnings
   via rAF on every theme/skin switch.
2. switchSkin() returns Promise<boolean>, but the @change handler discards the
   promise and trigger('change') only awaits Vue's nextTick. The unawaited
   loadStyles() dynamic import resolves later and may also call console.warn.

Vitest 4.x tightened teardown to fail rather than swallow pending RPC calls,
surfacing this latent bug as:

  EnvironmentTeardownError: [vitest-worker]: Closing rpc while
  "onUserConsoleLog" was pending

Reproducibly fails on Linux/Node 22 in CI; passes on macOS/Node 24 because rAF
+ dynamic-import timing differs.

Fix mirrors the existing precedent in tests/unit/router.test.ts: vi.mock both
composables at the top of the test file, returning shapes that match the real
contract (THEME_IDS / SKIN_IDS imported from ui-common rather than hand-rolled
subsets). The mocked switchSkin resolves immediately so no teardown leak occurs.

Also tightens the two affected tests to actually assert what their names claim
(switchTheme/switchSkin called with the selected value), instead of merely
checking the <select> exists.

* test(ui-web): use THEME_IDS/SKIN_IDS indices instead of hardcoded values

Address PR review: hardcoding 'dracula' and 'classic' as the target select
values would silently break the assertions if THEME_IDS or SKIN_IDS are
reordered or renamed in ui-common (the DOM $lt;select$gt; would keep its
current option, switchTheme/switchSkin would be called with that stale
value, and the toHaveBeenCalledWith assertion would compare against a
constant that no longer matches the dispatched event).

Pick targets that are guaranteed to differ from the mocked active values:
THEME_IDS[1] (≠ activeThemeId = THEME_IDS[0]) and the first SKIN_IDS entry
that is not 'modern' (≠ activeSkinId). The assertions then reference the
same constants, keeping the test coupled to the actual contract surface.

Note: the third reviewer comment about adding beforeEach(mockClear) is not
needed — vitest.config.ts already sets clearMocks: true and
restoreMocks: true, which run before each test.

* Revert "test(ui-web): use THEME_IDS/SKIN_IDS indices instead of hardcoded values"

This reverts commit 0941e5324d4501ca89094925654261ea1eda3fac.

* test(ui-web): add explicit afterEach mock cleanup in SimulatorBar test

Aligns SimulatorBar.test.ts with the dominant convention in ui/web's test
suite (Dialogs, StationCard, ConnectorRow, ClassicLayout, Actions, …),
which all add an explicit `afterEach(() => { vi.clearAllMocks() })`
alongside vitest.config.ts's global `clearMocks: true` / `restoreMocks: true`.
Belt-and-braces: the explicit reset keeps mock lifecycle visible next to
the mock declarations, even though it is technically redundant with the
global flags.
ui/web/tests/unit/skins/modern/SimulatorBar.test.ts