maker: anteprima del DXF nel wizard «Crea ricetta da DXF» (Refs #101)

Proxy Flask /maker/api/vision/dxf-preview (piano B), stato e funzioni
dxfPreview* nel wizard, riquadro SVG con L x H sotto il campo .dxf,
traduzioni e test (proxy, JS con node, pagina).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-25 15:56:45 +01:00
parent b78f2422d8
commit bdb1e8c8b9
8 changed files with 276 additions and 2 deletions
@@ -210,6 +210,49 @@ class TestDxfCompareProxy:
mock_api_client.post.assert_not_called()
class TestDxfPreviewProxy:
"""#101: anteprima del DXF scelto nel wizard (proxy verso il backend)."""
URL = "/maker/api/vision/dxf-preview"
OK = {
"contorni": [[[0.0, -5.0], [10.0, -5.0], [10.0, 0.0], [0.0, 0.0]]],
"bbox": {"xmin": 0.0, "ymin": -5.0, "xmax": 10.0, "ymax": 0.0},
"larghezza_mm": 10.0, "altezza_mm": 5.0, "entita": 1, "punti": 4,
}
def _post(self, client, with_file=True):
data = {"dxf": (io.BytesIO(b"0\nEOF"), "d.dxf")} if with_file else {}
return client.post(self.URL, data=data, content_type="multipart/form-data")
def test_forwards_file(self, logged_in_client, mock_api_client):
mock_api_client.post.return_value = self.OK
resp = self._post(logged_in_client)
assert resp.status_code == 200
assert resp.get_json()["larghezza_mm"] == 10.0
args, kwargs = mock_api_client.post.call_args
assert args[0] == "/api/vision/dxf-preview"
assert set(kwargs["files"]) == {"dxf"}
assert kwargs["files"]["dxf"][0] == "d.dxf"
assert kwargs["files"]["dxf"][1] == b"0\nEOF"
def test_missing_file_is_400(self, logged_in_client, mock_api_client):
resp = self._post(logged_in_client, with_file=False)
assert resp.status_code == 400
mock_api_client.post.assert_not_called()
def test_backend_422_propagates(self, logged_in_client, mock_api_client):
mock_api_client.post.return_value = {
"error": True, "status_code": 422, "detail": "DXF illeggibile: x"}
resp = self._post(logged_in_client)
assert resp.status_code == 422
assert resp.get_json()["detail"] == "DXF illeggibile: x"
def test_requires_maker_role(self, logged_in_client, mock_api_client):
with logged_in_client.session_transaction() as sess:
sess["user"] = {**sess["user"], "roles": ["MeasurementTec"]}
assert self._post(logged_in_client).status_code == 403
mock_api_client.post.assert_not_called()
class TestPages:
def test_stations_page_has_calibration_cell(self, logged_in_client):
with patch("blueprints.admin.api_client") as admin_api:
@@ -236,4 +279,5 @@ class TestPages:
assert "dxfRecipeWizard(" in html
assert "@dxf-recipe-saved" in html
assert 'x-model="mmPx"' in html # #98: campo mm/px a mano
assert "dxfPreviewPaths()" in html # #101: anteprima SVG del DXF
assert "Pezzo scuro su fondo chiaro" in html or "Dark part on light" in html