Files
svg2gcode_grbl/test_bounds.py
T
2026-11-06 08:12:29 +01:00

123 lines
5.2 KiB
Python

import tempfile
import unittest
from pathlib import Path
from unittest.mock import patch
import svg2gcode
class DrawingBoundsTests(unittest.TestCase):
def setUp(self):
self.directory = tempfile.TemporaryDirectory()
self.addCleanup(self.directory.cleanup)
self.source = Path(self.directory.name) / "drawing.svg"
self.output = Path(self.directory.name) / "drawing.gcode"
for name, value in (
("bed_max_x", 200),
("bed_max_y", 280),
("units", "mm"),
("auto_scale", False),
):
patcher = patch.object(svg2gcode, name, value)
patcher.start()
self.addCleanup(patcher.stop)
def write_line(self, x1, y1, x2, y2, width=200, height=280, transform=""):
self.source.write_text(
f'<svg xmlns="http://www.w3.org/2000/svg" '
f'width="{width}" height="{height}">'
f'<line x1="{x1}" y1="{y1}" x2="{x2}" y2="{y2}" '
f'transform="{transform}"/></svg>'
)
def test_exact_boundaries_are_allowed(self):
self.write_line(0, 0, 200, 280)
shapes = svg2gcode.get_shapes(self.source, False)
self.assertIn((0, 280), shapes[0])
self.assertIn((200, 0), shapes[0])
def test_each_boundary_is_enforced(self):
for x, y in ((-0.0001, 100), (200.0001, 100),
(100, -0.0001), (100, 280.0001)):
with self.subTest(x=x, y=y):
self.write_line(10, 10, x, y)
with self.assertRaisesRegex(ValueError, "outside bed limits"):
svg2gcode.get_shapes(self.source, False)
def test_transformed_coordinates_are_checked(self):
self.write_line(10, 10, 20, 20, transform="translate(200, 0)")
with self.assertRaisesRegex(ValueError, "outside bed limits"):
svg2gcode.get_shapes(self.source, False)
def test_points_are_converted_before_checking(self):
self.write_line(0, 0, 500, 500, width=500, height=500)
with patch.object(svg2gcode, "units", "points"):
shapes = svg2gcode.get_shapes(self.source, False)
self.assertAlmostEqual(shapes[0][-1][0], 500 * 0.352778)
def test_auto_scaling_is_applied_before_checking(self):
self.write_line(0, 0, 400, 560, width=400, height=560)
shapes = svg2gcode.get_shapes(self.source, True)
self.assertTrue(all(0 <= x <= 200 and 0 <= y <= 280
for shape in shapes for x, y in shape))
self.assertEqual(shapes[0], [(0, 280), (200, 0)])
def test_fitting_preserves_in_bounds_coordinates(self):
self.write_line(10, 10, 20, 20)
self.assertEqual(svg2gcode.get_shapes(self.source, True),
svg2gcode.get_shapes(self.source, False))
def test_negative_coordinates_are_shifted_and_scaled(self):
self.write_line(-100, -100, 300, 300, height=200)
shapes = svg2gcode.get_shapes(self.source, True)
self.assertEqual(shapes[0], [(0, 200), (200, 0)])
def test_horizontal_vertical_and_single_point_drawings(self):
for coords, expected in (
((-100, 100, 300, 100), [(0, 0), (200, 0)]),
((100, -100, 100, 300), [(0, 280), (0, 0)]),
((300, 100, 300, 100), [(0, 0)]),
):
with self.subTest(coords=coords):
self.write_line(*coords)
self.assertEqual(svg2gcode.get_shapes(self.source, True)[0],
expected)
def test_fitting_uses_drawing_not_canvas_dimensions(self):
self.write_line(10, 300, 20, 350, width=500, height=500)
self.assertEqual(svg2gcode.get_shapes(self.source, True)[0],
[(10, 200), (20, 150)])
def test_fitting_transformed_coordinates(self):
self.write_line(10, 10, 20, 20, transform="translate(200, 0)")
shapes = svg2gcode.get_shapes(self.source, True)
self.assertTrue(all(0 <= x <= 200 and 0 <= y <= 280
for shape in shapes for x, y in shape))
def test_invalid_bed_dimensions_are_rejected(self):
self.write_line(10, 10, 20, 20)
for dimension in (0, -1, float("inf")):
with patch.object(svg2gcode, "bed_max_x", dimension):
with self.assertRaisesRegex(ValueError, "Bed dimensions"):
svg2gcode.get_shapes(self.source, True)
def test_canvas_size_alone_does_not_reject_in_bounds_drawing(self):
self.write_line(10, 300, 20, 350, width=500, height=500)
self.assertTrue(svg2gcode.get_shapes(self.source, False))
def test_failure_does_not_create_or_overwrite_output(self):
self.write_line(10, 10, 201, 20)
with patch.object(svg2gcode, "optimise_path") as optimise_path:
with self.assertRaisesRegex(ValueError, "X201.000000"):
svg2gcode.main(self.source, self.output)
self.assertFalse(self.output.exists())
self.output.write_text("existing output")
with self.assertRaises(ValueError):
svg2gcode.main(self.source, self.output)
self.assertEqual(self.output.read_text(), "existing output")
optimise_path.assert_not_called()
if __name__ == "__main__":
unittest.main()