use ralph::tools::lsp_tools::{
find_references_grep, go_to_definition_grep, hover_grep, word_at_position,
};
use std::fs;
use tempfile::TempDir;
#[test]
fn word_at_position_middle_of_word() {
let src = "fn hello_world() {}";
assert_eq!(word_at_position(src, 1, 7), Some("hello_world".to_string()));
}
#[test]
fn word_at_position_start_of_word() {
let src = "fn hello() {}";
assert_eq!(word_at_position(src, 1, 4), Some("hello".to_string()));
}
#[test]
fn word_at_position_end_of_word() {
let src = "fn hello() {}";
assert_eq!(word_at_position(src, 1, 8), Some("hello".to_string()));
}
#[test]
fn word_at_position_just_past_word_returns_preceding_word() {
let src = "fn hello() {}";
assert_eq!(word_at_position(src, 1, 3), Some("fn".to_string()));
}
#[test]
fn word_at_position_out_of_range_col_returns_none() {
let src = "fn hello() {}";
assert_eq!(word_at_position(src, 1, 999), None);
}
#[test]
fn word_at_position_out_of_range_line_returns_none() {
let src = "fn hello() {}";
assert_eq!(word_at_position(src, 99, 1), None);
}
#[test]
fn word_at_position_second_line() {
let src = "first line\nsecond word here";
assert_eq!(word_at_position(src, 2, 8), Some("word".to_string()));
}
#[test]
fn go_to_definition_finds_fn() {
let dir = TempDir::new().unwrap();
let src = "fn my_function() {\n println!(\"hello\");\n}\n";
fs::write(dir.path().join("main.rs"), src).unwrap();
let caller = "fn main() {\n my_function();\n}\n";
fs::write(dir.path().join("caller.rs"), caller).unwrap();
let result = go_to_definition_grep(
dir.path(),
std::path::Path::new("caller.rs"),
2, 5, );
assert!(
result.contains("my_function"),
"expected symbol name in result: {}",
result
);
}
#[test]
fn go_to_definition_nonexistent_file() {
let dir = TempDir::new().unwrap();
let result = go_to_definition_grep(dir.path(), std::path::Path::new("missing.rs"), 1, 1);
assert!(
result.contains("Cannot read"),
"expected error message: {}",
result
);
}
#[test]
fn go_to_definition_no_match_returns_tip() {
let dir = TempDir::new().unwrap();
fs::write(dir.path().join("empty.rs"), "// just a comment\n").unwrap();
let result = go_to_definition_grep(dir.path(), std::path::Path::new("empty.rs"), 1, 4);
assert!(
result.contains("No definition found") || result.contains("Definition candidates"),
"unexpected result: {}",
result
);
}
#[test]
fn find_references_finds_usages() {
let dir = TempDir::new().unwrap();
let src = "fn foo() {}\nfn bar() { foo(); foo(); }\n";
fs::write(dir.path().join("lib.rs"), src).unwrap();
let result = find_references_grep(
dir.path(),
std::path::Path::new("lib.rs"),
1, 4, );
assert!(
result.contains("foo"),
"expected 'foo' in references: {}",
result
);
assert!(
result.contains("grep"),
"expected grep fallback note: {}",
result
);
}
#[test]
fn find_references_nonexistent_file() {
let dir = TempDir::new().unwrap();
let result = find_references_grep(dir.path(), std::path::Path::new("ghost.rs"), 1, 1);
assert!(result.contains("Cannot read"), "expected error: {}", result);
}
#[test]
fn hover_returns_context_lines() {
let dir = TempDir::new().unwrap();
let src = "line one\nline two\nline three\nline four\nline five\n";
fs::write(dir.path().join("sample.txt"), src).unwrap();
let result = hover_grep(
dir.path(),
std::path::Path::new("sample.txt"),
3, 1,
);
assert!(result.contains("three"), "target line missing: {}", result);
assert!(
result.contains("two") || result.contains("four"),
"context missing: {}",
result
);
}
#[test]
fn hover_nonexistent_file() {
let dir = TempDir::new().unwrap();
let result = hover_grep(dir.path(), std::path::Path::new("nope.rs"), 1, 1);
assert!(result.contains("Cannot read"), "expected error: {}", result);
}