115 lines
5.9 KiB
Rust
115 lines
5.9 KiB
Rust
//! Folder and duplicate commands share the headless registry surface.
|
|
mod common;
|
|
use common::{seed, temp_vault};
|
|
use notescraft_engine::{Registry, Session, register_core};
|
|
use serde_json::json;
|
|
|
|
#[test]
|
|
fn folder_commands_move_links_bookmarks_buffers_and_attachments() {
|
|
let vault = temp_vault("folders");
|
|
seed(
|
|
vault.path(),
|
|
&[("old/A.md", "[[old/deep/B]]"), ("old/deep/B.md", "[[old/A]]"), ("root.md", "[[old/A]] [[old/deep/B]] ![[old/pic.png]]"), ("old/pic.png", "image")],
|
|
);
|
|
let mut session = Session::open(vault.path()).expect("session");
|
|
session.add_bookmark("old/A.md", None, None).expect("bookmark");
|
|
session.open_buffer("old/A.md").expect("buffer");
|
|
session.buffer_mut("old/A.md").expect("buffer").edit(0..0, "unsaved ").expect("edit");
|
|
let mut reg = Registry::new();
|
|
register_core(&mut reg).expect("registry");
|
|
reg.run("folder.create", &mut session, &json!({"path":"empty"})).expect("create");
|
|
assert!(vault.path().join("empty").is_dir());
|
|
reg.run("folder.rename", &mut session, &json!({"from":"old","to":"new"})).expect("rename");
|
|
assert_eq!(session.read_note("root.md").expect("read"), "[[new/A]] [[new/deep/B]] ![[new/pic.png]]");
|
|
assert_eq!(session.read_note("new/A.md").expect("read"), "[[new/deep/B]]");
|
|
assert_eq!(session.read_note("new/deep/B.md").expect("read"), "[[new/A]]");
|
|
assert_eq!(session.bookmarks().expect("bookmarks").first().map(|b| b.path.as_str()), Some("new/A.md"));
|
|
assert!(session.buffer("new/A.md").is_some_and(|buffer| buffer.is_dirty() && buffer.text().starts_with("unsaved")));
|
|
assert!(session.index().files().contains(&"new/pic.png"));
|
|
assert!(session.index().note("old/A.md").is_none());
|
|
reg.run("folder.delete", &mut session, &json!({"path":"new"})).expect("trash");
|
|
assert!(!vault.path().join("new").exists());
|
|
assert!(session.index().note("new/A.md").is_none());
|
|
assert!(!session.index().files().contains(&"new/pic.png"));
|
|
assert!(session.buffer("new/A.md").is_none());
|
|
}
|
|
|
|
#[test]
|
|
fn duplicate_preserves_content_and_uses_first_free_copy_name() {
|
|
let vault = temp_vault("duplicate");
|
|
seed(vault.path(), &[("sub/Note.md", "héllo\r\n"), ("sub/Note copy.md", "occupied")]);
|
|
let mut session = Session::open(vault.path()).expect("session");
|
|
let mut reg = Registry::new();
|
|
register_core(&mut reg).expect("registry");
|
|
let result = reg.run("note.duplicate", &mut session, &json!({"path":"sub/Note.md"})).expect("duplicate");
|
|
assert_eq!(result.get("path"), Some(&json!("sub/Note copy 2.md")));
|
|
assert_eq!(session.read_note("sub/Note copy 2.md").expect("read"), "héllo\r\n");
|
|
assert!(session.index().note("sub/Note copy 2.md").is_some());
|
|
}
|
|
|
|
#[test]
|
|
fn folders_refuse_root_reserved_collisions_and_read_only() {
|
|
let vault = temp_vault("folder-guards");
|
|
seed(vault.path(), &[("old/A.md", "body"), ("taken/B.md", "body")]);
|
|
let mut session = Session::open(vault.path()).expect("session");
|
|
let mut reg = Registry::new();
|
|
register_core(&mut reg).expect("registry");
|
|
for path in ["", ".", ".obsidian", ".notescraft", "../outside"] {
|
|
for id in ["folder.create", "folder.delete"] {
|
|
assert!(reg.run(id, &mut session, &json!({"path":path})).is_err(), "{id}: {path}");
|
|
}
|
|
assert!(reg.run("folder.rename", &mut session, &json!({"from":"old","to":path})).is_err());
|
|
}
|
|
for to in ["taken", "old/nested"] {
|
|
assert!(reg.run("folder.rename", &mut session, &json!({"from":"old","to":to})).is_err());
|
|
}
|
|
let mut readonly = Session::open_read_only(vault.path()).expect("readonly");
|
|
for id in ["folder.create", "folder.rename", "folder.delete", "note.duplicate"] {
|
|
assert!(!reg.is_enabled(id, &readonly));
|
|
assert!(reg.run(id, &mut readonly, &json!({"path":"old"})).is_err());
|
|
}
|
|
}
|
|
|
|
#[cfg(unix)]
|
|
#[test]
|
|
fn folder_aliases_cannot_move_vault_root_or_private_state() {
|
|
let vault = temp_vault("folder-symlinks");
|
|
let mut session = Session::open(vault.path()).expect("session");
|
|
std::os::unix::fs::symlink(vault.path(), vault.path().join("alias")).expect("symlink");
|
|
std::os::unix::fs::symlink(vault.path().join(".notescraft"), vault.path().join("private")).expect("symlink");
|
|
let mut reg = Registry::new();
|
|
register_core(&mut reg).expect("registry");
|
|
for path in ["alias", "private"] {
|
|
assert!(reg.run("folder.rename", &mut session, &json!({"from":path,"to":"moved"})).is_err());
|
|
}
|
|
assert!(vault.path().is_dir());
|
|
assert!(vault.path().join(".notescraft").is_dir());
|
|
}
|
|
|
|
#[test]
|
|
fn folder_move_without_link_updates_keeps_links_and_moves_bookmarks() {
|
|
let vault = temp_vault("folder-no-rewrite");
|
|
seed(vault.path(), &[("old/A.md", "body"), ("root.md", "[[old/A]]")]);
|
|
let mut session = Session::open(vault.path()).expect("session");
|
|
session.add_bookmark("old/A.md", Some("Heading"), None).expect("bookmark");
|
|
let mut reg = Registry::new();
|
|
register_core(&mut reg).expect("registry");
|
|
reg.run("folder.rename", &mut session, &json!({"from":"old","to":"new","update_links":false})).expect("rename");
|
|
assert_eq!(session.read_note("root.md").expect("read"), "[[old/A]]");
|
|
assert_eq!(session.bookmarks().expect("bookmarks").first().map(|b| b.path.as_str()), Some("new/A.md"));
|
|
}
|
|
|
|
#[test]
|
|
fn renamed_links_refresh_clean_buffers_and_search() {
|
|
let vault = temp_vault("rename-mirrors");
|
|
seed(vault.path(), &[("A.md", "# A"), ("root.md", "[[A]]")]);
|
|
let mut session = Session::open(vault.path()).expect("session");
|
|
session.open_buffer("root.md").expect("buffer");
|
|
let mut reg = Registry::new();
|
|
register_core(&mut reg).expect("registry");
|
|
reg.run("note.rename", &mut session, &json!({"from":"A.md","to":"Zebra.md"})).expect("rename");
|
|
assert_eq!(session.buffer("root.md").map(notescraft_engine::Buffer::text), Some("[[Zebra]]"));
|
|
let result = reg.run("search", &mut session, &json!({"query":"Zebra"})).expect("search");
|
|
assert!(result.to_string().contains("root.md"));
|
|
}
|