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"
code_root = output_root / "code"
docs_root = output_root / "docs"
(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.assertEqual(report.code_root, code_root.resolve())
self.assertEqual(report.docs_root, docs_root.resolve())
self.assertFalse((code_root / "Flows" / "Old.xaml").exists())
self.assertFalse((code_root / "Scripts" / "Drop.bas").exists())
self.assertTrue((code_root / "Flows" / "Active.xaml").exists())
self.assertTrue((docs_root / "Flows" / "Active.xaml.analysis.md").exists())
self.assertTrue((docs_root / "manifest.json").exists())
overview = (docs_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)
self.assertIn("Code Root", overview)
self.assertIn("Docs Root", overview)
if __name__ == "__main__":
unittest.main()