CascadingDev/tests/test_config.py

99 lines
3.0 KiB
Python

from pathlib import Path
import textwrap
import pytest
from automation.config import RulesConfig
def write_yaml(path: Path, content: str) -> None:
path.write_text(textwrap.dedent(content).strip() + "\n", encoding="utf-8")
@pytest.fixture()
def sample_repo(tmp_path: Path) -> Path:
root = tmp_path / "repo"
(root / "Docs" / "features" / "FR_123" / "discussions").mkdir(parents=True, exist_ok=True)
write_yaml(
root / ".ai-rules.yml",
"""
file_associations:
feature_request.md: feature_request
rules:
feature_request:
outputs:
summary:
path: "{feature_id}/summary.md"
""",
)
write_yaml(
root / "Docs" / "features" / ".ai-rules.yml",
"""
file_associations:
design.md: design_rule
rules:
design_rule:
outputs:
diagram:
path: "diagrams/{stage}.puml"
""",
)
write_yaml(
root / "Docs" / "features" / "FR_123" / ".ai-rules.yml",
"""
rules:
design_rule:
outputs:
diagram:
instruction: "Draw updated design diagram"
""",
)
return root
def test_get_rule_name_cascades(sample_repo: Path) -> None:
cfg = RulesConfig.load(sample_repo)
assert cfg.get_rule_name(Path("feature_request.md")) == "feature_request"
assert cfg.get_rule_name(Path("Docs/features/design.md")) == "design_rule"
assert cfg.get_rule_name(Path("unknown.md")) is None
def test_cascade_for_merges_overrides(sample_repo: Path) -> None:
cfg = RulesConfig.load(sample_repo)
rel = Path("Docs/features/FR_123/discussions/design.discussion.md")
merged = cfg.cascade_for(rel, "design_rule")
outputs = merged["outputs"]
assert "diagram" in outputs
diagram_cfg = outputs["diagram"]
assert diagram_cfg["path"] == "diagrams/{stage}.puml"
assert diagram_cfg["instruction"] == "Draw updated design diagram"
def test_template_rendering(sample_repo: Path) -> None:
cfg = RulesConfig.load(sample_repo)
rel = Path("Docs/features/FR_123/discussions/design.discussion.md")
rendered = cfg.resolve_template("{feature_id}/{stage}.sum.md", rel)
assert rendered == "FR_123/design.sum.md"
rendered_dir = cfg.resolve_template("{dir}/generated.md", Path("Docs/features/FR_123/request.md"))
assert rendered_dir == "Docs/features/FR_123/generated.md"
rendered_repo = cfg.resolve_template("{repo}/README.md", Path("Docs/features/FR_123/request.md"))
assert rendered_repo == "./README.md"
rendered_path = cfg.resolve_template("copy-of-{path}", Path("Docs/features/FR_123/request.md"))
assert rendered_path == "copy-of-Docs/features/FR_123/request.md"
def test_normalize_repo_rel_blocks_escape(sample_repo: Path) -> None:
cfg = RulesConfig.load(sample_repo)
with pytest.raises(ValueError):
cfg.normalize_repo_rel("../outside.md")
assert cfg.normalize_repo_rel("Docs/features/file.md").as_posix() == "Docs/features/file.md"