Files
archlens/crates/domain/tests/policy_tests.rs
Gabriel Kaszewski e26151b4a1
Some checks failed
CI / Check / Test (push) Failing after 44s
Architecture Docs / Generate diagrams (push) Successful in 3m21s
refactor: move scattered business logic into domain
- CodeGraph::merge_project_edges() replaces presentation-layer function
- Language::is_test_file() centralises test file detection (was in walkdir)
- AnalysisConfig::is_standard_excluded() centralises default dir exclusions (was in walkdir)
- normalize_cargo_package() / normalize_python_package() in domain replace duplicated normalisers in each adapter
- walkdir, cargo-workspace, python-project updated to call domain methods
2026-06-17 10:58:46 +02:00

163 lines
5.4 KiB
Rust

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");
}