hololake-platform/tests/smoke/missing-active-vault-recovery.spec.ts

114 lines
3.9 KiB
TypeScript
Raw Normal View History

import { test, expect, type Page } from '@playwright/test'
import { executeCommand, openCommandPalette } from './helpers'
type MockHandlers = Record<string, (args?: unknown) => unknown>
type MockWindow = Window & {
__markVaultMissing?: () => void
}
const entry = {
path: '/vault/note/runtime.md',
filename: 'runtime.md',
title: 'Runtime Vault Note',
isA: 'Note',
aliases: [],
belongsTo: [],
relatedTo: [],
status: null,
archived: false,
modifiedAt: 1700000000,
createdAt: 1700000000,
fileSize: 64,
snippet: 'Loaded before the vault path disappears.',
wordCount: 7,
relationships: {},
icon: null,
color: null,
order: null,
sidebarLabel: null,
template: null,
sort: null,
view: null,
visible: true,
organized: false,
favorite: false,
favoriteIndex: null,
listPropertiesDisplay: [],
outgoingLinks: [],
properties: {},
hasH1: true,
fileKind: 'markdown',
}
async function installMissingVaultMock(page: Page): Promise<void> {
await page.addInitScript((noteEntry: typeof entry) => {
localStorage.setItem('tolaria_welcome_dismissed', '1')
localStorage.setItem('tolaria:ai-agents-onboarding-dismissed', '1')
localStorage.setItem('tolaria:claude-code-onboarding-dismissed', '1')
const missingError = () => new Error('Active vault is not available')
const mockWindow = window as MockWindow
let vaultAvailable = true
let handlers: MockHandlers | null = null
mockWindow.__markVaultMissing = () => {
vaultAvailable = false
}
Object.defineProperty(window, '__mockHandlers', {
configurable: true,
set(value: unknown) {
handlers = value as MockHandlers
handlers.load_vault_list = () => ({
vaults: [{ label: 'Runtime Vault', path: '/vault' }],
active_vault: '/vault',
hidden_defaults: [],
})
handlers.check_vault_exists = () => vaultAvailable
handlers.get_default_vault_path = () => '/vault'
handlers.get_settings = () => ({
auto_pull_interval_minutes: null,
auto_advance_inbox_after_organize: null,
telemetry_consent: true,
crash_reporting_enabled: null,
analytics_enabled: null,
anonymous_id: null,
release_channel: null,
})
handlers.get_vault_settings = () => ({ theme: null })
handlers.list_vault = () => vaultAvailable ? [noteEntry] : Promise.reject(new Error('No such file or directory'))
handlers.reload_vault = () => vaultAvailable ? [noteEntry] : Promise.reject(new Error('No such file or directory'))
handlers.list_vault_folders = () => vaultAvailable ? [] : Promise.reject(missingError())
handlers.list_views = () => vaultAvailable ? [] : Promise.reject(missingError())
handlers.get_modified_files = () => vaultAvailable ? [] : Promise.reject(missingError())
handlers.get_all_content = () => ({ [noteEntry.path]: '# Runtime Vault Note\n\nBody.' })
handlers.get_note_content = () => vaultAvailable
? '# Runtime Vault Note\n\nBody.'
: Promise.reject(missingError())
handlers.is_git_repo = () => true
handlers.sync_mcp_bridge_vault = () => null
},
get() {
return handlers
},
})
}, entry)
}
test('missing active vault reload shows recovery state and clears stale notes', async ({ page }) => {
await installMissingVaultMock(page)
await page.goto('/', { waitUntil: 'domcontentloaded' })
await expect(page.getByText('Runtime Vault Note')).toBeVisible({ timeout: 5_000 })
await page.evaluate(() => {
(window as MockWindow).__markVaultMissing?.()
})
await openCommandPalette(page)
await executeCommand(page, 'Reload Vault')
await expect(page.getByText('Vault not found')).toBeVisible({ timeout: 5_000 })
await expect(page.getByTestId('welcome-open-folder')).toContainText('Choose a different folder')
await expect(page.getByText('Runtime Vault Note')).not.toBeVisible()
})