114 lines
3.9 KiB
TypeScript
114 lines
3.9 KiB
TypeScript
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()
|
|
})
|