mod harness;
use harness::TestClient;
use harness::runtime::run_lsp_test;
use serde_json::Value;
fn get_completion_labels(response: &Value) -> Vec<String> {
response["result"]["items"]
.as_array()
.map(|items| {
items
.iter()
.filter_map(|item| item["label"].as_str().map(|s| s.to_string()))
.collect()
})
.unwrap_or_default()
}
fn has_completion_label(response: &Value, label: &str) -> bool {
get_completion_labels(response).contains(&label.to_string())
}
#[test]
fn test_completion_filter_prefix_returns_filter() {
run_lsp_test(|| async {
let client = TestClient::new();
client.initialize().await;
client
.open_document("file:///test.sparql", "SELECT * WHERE { FI }")
.await;
let id = client.complete("file:///test.sparql", 0, 19).await;
let response = client
.get_response(id)
.expect("Should receive completion response");
assert!(
response.get("result").is_some(),
"Completion should return a result: {:?}",
response
);
assert!(
has_completion_label(&response, "FILTER"),
"Should suggest FILTER for prefix 'FI', got: {:?}",
get_completion_labels(&response)
);
assert!(
!has_completion_label(&response, "BIND"),
"Should NOT suggest BIND for prefix 'FI'"
);
assert!(
!has_completion_label(&response, "OPTIONAL"),
"Should NOT suggest OPTIONAL for prefix 'FI'"
);
assert!(
!has_completion_label(&response, "VALUES"),
"Should NOT suggest VALUES for prefix 'FI'"
);
});
}
#[test]
fn test_completion_non_keyword_prefix_excludes_keywords() {
run_lsp_test(|| async {
let client = TestClient::new();
client.initialize().await;
client
.open_document("file:///test.sparql", "SELECT * WHERE { Germany }")
.await;
let id = client.complete("file:///test.sparql", 0, 24).await;
let response = client
.get_response(id)
.expect("Should receive completion response");
assert!(
response.get("result").is_some(),
"Completion should return a result: {:?}",
response
);
assert!(
!has_completion_label(&response, "FILTER"),
"Should NOT suggest FILTER for 'Germany'"
);
assert!(
!has_completion_label(&response, "BIND"),
"Should NOT suggest BIND for 'Germany'"
);
assert!(
!has_completion_label(&response, "OPTIONAL"),
"Should NOT suggest OPTIONAL for 'Germany'"
);
assert!(
!has_completion_label(&response, "VALUES"),
"Should NOT suggest VALUES for 'Germany'"
);
assert!(
!has_completion_label(&response, "SERVICE"),
"Should NOT suggest SERVICE for 'Germany'"
);
assert!(
!has_completion_label(&response, "MINUS"),
"Should NOT suggest MINUS for 'Germany'"
);
assert!(
!has_completion_label(&response, "UNION"),
"Should NOT suggest UNION for 'Germany'"
);
});
}
#[test]
fn test_completion_optional_prefix_returns_optional() {
run_lsp_test(|| async {
let client = TestClient::new();
client.initialize().await;
client
.open_document("file:///test.sparql", "SELECT * WHERE { OP }")
.await;
let id = client.complete("file:///test.sparql", 0, 19).await;
let response = client
.get_response(id)
.expect("Should receive completion response");
assert!(
response.get("result").is_some(),
"Completion should return a result: {:?}",
response
);
assert!(
has_completion_label(&response, "OPTIONAL"),
"Should suggest OPTIONAL for prefix 'OP', got: {:?}",
get_completion_labels(&response)
);
assert!(
!has_completion_label(&response, "FILTER"),
"Should NOT suggest FILTER for prefix 'OP'"
);
assert!(
!has_completion_label(&response, "BIND"),
"Should NOT suggest BIND for prefix 'OP'"
);
});
}
#[test]
fn test_completion_case_insensitive_prefix() {
run_lsp_test(|| async {
let client = TestClient::new();
client.initialize().await;
client
.open_document("file:///test.sparql", "SELECT * WHERE { fi }")
.await;
let id = client.complete("file:///test.sparql", 0, 19).await;
let response = client
.get_response(id)
.expect("Should receive completion response");
assert!(
response.get("result").is_some(),
"Completion should return a result: {:?}",
response
);
assert!(
has_completion_label(&response, "FILTER"),
"Should suggest FILTER for lowercase prefix 'fi', got: {:?}",
get_completion_labels(&response)
);
});
}
#[test]
fn test_completion_bind_prefix_returns_bind() {
run_lsp_test(|| async {
let client = TestClient::new();
client.initialize().await;
client
.open_document("file:///test.sparql", "SELECT * WHERE { BI }")
.await;
let id = client.complete("file:///test.sparql", 0, 19).await;
let response = client
.get_response(id)
.expect("Should receive completion response");
assert!(
response.get("result").is_some(),
"Completion should return a result: {:?}",
response
);
assert!(
has_completion_label(&response, "BIND"),
"Should suggest BIND for prefix 'BI', got: {:?}",
get_completion_labels(&response)
);
assert!(
!has_completion_label(&response, "FILTER"),
"Should NOT suggest FILTER for prefix 'BI'"
);
assert!(
!has_completion_label(&response, "OPTIONAL"),
"Should NOT suggest OPTIONAL for prefix 'BI'"
);
});
}
#[test]
fn test_completion_s_prefix_returns_service_and_sub_select() {
run_lsp_test(|| async {
let client = TestClient::new();
client.initialize().await;
client
.open_document("file:///test.sparql", "SELECT * WHERE { S }")
.await;
let id = client.complete("file:///test.sparql", 0, 18).await;
let response = client
.get_response(id)
.expect("Should receive completion response");
assert!(
response.get("result").is_some(),
"Completion should return a result: {:?}",
response
);
assert!(
has_completion_label(&response, "SERVICE"),
"Should suggest SERVICE for prefix 'S', got: {:?}",
get_completion_labels(&response)
);
assert!(
has_completion_label(&response, "Sub select"),
"Should suggest 'Sub select' for prefix 'S', got: {:?}",
get_completion_labels(&response)
);
assert!(
!has_completion_label(&response, "FILTER"),
"Should NOT suggest FILTER for prefix 'S'"
);
assert!(
!has_completion_label(&response, "BIND"),
"Should NOT suggest BIND for prefix 'S'"
);
});
}
#[test]
fn test_completion_solution_modifier_group_prefix() {
run_lsp_test(|| async {
let client = TestClient::new();
client.initialize().await;
client
.open_document("file:///test.sparql", "SELECT * WHERE { ?s ?p ?o } GR")
.await;
let id = client.complete("file:///test.sparql", 0, 30).await;
let response = client
.get_response(id)
.expect("Should receive completion response");
assert!(
response.get("result").is_some(),
"Completion should return a result: {:?}",
response
);
assert!(
has_completion_label(&response, "GROUP BY"),
"Should suggest 'GROUP BY' for prefix 'GR', got: {:?}",
get_completion_labels(&response)
);
assert!(
!has_completion_label(&response, "ORDER BY"),
"Should NOT suggest 'ORDER BY' for prefix 'GR'"
);
assert!(
!has_completion_label(&response, "LIMIT"),
"Should NOT suggest LIMIT for prefix 'GR'"
);
});
}
#[test]
fn test_completion_solution_modifier_non_keyword_excludes_all() {
run_lsp_test(|| async {
let client = TestClient::new();
client.initialize().await;
client
.open_document("file:///test.sparql", "SELECT * WHERE { ?s ?p ?o } xyz")
.await;
let id = client.complete("file:///test.sparql", 0, 31).await;
let response = client
.get_response(id)
.expect("Should receive completion response");
assert!(
response.get("result").is_some(),
"Completion should return a result: {:?}",
response
);
assert!(
!has_completion_label(&response, "GROUP BY"),
"Should NOT suggest 'GROUP BY' for 'xyz'"
);
assert!(
!has_completion_label(&response, "ORDER BY"),
"Should NOT suggest 'ORDER BY' for 'xyz'"
);
assert!(
!has_completion_label(&response, "HAVING"),
"Should NOT suggest HAVING for 'xyz'"
);
assert!(
!has_completion_label(&response, "LIMIT"),
"Should NOT suggest LIMIT for 'xyz'"
);
assert!(
!has_completion_label(&response, "OFFSET"),
"Should NOT suggest OFFSET for 'xyz'"
);
});
}