From 14a4d371e6acc80268ce70e25e13c3b1a3dbe869 Mon Sep 17 00:00:00 2001 From: Test Date: Wed, 11 Mar 2026 17:39:18 +0100 Subject: [PATCH] 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 --- src-tauri/src/vault/rename.rs | 30 ++++++++++++++++++++++++++++++ src/mock-tauri/mock-handlers.ts | 11 ++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src-tauri/src/vault/rename.rs b/src-tauri/src/vault/rename.rs index f0e39e68..b0cdd98d 100644 --- a/src-tauri/src/vault/rename.rs +++ b/src-tauri/src/vault/rename.rs @@ -826,6 +826,36 @@ mod tests { assert!(other_content.contains("[[Weekly Review]]")); } + #[test] + fn test_move_note_collision_preserves_both_contents() { + let dir = TempDir::new().unwrap(); + let vault = dir.path(); + let moving_content = + "---\ntype: Quarter\n---\n# Migrate newsletter to Beehiiv\n\nImportant content.\n"; + let existing_content = + "---\ntype: Quarter\n---\n# Feedback for Laputa\n\nCompletely different note.\n"; + create_test_file(vault, "note/my-note.md", moving_content); + create_test_file(vault, "quarter/my-note.md", existing_content); + + let old_path = vault.join("note/my-note.md"); + let result = move_note_to_type_folder( + vault.to_str().unwrap(), + old_path.to_str().unwrap(), + "Quarter", + ) + .unwrap(); + + assert!(result.moved); + // Must get a unique path, not the existing file's path + assert!(result.new_path.contains("/quarter/my-note-2.md")); + // Moved note must retain its own content + let moved_content = fs::read_to_string(&result.new_path).unwrap(); + assert_eq!(moved_content, moving_content); + // Existing note must be untouched + let untouched = fs::read_to_string(vault.join("quarter/my-note.md")).unwrap(); + assert_eq!(untouched, existing_content); + } + #[test] fn test_move_note_empty_type_error() { let dir = TempDir::new().unwrap(); diff --git a/src/mock-tauri/mock-handlers.ts b/src/mock-tauri/mock-handlers.ts index b805c6f0..b4841288 100644 --- a/src/mock-tauri/mock-handlers.ts +++ b/src/mock-tauri/mock-handlers.ts @@ -227,7 +227,16 @@ export const mockHandlers: Record any> = { if (currentFolder === slug) return { new_path: args.note_path, updated_links: 0, moved: false } const filename = args.note_path.split('/').pop() ?? '' const vaultPath = args.vault_path.replace(/\/$/, '') - const newPath = `${vaultPath}/${slug}/${filename}` + // Handle collisions: append -2, -3, etc. if the target path already exists + // (mirrors the Rust unique_dest_path logic). + let newPath = `${vaultPath}/${slug}/${filename}` + if (newPath in MOCK_CONTENT && newPath !== args.note_path) { + const stem = filename.replace(/\.md$/, '') + const ext = filename.endsWith('.md') ? '.md' : '' + let counter = 2 + while (`${vaultPath}/${slug}/${stem}-${counter}${ext}` in MOCK_CONTENT) counter++ + newPath = `${vaultPath}/${slug}/${stem}-${counter}${ext}` + } const content = MOCK_CONTENT[args.note_path] ?? '' delete MOCK_CONTENT[args.note_path] MOCK_CONTENT[newPath] = content