completion_test.rs
1 use crate::harness::{LspTestClient, TempWorkspace}; 2 use std::thread; 3 use std::time::Duration; 4 5 #[test] 6 fn test_completion_trigger_character() { 7 let workspace = TempWorkspace::new(); 8 let client = LspTestClient::spawn(workspace.root.clone()).expect("Failed to spawn LSP"); 9 client.initialize().expect("Initialize failed"); 10 11 let uri = workspace.file_uri("test.js"); 12 let content = "process.env."; 13 workspace.create_file("test.js", content); 14 15 client 16 .open_document(&uri, "javascript", content) 17 .expect("Failed to open document"); 18 thread::sleep(Duration::from_millis(300)); 19 20 let completion = client 21 .completion(&uri, 0, 12) 22 .expect("Completion request failed"); 23 24 assert!(!completion.is_null(), "Expected completion items"); 25 26 let items = completion.as_array().expect("Completion should be array"); 27 assert!(!items.is_empty(), "Should have completion items"); 28 29 let labels: Vec<&str> = items 30 .iter() 31 .filter_map(|i| i.get("label")?.as_str()) 32 .collect(); 33 34 assert!(labels.contains(&"DB_URL"), "Should have DB_URL completion"); 35 assert!( 36 labels.contains(&"API_KEY"), 37 "Should have API_KEY completion" 38 ); 39 assert!(labels.contains(&"PORT"), "Should have PORT completion"); 40 assert!(labels.contains(&"DEBUG"), "Should have DEBUG completion"); 41 42 client.shutdown().expect("Shutdown failed"); 43 } 44 45 #[test] 46 fn test_completion_on_alias() { 47 let workspace = TempWorkspace::new(); 48 let client = LspTestClient::spawn(workspace.root.clone()).expect("Failed to spawn LSP"); 49 client.initialize().expect("Initialize failed"); 50 51 let uri = workspace.file_uri("test.ts"); 52 let content = "const env = process.env; env."; 53 workspace.create_file("test.ts", content); 54 55 client 56 .open_document(&uri, "typescript", content) 57 .expect("Failed to open document"); 58 thread::sleep(Duration::from_millis(300)); 59 60 let completion = client 61 .completion(&uri, 0, 29) 62 .expect("Completion request failed"); 63 64 assert!(!completion.is_null(), "Expected completion items on alias"); 65 66 let items = completion.as_array().expect("Completion should be array"); 67 assert!(!items.is_empty(), "Should have completion items on alias"); 68 69 client.shutdown().expect("Shutdown failed"); 70 } 71 72 #[test] 73 fn test_completion_item_documentation() { 74 let workspace = TempWorkspace::new(); 75 let client = LspTestClient::spawn(workspace.root.clone()).expect("Failed to spawn LSP"); 76 client.initialize().expect("Initialize failed"); 77 78 let uri = workspace.file_uri("test.js"); 79 let content = "process.env."; 80 workspace.create_file("test.js", content); 81 82 client 83 .open_document(&uri, "javascript", content) 84 .expect("Failed to open document"); 85 thread::sleep(Duration::from_millis(300)); 86 87 let completion = client 88 .completion(&uri, 0, 12) 89 .expect("Completion request failed"); 90 91 let items = completion.as_array().expect("Completion should be array"); 92 let db_url_item = items 93 .iter() 94 .find(|i| i.get("label").map(|l| l == "DB_URL").unwrap_or(false)) 95 .expect("Should have DB_URL completion"); 96 97 let doc = db_url_item.get("documentation"); 98 assert!(doc.is_some(), "DB_URL completion should have documentation"); 99 100 let doc_value = doc 101 .unwrap() 102 .get("value") 103 .expect("Documentation should have value") 104 .as_str() 105 .expect("Documentation value should be string"); 106 107 assert!( 108 doc_value.contains("postgres://"), 109 "Documentation should contain the value" 110 ); 111 112 client.shutdown().expect("Shutdown failed"); 113 } 114 115 #[test] 116 fn test_completion_disabled_via_config() { 117 let workspace = TempWorkspace::new(); 118 workspace.create_config( 119 r#" 120 [features] 121 completion = false 122 "#, 123 ); 124 125 let client = LspTestClient::spawn(workspace.root.clone()).expect("Failed to spawn LSP"); 126 client.initialize().expect("Initialize failed"); 127 128 let uri = workspace.file_uri("test.js"); 129 let content = "process.env."; 130 workspace.create_file("test.js", content); 131 132 client 133 .open_document(&uri, "javascript", content) 134 .expect("Failed to open document"); 135 thread::sleep(Duration::from_millis(300)); 136 137 let completion = client 138 .completion(&uri, 0, 12) 139 .expect("Completion request failed"); 140 141 assert!( 142 completion.is_null() || completion.as_array().map(|a| a.is_empty()).unwrap_or(false), 143 "Completion should be null or empty when disabled" 144 ); 145 146 client.shutdown().expect("Shutdown failed"); 147 } 148 149 #[test] 150 fn test_completion_no_results_outside_env() { 151 let workspace = TempWorkspace::new(); 152 let client = LspTestClient::spawn(workspace.root.clone()).expect("Failed to spawn LSP"); 153 client.initialize().expect("Initialize failed"); 154 155 let uri = workspace.file_uri("test.js"); 156 let content = "const x = 1;"; 157 workspace.create_file("test.js", content); 158 159 client 160 .open_document(&uri, "javascript", content) 161 .expect("Failed to open document"); 162 thread::sleep(Duration::from_millis(300)); 163 164 let completion = client 165 .completion(&uri, 0, 5) 166 .expect("Completion request failed"); 167 168 assert!( 169 completion.is_null() || completion.as_array().map(|a| a.is_empty()).unwrap_or(false), 170 "Should not provide completion outside env context" 171 ); 172 173 client.shutdown().expect("Shutdown failed"); 174 } 175 176 #[test] 177 fn test_completion_python() { 178 let workspace = TempWorkspace::new(); 179 let client = LspTestClient::spawn(workspace.root.clone()).expect("Failed to spawn LSP"); 180 client.initialize().expect("Initialize failed"); 181 182 let uri = workspace.file_uri("test.py"); 183 let content = "import os\nos.environ['"; 184 workspace.create_file("test.py", content); 185 186 client 187 .open_document(&uri, "python", content) 188 .expect("Failed to open document"); 189 thread::sleep(Duration::from_millis(300)); 190 191 let _completion = client 192 .completion(&uri, 1, 13) 193 .expect("Completion request failed"); 194 195 client.shutdown().expect("Shutdown failed"); 196 }