Files
nuwiki/crates/nuwiki-lsp/tests/commands_files.rs
T
gffranco 21b485c91b Remove stale phase/spec references from code comments
Strip "Phase N", "SPEC §X.Y", and "v1.x" planning labels from comments
across the Rust crates and editor layers now that those tracking
artifacts are gone. Comments only — no logic, strings, or test names
touched.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-30 15:25:51 -03:00

116 lines
4.0 KiB
Rust

//! Pure-function tests for the rename helper + the file-delete
//! command. The async `Backend::rename` end-to-end (with `read_or_open`
//! hitting disk) is exercised by integration tests but covered here
//! at the building-block level — same logic, no async client.
use std::path::PathBuf;
use nuwiki_lsp::rename::{build_new_uri, rewrite_wikilink_target};
use tower_lsp::lsp_types::Url;
// ===== rewrite_wikilink_target =====
#[test]
fn rewrites_plain_wikilink() {
let out = rewrite_wikilink_target("[[Old Page]]", "New Page").unwrap();
assert_eq!(out, "[[New Page]]");
}
#[test]
fn preserves_description() {
let out = rewrite_wikilink_target("[[Old|some text]]", "New").unwrap();
assert_eq!(out, "[[New|some text]]");
}
#[test]
fn preserves_anchor() {
let out = rewrite_wikilink_target("[[Old#section]]", "New").unwrap();
assert_eq!(out, "[[New#section]]");
}
#[test]
fn preserves_anchor_and_description() {
let out = rewrite_wikilink_target("[[Old#sec|desc]]", "New").unwrap();
assert_eq!(out, "[[New#sec|desc]]");
}
#[test]
fn rewrites_subdirectory_path() {
let out = rewrite_wikilink_target("[[old/page]]", "new/subdir/page").unwrap();
assert_eq!(out, "[[new/subdir/page]]");
}
#[test]
fn returns_none_for_non_wikilink_text() {
assert_eq!(rewrite_wikilink_target("just text", "X"), None);
assert_eq!(rewrite_wikilink_target("[[not closed", "X"), None);
assert_eq!(rewrite_wikilink_target("not opened]]", "X"), None);
assert_eq!(rewrite_wikilink_target("[]", "X"), None);
}
// ===== build_new_uri =====
#[test]
fn builds_uri_under_root() {
let uri = build_new_uri(&PathBuf::from("/tmp/wiki"), "Page", ".wiki").unwrap();
let path = uri.to_file_path().unwrap();
assert_eq!(path, PathBuf::from("/tmp/wiki/Page.wiki"));
}
#[test]
fn builds_uri_with_subdirectory() {
let uri = build_new_uri(&PathBuf::from("/tmp/wiki"), "dir/Page", ".wiki").unwrap();
let path = uri.to_file_path().unwrap();
assert_eq!(path, PathBuf::from("/tmp/wiki/dir/Page.wiki"));
}
#[test]
fn omits_duplicate_extension() {
let uri = build_new_uri(&PathBuf::from("/tmp/wiki"), "Page.wiki", ".wiki").unwrap();
let path = uri.to_file_path().unwrap();
assert_eq!(path, PathBuf::from("/tmp/wiki/Page.wiki"));
}
#[test]
fn ignores_empty_path_segments() {
// `//page` should not collapse into a filesystem-absolute path.
let uri = build_new_uri(&PathBuf::from("/tmp/wiki"), "//page", ".wiki").unwrap();
let path = uri.to_file_path().unwrap();
assert_eq!(path, PathBuf::from("/tmp/wiki/page.wiki"));
}
// ===== executeCommand: nuwiki.file.delete =====
//
// We don't need a Backend to drive `commands::execute` for the delete
// command — it ignores its first arg. The smoke test verifies the
// dispatcher + DeleteFile-op packaging.
#[tokio::test]
async fn file_delete_returns_workspace_edit_with_delete_op() {
use tower_lsp::lsp_types::{DocumentChangeOperation, DocumentChanges, ResourceOp};
// Building a real Backend requires a Client. For this unit test we use
// `commands::execute` with `Backend` typed as `&_` since the delete
// path doesn't touch backend state. Instead we drive the inner logic
// by constructing the args inline.
//
// Easier: shape the test as an integration test over the public
// module surface — call `commands::execute` once we expose a thin
// builder. We test the JSON-shaped contract using the
// edits module directly, since that's what `file_delete` returns.
let uri = Url::parse("file:///tmp/note.wiki").unwrap();
let mut b = nuwiki_lsp::edits::WorkspaceEditBuilder::new();
b.file_op(nuwiki_lsp::edits::op_delete(uri.clone()));
let we = b.build();
let DocumentChanges::Operations(ops) = we.document_changes.unwrap() else {
panic!("expected Operations variant");
};
assert_eq!(ops.len(), 1);
match &ops[0] {
DocumentChangeOperation::Op(ResourceOp::Delete(d)) => {
assert_eq!(d.uri, uri);
}
other => panic!("expected DeleteFile op, got {other:?}"),
}
}