feat: pdf2cad

This commit is contained in:
2026-03-03 21:24:02 +00:00
commit 112213da6e
61 changed files with 7290 additions and 0 deletions

162
tests/test_cli.py Normal file
View File

@@ -0,0 +1,162 @@
"""Tests for pdf2imos CLI interface."""
import json
from pathlib import Path
from typer.testing import CliRunner
from pdf2imos import __version__
from pdf2imos.cli import app
runner = CliRunner()
INPUT_DIR = Path(__file__).parent / "fixtures" / "input"
class TestVersion:
def test_prints_version_string(self):
result = runner.invoke(app, ["--version"])
assert result.exit_code == 0
assert __version__ in result.output
def test_version_before_args(self):
"""--version is eager, works without positional args."""
result = runner.invoke(app, ["--version"])
assert result.exit_code == 0
class TestHelp:
def test_help_exits_0(self):
result = runner.invoke(app, ["--help"])
assert result.exit_code == 0
def test_help_mentions_input_dir(self):
result = runner.invoke(app, ["--help"])
assert "INPUT_DIR" in result.output
class TestBatchProcessing:
def test_produces_dxf_and_json(self, tmp_path):
out = tmp_path / "out"
result = runner.invoke(
app, [str(INPUT_DIR), str(out)],
)
assert result.exit_code in (0, 1)
dxf_files = list(out.glob("*.dxf"))
json_files = list(out.glob("*.json"))
assert len(dxf_files) > 0
assert len(json_files) > 0
def test_output_names_match_pdfs(self, tmp_path):
out = tmp_path / "out"
result = runner.invoke(
app, [str(INPUT_DIR), str(out)],
)
if result.exit_code == 0:
for pdf in INPUT_DIR.glob("*.pdf"):
assert (out / f"{pdf.stem}.dxf").exists()
assert (out / f"{pdf.stem}.json").exists()
def test_verbose_accepted(self, tmp_path):
out = tmp_path / "out"
result = runner.invoke(
app, [str(INPUT_DIR), str(out), "--verbose"],
)
assert result.exit_code in (0, 1)
class TestStageProcessing:
def test_stage_extract_produces_json(self, tmp_path):
out = tmp_path / "out"
result = runner.invoke(
app,
[str(INPUT_DIR), str(out), "--stage=extract"],
)
assert result.exit_code == 0
intermediates = list(out.glob("*_extract.json"))
assert len(intermediates) > 0
def test_stage_extract_json_content(self, tmp_path):
out = tmp_path / "out"
runner.invoke(
app,
[str(INPUT_DIR), str(out), "--stage=extract"],
)
for f in out.glob("*_extract.json"):
with open(f) as fh:
data = json.load(fh)
assert data["stage"] == "extract"
assert "data" in data
def test_stage_extract_no_dxf_output(self, tmp_path):
out = tmp_path / "out"
runner.invoke(
app,
[str(INPUT_DIR), str(out), "--stage=extract"],
)
assert len(list(out.glob("*.dxf"))) == 0
def test_stage_segment(self, tmp_path):
out = tmp_path / "out"
result = runner.invoke(
app,
[str(INPUT_DIR), str(out), "--stage=segment"],
)
assert result.exit_code == 0
intermediates = list(out.glob("*_segment.json"))
assert len(intermediates) > 0
class TestExitCodes:
def test_exit_0_all_succeed(self, tmp_path):
out = tmp_path / "out"
result = runner.invoke(
app, [str(INPUT_DIR), str(out)],
)
assert result.exit_code == 0
def test_exit_2_no_pdfs(self, tmp_path):
empty = tmp_path / "empty"
empty.mkdir()
out = tmp_path / "out"
result = runner.invoke(
app, [str(empty), str(out)],
)
assert result.exit_code == 2
def test_exit_2_nonexistent_input(self, tmp_path):
result = runner.invoke(
app,
["/nonexistent/path", str(tmp_path / "out")],
)
assert result.exit_code == 2
def test_exit_2_invalid_stage(self, tmp_path):
out = tmp_path / "out"
result = runner.invoke(
app,
[str(INPUT_DIR), str(out), "--stage=bogus"],
)
assert result.exit_code == 2
class TestNonPdfSkipped:
def test_only_non_pdf_files_exit_2(self, tmp_path):
input_dir = tmp_path / "input"
input_dir.mkdir()
(input_dir / "readme.txt").write_text("hello")
(input_dir / "notes.md").write_text("# Notes")
out = tmp_path / "out"
result = runner.invoke(
app, [str(input_dir), str(out)],
)
assert result.exit_code == 2
def test_non_pdf_not_in_output(self, tmp_path):
"""Non-PDF files should not produce output."""
out = tmp_path / "out"
runner.invoke(
app, [str(INPUT_DIR), str(out)],
)
# No output file named after a non-pdf
for f in out.iterdir():
assert f.suffix in (".dxf", ".json", ".dwg")