Files
cleveragents-core/robot/helper_change_tracking.py
T

139 lines
3.5 KiB
Python

"""Helper script for Robot Framework change tracking smoke tests."""
from __future__ import annotations
import sys
from pathlib import Path
# Ensure src is importable when run from workspace root
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
from pydantic import ValidationError
from cleveragents.domain.models.core.change import (
ChangeEntry,
ChangeOperation,
ChangeType,
InMemoryInvocationTracker,
SpecChangeSet,
ToolInvocation,
normalize_change_path,
)
def test_changetype_alias() -> None:
assert ChangeType is ChangeOperation
assert ChangeType.CREATE == "create"
print("changetype-ok")
def test_change_entry_validator() -> None:
# CREATE with before_hash should fail
try:
ChangeEntry(
plan_id="p",
resource_id="r",
tool_name="t",
operation=ChangeOperation.CREATE,
path="x.py",
before_hash="bad",
after_hash="ok",
)
print("validator-fail: no error raised")
sys.exit(1)
except (ValidationError, ValueError):
pass
# Valid CREATE
e = ChangeEntry(
plan_id="p",
resource_id="r",
tool_name="t",
operation=ChangeOperation.CREATE,
path="x.py",
after_hash="ok",
)
assert e.has_integrity_hashes is True
print("validator-ok")
def test_sorted_entries() -> None:
from datetime import UTC, datetime
entries = [
ChangeEntry(
plan_id="p",
resource_id="res-B",
tool_name="t",
operation=ChangeOperation.CREATE,
path="z.py",
after_hash="h",
timestamp=datetime(2026, 1, 1, 0, 0, 1, tzinfo=UTC),
),
ChangeEntry(
plan_id="p",
resource_id="res-A",
tool_name="t",
operation=ChangeOperation.CREATE,
path="a.py",
after_hash="h",
timestamp=datetime(2026, 1, 1, 0, 0, 0, tzinfo=UTC),
),
]
cs = SpecChangeSet(plan_id="p", entries=entries)
s = cs.sorted_entries()
assert s[0].resource_id == "res-A"
assert s[1].resource_id == "res-B"
print("sorted-ok")
def test_invocation_tracker() -> None:
tracker = InMemoryInvocationTracker()
tracker.track(
ToolInvocation(
plan_id="p1",
tool_name="t1",
sequence_number=1,
change_ids=["c1"],
)
)
tracker.track(
ToolInvocation(
plan_id="p1",
tool_name="t2",
sequence_number=0,
change_ids=["c2"],
)
)
invs = tracker.get_invocations("p1")
assert len(invs) == 2
assert invs[0].sequence_number == 0 # sorted
changes = tracker.get_changes("p1")
assert len(changes) == 2
print("tracker-ok")
def test_normalize_path() -> None:
result = normalize_change_path(
"/home/user/project/src/main.py", "/home/user/project"
)
assert result == "src/main.py", f"Got: {result}"
print("normalize-ok")
if __name__ == "__main__":
dispatch = {
"changetype": test_changetype_alias,
"validator": test_change_entry_validator,
"sorted": test_sorted_entries,
"tracker": test_invocation_tracker,
"normalize": test_normalize_path,
}
cmd = sys.argv[1] if len(sys.argv) > 1 else "changetype"
fn = dispatch.get(cmd)
if fn:
fn()
else:
print(f"Unknown command: {cmd}", file=sys.stderr)
sys.exit(1)