from __future__ import annotations import importlib.util from pathlib import Path import sys import unittest from unittest import mock SCRIPT = Path(__file__).resolve().parents[1] / "scripts" / "preflight.py" sys.path.insert(0, str(SCRIPT.parent)) SPEC = importlib.util.spec_from_file_location("materialsub_preflight", SCRIPT) assert SPEC is not None and SPEC.loader is not None preflight = importlib.util.module_from_spec(SPEC) SPEC.loader.exec_module(preflight) class PreflightTests(unittest.TestCase): def dependencies(self): return mock.patch.object( preflight.shutil, "which", side_effect=lambda name: f"/bin/{name}" if name != "deno" else None, ) def test_missing_font_requires_early_decision(self) -> None: with self.dependencies(), mock.patch.object( preflight.burn, "_required_executables", return_value=("/bin/ffmpeg", "/bin/ffprobe") ), mock.patch.object( preflight.burn, "_require_libass_subtitles_filter" ), mock.patch.object(preflight.burn, "_font_installed", return_value=False): exit_code, result = preflight.assess( font="MiSans", allow_missing_font=False, youtube=False ) self.assertEqual(exit_code, 3) self.assertEqual(result["stage"], "font_decision_required") def test_missing_font_can_accept_substitution_upfront(self) -> None: with self.dependencies(), mock.patch.object( preflight.burn, "_required_executables", return_value=("/bin/ffmpeg", "/bin/ffprobe") ), mock.patch.object( preflight.burn, "_require_libass_subtitles_filter" ), mock.patch.object(preflight.burn, "_font_installed", return_value=False): exit_code, result = preflight.assess( font="MiSans", allow_missing_font=True, youtube=True ) self.assertEqual(exit_code, 0) self.assertTrue(result["substitution_allowed"]) self.assertTrue(any("Deno" in item for item in result["warnings"])) if __name__ == "__main__": unittest.main()