/ tests / integration_go.rs
integration_go.rs
  1  mod common;
  2  use common::TestFixture;
  3  use ecolog_lsp::server::handlers::{compute_diagnostics, handle_completion, handle_hover};
  4  use tower_lsp::lsp_types::{
  5      HoverParams, Position, TextDocumentIdentifier, TextDocumentPositionParams,
  6  };
  7  
  8  #[tokio::test]
  9  async fn test_go_hover_getenv() {
 10      let fixture = TestFixture::new().await;
 11  
 12      let content = "package main\nimport \"os\"\nfunc main() {\n  val := os.Getenv(\"DB_URL\")\n}";
 13      let uri = fixture.create_file("test.go", content);
 14  
 15      fixture
 16          .state
 17          .document_manager
 18          .open(uri.clone(), "go".to_string(), content.to_string(), 0)
 19          .await;
 20  
 21      let hover = handle_hover(
 22          HoverParams {
 23              text_document_position_params: TextDocumentPositionParams {
 24                  text_document: TextDocumentIdentifier { uri },
 25                  position: Position::new(3, 22),
 26              },
 27              work_done_progress_params: Default::default(),
 28          },
 29          &fixture.state,
 30      )
 31      .await;
 32  
 33      assert!(hover.is_some(), "Hover failed for os.Getenv");
 34      assert!(format!("{:?}", hover.unwrap()).contains("postgres://"));
 35  }
 36  
 37  #[tokio::test]
 38  async fn test_go_hover_lookupenv() {
 39      let fixture = TestFixture::new().await;
 40      let uri = fixture.create_file(
 41          "test.go",
 42          "package main\nimport \"os\"\nfunc main() {\n  val, _ := os.LookupEnv(\"API_KEY\")\n}",
 43      );
 44  
 45      fixture
 46          .state
 47          .document_manager
 48          .open(
 49              uri.clone(),
 50              "go".to_string(),
 51              "package main\nimport \"os\"\nfunc main() {\n  val, _ := os.LookupEnv(\"API_KEY\")\n}"
 52                  .to_string(),
 53              0,
 54          )
 55          .await;
 56  
 57      let hover = handle_hover(
 58          HoverParams {
 59              text_document_position_params: TextDocumentPositionParams {
 60                  text_document: TextDocumentIdentifier { uri },
 61                  position: Position::new(3, 27),
 62              },
 63              work_done_progress_params: Default::default(),
 64          },
 65          &fixture.state,
 66      )
 67      .await;
 68  
 69      assert!(hover.is_some(), "Hover failed for os.LookupEnv");
 70      assert!(format!("{:?}", hover.unwrap()).contains("secret_key"));
 71  }
 72  
 73  #[tokio::test]
 74  async fn test_go_completion() {
 75      let fixture = TestFixture::new().await;
 76  
 77      tokio::time::sleep(std::time::Duration::from_millis(100)).await;
 78      let content = "package main\nimport \"os\"\nfunc main() {\n  os.LookupEnv(\"\")\n}";
 79      let uri = fixture.create_file("test.go", content);
 80  
 81      fixture
 82          .state
 83          .document_manager
 84          .open(uri.clone(), "go".to_string(), content.to_string(), 0)
 85          .await;
 86  
 87      let completion = handle_completion(
 88          tower_lsp::lsp_types::CompletionParams {
 89              text_document_position: TextDocumentPositionParams {
 90                  text_document: TextDocumentIdentifier { uri },
 91                  position: Position::new(3, 16),
 92              },
 93              work_done_progress_params: Default::default(),
 94              partial_result_params: Default::default(),
 95              context: None,
 96          },
 97          &fixture.state,
 98      )
 99      .await;
100  
101      assert!(completion.is_some(), "Completion failed for os.Getenv");
102      assert!(completion.unwrap().iter().any(|i| i.label == "PORT"));
103  }
104  
105  // ═══════════════════════════════════════════════════════════════════════════
106  // New Pattern Tests: struct init, multiple assignment, conditional binding, viper
107  // ═══════════════════════════════════════════════════════════════════════════
108  
109  #[tokio::test]
110  async fn test_go_hover_struct_init() {
111      let fixture = TestFixture::new().await;
112      let content = r#"package main
113  import "os"
114  type Config struct { DB string }
115  func main() {
116    cfg := Config{DB: os.Getenv("DB_URL")}
117  }"#;
118      let uri = fixture.create_file("test.go", content);
119  
120      fixture
121          .state
122          .document_manager
123          .open(uri.clone(), "go".to_string(), content.to_string(), 0)
124          .await;
125  
126      let hover = handle_hover(
127          HoverParams {
128              text_document_position_params: TextDocumentPositionParams {
129                  text_document: TextDocumentIdentifier { uri },
130                  position: Position::new(4, 33),
131              },
132              work_done_progress_params: Default::default(),
133          },
134          &fixture.state,
135      )
136      .await;
137  
138      assert!(hover.is_some(), "Expected hover for struct field init");
139      assert!(format!("{:?}", hover.unwrap()).contains("postgres://"));
140  }
141  
142  #[tokio::test]
143  async fn test_go_hover_lookupenv_with_ok() {
144      let fixture = TestFixture::new().await;
145      let content = r#"package main
146  import "os"
147  func main() {
148    val, ok := os.LookupEnv("DB_URL")
149    if ok { println(val) }
150  }"#;
151      let uri = fixture.create_file("test.go", content);
152  
153      fixture
154          .state
155          .document_manager
156          .open(uri.clone(), "go".to_string(), content.to_string(), 0)
157          .await;
158  
159      let hover = handle_hover(
160          HoverParams {
161              text_document_position_params: TextDocumentPositionParams {
162                  text_document: TextDocumentIdentifier { uri },
163                  position: Position::new(3, 28),
164              },
165              work_done_progress_params: Default::default(),
166          },
167          &fixture.state,
168      )
169      .await;
170  
171      assert!(hover.is_some(), "Expected hover for LookupEnv with ok");
172      assert!(format!("{:?}", hover.unwrap()).contains("postgres://"));
173  }
174  
175  #[tokio::test]
176  async fn test_go_hover_if_init() {
177      let fixture = TestFixture::new().await;
178      let content = r#"package main
179  import "os"
180  func main() {
181    if val, ok := os.LookupEnv("DB_URL"); ok {
182      println(val)
183    }
184  }"#;
185      let uri = fixture.create_file("test.go", content);
186  
187      fixture
188          .state
189          .document_manager
190          .open(uri.clone(), "go".to_string(), content.to_string(), 0)
191          .await;
192  
193      let hover = handle_hover(
194          HoverParams {
195              text_document_position_params: TextDocumentPositionParams {
196                  text_document: TextDocumentIdentifier { uri },
197                  position: Position::new(3, 31),
198              },
199              work_done_progress_params: Default::default(),
200          },
201          &fixture.state,
202      )
203      .await;
204  
205      assert!(hover.is_some(), "Expected hover for if statement init");
206      assert!(format!("{:?}", hover.unwrap()).contains("postgres://"));
207  }
208  
209  #[tokio::test]
210  async fn test_go_hover_viper_getstring() {
211      let fixture = TestFixture::new().await;
212      let content = r#"package main
213  import "github.com/spf13/viper"
214  func main() {
215    db := viper.GetString("DB_URL")
216  }"#;
217      let uri = fixture.create_file("test.go", content);
218  
219      fixture
220          .state
221          .document_manager
222          .open(uri.clone(), "go".to_string(), content.to_string(), 0)
223          .await;
224  
225      let hover = handle_hover(
226          HoverParams {
227              text_document_position_params: TextDocumentPositionParams {
228                  text_document: TextDocumentIdentifier { uri },
229                  position: Position::new(3, 26),
230              },
231              work_done_progress_params: Default::default(),
232          },
233          &fixture.state,
234      )
235      .await;
236  
237      assert!(hover.is_some(), "Expected hover for viper.GetString");
238      assert!(format!("{:?}", hover.unwrap()).contains("postgres://"));
239  }
240  
241  #[tokio::test]
242  async fn test_go_diagnostics_undefined() {
243      let fixture = TestFixture::new().await;
244      let content = r#"package main
245  import "os"
246  func main() {
247    val := os.Getenv("MISSING_VAR")
248    println(val)
249  }"#;
250      let uri = fixture.create_file("test.go", content);
251  
252      fixture
253          .state
254          .document_manager
255          .open(uri.clone(), "go".to_string(), content.to_string(), 0)
256          .await;
257  
258      let diags = compute_diagnostics(&uri, &fixture.state).await;
259  
260      assert!(!diags.is_empty());
261      assert!(diags.iter().any(|d| d.message.contains("not defined")));
262  }