from __future__ import annotations from pathlib import Path from tempfile import TemporaryDirectory import sys import unittest ROOT = Path(__file__).resolve().parents[1] sys.path.insert(0, str(ROOT / "src")) from uipath_explainator.pipeline import ProjectPipeline from uipath_explainator.scanner import crawl_dependencies, extract_dependencies, strip_comment_out_blocks MAIN_XAML = """ """ ACTIVE_XAML = """ ["Scripts/Keep.bas"] """ OLD_XAML = """ """ class StubAnalyzer: def analyze(self, relative_path: Path, content: str) -> str: return f"# {relative_path.as_posix()}\n\n{len(content)}" class PipelineTests(unittest.TestCase): def test_strip_comment_out_blocks_removes_nested_blocks(self) -> None: source = "" cleaned = strip_comment_out_blocks(source) self.assertEqual(cleaned, "") def test_extract_dependencies_reads_property_element_paths(self) -> None: with TemporaryDirectory() as tmp: root = Path(tmp) flows = root / "Flows" flows.mkdir() (root / "Main.xaml").write_text(ACTIVE_XAML, encoding="utf-8") (root / "Scripts").mkdir() (root / "Scripts" / "Keep.bas").write_text("Sub Keep()", encoding="utf-8") dependencies, warnings = extract_dependencies(root, root / "Main.xaml") self.assertEqual(len(warnings), 0) self.assertEqual(len(dependencies), 1) self.assertEqual(dependencies[0].target, root / "Scripts" / "Keep.bas") def test_pipeline_prunes_files_only_reachable_before_comment_cleanup(self) -> None: with TemporaryDirectory() as tmp: tmp_path = Path(tmp) project_root = tmp_path / "project" output_root = tmp_path / "workspace" (project_root / "Flows").mkdir(parents=True) (project_root / "Flows" / "Active.xaml").write_text(ACTIVE_XAML, encoding="utf-8") (project_root / "Flows" / "Old.xaml").write_text(OLD_XAML, encoding="utf-8") (project_root / "Scripts").mkdir() (project_root / "Scripts" / "Keep.bas").write_text("Sub Keep()\nEnd Sub", encoding="utf-8") (project_root / "Scripts" / "Drop.bas").write_text("Sub Drop()\nEnd Sub", encoding="utf-8") (project_root / "main.xaml").write_text(MAIN_XAML, encoding="utf-8") initial_scan = crawl_dependencies(project_root, project_root / "main.xaml") initial_files = {path.relative_to(project_root).as_posix() for path in initial_scan.files} self.assertIn("Flows/Old.xaml", initial_files) self.assertIn("Scripts/Drop.bas", initial_files) report = ProjectPipeline(project_root, output_root, "main.xaml", force=True).run(StubAnalyzer()) final_files = {path.as_posix() for path in report.final_files} self.assertIn("main.xaml", final_files) self.assertIn("Flows/Active.xaml", final_files) self.assertIn("Scripts/Keep.bas", final_files) self.assertNotIn("Flows/Old.xaml", final_files) self.assertNotIn("Scripts/Drop.bas", final_files) self.assertFalse((output_root / "Flows" / "Old.xaml").exists()) self.assertFalse((output_root / "Scripts" / "Drop.bas").exists()) self.assertTrue((output_root / "Flows" / "Active.xaml.analysis.md").exists()) overview = (output_root / "OVERVIEW.md").read_text(encoding="utf-8") self.assertIn("## Processing Logic", overview) self.assertIn("Initial Scan", overview) self.assertIn("## How To Read This Output", overview) self.assertIn("## Cleaned XAML Files", overview) if __name__ == "__main__": unittest.main()