Files
tolaria/src/hooks/useRawMode.test.ts
Test 185feb5a2c feat: raw editor mode — plain textarea with frontmatter + wikilink autocomplete
Adds a third editor mode (alongside WYSIWYG and Diff) that shows the raw
markdown file in a monospaced textarea. Includes:

- useRawMode hook with derived state (no setState-in-effect) and onFlushPending
- RawEditorView: textarea with 500ms debounce, YAML error banner, wikilink
  autocomplete via [[  trigger, Cmd+S save
- BreadcrumbBar Code icon toggles raw mode; mutual exclusion with diff mode
- Command palette: "Toggle Raw Editor" (View group, requires active tab)
- useEditorModeExclusion hook extracted to keep Editor.tsx under complexity threshold
- buildViewCommands extracted from useCommandRegistry for same reason
- RawToggleButton and RawModeEditorSection components extracted for clean CC

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 18:44:47 +01:00

88 lines
2.6 KiB
TypeScript

import { describe, it, expect, vi, beforeEach } from 'vitest'
import { renderHook, act } from '@testing-library/react'
import { useRawMode } from './useRawMode'
describe('useRawMode', () => {
let onFlushPending: ReturnType<typeof vi.fn>
beforeEach(() => {
onFlushPending = vi.fn().mockResolvedValue(true)
})
function renderRawHook(activeTabPath: string | null = '/note.md') {
return renderHook(
({ path }) => useRawMode({ activeTabPath: path, onFlushPending }),
{ initialProps: { path: activeTabPath } },
)
}
it('starts with raw mode off', () => {
const { result } = renderRawHook()
expect(result.current.rawMode).toBe(false)
})
it('toggles raw mode on', async () => {
const { result } = renderRawHook()
await act(async () => { await result.current.handleToggleRaw() })
expect(result.current.rawMode).toBe(true)
})
it('flushes pending edits when activating raw mode', async () => {
const { result } = renderRawHook()
await act(async () => { await result.current.handleToggleRaw() })
expect(onFlushPending).toHaveBeenCalledOnce()
})
it('does not flush pending edits when deactivating raw mode', async () => {
const { result } = renderRawHook()
await act(async () => { await result.current.handleToggleRaw() })
onFlushPending.mockClear()
await act(async () => { await result.current.handleToggleRaw() })
expect(onFlushPending).not.toHaveBeenCalled()
})
it('toggles raw mode off when already on', async () => {
const { result } = renderRawHook()
await act(async () => { await result.current.handleToggleRaw() })
expect(result.current.rawMode).toBe(true)
await act(async () => { await result.current.handleToggleRaw() })
expect(result.current.rawMode).toBe(false)
})
it('resets raw mode when activeTabPath changes', async () => {
const { result, rerender } = renderRawHook('/note-a.md')
await act(async () => { await result.current.handleToggleRaw() })
expect(result.current.rawMode).toBe(true)
rerender({ path: '/note-b.md' })
expect(result.current.rawMode).toBe(false)
})
it('works without onFlushPending callback', async () => {
const { result } = renderHook(() => useRawMode({ activeTabPath: '/note.md' }))
await act(async () => { await result.current.handleToggleRaw() })
expect(result.current.rawMode).toBe(true)
})
it('does not activate raw mode when activeTabPath is null', async () => {
const { result } = renderRawHook(null)
await act(async () => { await result.current.handleToggleRaw() })
// Cannot activate raw mode without an active tab path
expect(result.current.rawMode).toBe(false)
})
})