mod common;
use common::TestServer;
#[tokio::test]
async fn hover_on_empty_file_returns_null_not_error() {
let mut server = TestServer::new().await;
server.open("empty.php", "").await;
let resp = server.hover("empty.php", 0, 0).await;
assert!(
resp["error"].is_null(),
"hover errored on empty file: {resp:?}"
);
assert!(
resp["result"].is_null(),
"hover on empty file should be null, got: {:?}",
resp["result"]
);
}
#[tokio::test]
async fn hover_past_eof_does_not_crash() {
let mut server = TestServer::new().await;
server
.open("short.php", "<?php\nfunction f(): void {}\n")
.await;
let resp = server.hover("short.php", 500, 500).await;
assert!(resp["error"].is_null(), "hover past EOF errored: {resp:?}");
}
#[tokio::test]
async fn definition_on_unknown_symbol_returns_null() {
let mut server = TestServer::new().await;
server
.open("unk.php", "<?php\n$x = new UnknownClass();\n")
.await;
let resp = server.definition("unk.php", 1, 13).await;
assert!(resp["error"].is_null(), "definition errored: {resp:?}");
let result = &resp["result"];
let is_empty = result.is_null() || result.as_array().map(|a| a.is_empty()).unwrap_or(false);
assert!(
is_empty,
"unknown symbol should have no definition, got: {result:?}"
);
}
#[tokio::test]
async fn requests_on_parse_error_file_do_not_error() {
let mut server = TestServer::new().await;
let notif = server
.open("broken.php", "<?php\nfunction f( $x { // missing ): body\n")
.await;
let diags = notif["params"]["diagnostics"]
.as_array()
.cloned()
.unwrap_or_default();
assert!(
!diags.is_empty(),
"expected parse diagnostics for broken source"
);
let resp = server.hover("broken.php", 1, 10).await;
assert!(resp["error"].is_null(), "hover errored: {resp:?}");
let resp = server.document_symbols("broken.php").await;
assert!(resp["error"].is_null(), "documentSymbol errored: {resp:?}");
let resp = server.folding_range("broken.php").await;
assert!(resp["error"].is_null(), "foldingRange errored: {resp:?}");
}
#[tokio::test]
async fn references_on_unopened_uri_returns_empty() {
let mut server = TestServer::new().await;
let resp = server.references("ghost.php", 0, 0, false).await;
assert!(resp["error"].is_null(), "references errored: {resp:?}");
let result = &resp["result"];
let is_empty = result.is_null() || result.as_array().map(|a| a.is_empty()).unwrap_or(false);
assert!(
is_empty,
"references on unopened file should be empty, got: {result:?}"
);
}
#[tokio::test]
async fn rename_on_nonexistent_symbol_does_not_error() {
let mut server = TestServer::new().await;
server.open("rn.php", "<?php\n// nothing to rename\n").await;
let resp = server.rename("rn.php", 1, 5, "NewName").await;
assert!(resp["error"].is_null(), "rename errored: {resp:?}");
}