/ tests / integration_php.rs
integration_php.rs
  1  mod common;
  2  use common::TestFixture;
  3  use ecolog_lsp::server::handlers::compute_diagnostics;
  4  use ecolog_lsp::server::handlers::handle_completion;
  5  use ecolog_lsp::server::handlers::handle_hover;
  6  use tower_lsp::lsp_types::{
  7      CompletionContext, CompletionParams, CompletionTriggerKind, HoverParams, Position,
  8      TextDocumentIdentifier, TextDocumentPositionParams,
  9  };
 10  
 11  #[tokio::test]
 12  async fn test_php_hover_env_subscript() {
 13      let fixture = TestFixture::new().await;
 14      let uri = fixture.create_file("test.php", "<?php\n$db = $_ENV['DB_URL'];");
 15  
 16      fixture
 17          .state
 18          .document_manager
 19          .open(
 20              uri.clone(),
 21              "php".to_string(),
 22              "<?php\n$db = $_ENV['DB_URL'];".to_string(),
 23              0,
 24          )
 25          .await;
 26  
 27      let hover = handle_hover(
 28          HoverParams {
 29              text_document_position_params: TextDocumentPositionParams {
 30                  text_document: TextDocumentIdentifier { uri },
 31                  position: Position::new(1, 15),
 32              },
 33              work_done_progress_params: Default::default(),
 34          },
 35          &fixture.state,
 36      )
 37      .await;
 38  
 39      assert!(hover.is_some());
 40      assert!(format!("{:?}", hover.unwrap()).contains("postgres://"));
 41  }
 42  
 43  #[tokio::test]
 44  async fn test_php_hover_server_subscript() {
 45      let fixture = TestFixture::new().await;
 46      let uri = fixture.create_file("test.php", "<?php\n$key = $_SERVER['API_KEY'];");
 47  
 48      fixture
 49          .state
 50          .document_manager
 51          .open(
 52              uri.clone(),
 53              "php".to_string(),
 54              "<?php\n$key = $_SERVER['API_KEY'];".to_string(),
 55              0,
 56          )
 57          .await;
 58  
 59      let hover = handle_hover(
 60          HoverParams {
 61              text_document_position_params: TextDocumentPositionParams {
 62                  text_document: TextDocumentIdentifier { uri },
 63                  position: Position::new(1, 20),
 64              },
 65              work_done_progress_params: Default::default(),
 66          },
 67          &fixture.state,
 68      )
 69      .await;
 70  
 71      assert!(hover.is_some());
 72      assert!(format!("{:?}", hover.unwrap()).contains("secret_key"));
 73  }
 74  
 75  #[tokio::test]
 76  async fn test_php_hover_getenv() {
 77      let fixture = TestFixture::new().await;
 78      let uri = fixture.create_file("test.php", "<?php\n$port = getenv('PORT');");
 79  
 80      fixture
 81          .state
 82          .document_manager
 83          .open(
 84              uri.clone(),
 85              "php".to_string(),
 86              "<?php\n$port = getenv('PORT');".to_string(),
 87              0,
 88          )
 89          .await;
 90  
 91      let hover = handle_hover(
 92          HoverParams {
 93              text_document_position_params: TextDocumentPositionParams {
 94                  text_document: TextDocumentIdentifier { uri },
 95                  position: Position::new(1, 18),
 96              },
 97              work_done_progress_params: Default::default(),
 98          },
 99          &fixture.state,
100      )
101      .await;
102  
103      assert!(hover.is_some());
104      assert!(format!("{:?}", hover.unwrap()).contains("8080"));
105  }
106  
107  #[tokio::test]
108  async fn test_php_hover_env_helper() {
109      let fixture = TestFixture::new().await;
110      let uri = fixture.create_file("test.php", "<?php\n$debug = env('DEBUG');");
111  
112      fixture
113          .state
114          .document_manager
115          .open(
116              uri.clone(),
117              "php".to_string(),
118              "<?php\n$debug = env('DEBUG');".to_string(),
119              0,
120          )
121          .await;
122  
123      let hover = handle_hover(
124          HoverParams {
125              text_document_position_params: TextDocumentPositionParams {
126                  text_document: TextDocumentIdentifier { uri },
127                  position: Position::new(1, 15),
128              },
129              work_done_progress_params: Default::default(),
130          },
131          &fixture.state,
132      )
133      .await;
134  
135      assert!(hover.is_some());
136      assert!(format!("{:?}", hover.unwrap()).contains("true"));
137  }
138  
139  #[tokio::test]
140  async fn test_php_completion_env() {
141      let fixture = TestFixture::new().await;
142      // Use a complete subscript expression where cursor is inside string
143      let uri = fixture.create_file("test.php", "<?php\n$_ENV[\"\"]");
144  
145      fixture
146          .state
147          .document_manager
148          .open(
149              uri.clone(),
150              "php".to_string(),
151              "<?php\n$_ENV[\"\"]".to_string(),
152              0,
153          )
154          .await;
155  
156      let completion = handle_completion(
157          CompletionParams {
158              text_document_position: TextDocumentPositionParams {
159                  text_document: TextDocumentIdentifier { uri },
160                  position: Position::new(1, 8), // Inside the quotes
161              },
162              work_done_progress_params: Default::default(),
163              partial_result_params: Default::default(),
164              context: Some(CompletionContext {
165                  trigger_kind: CompletionTriggerKind::INVOKED,
166                  trigger_character: None,
167              }),
168          },
169          &fixture.state,
170      )
171      .await;
172  
173      // Completion may or may not return results depending on how the handler
174      // processes the PHP subscript pattern. This test verifies basic functionality.
175      if let Some(items) = completion {
176          // If we get completions, verify they include expected env vars
177          if !items.is_empty() {
178              assert!(items.iter().any(|i| i.label == "DB_URL"));
179          }
180      }
181  }
182  
183  #[tokio::test]
184  async fn test_php_diagnostics_undefined() {
185      let fixture = TestFixture::new().await;
186      let uri = fixture.create_file("test.php", "<?php\n$x = $_ENV['MISSING_VAR'];");
187  
188      fixture
189          .state
190          .document_manager
191          .open(
192              uri.clone(),
193              "php".to_string(),
194              "<?php\n$x = $_ENV['MISSING_VAR'];".to_string(),
195              0,
196          )
197          .await;
198  
199      let diags = compute_diagnostics(&uri, &fixture.state).await;
200  
201      assert!(!diags.is_empty());
202      assert!(diags.iter().any(|d| d.message.contains("not defined")));
203  }
204  
205  #[tokio::test]
206  async fn test_php_hover_binding() {
207      let fixture = TestFixture::new().await;
208      let uri = fixture.create_file("test.php", "<?php\n$db = $_ENV['DB_URL'];\necho $db;");
209  
210      fixture
211          .state
212          .document_manager
213          .open(
214              uri.clone(),
215              "php".to_string(),
216              "<?php\n$db = $_ENV['DB_URL'];\necho $db;".to_string(),
217              0,
218          )
219          .await;
220  
221      // Hover over the env var name in the $_ENV subscript
222      let hover = handle_hover(
223          HoverParams {
224              text_document_position_params: TextDocumentPositionParams {
225                  text_document: TextDocumentIdentifier { uri: uri.clone() },
226                  position: Position::new(1, 15), // Position on DB_URL
227              },
228              work_done_progress_params: Default::default(),
229          },
230          &fixture.state,
231      )
232      .await;
233  
234      assert!(hover.is_some());
235      assert!(format!("{:?}", hover.unwrap()).contains("postgres://"));
236  }