Files
lai_automatisierung/tests/test_policy.py
Christian Meyer c2028fa256
Some checks failed
CI / test (push) Has been cancelled
CI / test (pull_request) Has been cancelled
fix: tighten agent patch hygiene
2026-08-31 03:02:42 +02:00

100 lines
2.8 KiB
Python

from __future__ import annotations
from unittest.mock import Mock
import pytest
from lai_automation.models import ChangeSummary
from lai_automation.policy import validate_changes
def workspace_with_no_symlinks() -> Mock:
workspace = Mock()
workspace.has_symlink.return_value = False
workspace.has_path.return_value = False
return workspace
def test_accepts_small_application_change(settings) -> None:
summary = ChangeSummary(
("app/Services/AIService.php", "tests/Feature/AITest.php"),
25,
4,
)
validate_changes(workspace_with_no_symlinks(), summary, settings)
@pytest.mark.parametrize(
"filename",
[
".env",
".env.example",
".gitea/workflows/ci.yml",
"docker-compose.yml",
"docker/php/Dockerfile",
"storage/logs/output.log",
"vendor/package/file.php",
],
)
def test_rejects_protected_paths(settings, filename: str) -> None:
summary = ChangeSummary((filename, "app/Fix.php"), 2, 0)
with pytest.raises(ValueError, match="Protected"):
validate_changes(workspace_with_no_symlinks(), summary, settings)
@pytest.mark.parametrize(
"filename",
[
"config/erp_semantics.php.backup",
"app/Service.php.orig",
"test_debug.php",
"scratch.php",
],
)
def test_rejects_temporary_artifacts(settings, filename: str) -> None:
summary = ChangeSummary((filename, "app/Fix.php"), 2, 0)
with pytest.raises(ValueError, match="Temporary artifact"):
validate_changes(workspace_with_no_symlinks(), summary, settings)
def test_rejects_git_metadata_created_in_worktree(settings) -> None:
workspace = workspace_with_no_symlinks()
workspace.has_path.return_value = True
with pytest.raises(ValueError, match="Git metadata"):
validate_changes(
workspace,
ChangeSummary(("app/Fix.php",), 1, 0),
settings,
)
def test_rejects_tests_without_application_change(settings) -> None:
summary = ChangeSummary(("tests/Feature/FixTest.php",), 20, 0)
with pytest.raises(ValueError, match="application source"):
validate_changes(workspace_with_no_symlinks(), summary, settings)
def test_rejects_symlink(settings) -> None:
workspace = workspace_with_no_symlinks()
workspace.has_symlink.return_value = True
summary = ChangeSummary(("app/Fix.php",), 1, 0)
with pytest.raises(ValueError, match="Symbolic links"):
validate_changes(workspace, summary, settings)
def test_rejects_oversized_diff(settings) -> None:
summary = ChangeSummary(
("app/Fix.php",),
settings.max_changed_lines + 1,
0,
)
with pytest.raises(ValueError, match="line limit"):
validate_changes(workspace_with_no_symlinks(), summary, settings)