test: keep Desktop pane-focus setup outside cold imports

This commit is contained in:
Teknium
2026-09-08 07:02:54 -07:00
parent 63ec22e797
commit a25967b434
3 changed files with 119 additions and 17 deletions

View File

@@ -1,21 +1,24 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { afterEach, beforeAll, beforeEach, describe, expect, it } from 'vitest'
async function setup() {
const tree = await import('@/components/pane-shell/tree/store')
const model = await import('@/components/pane-shell/tree/model')
const { registry } = await import('@/contrib/registry')
const session = await import('@/store/session')
const states = await import('@/store/session-states')
const { paneMirror } = await import('@/app/chat/pane-mirror')
import { paneMirror } from '@/app/chat/pane-mirror'
import * as model from '@/components/pane-shell/tree/model'
import * as tree from '@/components/pane-shell/tree/store'
import { registry } from '@/contrib/registry'
import { applyDesktopOverlay } from '@/store/profile-share'
import * as session from '@/store/session'
import * as states from '@/store/session-states'
registry.register({
// These app-lifetime watchers have no unsubscribe API. Install them once in
// Vitest's isolated file graph, not once per case (which accumulates listeners).
beforeAll(() => {
const disposeWorkspace = registry.register({
area: 'panes',
data: { placement: 'main', uncloseable: true },
id: 'workspace',
render: () => null,
title: 'Chat'
})
tree.declareDefaultTree(model.group(['workspace'], { active: 'workspace', id: 'main' }))
tree.watchContributedPanes()
paneMirror({
source: states.$sessionTiles,
@@ -27,6 +30,23 @@ async function setup() {
render: () => null,
close: states.closeSessionTile
})()
return disposeWorkspace
})
function resetState() {
// Empty the source while the mirror is live so it also disposes its pane.
states.discardSessionTile('canonical-chat')
tree.$layoutTree.set(null)
tree.$activeTreeGroup.set(null)
tree.$activePresetId.set('default')
session.$selectedStoredSessionId.set(null)
session.$lastReadAtBySessionId.set({})
window.localStorage.clear()
}
function setup() {
tree.declareDefaultTree(model.group(['workspace'], { active: 'workspace', id: 'main' }))
session.$selectedStoredSessionId.set('previous-chat')
const scope = {
@@ -42,17 +62,19 @@ async function setup() {
}
describe('focusing a saved Bot Chat requires a visible pane', () => {
let ctx: Awaited<ReturnType<typeof setup>>
let ctx: ReturnType<typeof setup>
const paneId = 'session-tile:canonical-chat'
beforeEach(async () => {
window.localStorage.clear()
vi.resetModules()
ctx = await setup()
beforeEach(() => {
resetState()
ctx = setup()
expect(model.findGroupOfPane(tree.$layoutTree.get()!, 'workspace')?.id).toBe('main')
expect(states.$sessionTiles.get().map(tile => tile.storedSessionId)).toEqual(['canonical-chat'])
})
it('re-adopts a saved tab after a profile overlay replaces the layout', async () => {
const { applyDesktopOverlay } = await import('@/store/profile-share')
afterEach(resetState)
it('re-adopts a saved tab after a profile overlay replaces the layout', () => {
const { model, scope, states, tree } = ctx
const saved = states.$sessionTiles.get()
applyDesktopOverlay('imported-profile', {

View File

@@ -0,0 +1,52 @@
# Saved-pane fixture import-delay control
From a root `npm ci` installation, run in `apps/desktop`:
```sh
npx vitest run --config ../../evals/desktop-pane-fixture/vitest.config.mts --reporter verbose
npx vitest run --project ui src/store/session-pane-focus.test.ts --sequence.shuffle.tests --sequence.seed=12345 --reporter verbose
```
The Vite plugin appends an 11-second asynchronous wait to the real pane-tree
store's evaluation. It does not mock pane functions, inspect source text in an
assertion, lower a deadline, or alter the two test bodies. The UI test deadline
remains 15 seconds and the default hook deadline remains 10 seconds. This is a
scheduling-controlled reproduction of import latency, not a claim that a local
machine reproduced the original CI load unassisted. It is opt-in, not a slow CI
test.
For A/B, apply this eval directory to the parent revision and run the same
command, then run on the fixture fix. Base evaluates the graph inside each
`beforeEach`; fixed evaluates it once during test collection. The delay marker
appears twice on base and once on fixed. Expected: base fails with `Hook timed
out in 10000ms`; fixed runs both behavioral assertions successfully.
Measured on the initial base `fb3446a281e`:
| Control | Result |
| --- | --- |
| Base + evaluation delay | 2 hook timeouts, 20.04s test phase |
| Fixed + identical delay | 2 passed, 5ms test phase; 11.84s import phase |
| Fixed normal and reversed test order (seed 12345) | 2 passed in each order |
| Store directory, 8 workers | 123 files / 1491 tests passed |
| Complete UI project, 8 workers | 753 files / 7355 assertions passed, but exit 1 from an unrelated Radix focus-scope timer's wrong-realm Event in `statusbar-visibility.test.tsx` |
Mutation controls, applied separately to `session-states.ts` and then restored:
- Remove `revealTreePane(paneId)` in `focusOpenSession`: the overlay re-adoption
case fails (`null` instead of `canonical-chat`); the miss case passes.
- Make `focusWorkspaceOwnerSessionTile` return the stored id regardless of
`focusOpenSession`'s result: the miss case fails (`canonical-chat` instead of
`null`); the overlay case passes.
The fixture uses the real registry, tree watcher, pane mirror, overlay, tile
store, and focus helpers. Install app-lifetime watchers once per isolated Vitest
file graph. Discard the fixture tile through the real action to clear both the
reactive source and its persisted in-memory bucket; reset layout, focus, preset,
selection, read baseline, and localStorage between cases. The mirror observes the
discard and unregisters its contribution. No production API needs a test-only
reset or disposer.
If the host has exhausted inotify watches, prefix commands with
`CHOKIDAR_USEPOLLING=true`; this changes file watching, not test deadlines. The
recorded store/full-suite and final focused controls used that workaround.

View File

@@ -0,0 +1,28 @@
// From apps/desktop: npx vitest run --config ../../evals/desktop-pane-fixture/vitest.config.mts
// Replay a slow module evaluation without changing any pane behavior or deadlines.
import { defineConfig, mergeConfig } from 'vitest/config'
import desktopConfig from '../../apps/desktop/vite.config.ts'
export default defineConfig(env =>
mergeConfig(desktopConfig(env), {
plugins: [
{
name: 'slow-pane-store-evaluation',
enforce: 'post',
transform(code: string, id: string) {
if (id.endsWith('/components/pane-shell/tree/store.ts')) {
return `${code}\nconsole.info('[pane-fixture] delaying real tree store evaluation by 11000ms');\nawait new Promise(resolve => setTimeout(resolve, 11000));\n`
}
}
}
],
test: {
environment: 'jsdom',
setupFiles: ['./vitest.setup.ts'],
include: ['src/store/session-pane-focus.test.ts'],
globals: true,
testTimeout: 15_000
}
})
)