"""Tests for scanner parsers (CSV, MD, YAML, OpenAPI).""" from pathlib import Path import pytest from app.modules.scanner.infrastructure.parsers.csv_parser import CsvParser DESIGN_DIR = Path("/workspace/arch-design-agent-skill-dashboard/design") @pytest.fixture def csv_parser(): return CsvParser() # ── CSV Parser Tests ── class TestCsvParserCapabilities: def test_parse_capability_map(self, csv_parser): result = csv_parser.parse(DESIGN_DIR / "business-architecture" / "02-capability-map.csv") assert "capabilities" in result caps = result["capabilities"] assert len(caps) > 0 cap = caps[0] assert cap.capability_id.startswith("CAP-") assert cap.name # should have a name assert isinstance(cap.related_value_flows, list) def test_capability_related_value_flows_split(self, csv_parser): result = csv_parser.parse(DESIGN_DIR / "business-architecture" / "02-capability-map.csv") caps = result["capabilities"] # CAP-PROGRESS-DESIGN has "VF-02 VF-03" which should be split progress_cap = [c for c in caps if c.capability_id == "CAP-PROGRESS-DESIGN"] assert len(progress_cap) == 1 assert progress_cap[0].related_value_flows == ["VF-02", "VF-03"] class TestCsvParserModules: def test_parse_modules(self, csv_parser): result = csv_parser.parse(DESIGN_DIR / "application-architecture" / "02-modules.csv") assert "modules" in result mods = result["modules"] assert len(mods) > 0 mod = mods[0] assert mod.module_id.startswith("MOD-") assert isinstance(mod.depends_on, list) assert isinstance(mod.capabilities, list) def test_module_list_fields(self, csv_parser): result = csv_parser.parse(DESIGN_DIR / "application-architecture" / "02-modules.csv") mods = result["modules"] scanner = [m for m in mods if m.module_id == "MOD-SCANNER"] assert len(scanner) == 1 assert "MOD-DESIGN" in scanner[0].depends_on assert len(scanner[0].capabilities) > 0 class TestCsvParserTraceability: def test_parse_traceability(self, csv_parser): result = csv_parser.parse(DESIGN_DIR / "traceability.csv") assert "traceability_links" in result links = result["traceability_links"] assert len(links) > 0 link = links[0] assert link.trace_id.startswith("TR-") assert isinstance(link.entity_ids, list) assert isinstance(link.value_flow_ids, list) def test_traceability_space_split(self, csv_parser): result = csv_parser.parse(DESIGN_DIR / "traceability.csv") links = result["traceability_links"] # TR-04 has many entity_ids space-separated tr04 = [l for l in links if l.trace_id == "TR-04"] assert len(tr04) == 1 assert len(tr04[0].entity_ids) > 5 class TestCsvParserOtherTypes: def test_parse_value_flows(self, csv_parser): result = csv_parser.parse(DESIGN_DIR / "business-architecture" / "03-value-flows.csv") assert "value_flows" in result assert len(result["value_flows"]) > 0 def test_parse_user_journeys(self, csv_parser): result = csv_parser.parse(DESIGN_DIR / "business-architecture" / "04-user-journeys.csv") assert "user_journeys" in result assert len(result["user_journeys"]) > 0 def test_parse_integrations(self, csv_parser): result = csv_parser.parse(DESIGN_DIR / "application-architecture" / "03-integrations.csv") assert "integrations" in result assert len(result["integrations"]) > 0 def test_parse_external_systems(self, csv_parser): result = csv_parser.parse(DESIGN_DIR / "application-architecture" / "01-external-systems.csv") assert "external_systems" in result assert len(result["external_systems"]) > 0 def test_parse_entities(self, csv_parser): result = csv_parser.parse(DESIGN_DIR / "data-architecture" / "01-entities.csv") assert "entities" in result assert len(result["entities"]) > 0 def test_parse_data_flows(self, csv_parser): result = csv_parser.parse(DESIGN_DIR / "data-architecture" / "02-data-flows.csv") assert "data_flows" in result assert len(result["data_flows"]) > 0 def test_parse_data_security(self, csv_parser): result = csv_parser.parse(DESIGN_DIR / "data-architecture" / "03-data-security.csv") assert "data_securities" in result assert len(result["data_securities"]) > 0 def test_parse_tech_selections(self, csv_parser): result = csv_parser.parse(DESIGN_DIR / "technology-architecture" / "00-technology-selection.csv") assert "tech_selections" in result assert len(result["tech_selections"]) > 0 def test_parse_runtime_components(self, csv_parser): result = csv_parser.parse(DESIGN_DIR / "technology-architecture" / "01-runtime-components.csv") assert "runtime_components" in result assert len(result["runtime_components"]) > 0 def test_parse_environments(self, csv_parser): result = csv_parser.parse(DESIGN_DIR / "technology-architecture" / "02-environments.csv") assert "environments" in result assert len(result["environments"]) > 0 def test_parse_change_log(self, csv_parser): result = csv_parser.parse(DESIGN_DIR / "change-log.csv") assert "change_log_entries" in result assert len(result["change_log_entries"]) > 0 def test_parse_shared_terminology(self, csv_parser): result = csv_parser.parse(DESIGN_DIR / "domains" / "_shared" / "01-shared-terminology.csv") assert "shared_terms" in result terms = result["shared_terms"] assert len(terms) > 0 # Check used_by_domains is a list (space-split) assert isinstance(terms[0].used_by_domains, list) assert len(terms[0].used_by_domains) > 0 def test_parse_ubiquitous_language(self, csv_parser): result = csv_parser.parse(DESIGN_DIR / "domains" / "design" / "02-ubiquitous-language.csv") assert "ubiquitous_terms" in result assert len(result["ubiquitous_terms"]) > 0 def test_parse_scenarios(self, csv_parser): result = csv_parser.parse(DESIGN_DIR / "domains" / "design" / "03-scenarios-and-flows.csv") assert "scenarios" in result assert len(result["scenarios"]) > 0 def test_parse_domain_modules(self, csv_parser): result = csv_parser.parse(DESIGN_DIR / "domains" / "design" / "04-domain-modules.csv") assert "domain_modules" in result assert len(result["domain_modules"]) > 0 def test_parse_domain_entities(self, csv_parser): result = csv_parser.parse(DESIGN_DIR / "domains" / "design" / "05-domain-entities.csv") assert "domain_entities" in result assert len(result["domain_entities"]) > 0 def test_parse_codebase_alignment(self, csv_parser): result = csv_parser.parse(DESIGN_DIR / "application-architecture" / "06-codebase-alignment.csv") assert "codebase_alignments" in result assert len(result["codebase_alignments"]) > 0 def test_parse_codebase_mapping(self, csv_parser): result = csv_parser.parse(DESIGN_DIR / "domains" / "design" / "07-codebase-mapping.csv") assert "codebase_alignments" in result assert len(result["codebase_alignments"]) > 0 class TestCsvParserUnknown: def test_unknown_csv_returns_empty(self, csv_parser, tmp_path): unknown = tmp_path / "unknown-file.csv" unknown.write_text("col1,col2\nval1,val2\n") result = csv_parser.parse(unknown) assert result == {} def test_nonexistent_file_returns_empty(self, csv_parser): result = csv_parser.parse(Path("/nonexistent/file.csv")) assert result == {}