use std::time::Duration;
use lsp_types::TextDocumentSyncKind;
mod integration;
use integration::TestServer;
const SHORT_TIMEOUT: Duration = Duration::from_secs(2);
#[test]
fn test_initialize_response_has_expected_capabilities() {
let server = TestServer::start();
let caps = &server.capabilities().capabilities;
assert!(
matches!(
caps.text_document_sync,
Some(lsp_types::TextDocumentSyncCapability::Kind(
TextDocumentSyncKind::FULL
))
),
"Expected textDocumentSync to be FULL, got: {:?}",
caps.text_document_sync,
);
assert!(
caps.code_action_provider.is_some(),
"Expected codeActionProvider to be Some, got None"
);
let exec_provider = caps
.execute_command_provider
.as_ref()
.expect("Expected executeCommandProvider to be Some");
assert!(
exec_provider
.commands
.contains(&"diffguard.explainRule".to_string()),
"Expected 'diffguard.explainRule' in commands, got: {:?}",
exec_provider.commands,
);
assert!(
exec_provider
.commands
.contains(&"diffguard.reloadConfig".to_string()),
"Expected 'diffguard.reloadConfig' in commands, got: {:?}",
exec_provider.commands,
);
assert!(
exec_provider
.commands
.contains(&"diffguard.showRuleUrl".to_string()),
"Expected 'diffguard.showRuleUrl' in commands, got: {:?}",
exec_provider.commands,
);
}
#[test]
fn test_initialize_response_contains_server_info() {
let server = TestServer::start();
let info = server
.capabilities()
.server_info
.as_ref()
.expect("Expected serverInfo in InitializeResult");
assert_eq!(info.name, "diffguard-lsp");
assert!(info.version.is_some(), "Expected server version to be set");
}
#[test]
fn test_shutdown_exit_lifecycle_is_clean() {
let server = TestServer::start();
server.shutdown();
}
#[test]
fn test_did_open_publishes_diagnostics_for_changed_content() {
let mut server = TestServer::start();
let content = "// TODO: implement this function\nfn main() {}\n";
let uri = server.create_file("src/main.rs", content);
server.send_did_open(&uri, "rust", 1, content);
let diagnostics = server.collect_diagnostics_for_uri(&uri, SHORT_TIMEOUT);
for diag in &diagnostics {
assert!(diag.source.is_some(), "diagnostic should have a source");
assert_eq!(diag.source.as_deref(), Some("diffguard"));
}
}
#[test]
fn test_did_change_updates_diagnostics() {
let mut server = TestServer::start();
let initial_content = "fn main() {\n println!(\"hello\");\n}\n";
let uri = server.create_file("src/main.rs", initial_content);
server.send_did_open(&uri, "rust", 1, initial_content);
let _initial_diags = server.collect_diagnostics_for_uri(&uri, SHORT_TIMEOUT);
let _initial_count = _initial_diags.len();
let changed_content = "fn main() {\n // TODO: fix this\n println!(\"hello\");\n}\n";
server.send_did_change(&uri, 2, changed_content);
let _updated_diags = server.collect_diagnostics_for_uri(&uri, SHORT_TIMEOUT);
}
#[test]
fn test_did_close_clears_diagnostics() {
let mut server = TestServer::start();
let content = "// TODO: something\nfn main() {}\n";
let uri = server.create_file("src/main.rs", content);
server.send_did_open(&uri, "rust", 1, content);
let _ = server.collect_diagnostics_for_uri(&uri, SHORT_TIMEOUT);
server.send_did_close(&uri);
let after_close_diags = server.collect_diagnostics_for_uri(&uri, SHORT_TIMEOUT);
assert!(
after_close_diags.is_empty(),
"Expected empty diagnostics after didClose, got: {:?}",
after_close_diags,
);
}
#[test]
fn test_did_save_triggers_diagnostic_refresh() {
let mut server = TestServer::start();
let content = "fn main() {\n // TODO: save me\n}\n";
let uri = server.create_file("src/main.rs", content);
server.send_did_open(&uri, "rust", 1, content);
let _ = server.collect_diagnostics_for_uri(&uri, SHORT_TIMEOUT);
server.send_did_save(&uri);
let _after_save_diags = server.collect_diagnostics_for_uri(&uri, SHORT_TIMEOUT);
}
#[test]
fn test_multiple_did_open_documents_are_independent() {
let mut server = TestServer::start();
let uri1 = server.create_file("src/a.rs", "// TODO: file a\nfn a() {}\n");
let uri2 = server.create_file("src/b.rs", "// TODO: file b\nfn b() {}\n");
server.send_did_open(&uri1, "rust", 1, "// TODO: file a\nfn a() {}\n");
server.send_did_open(&uri2, "rust", 1, "// TODO: file b\nfn b() {}\n");
let _diags1 = server.collect_diagnostics_for_uri(&uri1, SHORT_TIMEOUT);
let _diags2 = server.collect_diagnostics_for_uri(&uri2, SHORT_TIMEOUT);
}
#[test]
fn test_did_open_with_incremental_version_numbers() {
let mut server = TestServer::start();
let content = "fn main() {}\n";
let uri = server.create_file("src/main.rs", content);
server.send_did_open(&uri, "rust", 1, content);
let _ = server.collect_diagnostics_for_uri(&uri, SHORT_TIMEOUT);
server.send_did_change(&uri, 2, "fn main() {\n // TODO\n}\n");
let _ = server.collect_diagnostics_for_uri(&uri, SHORT_TIMEOUT);
server.send_did_change(&uri, 3, "fn main() {\n println!(\"ok\");\n}\n");
let _ = server.collect_diagnostics_for_uri(&uri, SHORT_TIMEOUT);
}