Spaces:
Sleeping
Sleeping
| """Tests for core/cam.py — CAM engine.""" | |
| from core.cam import CAMResult, ToolConfig | |
| class TestToolConfig: | |
| def test_defaults(self): | |
| tc = ToolConfig() | |
| assert tc.diameter == 6.0 | |
| assert tc.h_feed == 800 | |
| assert tc.v_feed == 200 | |
| assert tc.speed == 18000 | |
| def test_custom_values(self): | |
| tc = ToolConfig(diameter=3.0, h_feed=400, v_feed=100, speed=24000) | |
| assert tc.diameter == 3.0 | |
| assert tc.h_feed == 400 | |
| assert tc.v_feed == 100 | |
| assert tc.speed == 24000 | |
| def test_model_dump(self): | |
| tc = ToolConfig(diameter=10.0, h_feed=1000, v_feed=300, speed=12000) | |
| d = tc.model_dump() | |
| assert d == {"diameter": 10.0, "h_feed": 1000, "v_feed": 300, "speed": 12000} | |
| class TestCAMResult: | |
| def test_success_result(self): | |
| r = CAMResult( | |
| success=True, | |
| gcode="G21 G90\nG00 X0 Y0 Z10\nM30", | |
| operations=["pocket", "profile"], | |
| tool_config=ToolConfig(diameter=6, h_feed=800), | |
| post_processor="grbl", | |
| ) | |
| assert r.success is True | |
| assert "G21" in r.gcode | |
| assert r.operations == ["pocket", "profile"] | |
| assert r.error is None | |
| def test_failure_result(self): | |
| r = CAMResult(success=False, error="ocp-freecad-cam not available") | |
| assert r.success is False | |
| assert r.gcode is None | |
| assert r.error == "ocp-freecad-cam not available" | |
| def test_model_dump(self): | |
| r = CAMResult( | |
| success=True, gcode="G21 G90\nM30", | |
| operations=["pocket"], tool_config=ToolConfig(diameter=6), | |
| ) | |
| d = r.model_dump() | |
| assert d["success"] is True | |
| assert d["gcode"] == "G21 G90\nM30" | |
| assert d["operations"] == ["pocket"] | |
| assert d["tool_config"] == {"diameter": 6.0, "h_feed": 800, "v_feed": 200, "speed": 18000} | |
| assert d["post_processor"] == "grbl" | |
| assert d["error"] is None | |
| def test_default_tool_config_is_toolconfig(self): | |
| r = CAMResult(success=True) | |
| assert isinstance(r.tool_config, ToolConfig) | |
| from unittest.mock import patch, MagicMock | |
| from core.cam import generate_gcode | |
| class TestGenerateGcode: | |
| def test_returns_failure_when_ocp_not_available(self): | |
| """When ocp-freecad-cam is not installed, return a failure CAMResult.""" | |
| mock_shape = MagicMock() | |
| result = generate_gcode( | |
| shape=mock_shape, | |
| operations=["pocket"], | |
| tool_config=ToolConfig(diameter=6, h_feed=800, v_feed=200, speed=18000), | |
| post_processor="grbl", | |
| ) | |
| assert result.success is False | |
| assert "not available" in result.error.lower() or "not installed" in result.error.lower() | |
| def test_returns_failure_on_empty_operations(self): | |
| mock_shape = MagicMock() | |
| result = generate_gcode( | |
| shape=mock_shape, | |
| operations=[], | |
| ) | |
| assert result.success is False | |
| assert "no operations" in result.error.lower() | |
| def test_uses_default_tool_config_when_none(self): | |
| mock_shape = MagicMock() | |
| result = generate_gcode( | |
| shape=mock_shape, | |
| operations=["pocket"], | |
| tool_config=None, | |
| ) | |
| assert result.tool_config is not None | |
| assert isinstance(result.tool_config, ToolConfig) | |
| assert result.tool_config.diameter == 6.0 | |
| def test_uses_default_post_processor(self): | |
| mock_shape = MagicMock() | |
| result = generate_gcode(shape=mock_shape, operations=["pocket"]) | |
| assert result.post_processor == "grbl" | |
| def test_tool_config_attribute_access(self): | |
| mock_shape = MagicMock() | |
| tc = ToolConfig(diameter=3.0, h_feed=400, v_feed=100, speed=24000) | |
| result = generate_gcode( | |
| shape=mock_shape, | |
| operations=["pocket"], | |
| tool_config=tc, | |
| ) | |
| assert result.tool_config.diameter == 3.0 | |
| assert result.tool_config.h_feed == 400 | |
| from core.cam import CAMPlan | |
| class TestCAMPlan: | |
| def test_default_values(self): | |
| plan = CAMPlan(operations=["pocket", "profile"]) | |
| assert plan.operations == ["pocket", "profile"] | |
| assert plan.tool_diameter == 6.0 | |
| assert plan.tool_h_feed == 800 | |
| assert plan.tool_v_feed == 200 | |
| assert plan.tool_speed == 18000 | |
| assert plan.post_processor == "grbl" | |
| def test_custom_values(self): | |
| plan = CAMPlan( | |
| operations=["adaptive", "surface"], | |
| tool_diameter=3.0, | |
| tool_h_feed=400, | |
| tool_v_feed=100, | |
| tool_speed=24000, | |
| post_processor="linuxcnc", | |
| ) | |
| assert plan.tool_diameter == 3.0 | |
| assert plan.post_processor == "linuxcnc" | |
| def test_to_tool_config(self): | |
| plan = CAMPlan(operations=["pocket"]) | |
| config = plan.to_tool_config() | |
| assert isinstance(config, ToolConfig) | |
| assert config.diameter == 6.0 | |
| assert config.h_feed == 800 | |
| assert config.v_feed == 200 | |
| assert config.speed == 18000 | |