# The component and store tier (`make ui-test`) 313 tests in a real Chromium in ~2 s with no Wails, no backend, no seeded library and no virtual display. This is the cheapest coverage available and where the bulk of UI regression belongs. ```bash make ui-setup # once: the Vitest provider's own Chromium make ui-test # behaviour only make ui-watch make ui-visual # + toMatchScreenshot baselines (YJ_VISUAL=1) make ui-visual-update # re-record them make ui-test UI_ARGS='store/queue' # filter ``` ## How it works `frontend/wailsjs/` is a pure passthrough — every binding is `window.go[svc][Type][Method](args)`, every runtime call is `window.runtime.X(...)`. So `frontend/test/support/wails-fake.ts` replaces **those two globals and nothing else**, and the tests then exercise the *real* generated bindings and the *real* store code. No module mocking, and no second description of the Wails layer. ```ts emit(Events.QueueChanged, payload); // push a backend event stub('queue.Queue.GetState', state); // a value, or a function of the args stubFailure('queue.Queue.SetQueue'); // reject, as a Go error does calls('queue.Queue.SetQueue'); // what the frontend called back with lastArgs('queue.Queue.SetQueue'); const el = await fixture('now-playing'); // mount; shadow()/text() query it ``` The dispatcher mirrors wails' own `desktop/events.js`, including `maxCallbacks` expiry and the fact that a frontend `EventsEmit` notifies local listeners *before* Go. ## Four things that will cost you time - **Store singletons are constructed at module import**, before any test can stub. `test/setup.ts` therefore carries import-time defaults for the stores that read config in their constructor. Without one, a store caches `undefined` where Go would have sent `[]`, and components crash on `.length` — which reads exactly like a component bug and is not. Adding a store that reads config on construction means adding its default there. - **`vitest.config.mts`, not `.ts`** — it `mergeConfig`s the repo's `vite.config.mts` to reuse the `@go`/`@store`/`@components` aliases, and a `.ts` sibling cannot import it. - **Screenshots need the theme.** The setup file imports `@store/theme-store` for its side effect (it applies the `--yj-*` ramp to `:root`); without it a component renders white-on-white and the baseline is blank. - **`@lit-labs/virtualizer` never produces two identical frames**, so `toMatchScreenshot` on `` fails with "could not capture a stable screenshot" rather than a diff. Assert on its rows instead. Visual baselines are font-hinting and compositing sensitive, which is why they are opt-in: they only mean anything on the machine that recorded them. ## Bindings `frontend/wailsjs/` is generated by `wails`, **not** by `go generate`, so the pre-commit codegen check does not cover it — a renamed Go bound method first shows up at runtime, as a call that never settles. ```bash make bindings-check # ~1.5 s, also a pre-commit hook make bindings # regenerate for real ``` The generator rewrites `wailsjs/runtime/*` as mode 755 every run; that is churn, not drift, and the check ignores it.