test: keep Desktop pane-focus setup outside cold imports
This commit is contained in:
@@ -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', {
|
||||
|
||||
52
evals/desktop-pane-fixture/README.md
Normal file
52
evals/desktop-pane-fixture/README.md
Normal 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.
|
||||
28
evals/desktop-pane-fixture/vitest.config.mts
Normal file
28
evals/desktop-pane-fixture/vitest.config.mts
Normal 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
|
||||
}
|
||||
})
|
||||
)
|
||||
Reference in New Issue
Block a user