@@ -288,6 +288,42 @@ def test_cli_validate_pre_push_missing_recording_is_soft(tmp_path: Path) -> None
288288 assert "Traceback" not in combined
289289
290290
291+ def test_cli_validate_default_fail_exits_1 (tmp_path : Path ) -> None :
292+ """Click-invoke default validate (no --pre-push) must exit 1 on FAIL."""
293+ from click .testing import CliRunner
294+
295+ from docgen .cli import main
296+
297+ raw = {
298+ "dirs" : {
299+ "narration" : "narration" ,
300+ "audio" : "audio" ,
301+ "animations" : "animations" ,
302+ "recordings" : "recordings" ,
303+ },
304+ "segments" : {"default" : ["01" ], "all" : ["01" ]},
305+ "segment_names" : {"01" : "01-intro" },
306+ "visual_map" : {"01" : {"type" : "still" , "source" : "01.mp4" }},
307+ }
308+ yaml_path = tmp_path / "docgen.yaml"
309+ yaml_path .write_text (yaml .dump (raw ), encoding = "utf-8" )
310+ (tmp_path / "narration" ).mkdir ()
311+ (tmp_path / "narration" / "01-intro.md" ).write_text (
312+ "This segment is a short still-image intro.\n " ,
313+ encoding = "utf-8" ,
314+ )
315+ for name in ("audio" , "animations" , "recordings" ):
316+ (tmp_path / name ).mkdir ()
317+
318+ result = CliRunner ().invoke (main , ["--config" , str (yaml_path ), "validate" ])
319+ combined = result .output + result .stderr
320+ assert result .exit_code == 1 , combined
321+ assert "FAIL" in combined
322+ assert "recording_exists" in combined
323+ assert "AttributeError" not in combined
324+ assert "Traceback" not in combined
325+
326+
291327def test_cli_lint_empty_segments_is_click_error (tmp_path : Path ) -> None :
292328 from click .testing import CliRunner
293329
0 commit comments