Commit Graph

1076 Commits

Author SHA1 Message Date
Test
a25f9ee1fc style: format Rust theme modules with cargo fmt
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 23:28:24 +01:00
Test
8a48c21445 test: add Playwright smoke test for theme properties defaults
Validates that all 140 CSS custom properties from the expanded
DEFAULT_VAULT_THEME_VARS are applied to the DOM when a theme is
activated, including editor, heading, list, checkbox, inline-style,
code-block, blockquote, table, and horizontal-rule properties.

Also updates mock content and handlers to use the full 140-property
frontmatter, matching the Rust backend output.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 23:28:24 +01:00
Test
7c72494efb fix: write all theme.json defaults to vault theme frontmatter
Previously, only UI chrome colours and 3 editor vars were written to
theme note frontmatter. CSS vars like --lists-bullet-size, --headings-h1-font-size,
etc. remained unset, so EditorTheme.css rules had no effect.

- Expand DEFAULT_VAULT_THEME_VARS from 46 to 140 entries, covering every
  property from theme.json (editor, headings, lists, checkboxes, inline
  styles, code blocks, blockquote, table, horizontal rule, colors)
- Fix missing px suffix on editor-font-size and editor-max-width
- Add missing semantic vars: bg-card, text-tertiary
- Refactor built-in vault themes from const strings to generated functions
  with per-theme colour overrides (DRY, all themes get editor properties)
- Quote var() references in frontmatter to prevent YAML parse issues
- Add regression tests for create_vault_theme and seed_vault_themes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 23:28:23 +01:00
Test
10b4e6d038 test: add Playwright smoke test for note list preview snippets
Verifies: snippet visibility, snippet update on save, and markdown
stripping in the note list.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v0.20260311.399
2026-03-11 22:44:38 +01:00
Test
55519e53ad fix: update note list snippet on save so all notes show preview
The snippet was extracted once at vault load time (Rust backend) and
never updated when content was saved. Notes created or edited during
a session showed stale/empty snippets until the next app restart.

Added extractSnippet() to the frontend (mirroring Rust logic) and
wired it into useEditorSaveWithLinks so snippet + wordCount are
updated alongside outgoingLinks on every save.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 22:38:25 +01:00
Test
fafa4e394b fix: sync raw editor (CodeMirror) content to BlockNote on mode switch
When toggling from raw mode back to BlockNote, the editor now correctly
re-parses content from tab.content instead of using stale cached blocks.

Key changes:
- useEditorTabSwap: detect rawMode true→false transition, invalidate
  block cache, and re-parse from tab.content. Added rawSwapPendingRef
  guard to prevent a second effect run from re-caching stale blocks
  before the deferred doSwap microtask runs.
- useRawMode: added onBeforeRawEnd callback to flush debounced raw
  editor content synchronously before toggling off.
- Editor.tsx: wired rawLatestContentRef and handleBeforeRawEnd to
  ensure the latest raw content reaches tab.content before the swap.
- RawEditorView: exposed latestContentRef so parent can read the
  latest keystroke content without waiting for the 500ms debounce.
- EditorContent: threaded rawLatestContentRef through to RawEditorView.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v0.20260311.398
2026-03-11 22:14:20 +01:00
Test
ab02aa5e96 feat: wire create-open relationship note to all panel contexts v0.20260311.397 2026-03-11 21:25:20 +01:00
Test
4dd27cf0c3 feat: add 'Create & open' option to relationship input dropdowns
When typing a non-existent note title in the relationship target input,
a 'Create & open' option now appears at the bottom of the dropdown.
Selecting it creates the note, adds the wikilink, and opens the new note.

- Added SearchDropdownWithCreate with create option
- Modified InlineAddNote and NoteTargetInput to support create flow
- Added onCreateAndOpenNote prop to DynamicRelationshipsPanel
- Keyboard accessible (arrow keys + Enter)
- 6 new tests covering create-and-open behavior

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 21:25:20 +01:00
Test
c499ef30f0 fix: case-insensitive type entry lookup + Playwright smoke test
buildTypeEntryMap now stores both original title and lowercase key so
isA: 'config' matches type entry titled 'Config'. Adds Playwright smoke
test that blocks the vault API to test against mock data fixtures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 21:24:51 +01:00
Test
b3bf2bf76e fix: sidebar section header reflects type icon, color, and label
- Add GearSix icon ('gear-six') to icon registry — was missing, causing
  Config type to show FileText fallback instead of its configured icon
- Add 'gray' to ACCENT_COLORS palette with CSS variables — was missing,
  causing Config type color to fall back to muted foreground
