use std::path::Path; use archlens_domain::{ CodeElement, CodeElementKind, CodeGraph, FilePath, Language, ModuleName, Relationship, RelationshipKind, normalize_cargo_package, normalize_python_package, }; fn make_element(name: &str, module: Option<&str>) -> CodeElement { let mut el = CodeElement::new( name, CodeElementKind::Class, FilePath::new(&format!("src/{name}.rs")).unwrap(), 1, ) .unwrap(); if let Some(m) = module { el = el.with_module(ModuleName::new(m).unwrap()); } el } // ── merge_project_edges ─────────────────────────────────────────────────────── #[test] fn merge_project_edges_adds_module_level_edges_from_project_deps() { let mut graph = CodeGraph::new(); graph.add_element(make_element("Service", Some("Application"))); graph.add_element(make_element("Order", Some("Domain"))); let mut project_graph = CodeGraph::new(); project_graph.add_element( CodeElement::new( "myapp-application", CodeElementKind::Project, FilePath::new("crates/application/Cargo.toml").unwrap(), 1, ) .unwrap(), ); project_graph.add_element( CodeElement::new( "myapp-domain", CodeElementKind::Project, FilePath::new("crates/domain/Cargo.toml").unwrap(), 1, ) .unwrap(), ); project_graph.add_relationship( Relationship::new( "myapp-application", "myapp-domain", RelationshipKind::Composition, ) .unwrap(), ); graph.merge_project_edges(&project_graph); let module_edges = graph.module_edges(); assert!( module_edges.contains_key(&("Application".to_string(), "Domain".to_string())), "expected Application -> Domain edge, got: {module_edges:?}" ); } #[test] fn merge_project_edges_ignores_crates_with_no_matching_module() { let mut graph = CodeGraph::new(); graph.add_element(make_element("Order", Some("Domain"))); let mut project_graph = CodeGraph::new(); project_graph.add_element( CodeElement::new( "external-lib", CodeElementKind::Project, FilePath::new("external/Cargo.toml").unwrap(), 1, ) .unwrap(), ); project_graph.add_element( CodeElement::new( "myapp-domain", CodeElementKind::Project, FilePath::new("crates/domain/Cargo.toml").unwrap(), 1, ) .unwrap(), ); project_graph.add_relationship( Relationship::new( "external-lib", "myapp-domain", RelationshipKind::Composition, ) .unwrap(), ); graph.merge_project_edges(&project_graph); // "External" (from external-lib) isn't a known module in graph → no edge assert!(graph.module_edges().is_empty()); } // ── Language::is_test_file ──────────────────────────────────────────────────── #[test] fn language_detects_python_test_prefix_files() { assert!(Language::Python.is_test_file(Path::new("src/test_orders.py"))); } #[test] fn language_detects_python_test_suffix_files() { assert!(Language::Python.is_test_file(Path::new("src/orders_test.py"))); } #[test] fn language_detects_rust_test_files() { assert!(Language::Rust.is_test_file(Path::new("src/orders_tests.rs"))); } #[test] fn language_detects_files_in_tests_dir() { assert!(Language::Rust.is_test_file(Path::new("tests/integration.rs"))); assert!(Language::Python.is_test_file(Path::new("tests/helpers.py"))); } #[test] fn language_does_not_flag_regular_files_as_tests() { assert!(!Language::Rust.is_test_file(Path::new("src/orders.rs"))); assert!(!Language::Python.is_test_file(Path::new("src/orders.py"))); } // ── AnalysisConfig::is_standard_excluded ───────────────────────────────────── #[test] fn analysis_config_identifies_standard_excluded_dirs() { use archlens_domain::AnalysisConfig; assert!(AnalysisConfig::is_standard_excluded(".venv")); assert!(AnalysisConfig::is_standard_excluded("node_modules")); assert!(AnalysisConfig::is_standard_excluded("target")); assert!(AnalysisConfig::is_standard_excluded("__pycache__")); } #[test] fn analysis_config_does_not_exclude_source_dirs() { use archlens_domain::AnalysisConfig; assert!(!AnalysisConfig::is_standard_excluded("src")); assert!(!AnalysisConfig::is_standard_excluded("domain")); assert!(!AnalysisConfig::is_standard_excluded("application")); } // ── Name normalization ──────────────────────────────────────────────────────── #[test] fn normalize_cargo_package_converts_underscores_to_hyphens() { assert_eq!(normalize_cargo_package("myapp_domain"), "myapp-domain"); assert_eq!(normalize_cargo_package("myapp-domain"), "myapp-domain"); } #[test] fn normalize_python_package_lowercases_and_unifies_separators() { assert_eq!(normalize_python_package("My-Package"), "my_package"); assert_eq!(normalize_python_package("my.package"), "my_package"); assert_eq!(normalize_python_package("my_package"), "my_package"); }