Skip to content

Commit e5906d4

Browse files
committed
Restructure tests
1 parent 1724da7 commit e5906d4

15 files changed

Lines changed: 5810 additions & 5723 deletions

src/composer.rs

Lines changed: 1 addition & 349 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ fn extract_psr4_entries(prefix: &str, paths: &serde_json::Value, mappings: &mut
9999
}
100100

101101
/// Normalise a directory path: ensure it uses forward slashes and ends with `/`.
102-
fn normalise_path(path: &str) -> String {
102+
pub fn normalise_path(path: &str) -> String {
103103
let p = path.replace('\\', "/");
104104
if p.ends_with('/') || p.is_empty() {
105105
p
@@ -177,351 +177,3 @@ fn is_builtin_type(name: &str) -> bool {
177177
| "iterable"
178178
)
179179
}
180-
181-
// ─── Tests ──────────────────────────────────────────────────────────────────
182-
183-
#[cfg(test)]
184-
mod tests {
185-
use super::*;
186-
use std::fs;
187-
188-
/// Helper: create a temporary workspace with a composer.json and
189-
/// optional PHP class files.
190-
struct TestWorkspace {
191-
dir: tempfile::TempDir,
192-
}
193-
194-
impl TestWorkspace {
195-
fn new(composer_json: &str) -> Self {
196-
let dir = tempfile::tempdir().expect("failed to create temp dir");
197-
fs::write(dir.path().join("composer.json"), composer_json)
198-
.expect("failed to write composer.json");
199-
TestWorkspace { dir }
200-
}
201-
202-
fn root(&self) -> &Path {
203-
self.dir.path()
204-
}
205-
206-
/// Create a PHP file at the given relative path with minimal content.
207-
fn create_php_file(&self, relative_path: &str, content: &str) {
208-
let full_path = self.dir.path().join(relative_path);
209-
if let Some(parent) = full_path.parent() {
210-
fs::create_dir_all(parent).expect("failed to create dirs");
211-
}
212-
fs::write(&full_path, content).expect("failed to write PHP file");
213-
}
214-
}
215-
216-
#[test]
217-
fn test_parse_basic_psr4() {
218-
let ws = TestWorkspace::new(
219-
r#"{
220-
"autoload": {
221-
"psr-4": {
222-
"Klarna\\": "src/Klarna/"
223-
}
224-
}
225-
}"#,
226-
);
227-
228-
let mappings = parse_composer_json(ws.root());
229-
assert_eq!(mappings.len(), 1);
230-
assert_eq!(mappings[0].prefix, "Klarna\\");
231-
assert_eq!(mappings[0].base_path, "src/Klarna/");
232-
}
233-
234-
#[test]
235-
fn test_parse_autoload_dev() {
236-
let ws = TestWorkspace::new(
237-
r#"{
238-
"autoload": {
239-
"psr-4": {
240-
"Klarna\\": "src/Klarna/"
241-
}
242-
},
243-
"autoload-dev": {
244-
"psr-4": {
245-
"Klarna\\Rest\\Tests\\": "tests/"
246-
}
247-
}
248-
}"#,
249-
);
250-
251-
let mappings = parse_composer_json(ws.root());
252-
assert_eq!(mappings.len(), 2);
253-
254-
// Longest prefix first
255-
assert_eq!(mappings[0].prefix, "Klarna\\Rest\\Tests\\");
256-
assert_eq!(mappings[0].base_path, "tests/");
257-
assert_eq!(mappings[1].prefix, "Klarna\\");
258-
assert_eq!(mappings[1].base_path, "src/Klarna/");
259-
}
260-
261-
#[test]
262-
fn test_parse_array_paths() {
263-
let ws = TestWorkspace::new(
264-
r#"{
265-
"autoload": {
266-
"psr-4": {
267-
"App\\": ["src/", "lib/"]
268-
}
269-
}
270-
}"#,
271-
);
272-
273-
let mappings = parse_composer_json(ws.root());
274-
assert_eq!(mappings.len(), 2);
275-
assert_eq!(mappings[0].prefix, "App\\");
276-
assert_eq!(mappings[0].base_path, "src/");
277-
assert_eq!(mappings[1].prefix, "App\\");
278-
assert_eq!(mappings[1].base_path, "lib/");
279-
}
280-
281-
#[test]
282-
fn test_parse_no_composer_json() {
283-
let dir = tempfile::tempdir().expect("failed to create temp dir");
284-
let mappings = parse_composer_json(dir.path());
285-
assert!(mappings.is_empty());
286-
}
287-
288-
#[test]
289-
fn test_parse_invalid_json() {
290-
let ws = TestWorkspace::new("not valid json {{{");
291-
let mappings = parse_composer_json(ws.root());
292-
assert!(mappings.is_empty());
293-
}
294-
295-
#[test]
296-
fn test_parse_no_psr4_section() {
297-
let ws = TestWorkspace::new(
298-
r#"{
299-
"name": "vendor/project",
300-
"autoload": {
301-
"classmap": ["src/"]
302-
}
303-
}"#,
304-
);
305-
306-
let mappings = parse_composer_json(ws.root());
307-
assert!(mappings.is_empty());
308-
}
309-
310-
#[test]
311-
fn test_resolve_simple_class() {
312-
let ws = TestWorkspace::new(
313-
r#"{
314-
"autoload": {
315-
"psr-4": {
316-
"Klarna\\": "src/Klarna/"
317-
}
318-
}
319-
}"#,
320-
);
321-
ws.create_php_file(
322-
"src/Klarna/Customer.php",
323-
"<?php\nnamespace Klarna;\nclass Customer {}\n",
324-
);
325-
326-
let mappings = parse_composer_json(ws.root());
327-
let result = resolve_class_path(&mappings, ws.root(), "Klarna\\Customer");
328-
329-
assert!(result.is_some());
330-
let path = result.unwrap();
331-
assert!(path.ends_with("src/Klarna/Customer.php"));
332-
}
333-
334-
#[test]
335-
fn test_resolve_nested_namespace() {
336-
let ws = TestWorkspace::new(
337-
r#"{
338-
"autoload": {
339-
"psr-4": {
340-
"Klarna\\": "src/Klarna/"
341-
}
342-
}
343-
}"#,
344-
);
345-
ws.create_php_file(
346-
"src/Klarna/Rest/Order.php",
347-
"<?php\nnamespace Klarna\\Rest;\nclass Order {}\n",
348-
);
349-
350-
let mappings = parse_composer_json(ws.root());
351-
let result = resolve_class_path(&mappings, ws.root(), "Klarna\\Rest\\Order");
352-
353-
assert!(result.is_some());
354-
let path = result.unwrap();
355-
assert!(path.ends_with("src/Klarna/Rest/Order.php"));
356-
}
357-
358-
#[test]
359-
fn test_resolve_strips_leading_backslash() {
360-
let ws = TestWorkspace::new(
361-
r#"{
362-
"autoload": {
363-
"psr-4": {
364-
"Klarna\\": "src/Klarna/"
365-
}
366-
}
367-
}"#,
368-
);
369-
ws.create_php_file(
370-
"src/Klarna/Customer.php",
371-
"<?php\nnamespace Klarna;\nclass Customer {}\n",
372-
);
373-
374-
let mappings = parse_composer_json(ws.root());
375-
let result = resolve_class_path(&mappings, ws.root(), "\\Klarna\\Customer");
376-
377-
assert!(result.is_some());
378-
}
379-
380-
#[test]
381-
fn test_resolve_nonexistent_file_returns_none() {
382-
let ws = TestWorkspace::new(
383-
r#"{
384-
"autoload": {
385-
"psr-4": {
386-
"Klarna\\": "src/Klarna/"
387-
}
388-
}
389-
}"#,
390-
);
391-
392-
let mappings = parse_composer_json(ws.root());
393-
let result = resolve_class_path(&mappings, ws.root(), "Klarna\\DoesNotExist");
394-
395-
assert!(result.is_none());
396-
}
397-
398-
#[test]
399-
fn test_resolve_no_matching_prefix() {
400-
let ws = TestWorkspace::new(
401-
r#"{
402-
"autoload": {
403-
"psr-4": {
404-
"Klarna\\": "src/Klarna/"
405-
}
406-
}
407-
}"#,
408-
);
409-
410-
let mappings = parse_composer_json(ws.root());
411-
let result = resolve_class_path(&mappings, ws.root(), "Acme\\Foo");
412-
413-
assert!(result.is_none());
414-
}
415-
416-
#[test]
417-
fn test_resolve_longest_prefix_wins() {
418-
let ws = TestWorkspace::new(
419-
r#"{
420-
"autoload": {
421-
"psr-4": {
422-
"Klarna\\": "src/Klarna/",
423-
"Klarna\\Rest\\Tests\\": "tests/"
424-
}
425-
}
426-
}"#,
427-
);
428-
ws.create_php_file(
429-
"tests/OrderTest.php",
430-
"<?php\nnamespace Klarna\\Rest\\Tests;\nclass OrderTest {}\n",
431-
);
432-
433-
let mappings = parse_composer_json(ws.root());
434-
let result = resolve_class_path(&mappings, ws.root(), "Klarna\\Rest\\Tests\\OrderTest");
435-
436-
assert!(result.is_some());
437-
let path = result.unwrap();
438-
assert!(path.ends_with("tests/OrderTest.php"));
439-
}
440-
441-
#[test]
442-
fn test_resolve_builtin_types_return_none() {
443-
let ws = TestWorkspace::new(
444-
r#"{
445-
"autoload": {
446-
"psr-4": {
447-
"": "src/"
448-
}
449-
}
450-
}"#,
451-
);
452-
453-
let mappings = parse_composer_json(ws.root());
454-
455-
for builtin in &[
456-
"self", "static", "parent", "string", "int", "float", "bool", "array", "object",
457-
"mixed", "void", "never", "null", "true", "false", "callable", "iterable",
458-
] {
459-
assert!(
460-
resolve_class_path(&mappings, ws.root(), builtin).is_none(),
461-
"builtin type '{}' should not resolve",
462-
builtin
463-
);
464-
}
465-
}
466-
467-
#[test]
468-
fn test_resolve_array_paths_first_match() {
469-
let ws = TestWorkspace::new(
470-
r#"{
471-
"autoload": {
472-
"psr-4": {
473-
"App\\": ["src/", "lib/"]
474-
}
475-
}
476-
}"#,
477-
);
478-
// File exists only in lib/
479-
ws.create_php_file(
480-
"lib/Service.php",
481-
"<?php\nnamespace App;\nclass Service {}\n",
482-
);
483-
484-
let mappings = parse_composer_json(ws.root());
485-
let result = resolve_class_path(&mappings, ws.root(), "App\\Service");
486-
487-
assert!(result.is_some());
488-
let path = result.unwrap();
489-
assert!(path.ends_with("lib/Service.php"));
490-
}
491-
492-
#[test]
493-
fn test_normalise_path_adds_trailing_slash() {
494-
assert_eq!(normalise_path("src"), "src/");
495-
assert_eq!(normalise_path("src/"), "src/");
496-
assert_eq!(normalise_path(""), "");
497-
}
498-
499-
#[test]
500-
fn test_normalise_path_converts_backslashes() {
501-
assert_eq!(normalise_path("src\\Klarna\\"), "src/Klarna/");
502-
}
503-
504-
#[test]
505-
fn test_prefix_without_trailing_backslash() {
506-
let ws = TestWorkspace::new(
507-
r#"{
508-
"autoload": {
509-
"psr-4": {
510-
"App": "src/"
511-
}
512-
}
513-
}"#,
514-
);
515-
ws.create_php_file(
516-
"src/Service.php",
517-
"<?php\nnamespace App;\nclass Service {}\n",
518-
);
519-
520-
let mappings = parse_composer_json(ws.root());
521-
// The prefix gets normalised to "App\"
522-
assert_eq!(mappings[0].prefix, "App\\");
523-
524-
let result = resolve_class_path(&mappings, ws.root(), "App\\Service");
525-
assert!(result.is_some());
526-
}
527-
}

