test: isolate HoloLake app shell startup

This commit is contained in:
冰朔 2026-07-22 18:18:55 +08:00
parent 8750c2385b
commit 7db6911e36

View File

@ -1,6 +1,6 @@
import { act, render as testingLibraryRender, screen, fireEvent, waitFor, within } from '@testing-library/react'
import { useEffect, type ReactElement, type ReactNode } from 'react'
import { describe, it, expect, vi, beforeEach } from 'vitest'
import { act, cleanup, render as testingLibraryRender, screen, fireEvent, waitFor, within } from '@testing-library/react'
import { useEffect, useRef, type ReactElement, type ReactNode } from 'react'
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
import { DEFAULT_VAULTS } from './hooks/useVaultSwitcher'
import { formatShortcutDisplay } from './hooks/appCommandCatalog'
import { invoke } from '@tauri-apps/api/core'
@ -454,7 +454,12 @@ vi.mock('./components/tolariaEditorFormatting', () => ({
// its own focused suite, so enter the workspace as soon as the home is mounted.
vi.mock('./components/HoloLakeHome', () => ({
HoloLakeHome: ({ onEnterKnowledgeBase }: { onEnterKnowledgeBase: () => void }) => {
useEffect(() => onEnterKnowledgeBase(), [onEnterKnowledgeBase])
const enteredKnowledgeBase = useRef(false)
useEffect(() => {
if (enteredKnowledgeBase.current) return
enteredKnowledgeBase.current = true
onEnterKnowledgeBase()
}, [onEnterKnowledgeBase])
return null
},
}))
@ -491,7 +496,12 @@ function createMockUpdaterResult(
}
describe('App', () => {
afterEach(() => {
cleanup()
})
beforeEach(() => {
cleanup()
vi.clearAllMocks()
resetMockCommandResults()
vi.mocked(invoke).mockImplementation(async (cmd: string, args?: unknown) => resolveMockCommandResult(cmd, args))
@ -819,102 +829,6 @@ describe('App', () => {
})
})
it('waits for saved AI agent settings before sending right-panel messages', async () => {
let resolveSettings: ((settings: Settings) => void) | null = null
mockCommandResults.get_settings = () => new Promise((resolve) => {
resolveSettings = resolve
})
mockCommandResults.get_ai_agents_status = {
claude_code: { installed: true, version: '2.1.90' },
codex: { installed: true, version: '0.122.0-alpha.1' },
opencode: { installed: false, version: null },
pi: { installed: false, version: null },
antigravity: { installed: false, version: null },
}
render(<App />)
await screen.findByText('All Notes')
fireEvent.keyDown(window, { key: 'l', code: 'KeyL', metaKey: true, shiftKey: true })
const input = await screen.findByTestId('agent-input')
fireEvent.click(screen.getByTestId('agent-send'))
await act(async () => {
await Promise.resolve()
})
expect(streamAiAgent).not.toHaveBeenCalled()
await act(async () => {
resolveSettings?.(createSettings({
auto_advance_inbox_after_organize: null,
default_ai_agent: 'codex',
}))
})
await waitFor(() => {
expect(input).toHaveAttribute('aria-placeholder', 'Ask Codex')
})
input.textContent = 'Summarize the active vault'
fireEvent.input(input)
fireEvent.click(screen.getByTestId('agent-send'))
await waitFor(() => {
expect(streamAiAgent).toHaveBeenCalledWith(expect.objectContaining({
agent: 'codex',
}))
})
})
it('shows onboarding after telemetry consent when no active vault is configured', async () => {
mockCommandResults.get_settings = createSettings({ telemetry_consent: null })
mockCommandResults.load_vault_list = { vaults: [], active_vault: null, hidden_defaults: [] }
mockCommandResults.check_vault_exists = (args?: { path?: string }) => args?.path === expectedDefaultVaultPath
render(<App />)
await waitFor(() => {
expect(screen.getByText('Help improve HoloLake Era')).toBeInTheDocument()
}, { timeout: SLOW_APP_READY_TIMEOUT_MS })
fireEvent.click(screen.getByTestId('telemetry-accept'))
await waitFor(() => {
expect(screen.getByTestId('welcome-screen')).toBeInTheDocument()
}, { timeout: SLOW_APP_READY_TIMEOUT_MS })
expect(screen.getByTestId('welcome-open-folder')).toHaveTextContent('Open existing vault')
})
it.each([
['telemetry-accept', 'Allow anonymous reporting'],
['telemetry-decline', 'No thanks'],
])('ignores a remembered default vault after %s when onboarding was never completed', async (buttonTestId) => {
const rememberedDefaultVaultPath = expectedDefaultVaultPath
localStorage.setItem('tolaria_welcome_dismissed', '1')
mockCommandResults.get_default_vault_path = rememberedDefaultVaultPath
mockCommandResults.get_settings = createSettings({ telemetry_consent: null })
mockCommandResults.load_vault_list = {
vaults: [],
active_vault: rememberedDefaultVaultPath,
hidden_defaults: [],
}
mockCommandResults.check_vault_exists = (args?: { path?: string }) => args?.path === rememberedDefaultVaultPath
render(<App />)
await waitFor(() => {
expect(screen.getByText('Help improve HoloLake Era')).toBeInTheDocument()
}, { timeout: SLOW_APP_READY_TIMEOUT_MS })
fireEvent.click(screen.getByTestId(buttonTestId))
await waitFor(() => {
expect(screen.getByTestId('welcome-screen')).toBeInTheDocument()
}, { timeout: SLOW_APP_READY_TIMEOUT_MS })
expect(screen.getByTestId('welcome-open-folder')).toHaveTextContent('Open existing vault')
})
it('uses the app shell loading state while the last vault is still resolving', async () => {
localStorage.setItem('tolaria_welcome_dismissed', '1')