test(lsp): cover documented completions
Add protocol and helper coverage for documented hemplate completion items, including data-hemx-root. req: diagnostics/006
This commit is contained in:
@@ -394,6 +394,11 @@ fn hemplate_completion_items(
|
||||
"{+= trusted_html =+}",
|
||||
"Trusted/rendered HTML expression; prefer escaped `{+ expr +}` for user content.",
|
||||
),
|
||||
completion_item(
|
||||
"data-hemx-root",
|
||||
"data-hemx-root=\"app\"",
|
||||
"Generated hemx root for delegated runtime behavior.",
|
||||
),
|
||||
completion_item(
|
||||
"data-hemx-slot",
|
||||
"data-hemx-slot=\"content\"",
|
||||
@@ -746,6 +751,81 @@ mod tests {
|
||||
assert!(!outside_hover.to_string().contains("exercise.name: String"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn completion_items_cover_documented_hemplate_surface() {
|
||||
// req: diagnostics/006
|
||||
let text = r#"<main data-hemx-root="app"><template h-for="item in &self.items" h-key="item.id"><p +class="self.class_name">{+ self.title +}{+= trusted =+}</p></template></main>"#;
|
||||
let items = hemplate_completion_items("file:///tmp/app.heml", text, Some((0, 6)));
|
||||
let labels = items
|
||||
.iter()
|
||||
.filter_map(|item| item["label"].as_str())
|
||||
.collect::<std::collections::BTreeSet<_>>();
|
||||
for label in [
|
||||
"h-for",
|
||||
"h-key",
|
||||
"h-if",
|
||||
"h-match",
|
||||
"h-case",
|
||||
"+attr",
|
||||
"{+ expr +}",
|
||||
"{+= expr =+}",
|
||||
"data-hemx-root",
|
||||
"data-hemx-slot",
|
||||
"data-hemx-form",
|
||||
"data-hemx-handle",
|
||||
] {
|
||||
assert!(labels.contains(label), "missing completion item `{label}`");
|
||||
}
|
||||
assert!(items.iter().all(|item| item["documentation"]["value"]
|
||||
.as_str()
|
||||
.unwrap_or_default()
|
||||
.contains("docs/hemplate-syntax.md")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lsp_completion_returns_documented_items() {
|
||||
// req: diagnostics/006
|
||||
let text = r#"<main data-hemx-root="todos"><div data-hemx-slot="content">{+ self.title +}</div></main>"#;
|
||||
let uri = "file:///tmp/completion.heml";
|
||||
let input = [
|
||||
lsp_message(serde_json::json!({"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {}})),
|
||||
lsp_message(serde_json::json!({
|
||||
"jsonrpc": "2.0",
|
||||
"method": "textDocument/didOpen",
|
||||
"params": {"textDocument": {"uri": uri, "languageId": "heml", "version": 1, "text": text}}
|
||||
})),
|
||||
lsp_message(serde_json::json!({
|
||||
"jsonrpc": "2.0",
|
||||
"id": 2,
|
||||
"method": "textDocument/completion",
|
||||
"params": {"textDocument": {"uri": uri}, "position": {"line": 0, "character": 6}}
|
||||
})),
|
||||
lsp_message(serde_json::json!({"jsonrpc": "2.0", "method": "exit"})),
|
||||
]
|
||||
.join("");
|
||||
let mut reader = std::io::BufReader::new(input.as_bytes());
|
||||
let mut output = Vec::new();
|
||||
|
||||
serve_lsp(&mut reader, &mut output).expect("serve LSP");
|
||||
let messages = lsp_messages(&output);
|
||||
let completion = messages
|
||||
.iter()
|
||||
.find(|message| message["id"] == 2)
|
||||
.expect("completion response");
|
||||
let completion_items = completion["result"]
|
||||
.as_array()
|
||||
.or_else(|| completion["result"]["items"].as_array())
|
||||
.expect("completion items");
|
||||
let labels = completion_items
|
||||
.iter()
|
||||
.filter_map(|item| item["label"].as_str())
|
||||
.collect::<std::collections::BTreeSet<_>>();
|
||||
assert!(labels.contains("h-if"));
|
||||
assert!(labels.contains("data-hemx-root"));
|
||||
assert!(labels.contains("data-hemx-slot"));
|
||||
assert!(labels.contains("{+ expr +}"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn workout_template_fields_are_available_from_repo_facts() {
|
||||
// req: diagnostics/006
|
||||
|
||||
Reference in New Issue
Block a user