From 30a3672724209035df88fde39951af724ec0f300 Mon Sep 17 00:00:00 2001 From: Matti Airas Date: Mon, 10 Aug 2026 18:25:30 +0300 Subject: [PATCH] docs(testing): record the gauge test-shim trap The gauge library is aliased to a shim with no update(), so every imperative push in the gauge widgets throws into a swallowing catch and anything asserted only through them is unobservable. The barProgress construction trap is already commented at both call sites in widget-gauge-ng-linear and guarded by a spec, so it stays there instead of costing every session's context. --- CLAUDE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CLAUDE.md b/CLAUDE.md index 1b5f261d..12ea442c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -69,6 +69,7 @@ The mock serves Skip's full session/config surface (`loginStatus`, `applicationD - **A spec that needs a fake declares it locally.** Add a local provider in that spec's `configureTestingModule` (globals are prepended, so a local `{ provide: X, useValue: … }` wins). That is the whole mocking model — there is no shared app-service stub to extend. A local `SignalKConnectionService` fake must still expose `serverServiceEndpoint$` and `serverVersion$` (services subscribe to them at construction). - **The failure mode is real-service construction, not stub drift.** Because components receive the real services, a service that throws at construction (missing dependency, a `requireSync`/NG0601 hazard) fails the spec directly — construction-time resilience of the real services is load-bearing for ~30 spec files. Fix the app code or add a local fake; do **not** re-add a global app-service stub (it is inert anyway). - **Chart.js is a shim, aliased not mocked.** `vitest.config.ts` aliases `chart.js`, `chartjs-plugin-annotation`, `chartjs-adapter-date-fns` and `@aziham/chartjs-plugin-streaming` to `src/test-shims/chartjs-*`, the same way gridstack and canvas-gauges are aliased. **Do not add a per-file `vi.mock('chart.js')`** — that is what #544 was: a per-file mock only wins when its spec is the first in the worker to load the module, and `widget-numeric` reaches chart.js through `MinichartComponent` without mocking, so the real library was sometimes cached first. The real library cannot acquire a 2D context under jsdom, so `chart.ctx` comes out falsy and components silently drop everything they feed the chart — a live subscription plotting nothing, which reads as a flake rather than a wiring error. The shims are imported from `src/test.ts` so their chunks resolve during setup; a spec that first reaches one lazily can otherwise request it after its worker's environment is torn down (`EnvironmentTeardownError`, which fails the suite file while every test passes). +- **The gauge library is a no-op shim in tests.** `vitest.config.ts` aliases `@godind/ng-canvas-gauges` to `src/test-shims/ng-canvas-gauges-shim.ts`, whose `LinearGauge`/`RadialGauge` expose only the `options` and `value` inputs — **there is no `update()`**. Every `this.ngGauge()?.update(...)` in the gauge widgets therefore throws `update is not a function` and is swallowed by the surrounding `catch`, so anything asserted only through those imperative pushes is unobservable: a misspelled option key or a null option value passes CI. Test the *decision* instead — call `buildGaugeOptions()` and assert `gaugeOptions`, or extract the rule into a method and assert that. Real library behaviour needs a browser (see `perf-harness/`). - **Local runs work.** The whole suite runs locally via `npm test` (~90s, build-dominated), and a single spec via `ng test --include=''`; plain `npx vitest run ` fails (`@angular/compiler is not available`) because it bypasses the builder. **CI on Node 24 is the authoritative gate** (`npm run ci` = `lint` + `snc` + `test:headless` + `test:mcp-schema`). - CI uses **`npm ci`** (the `run-tests` action and `release.yml`) against a lockfile that is in sync. If `npm ci` ever fails on missing optional platform deps, regenerate the lockfile (`rm package-lock.json && npm install`) and commit it — don't switch CI back to `npm install`.