import os import json import subprocess import sys import tarfile import tempfile import unittest from pathlib import Path ROOT = Path(__file__).resolve().parents[1] SRC = ROOT / "src" sys.path.insert(0, str(SRC)) from iftypeset.rendering import detect_pdf_engines # noqa: E402 class IntegrationTests(unittest.TestCase): def test_pipeline_on_fixture(self) -> None: fixture = ROOT / "fixtures" / "headings_basic.md" self.assertTrue(fixture.exists()) env = os.environ.copy() env["PYTHONPATH"] = str(SRC) with tempfile.TemporaryDirectory() as tmp: out_dir = Path(tmp) lint_cmd = [ sys.executable, "-m", "iftypeset.cli", "lint", "--input", str(fixture), "--out", str(out_dir), "--profile", "web_pdf", "--format", "json", "--degraded-ok", ] lint = subprocess.run(lint_cmd, env=env, capture_output=True, text=True) self.assertEqual(lint.returncode, 0) render_cmd = [ sys.executable, "-m", "iftypeset.cli", "render-html", "--input", str(fixture), "--out", str(out_dir), "--profile", "web_pdf", ] render = subprocess.run(render_cmd, env=env, capture_output=True, text=True) self.assertEqual(render.returncode, 0) self.assertTrue((out_dir / "render.html").exists()) self.assertTrue((out_dir / "render.css").exists()) if detect_pdf_engines(): pdf_cmd = [ sys.executable, "-m", "iftypeset.cli", "render-pdf", "--input", str(fixture), "--out", str(out_dir), "--profile", "web_pdf", ] pdf = subprocess.run(pdf_cmd, env=env, capture_output=True, text=True) self.assertIn(pdf.returncode, (0, 3)) self.assertTrue((out_dir / "render-log.json").exists()) qa_cmd = [ sys.executable, "-m", "iftypeset.cli", "qa", "--out", str(out_dir), "--profile", "web_pdf", ] qa = subprocess.run(qa_cmd, env=env, capture_output=True, text=True) self.assertIn(qa.returncode, (0, 1)) self.assertTrue((out_dir / "layout-report.json").exists()) self.assertTrue((out_dir / "qa-report.json").exists()) def test_run_command_emits_summary(self) -> None: fixture = ROOT / "fixtures" / "headings_basic.md" self.assertTrue(fixture.exists()) env = os.environ.copy() env["PYTHONPATH"] = str(SRC) with tempfile.TemporaryDirectory() as tmp: out_dir = Path(tmp) run_cmd = [ sys.executable, "-m", "iftypeset.cli", "run", "--input", str(fixture), "--out", str(out_dir), "--profile", "web_pdf", "--degraded-ok", "--skip-pdf", ] run = subprocess.run(run_cmd, env=env, capture_output=True, text=True) self.assertIn(run.returncode, (0, 1)) self.assertTrue((out_dir / "run-summary.json").exists()) def test_run_require_pdf_conflict(self) -> None: fixture = ROOT / "fixtures" / "headings_basic.md" self.assertTrue(fixture.exists()) env = os.environ.copy() env["PYTHONPATH"] = str(SRC) with tempfile.TemporaryDirectory() as tmp: out_dir = Path(tmp) run_cmd = [ sys.executable, "-m", "iftypeset.cli", "run", "--input", str(fixture), "--out", str(out_dir), "--profile", "web_pdf", "--skip-pdf", "--require-pdf", ] run = subprocess.run(run_cmd, env=env, capture_output=True, text=True) self.assertEqual(run.returncode, 2) def test_run_require_pdf_invalid_engine_fails(self) -> None: fixture = ROOT / "fixtures" / "headings_basic.md" self.assertTrue(fixture.exists()) env = os.environ.copy() env["PYTHONPATH"] = str(SRC) with tempfile.TemporaryDirectory() as tmp: out_dir = Path(tmp) run_cmd = [ sys.executable, "-m", "iftypeset.cli", "run", "--input", str(fixture), "--out", str(out_dir), "--profile", "web_pdf", "--engine", "doesnotexist", "--require-pdf", ] run = subprocess.run(run_cmd, env=env, capture_output=True, text=True) self.assertEqual(run.returncode, 3) self.assertTrue((out_dir / "run-summary.json").exists()) def test_run_invalid_engine_warns_without_require_pdf(self) -> None: fixture = ROOT / "fixtures" / "headings_basic.md" self.assertTrue(fixture.exists()) env = os.environ.copy() env["PYTHONPATH"] = str(SRC) with tempfile.TemporaryDirectory() as tmp: out_dir = Path(tmp) run_cmd = [ sys.executable, "-m", "iftypeset.cli", "run", "--input", str(fixture), "--out", str(out_dir), "--profile", "web_pdf", "--engine", "doesnotexist", ] run = subprocess.run(run_cmd, env=env, capture_output=True, text=True) self.assertIn(run.returncode, (0, 1)) self.assertTrue((out_dir / "run-summary.json").exists()) def test_run_directory_emits_aggregate_index(self) -> None: env = os.environ.copy() env["PYTHONPATH"] = str(SRC) with tempfile.TemporaryDirectory() as tmp: tmp_path = Path(tmp) input_dir = tmp_path / "docs" input_dir.mkdir() (input_dir / "a.md").write_text("# A\n\nAlpha.\n", encoding="utf-8") (input_dir / "b.md").write_text("# B\n\nBeta.\n", encoding="utf-8") out_dir = tmp_path / "out" run_cmd = [ sys.executable, "-m", "iftypeset.cli", "run", "--input", str(input_dir), "--out", str(out_dir), "--profile", "web_pdf", "--degraded-ok", "--skip-pdf", ] run = subprocess.run(run_cmd, env=env, capture_output=True, text=True) self.assertIn(run.returncode, (0, 1)) self.assertTrue((out_dir / "run-summary.json").exists()) self.assertTrue((out_dir / "report" / "index.html").exists()) self.assertTrue((out_dir / "docs" / "a" / "run-summary.json").exists()) self.assertTrue((out_dir / "docs" / "b" / "run-summary.json").exists()) def test_config_defaults_apply(self) -> None: fixture = ROOT / "fixtures" / "headings_basic.md" self.assertTrue(fixture.exists()) env = os.environ.copy() env["PYTHONPATH"] = str(SRC) with tempfile.TemporaryDirectory() as tmp: tmp_path = Path(tmp) config_path = tmp_path / "iftypeset.yaml" config_path.write_text( "defaults:\n" " profile: web_pdf\n" " out: out\n" "lint:\n" " degraded_ok: true\n", encoding="utf-8", ) lint_cmd = [ sys.executable, "-m", "iftypeset.cli", "lint", "--input", str(fixture), "--spec", str(ROOT / "spec"), ] lint = subprocess.run(lint_cmd, env=env, cwd=tmp_path, capture_output=True, text=True) self.assertEqual(lint.returncode, 0) self.assertTrue((tmp_path / "out" / "lint-report.json").exists()) def test_config_run_engine_and_require_pdf(self) -> None: fixture = ROOT / "fixtures" / "headings_basic.md" self.assertTrue(fixture.exists()) env = os.environ.copy() env["PYTHONPATH"] = str(SRC) with tempfile.TemporaryDirectory() as tmp: tmp_path = Path(tmp) config_path = tmp_path / "iftypeset.yaml" config_path.write_text( "defaults:\n" " profile: web_pdf\n" "run:\n" " require_pdf: true\n" " engine: doesnotexist\n", encoding="utf-8", ) run_cmd = [ sys.executable, "-m", "iftypeset.cli", "run", "--input", str(fixture), "--spec", str(ROOT / "spec"), "--out", str(tmp_path / "out"), ] run = subprocess.run(run_cmd, env=env, cwd=tmp_path, capture_output=True, text=True) self.assertEqual(run.returncode, 3) self.assertTrue((tmp_path / "out" / "run-summary.json").exists()) def test_cli_introspection_commands(self) -> None: env = os.environ.copy() env["PYTHONPATH"] = str(SRC) profiles_cmd = [sys.executable, "-m", "iftypeset.cli", "profiles", "list", "--spec", str(ROOT / "spec")] profiles = subprocess.run(profiles_cmd, env=env, capture_output=True, text=True) self.assertEqual(profiles.returncode, 0) profiles_payload = json.loads(profiles.stdout) self.assertIn("web_pdf", profiles_payload.get("profiles", [])) gates_cmd = [ sys.executable, "-m", "iftypeset.cli", "gates", "show", "--spec", str(ROOT / "spec"), "--profile", "web_pdf", ] gates = subprocess.run(gates_cmd, env=env, capture_output=True, text=True) self.assertEqual(gates.returncode, 0) gates_payload = json.loads(gates.stdout) self.assertEqual(gates_payload.get("profile"), "web_pdf") rules_cmd = [ sys.executable, "-m", "iftypeset.cli", "rules", "show", "HOUSE.LINKS.URLS.PREFER_HTTPS", "--spec", str(ROOT / "spec"), ] rules = subprocess.run(rules_cmd, env=env, capture_output=True, text=True) self.assertEqual(rules.returncode, 0) rules_payload = json.loads(rules.stdout) self.assertEqual(rules_payload.get("rule", {}).get("id"), "HOUSE.LINKS.URLS.PREFER_HTTPS") def test_report_index_emits(self) -> None: env = os.environ.copy() env["PYTHONPATH"] = str(SRC) with tempfile.TemporaryDirectory() as tmp: out_dir = Path(tmp) report_cmd = [ sys.executable, "-m", "iftypeset.cli", "report", "--spec", str(ROOT / "spec"), "--out", str(out_dir), ] report = subprocess.run(report_cmd, env=env, capture_output=True, text=True) self.assertEqual(report.returncode, 0) index_path = out_dir / "report" / "index.html" self.assertTrue(index_path.exists()) self.assertIn("iftypeset report index", index_path.read_text(encoding="utf-8")) def test_doctor_emits_reports(self) -> None: env = os.environ.copy() env["PYTHONPATH"] = str(SRC) with tempfile.TemporaryDirectory() as tmp: out_dir = Path(tmp) doctor_cmd = [ sys.executable, "-m", "iftypeset.cli", "doctor", "--spec", str(ROOT / "spec"), "--out", str(out_dir), ] doctor = subprocess.run(doctor_cmd, env=env, capture_output=True, text=True) self.assertEqual(doctor.returncode, 0) self.assertTrue((out_dir / "doctor.json").exists()) self.assertTrue((out_dir / "doctor.md").exists()) def test_bundle_emits_manifest_and_tar(self) -> None: env = os.environ.copy() env["PYTHONPATH"] = str(SRC) with tempfile.TemporaryDirectory() as tmp: out_dir = Path(tmp) (out_dir / "render.html").write_text("ok\n", encoding="utf-8") bundle_cmd = [ sys.executable, "-m", "iftypeset.cli", "bundle", "--out", str(out_dir), ] bundle = subprocess.run(bundle_cmd, env=env, capture_output=True, text=True) self.assertEqual(bundle.returncode, 0) manifest_path = out_dir / "bundle-manifest.json" bundle_path = out_dir / "iftypeset-bundle.tar.gz" self.assertTrue(manifest_path.exists()) self.assertTrue(bundle_path.exists()) manifest = json.loads(manifest_path.read_text(encoding="utf-8")) included = [item.get("path") for item in manifest.get("included", [])] self.assertIn("render.html", included) with tarfile.open(bundle_path, "r:gz") as tar: names = tar.getnames() self.assertIn("bundle-manifest.json", names) self.assertIn("render.html", names) if __name__ == "__main__": unittest.main()