2026-02-14 18:20:07 +01:00
|
|
|
import '@testing-library/jest-dom/vitest'
|
2026-02-23 21:11:41 +01:00
|
|
|
import { vi } from 'vitest'
|
2026-02-23 21:16:20 +01:00
|
|
|
import { createElement, type ReactNode, type ComponentType } from 'react'
|
2026-02-23 21:11:41 +01:00
|
|
|
|
2026-03-04 11:07:56 +01:00
|
|
|
// Suppress undici WebSocket ERR_INVALID_ARG_TYPE in jsdom (jsdom Event ≠ Node Event)
|
|
|
|
|
process.on('uncaughtException', (err: NodeJS.ErrnoException) => {
|
|
|
|
|
if (err.code === 'ERR_INVALID_ARG_TYPE' && err.message?.includes('Event')) return
|
|
|
|
|
throw err
|
|
|
|
|
})
|
|
|
|
|
|
feat: full-text search with qmd backend and SearchPanel UI (Cmd+Shift+F) (#64)
* feat: add search backend (qmd CLI) and design file
- Add search.rs: qmd integration for keyword (BM25), semantic (vsearch),
and hybrid search modes via CLI JSON output
- Register search_vault Tauri command in lib.rs
- Design file with 3 frames: empty, results, no-results states
- Fix pre-existing test failures: install @tauri-apps/plugin-opener,
add mock in test setup
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add SearchPanel UI with Cmd+Shift+F shortcut
- SearchPanel component: full-text search overlay with keyword/semantic
mode toggle, debounced search (200ms), arrow key navigation, result
count + elapsed time display, note type badges from vault entries
- Cmd+Shift+F shortcut registered in useAppKeyboard
- Mock search_vault handler in mock-tauri for browser dev mode
- SearchResult/SearchResponse types in types.ts
- Tests: 15 new tests for SearchPanel + 2 for keyboard shortcut
- scrollIntoView mock in test setup for jsdom compatibility
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: correct SearchPanel imports for Tauri/browser dual-mode
Use invoke from @tauri-apps/api/core and mockInvoke from mock-tauri
with a searchCall wrapper, fixing the TypeScript build error.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: make test_detect_collection_fallback robust when qmd not installed
* fix: reset localStorage between App tests to prevent view mode state leak
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 17:09:50 +01:00
|
|
|
// Mock scrollIntoView for jsdom (not implemented)
|
|
|
|
|
Element.prototype.scrollIntoView = vi.fn()
|
|
|
|
|
|
2026-03-02 11:57:26 +01:00
|
|
|
// Mock ResizeObserver for jsdom (not implemented)
|
2026-03-02 12:02:24 +01:00
|
|
|
globalThis.ResizeObserver = class {
|
2026-03-02 11:57:26 +01:00
|
|
|
observe() {}
|
|
|
|
|
unobserve() {}
|
|
|
|
|
disconnect() {}
|
|
|
|
|
} as unknown as typeof ResizeObserver
|
|
|
|
|
|
feat: full-text search with qmd backend and SearchPanel UI (Cmd+Shift+F) (#64)
* feat: add search backend (qmd CLI) and design file
- Add search.rs: qmd integration for keyword (BM25), semantic (vsearch),
and hybrid search modes via CLI JSON output
- Register search_vault Tauri command in lib.rs
- Design file with 3 frames: empty, results, no-results states
- Fix pre-existing test failures: install @tauri-apps/plugin-opener,
add mock in test setup
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add SearchPanel UI with Cmd+Shift+F shortcut
- SearchPanel component: full-text search overlay with keyword/semantic
mode toggle, debounced search (200ms), arrow key navigation, result
count + elapsed time display, note type badges from vault entries
- Cmd+Shift+F shortcut registered in useAppKeyboard
- Mock search_vault handler in mock-tauri for browser dev mode
- SearchResult/SearchResponse types in types.ts
- Tests: 15 new tests for SearchPanel + 2 for keyboard shortcut
- scrollIntoView mock in test setup for jsdom compatibility
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: correct SearchPanel imports for Tauri/browser dual-mode
Use invoke from @tauri-apps/api/core and mockInvoke from mock-tauri
with a searchCall wrapper, fixing the TypeScript build error.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: make test_detect_collection_fallback robust when qmd not installed
* fix: reset localStorage between App tests to prevent view mode state leak
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 17:09:50 +01:00
|
|
|
// Mock @tauri-apps/plugin-opener for test environment
|
|
|
|
|
vi.mock('@tauri-apps/plugin-opener', () => ({
|
|
|
|
|
openUrl: vi.fn(),
|
|
|
|
|
}))
|
|
|
|
|
|
2026-02-26 23:35:17 +01:00
|
|
|
// Mock react-day-picker: Calendar component uses DayPicker which needs real DOM APIs not available in jsdom
|
|
|
|
|
vi.mock('react-day-picker', () => ({
|
|
|
|
|
DayPicker: () => null,
|
|
|
|
|
getDefaultClassNames: () => ({}),
|
|
|
|
|
}))
|
|
|
|
|
|
2026-02-23 21:11:41 +01:00
|
|
|
// Mock react-virtuoso: JSDOM has no real viewport, so render all items directly
|
2026-02-23 21:16:20 +01:00
|
|
|
vi.mock('react-virtuoso', () => ({
|
|
|
|
|
Virtuoso: ({ data, itemContent, components }: {
|
|
|
|
|
data?: unknown[]
|
|
|
|
|
itemContent?: (index: number, item: unknown) => ReactNode
|
|
|
|
|
components?: { Header?: ComponentType }
|
|
|
|
|
}) => {
|
|
|
|
|
const Header = components?.Header
|
|
|
|
|
return createElement('div', { 'data-testid': 'virtuoso-mock' },
|
|
|
|
|
Header ? createElement(Header) : null,
|
|
|
|
|
data?.map((item: unknown, index: number) =>
|
|
|
|
|
createElement('div', { key: index }, itemContent?.(index, item))
|
2026-02-23 21:11:41 +01:00
|
|
|
)
|
2026-02-23 21:16:20 +01:00
|
|
|
)
|
|
|
|
|
},
|
|
|
|
|
GroupedVirtuoso: ({ groupCounts, groupContent, itemContent }: {
|
|
|
|
|
groupCounts: number[]
|
|
|
|
|
groupContent: (index: number) => ReactNode
|
|
|
|
|
itemContent: (index: number, groupIndex: number) => ReactNode
|
|
|
|
|
}) => {
|
|
|
|
|
let globalIndex = 0
|
|
|
|
|
return createElement('div', { 'data-testid': 'grouped-virtuoso-mock' },
|
|
|
|
|
groupCounts?.map((count: number, groupIndex: number) => {
|
|
|
|
|
const items = []
|
|
|
|
|
for (let i = 0; i < count; i++) {
|
|
|
|
|
items.push(createElement('div', { key: globalIndex }, itemContent(globalIndex, groupIndex)))
|
|
|
|
|
globalIndex++
|
|
|
|
|
}
|
|
|
|
|
return createElement('div', { key: `group-${groupIndex}` },
|
|
|
|
|
groupContent(groupIndex),
|
|
|
|
|
...items
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
)
|
|
|
|
|
},
|
|
|
|
|
}))
|