use archlens_domain::{ BoundaryRule, CodeElement, CodeElementKind, CodeGraph, FilePath, ModuleName, Relationship, RelationshipKind, check_boundary_rules, }; fn make_element(name: &str, module: &str) -> CodeElement { CodeElement::new( name, CodeElementKind::Class, FilePath::new(&format!("src/{name}.rs")).unwrap(), 1, ) .unwrap() .with_module(ModuleName::new(module).unwrap()) } fn graph_with_edge( src_name: &str, src_module: &str, tgt_name: &str, tgt_module: &str, ) -> CodeGraph { let mut graph = CodeGraph::new(); graph.add_element(make_element(src_name, src_module)); graph.add_element(make_element(tgt_name, tgt_module)); graph.add_relationship( Relationship::new(src_name, tgt_name, RelationshipKind::Composition).unwrap(), ); graph.qualify() } #[test] fn boundary_rule_parses_source_and_target() { let rule = BoundaryRule::parse("Application --> Domain").unwrap(); assert_eq!(rule.source(), "Application"); assert_eq!(rule.target(), "Domain"); } #[test] fn check_returns_denied_violation_when_deny_rule_matches_edge() { let graph = graph_with_edge("Service", "Domain", "Adapter", "Adapters"); let deny = vec![BoundaryRule::parse("Domain --> Adapters").unwrap()]; let violations = check_boundary_rules(&graph, &[], &deny); assert_eq!(violations.len(), 1); assert_eq!(violations[0].source_module(), "Domain"); assert_eq!(violations[0].target_module(), "Adapters"); assert!(matches!( violations[0].kind(), archlens_domain::RuleKind::Denied )); } #[test] fn check_returns_no_violation_when_edge_matches_allow_rule() { let graph = graph_with_edge("Service", "Application", "Order", "Domain"); let allow = vec![BoundaryRule::parse("Application --> Domain").unwrap()]; let violations = check_boundary_rules(&graph, &allow, &[]); assert!( violations.is_empty(), "expected no violations, got: {}", violations.len() ); } #[test] fn check_returns_not_allowed_when_edge_absent_from_allow_list() { let graph = graph_with_edge("Repo", "Adapters", "Order", "Domain"); // Only Application --> Domain is allowed; Adapters --> Domain is not in the list let allow = vec![BoundaryRule::parse("Application --> Domain").unwrap()]; let violations = check_boundary_rules(&graph, &allow, &[]); assert_eq!(violations.len(), 1); assert_eq!(violations[0].source_module(), "Adapters"); assert_eq!(violations[0].target_module(), "Domain"); }