- Extract sidebar section logic to utils/sidebarSections.ts for testability
- Add Config type + instance to mock entries for browser dev mode
- Add tests: icon resolution, gray color, sidebar section builder

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 21:24:51 +01:00
Test
13622bc236 test: add real filesystem vault integration tests
Replace mock vault approach with real filesystem I/O for integration
tests. Each test copies tests/fixtures/test-vault/ to a temp directory,
overrides mock handlers to point at it, and verifies actual file
operations through the vite dev server middleware.

Tests cover: vault loading, archive/trash filtering, note creation,
rename with filesystem update, wikilink cascade on rename, relationship
display, and real file content loading.

Also extends vite.config.ts vault API middleware with write endpoints
(save, rename, delete, search, entry) and fixes getBool to handle
YAML 1.2 string values like "Yes"/"yes" (js-yaml 4.x compatibility).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 21:24:44 +01:00
Test
80ad5cfad7 fix: update fix-note-filename-on-rename smoke test for title-sync rename
Title sync now triggers a full rename flow instead of in-memory update,
so the Cmd+S test expectations needed updating.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v0.20260311.394
2026-03-11 19:55:51 +01:00
Test
068d70c264 fix: add missing old_title_hint arg to tests added on main
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 19:47:46 +01:00
Test
86ffb43eb7 style: cargo fmt on rename.rs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 19:47:46 +01:00
Test
3504bb221a fix: remove needless borrow flagged by clippy in rename.rs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 19:47:46 +01:00
Test
f2136f17ef test: Playwright smoke test for rename-wikilink-update
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 19:47:46 +01:00
Test
75ca18d4d0 test: unit tests for rename-wikilink-update feature
- handleRenameNote passes entry title as old_title to Rust
- handleUpdateFrontmatter triggers rename on title key change
- non-title keys don't trigger rename
- null old_title when entry not found

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 19:47:46 +01:00
Test
47c408dc50 feat: wire H1 sync and frontmatter title change to full rename flow
handleTitleSync now saves pending content and calls rename_note
(which renames the file and updates wikilinks) instead of only
updating in-memory state. handleUpdateFrontmatter also triggers
rename when the title: key is changed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 19:47:46 +01:00
Test
96d7df368a feat: add old_title_hint to rename_note for H1 sync rename support
When the editor saves content with a new H1 before triggering rename,
the on-disk H1 already matches the new title, causing rename_note to
noop. The old_title_hint parameter lets the caller provide the
original title so wikilinks are still found and updated.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 19:47:46 +01:00
Test
c7b0c15537 test: Playwright smoke test for serializer blank lines fix
Verifies tight lists stay tight, headings don't gain extra blank lines,
and saving without editing doesn't add whitespace changes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v0.20260311.393
2026-03-11 19:38:05 +01:00
Test
0ee6e76d10 fix: post-process BlockNote serializer to remove extra blank lines
blocksToMarkdownLossy() inserts blank lines between every block, making
tight lists loose and polluting git history. Add compactMarkdown() that
collapses inter-list-item blanks and excessive blank line runs while
preserving code blocks and intentional paragraph spacing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 19:38:05 +01:00
Test
25c44910d1 test: add Playwright smoke tests for wikilink insertion and navigation
- Test [[ autocomplete inserts wikilink with correct data-target attribute
- Test inserted wikilink does not show as broken (correct color resolution)
- Test clicking inserted wikilink navigates to the correct note

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v0.20260311.392
2026-03-11 19:22:42 +01:00
Test
61760c4a41 fix: unify wikilink resolution and disambiguate duplicate titles
- Create resolveEntry() in wikilink.ts: single case-insensitive resolution
  function that handles title, alias, filename stem, path suffix, and
  pipe syntax matching
- Replace findEntryByTarget (case-sensitive) and entryMatchesTarget
  (hardcoded /Laputa/ path) with unified resolveEntry
- Fix attachClickHandlers to insert path|title pipe syntax when multiple
  candidates share the same title (disambiguation)
- Update ai-context.ts resolveTarget to use unified resolution
- Add comprehensive tests for resolveEntry and disambiguation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 19:12:05 +01:00
Test
8104a8380c fix: image drop overlay no longer triggers on internal drags (tabs, blocks)
Remove setIsDragOver(true) from Tauri onDragDropEvent 'over' handler —
Tauri over events can't distinguish OS file drags from internal drags.
The HTML5 dragover handler already checks hasImageFiles() correctly and
now solely drives the overlay state. Tauri handler only processes drops.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v0.20260311.391
2026-03-11 18:36:16 +01:00
Test
593a0d3d54 test: Playwright smoke test for note filename rename on save
Covers: title change + save renames file, no rename when filename matches,
rapid title edits rename to final title.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v0.20260311.390
2026-03-11 18:09:55 +01:00
Test
a50aae70e8 feat: rename file on save when title slug doesn't match filename
When Cmd+S is pressed, after saving content, checks if the note's
title slug differs from its current filename. If so, triggers
rename_note to update the file on disk, tabs, breadcrumbs, and
wikilinks. Adds needsRenameOnSave() utility with tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 18:09:55 +01:00
Test
2387b9a637 fix: rename_note handles filename-slug mismatch and collisions
When the note content already has the correct title but the filename
doesn't match (e.g. untitled-note-9.md after user changed H1), the
rename was a no-op. Now checks both title AND filename slug before
early-returning. Also uses unique_dest_path for collision handling.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 18:09:55 +01:00
Test
27452515d7 test: Playwright smoke test for changing-type data corruption regression
Verifies that changing a note's type preserves the editor content —
the bug caused the tab to load a different note's content after the move.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v0.20260311.389
2026-03-11 17:50:22 +01:00
Test
14a4d371e6 fix: mock move_note_to_type_folder collision handling + Rust collision content test
The mock handler now appends -2, -3, etc. when the target path already
exists, matching the Rust unique_dest_path logic.  Previously it would
silently overwrite the existing note's content in MOCK_CONTENT.

Also adds a Rust test that verifies both the moved note and the
pre-existing note retain their respective content after a collision.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 17:39:18 +01:00
Test
9199ceaa35 fix: prevent data corruption when changing note type — preserve tab content instead of re-reading from disk
After runFrontmatterOp updates the frontmatter and sets the tab content,
move_note_to_type_folder only changes the file location (not its content).
Re-reading via loadNoteContent(result.new_path) was redundant and dangerous:
if the path collided or a stale cache intervened, it could load a different
note's content into the tab — the root cause of the data-corruption bug.

Also fixes stale-closure issue: replaceEntry no longer spreads the captured
`entries` array (which could be stale after the await), avoiding reverting
the isA field that runFrontmatterOp already updated.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 17:37:53 +01:00
Test
6af18655de style: rustfmt formatting fix
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v0.20260311.388
2026-03-11 17:09:36 +01:00
Test
90bf73524c fix: bump cache version + handle Yes/No in TS frontmatter parser
Root cause: commit 4743537 added a custom Rust deserializer for
Archived/Trashed Yes/No strings but did not bump CACHE_VERSION.
Existing vaults had stale cached entries with archived: false from the
old parser, and since the cache version (5) matched, stale values were
served without re-parsing from disk.

- Bump CACHE_VERSION 5 → 6 to force full rescan on next vault load
- Add Yes/No handling to TypeScript parseScalar (Inspector display)
- Add integration tests: cached vault path with Archived/Trashed: Yes
- Add stale cache version invalidation test
- Add frontmatter.test.ts for TS Yes/No boolean parsing
- Add Playwright smoke test for archived note filtering

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 17:07:22 +01:00
Test
c1f7f7ec6f test: Playwright smoke test for create note crash fix
Covers all acceptance criteria:
- Click '+' next to type section → note created, no crash
- Cmd+N → note created, no crash
- Custom type → note created, no crash
- Rapid double-click → both notes created, no crash

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v0.20260311.387
2026-03-11 16:50:05 +01:00
Test
d1021b9131 fix: prevent crash in handleCreateNoteImmediate — slugify fallback + try/catch
- slugify now returns 'untitled' instead of empty string when input has only
  special characters, preventing invalid paths like '/vault//note.md'
- handleCreateNoteImmediate wrapped in try/catch — worst case shows a toast
  error instead of crashing the app
- Added Rust test for deeply nested directory creation in save_note_content
- Regression tests for slugify edge cases and handleCreateNoteImmediate with
  special-character types

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 16:50:05 +01:00
Test
b9139e2d57 test: Playwright smoke test for theme live reload on save
Verifies that editing a theme note frontmatter in raw mode and pressing
Ctrl+S immediately updates CSS vars on the DOM. Also verifies saving a
non-theme note does not affect the active theme.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v0.20260311.386
2026-03-11 16:36:56 +01:00
Test
c692c5d067 fix: live-reload CSS vars when saving active theme note in editor
When user edits a theme note directly in the editor and presses Cmd+S,
the app now immediately re-applies CSS variables — no manual reload
needed. Added notifyThemeSaved(path, content) to ThemeManager; wired
into onNotePersisted callback so saving the active theme updates
cachedThemeContent, triggering useThemeApplier.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 16:31:03 +01:00
Test
b86f6d5b88 test: add Playwright smoke test for rapid note switching latency
Validates that rapid keyboard navigation and click-based note switching
don't produce stale content or crash the editor.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v0.20260309.385
2026-03-09 13:28:46 +01:00
Test
3426cbc882 test: add unit tests for prefetch cache, optimistic rollback, rapid switching
- Prefetch: content served from cache, cache cleared on vault reload,
  deduplication of concurrent requests
- Optimistic rollback: trash/archive/restore/unarchive roll back
  updateEntry on disk write failure with error toast
- Optimistic ordering: updateEntry called before frontmatter writes
- Rapid switching: sequence counter prevents stale active tab when
  notes are opened faster than IPC resolves

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 13:28:46 +01:00
Test
57ff0f18f8 feat: optimize note open and trash/archive latency
Latency root causes:
1. handleSelectNote/handleReplaceActiveTab awaited IPC before updating
   activeTabPath — zero visual feedback for 50-200ms file I/O
2. Trash/archive called updateEntry AFTER two sequential IPC calls —
   note stayed visible in list for 100-400ms

Optimizations:
- Content prefetch cache: hover on NoteItem and keyboard arrow
  navigation pre-load note content via IPC. When user clicks, content is
  already in memory — eliminates the IPC round-trip entirely.
- Optimistic trash/archive/restore/unarchive: updateEntry runs
  immediately, frontmatter writes happen async. On failure, UI rolls
  back and shows error toast.
- Rapid-switch safety: sequence counter (navSeqRef) ensures only the
  latest navigation sets activeTabPath — prevents stale content flash
  when user clicks multiple notes in quick succession.
- Prefetch cache cleared on vault reload to prevent stale content after
  external edits.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 13:28:46 +01:00
Test
abf6b51369 fix: scope Playwright selectors to dialog overlays to avoid sidebar matches
The `span.truncate` selector was matching sidebar note titles in addition
to search results, causing false positives in the full-text search test.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v0.20260309.384
2026-03-09 12:59:57 +01:00
Test
02c784b286 style: apply cargo fmt to is_file_trashed tests
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 12:44:37 +01:00
Test
fc4ba24c4e fix: exclude trashed notes from search results and autocomplete
Trashed notes were appearing in search (Cmd+F), Quick Open (Ctrl+P),
wikilink autocomplete ([[), and person mention autocomplete (@).

Rust: add is_file_trashed() to check frontmatter, filter search_vault results.
Frontend: filter trashed entries from useNoteSearch, baseItems in both
editor views, and mock search_vault handler.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 12:42:56 +01:00
Test
eaeb6e5d40 fix: simplify cache-invalidation smoke test — container visibility only v0.20260309.383 2026-03-09 12:20:24 +01:00
Test
64fe0f1c25 chore: rotate Tauri signing keypair — fix CI release builds 2026-03-09 12:20:24 +01:00
Test
474353718a fix: handle Archived/Trashed Yes/No string values in frontmatter parser
The Rust YAML parser only accepted boolean values (true/false) for the
archived and trashed fields. When the vault writes Archived: Yes or
Trashed: Yes (YAML string, not boolean), serde silently returned None
and the note appeared as non-archived/non-trashed.

Add a custom deserializer that accepts both booleans and string
representations (Yes/yes/YES/true/1 → true, No/no/false/0 → false).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v0.20260309.382
2026-03-09 11:59:27 +01:00
Test
a933e6a787 fix: add reload_vault to vault API proxy for browser mock
The vault-api proxy maps Tauri commands to HTTP endpoints when a vault
API server is running. Without this, reload_vault bypassed the proxy
and Playwright route interceptors couldn't catch vault reload calls.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 11:14:34 +01:00
Test
79689839b2 style: apply cargo fmt to new tests
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 11:14:34 +01:00
Test
b10e9facad fix: reload vault invalidates cache and rescans from filesystem
Reload Vault (Cmd+K) now calls the new `reload_vault` Tauri command which
deletes the cache file before scanning, guaranteeing a full filesystem
rescan. Previously it called `list_vault` which used incremental git-based
cache updates that could miss recent changes (e.g. trashing a note then
reloading showed stale data).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 11:14:34 +01:00
Test
2a32d2b5ad fix: resolve TypeScript overload errors in zoomCursorFix
Use untyped function references to avoid conflicts with
posAtCoords overloaded type signatures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 10:54:42 +01:00
Test
11a4e1593b test: add Playwright smoke test for CodeMirror cursor at non-100% zoom
Covers clicking at 150%, 80%, and double-click word selection at 125%.
Verifies cursor lands near the click point (within first 30 chars of line)
and that word selection produces a non-empty range.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 10:51:57 +01:00