Skip to content

Commit 2003fcc

Browse files
test: snapshot emitter targets in scaffold guard tests
1 parent d2a4d1a commit 2003fcc

1 file changed

Lines changed: 59 additions & 9 deletions

File tree

tests/test_scaffold_tool_type.py

Lines changed: 59 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
pascal_to_snake,
1919
snake_to_pascal,
2020
)
21-
from scripts.scaffold_tool_type import ScaffoldEmitter, main
21+
from scripts.scaffold_tool_type import ScaffoldEmitter, ScaffoldPaths, main
2222

2323
_REPO_ROOT = Path(__file__).resolve().parents[1]
2424
_IGNORE = shutil.ignore_patterns(
@@ -138,6 +138,7 @@ def test_dry_run_reports_planned_artifact_count(capsys: pytest.CaptureFixture[st
138138

139139
def test_write_record_only_writes_json_without_codegen(tmp_path: Path) -> None:
140140
repo = _mirror_repo(tmp_path)
141+
snapshot = _snapshot_emitter_targets(repo)
141142
code = main(
142143
[
143144
"--name",
@@ -152,26 +153,24 @@ def test_write_record_only_writes_json_without_codegen(tmp_path: Path) -> None:
152153
assert record_path.is_file()
153154
loaded = ToolTypeRecord.load(record_path)
154155
assert loaded.name == "RecordOnlyTool"
155-
dispatch = (repo / "utils" / "tool_dispatch.py").read_text(encoding="utf-8")
156-
assert "RecordOnlyTool" not in dispatch
157-
assert not (repo / "static" / "js" / "render" / "tool_use" / "record_only_tool.js").exists()
156+
_assert_emitter_targets_unchanged(repo, snapshot, allowed_new={record_path})
158157

159158

160159
def test_emit_anchor_miss_in_tool_results_leaves_repo_unchanged(tmp_path: Path) -> None:
161160
repo = _mirror_repo(tmp_path)
162161
tool_results = repo / "models" / "tool_results.py"
163-
dispatch = repo / "utils" / "tool_dispatch.py"
164-
corrupt = tool_results.read_text(encoding="utf-8").replace(
162+
original = tool_results.read_text(encoding="utf-8")
163+
corrupt = original.replace(
165164
' "WebSearch",\n]',
166165
' "WebSearch",\n "Legacy",\n]',
167166
)
167+
assert corrupt != original, "fixture corruption must change tool_results.py"
168168
tool_results.write_text(corrupt, encoding="utf-8")
169-
dispatch_before = dispatch.read_text(encoding="utf-8")
169+
snapshot = _snapshot_emitter_targets(repo)
170170
record = ToolTypeRecord.from_cli_name("example_tool")
171171
with pytest.raises(ValueError, match="replacement anchor not found"):
172172
ScaffoldEmitter(repo).emit(record)
173-
assert tool_results.read_text(encoding="utf-8") == corrupt
174-
assert dispatch.read_text(encoding="utf-8") == dispatch_before
173+
_assert_emitter_targets_unchanged(repo, snapshot)
175174

176175

177176
def test_dry_run_main_exits_zero(capsys: pytest.CaptureFixture[str]) -> None:
@@ -279,3 +278,54 @@ def _mirror_repo(tmp_path: Path) -> Path:
279278
dest = tmp_path / "repo"
280279
shutil.copytree(_REPO_ROOT, dest, ignore=_IGNORE)
281280
return dest
281+
282+
283+
def _emitter_target_paths(repo: Path) -> list[Path]:
284+
paths = ScaffoldPaths.from_root(repo)
285+
targets: set[Path] = {
286+
paths.tool_dispatch,
287+
paths.tool_results,
288+
paths.md_exporter,
289+
paths.registry_js,
290+
paths.ordering_test,
291+
paths.tool_types_manifest,
292+
}
293+
for directory in (
294+
paths.tool_use_dir,
295+
paths.tool_result_dir,
296+
paths.fixtures_dir,
297+
paths.records_dir,
298+
):
299+
if directory.is_dir():
300+
targets.update(p for p in directory.rglob("*") if p.is_file())
301+
return sorted(targets)
302+
303+
304+
def _snapshot_emitter_targets(repo: Path) -> dict[Path, str]:
305+
return {path: path.read_text(encoding="utf-8") for path in _emitter_target_paths(repo)}
306+
307+
308+
def _assert_emitter_targets_unchanged(
309+
repo: Path,
310+
snapshot: dict[Path, str],
311+
*,
312+
allowed_new: set[Path] | None = None,
313+
) -> None:
314+
allowed = allowed_new or set()
315+
for path, content in snapshot.items():
316+
assert path.read_text(encoding="utf-8") == content, (
317+
f"emitter modified existing file: {path.relative_to(repo)}"
318+
)
319+
paths = ScaffoldPaths.from_root(repo)
320+
for directory in (
321+
paths.tool_use_dir,
322+
paths.tool_result_dir,
323+
paths.fixtures_dir,
324+
paths.records_dir,
325+
):
326+
if not directory.is_dir():
327+
continue
328+
for path in directory.rglob("*"):
329+
if path.is_file() and path not in snapshot and path not in allowed:
330+
msg = f"emitter created unexpected file: {path.relative_to(repo)}"
331+
raise AssertionError(msg)

0 commit comments

Comments
 (0)