/ tests / e2e / hover_test.rs
hover_test.rs
  1  use crate::harness::{LspTestClient, TempWorkspace};
  2  use std::thread;
  3  use std::time::Duration;
  4  
  5  #[test]
  6  fn test_hover_direct_env_reference_js() {
  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 = "const url = process.env.DB_URL;";
 13      workspace.create_file("test.js", content);
 14  
 15      client
 16          .open_document(&uri, "javascript", content)
 17          .expect("Failed to open document");
 18  
 19      thread::sleep(Duration::from_millis(300));
 20  
 21      let hover = client.hover(&uri, 0, 24).expect("Hover request failed");
 22  
 23      assert!(!hover.is_null(), "Expected hover result for DB_URL");
 24  
 25      let contents = hover.get("contents").expect("Missing contents");
 26      let value = contents
 27          .get("value")
 28          .expect("Missing value")
 29          .as_str()
 30          .expect("Value not string");
 31  
 32      assert!(
 33          value.contains("DB_URL"),
 34          "Hover should contain variable name"
 35      );
 36      assert!(value.contains("postgres://"));
 37  
 38      client.shutdown().expect("Shutdown failed");
 39  }
 40  
 41  #[test]
 42  fn test_hover_bracket_notation_js() {
 43      let workspace = TempWorkspace::new();
 44      let client = LspTestClient::spawn(workspace.root.clone()).expect("Failed to spawn LSP");
 45      client.initialize().expect("Initialize failed");
 46  
 47      let uri = workspace.file_uri("test.js");
 48      let content = "const key = process.env['API_KEY'];";
 49      workspace.create_file("test.js", content);
 50  
 51      client
 52          .open_document(&uri, "javascript", content)
 53          .expect("Failed to open document");
 54      thread::sleep(Duration::from_millis(300));
 55  
 56      let hover = client.hover(&uri, 0, 26).expect("Hover request failed");
 57  
 58      assert!(!hover.is_null(), "Expected hover result for API_KEY");
 59  
 60      let contents = hover.get("contents").expect("Missing contents");
 61      let value = contents
 62          .get("value")
 63          .expect("Missing value")
 64          .as_str()
 65          .expect("Value not string");
 66  
 67      assert!(
 68          value.contains("secret_key"),
 69          "Hover should contain API_KEY value"
 70      );
 71  
 72      client.shutdown().expect("Shutdown failed");
 73  }
 74  
 75  #[test]
 76  fn test_hover_destructuring() {
 77      let workspace = TempWorkspace::new();
 78      let client = LspTestClient::spawn(workspace.root.clone()).expect("Failed to spawn LSP");
 79      client.initialize().expect("Initialize failed");
 80  
 81      let uri = workspace.file_uri("test.js");
 82      let content = "const { PORT } = process.env;";
 83      workspace.create_file("test.js", content);
 84  
 85      client
 86          .open_document(&uri, "javascript", content)
 87          .expect("Failed to open document");
 88      thread::sleep(Duration::from_millis(300));
 89  
 90      let hover = client.hover(&uri, 0, 8).expect("Hover request failed");
 91  
 92      assert!(!hover.is_null(), "Expected hover result for PORT");
 93  
 94      let contents = hover.get("contents").expect("Missing contents");
 95      let value = contents
 96          .get("value")
 97          .expect("Missing value")
 98          .as_str()
 99          .expect("Value not string");
100  
101      assert!(value.contains("8080"), "Hover should contain PORT value");
102  
103      client.shutdown().expect("Shutdown failed");
104  }
105  
106  #[test]
107  fn test_hover_object_alias_chain() {
108      let workspace = TempWorkspace::new();
109      let client = LspTestClient::spawn(workspace.root.clone()).expect("Failed to spawn LSP");
110      client.initialize().expect("Initialize failed");
111  
112      let uri = workspace.file_uri("test.js");
113      let content = "const e = process.env; const port = e.PORT;";
114      workspace.create_file("test.js", content);
115  
116      client
117          .open_document(&uri, "javascript", content)
118          .expect("Failed to open document");
119      thread::sleep(Duration::from_millis(300));
120  
121      let hover = client.hover(&uri, 0, 40).expect("Hover request failed");
122  
123      assert!(!hover.is_null(), "Expected hover result for PORT via alias");
124  
125      let contents = hover.get("contents").expect("Missing contents");
126      let value = contents
127          .get("value")
128          .expect("Missing value")
129          .as_str()
130          .expect("Value not string");
131  
132      assert!(value.contains("8080"), "Hover should contain PORT value");
133  
134      client.shutdown().expect("Shutdown failed");
135  }
136  
137  #[test]
138  fn test_hover_undefined_returns_null() {
139      let workspace = TempWorkspace::new();
140      let client = LspTestClient::spawn(workspace.root.clone()).expect("Failed to spawn LSP");
141      client.initialize().expect("Initialize failed");
142  
143      let uri = workspace.file_uri("test.js");
144      let content = "process.env.UNDEFINED_VAR";
145      workspace.create_file("test.js", content);
146  
147      client
148          .open_document(&uri, "javascript", content)
149          .expect("Failed to open document");
150      thread::sleep(Duration::from_millis(300));
151  
152      let hover = client.hover(&uri, 0, 15).expect("Hover request failed");
153  
154      assert!(hover.is_null(), "Undefined vars should return null hover");
155  
156      client.shutdown().expect("Shutdown failed");
157  }
158  
159  #[test]
160  fn test_hover_python() {
161      let workspace = TempWorkspace::new();
162      let client = LspTestClient::spawn(workspace.root.clone()).expect("Failed to spawn LSP");
163      client.initialize().expect("Initialize failed");
164  
165      let uri = workspace.file_uri("test.py");
166      let content = "import os\ndb = os.environ['DB_URL']";
167      workspace.create_file("test.py", content);
168  
169      client
170          .open_document(&uri, "python", content)
171          .expect("Failed to open document");
172      thread::sleep(Duration::from_millis(300));
173  
174      let hover = client.hover(&uri, 1, 18).expect("Hover request failed");
175  
176      assert!(!hover.is_null(), "Expected hover result for Python");
177  
178      client.shutdown().expect("Shutdown failed");
179  }
180  
181  #[test]
182  fn test_hover_rust() {
183      let workspace = TempWorkspace::new();
184      let client = LspTestClient::spawn(workspace.root.clone()).expect("Failed to spawn LSP");
185      client.initialize().expect("Initialize failed");
186  
187      let uri = workspace.file_uri("test.rs");
188      let content = r#"fn main() { std::env::var("PORT"); }"#;
189      workspace.create_file("test.rs", content);
190  
191      client
192          .open_document(&uri, "rust", content)
193          .expect("Failed to open document");
194      thread::sleep(Duration::from_millis(300));
195  
196      let hover = client.hover(&uri, 0, 28).expect("Hover request failed");
197  
198      assert!(!hover.is_null(), "Expected hover result for Rust");
199  
200      client.shutdown().expect("Shutdown failed");
201  }
202  
203  #[test]
204  fn test_hover_go() {
205      let workspace = TempWorkspace::new();
206      let client = LspTestClient::spawn(workspace.root.clone()).expect("Failed to spawn LSP");
207      client.initialize().expect("Initialize failed");
208  
209      let uri = workspace.file_uri("test.go");
210      let content = r#"package main
211  import "os"
212  func main() { os.Getenv("DEBUG") }"#;
213      workspace.create_file("test.go", content);
214  
215      client
216          .open_document(&uri, "go", content)
217          .expect("Failed to open document");
218      thread::sleep(Duration::from_millis(300));
219  
220      let hover = client.hover(&uri, 2, 26).expect("Hover request failed");
221  
222      assert!(!hover.is_null(), "Expected hover result for Go");
223  
224      client.shutdown().expect("Shutdown failed");
225  }
226  
227  #[test]
228  fn test_hover_typescript() {
229      let workspace = TempWorkspace::new();
230      let client = LspTestClient::spawn(workspace.root.clone()).expect("Failed to spawn LSP");
231      client.initialize().expect("Initialize failed");
232  
233      let uri = workspace.file_uri("test.ts");
234      let content = "const apiKey: string = process.env.API_KEY!;";
235      workspace.create_file("test.ts", content);
236  
237      client
238          .open_document(&uri, "typescript", content)
239          .expect("Failed to open document");
240      thread::sleep(Duration::from_millis(300));
241  
242      let hover = client.hover(&uri, 0, 38).expect("Hover request failed");
243  
244      assert!(!hover.is_null(), "Expected hover result for TypeScript");
245  
246      client.shutdown().expect("Shutdown failed");
247  }