tests/common/mod.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#![allow(dead_code)]
2+
3+
use phpantom_lsp::Backend;
4+
use std::fs;
5+
6+
pub fn create_test_backend() -> Backend {
7+
Backend::new_test()
8+
}
9+
10+
/// Helper: create a temp workspace with a composer.json and PHP files,
11+
/// then return a Backend configured with that workspace root + PSR-4 mappings.
12+
pub fn create_psr4_workspace(
13+
composer_json: &str,
14+
files: &[(&str, &str)],
15+
) -> (Backend, tempfile::TempDir) {
16+
let dir = tempfile::tempdir().expect("failed to create temp dir");
17+
fs::write(dir.path().join("composer.json"), composer_json)
18+
.expect("failed to write composer.json");
19+
for (rel_path, content) in files {
20+
let full = dir.path().join(rel_path);
21+
if let Some(parent) = full.parent() {
22+
fs::create_dir_all(parent).expect("failed to create dirs");
23+
}
24+
fs::write(&full, content).expect("failed to write PHP file");
25+
}
26+
27+
let mappings = phpantom_lsp::composer::parse_composer_json(dir.path());
28+
let backend = Backend::new_test_with_workspace(dir.path().to_path_buf(), mappings);
29+
(backend, dir)
30+
}

0 commit comments

Comments
 (0)