"""Tests for core/executor.py — CadQuery code execution and export. These tests require CadQuery to be installed. """ import pytest from pathlib import Path from core.executor import sanitize_code, execute_cadquery, export_step, export_stl, export_3mf, export_all pytestmark = pytest.mark.requires_cadquery class TestSanitizeCode: def test_strips_markdown_fences(self): code = "```python\nresult = 1\n```" assert "```" not in sanitize_code(code) def test_strips_plain_fences(self): code = "```\nresult = 1\n```" assert "```" not in sanitize_code(code) def test_removes_cadquery_imports(self): code = "import cadquery as cq\nresult = cq.Workplane('XY').box(10,10,10)" cleaned = sanitize_code(code) assert "import cadquery" not in cleaned assert "result" in cleaned def test_removes_math_import(self): code = "import math\nresult = cq.Workplane('XY').box(10,10,10)" cleaned = sanitize_code(code) assert "import math" not in cleaned def test_preserves_valid_code(self): code = "result = cq.Workplane('XY').box(10, 20, 30)" assert sanitize_code(code) == code class TestExecuteCadquery: def test_simple_box(self): result = execute_cadquery("result = cq.Workplane('XY').box(10, 20, 30)") assert result.success is True assert result.volume > 0 assert result.face_count == 6 assert result.edge_count == 12 assert len(result.bounding_box) == 3 def test_cylinder(self): result = execute_cadquery("result = cq.Workplane('XY').cylinder(20, 10)") assert result.success is True assert result.volume > 0 def test_missing_result_variable(self): result = execute_cadquery("x = cq.Workplane('XY').box(10,10,10)") assert result.success is False assert "result" in result.error def test_syntax_error(self): result = execute_cadquery("result = cq.Workplane('XY').box(10, 10,") assert result.success is False assert result.error is not None def test_wrong_type(self): result = execute_cadquery("result = 42") assert result.success is False assert "Workplane" in result.error def test_code_with_markdown_fences(self): code = "```python\nimport cadquery as cq\nresult = cq.Workplane('XY').box(5,5,5)\n```" result = execute_cadquery(code) assert result.success is True def test_summary_on_success(self): result = execute_cadquery("result = cq.Workplane('XY').box(10, 20, 30)") summary = result.summary() assert "OK" in summary assert "Volume" in summary def test_summary_on_failure(self): result = execute_cadquery("result = bad_code") summary = result.summary() assert "FAILED" in summary class TestExport: def test_export_step(self, tmp_path): exec_result = execute_cadquery("result = cq.Workplane('XY').box(10,10,10)") assert exec_result.success path = export_step(exec_result.result, tmp_path / "test.step") assert path.exists() assert path.suffix == ".step" def test_export_stl(self, tmp_path): exec_result = execute_cadquery("result = cq.Workplane('XY').box(10,10,10)") assert exec_result.success path = export_stl(exec_result.result, tmp_path / "test.stl") assert path.exists() assert path.suffix == ".stl" def test_export_all(self, tmp_path): exec_result = execute_cadquery("result = cq.Workplane('XY').box(10,10,10)") assert exec_result.success files = export_all(exec_result.result, tmp_path / "part") assert files["step"].exists() assert files["stl"].exists() class TestExport3MF: def test_export_3mf(self, tmp_path): import cadquery as cq from core.executor import export_3mf shape = cq.Workplane("XY").box(10, 10, 10) path = tmp_path / "test.3mf" result = export_3mf(shape, path) assert result.exists() assert result.suffix == ".3mf" assert result.stat().st_size > 0 def test_export_all_includes_3mf(self, tmp_path): import cadquery as cq from core.executor import export_all shape = cq.Workplane("XY").box(10, 10, 10) base = tmp_path / "part" files = export_all(shape, base) assert "3mf" in files assert files["3mf"].exists() assert files["step"].exists() assert files["stl"].exists()