413 lines
14 KiB
Python
413 lines
14 KiB
Python
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("<html>ok</html>\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()
|