test_design_settings_plates.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. """The plates endpoints must surface the designer's changed settings (#2622).
  2. Parsing is covered in ``unit/test_design_settings.py``. What is asserted here is
  3. the wiring: SliceModal reads ``design_overrides`` off the plates response, so a
  4. correct parser that never reaches the payload is a feature that silently does
  5. nothing.
  6. """
  7. import json
  8. import zipfile
  9. from pathlib import Path
  10. import pytest
  11. from httpx import AsyncClient
  12. def _designed_3mf(path: Path, *, with_deviations: bool = True) -> None:
  13. """A Bambu-style project 3MF, optionally carrying designer deviations."""
  14. config = {
  15. "print_settings_id": "0.20mm Standard @BBL A1",
  16. "printer_settings_id": "Bambu Lab A1 0.4 nozzle",
  17. "filament_settings_id": ["Bambu PLA Basic @BBL A1"],
  18. "wall_loops": "5",
  19. "outer_wall_speed": "200",
  20. "machine_start_gcode": "G28 ; designer printer",
  21. "different_settings_to_system": (
  22. ["wall_loops;outer_wall_speed", "", "machine_start_gcode"] if with_deviations else ["", "", ""]
  23. ),
  24. }
  25. with zipfile.ZipFile(path, "w", zipfile.ZIP_DEFLATED) as zf:
  26. zf.writestr("Metadata/plate_1.gcode", "G0\n")
  27. zf.writestr("Metadata/project_settings.config", json.dumps(config))
  28. @pytest.fixture
  29. def _patch_base_dir(monkeypatch, tmp_path):
  30. from backend.app.core.config import settings
  31. monkeypatch.setattr(settings, "base_dir", tmp_path)
  32. return tmp_path
  33. class TestArchivePlatesDesignOverrides:
  34. @pytest.mark.asyncio
  35. @pytest.mark.integration
  36. async def test_returns_the_process_deviations_with_classification(
  37. self, async_client: AsyncClient, archive_factory, printer_factory, _patch_base_dir
  38. ):
  39. _designed_3mf(_patch_base_dir / "designed.3mf")
  40. printer = await printer_factory()
  41. archive = await archive_factory(printer.id, filename="designed.3mf", file_path="designed.3mf")
  42. response = await async_client.get(f"/api/v1/archives/{archive.id}/plates")
  43. assert response.status_code == 200
  44. overrides = response.json()["design_overrides"]
  45. assert [o["key"] for o in overrides] == ["outer_wall_speed", "wall_loops"]
  46. by_key = {o["key"]: o for o in overrides}
  47. assert by_key["wall_loops"] == {"key": "wall_loops", "value": "5", "printer_coupled": False}
  48. assert by_key["outer_wall_speed"]["printer_coupled"] is True
  49. # The printer slot must never leak into the process list.
  50. assert "machine_start_gcode" not in by_key
  51. @pytest.mark.asyncio
  52. @pytest.mark.integration
  53. async def test_empty_for_a_file_that_changes_nothing(
  54. self, async_client: AsyncClient, archive_factory, printer_factory, _patch_base_dir
  55. ):
  56. _designed_3mf(_patch_base_dir / "stock.3mf", with_deviations=False)
  57. printer = await printer_factory()
  58. archive = await archive_factory(printer.id, filename="stock.3mf", file_path="stock.3mf")
  59. response = await async_client.get(f"/api/v1/archives/{archive.id}/plates")
  60. assert response.status_code == 200
  61. assert response.json()["design_overrides"] == []
  62. class TestLibraryPlatesDesignOverrides:
  63. @pytest.mark.asyncio
  64. @pytest.mark.integration
  65. async def test_returns_the_process_deviations(self, async_client: AsyncClient, db_session, tmp_path):
  66. from backend.app.models.library import LibraryFile
  67. path = tmp_path / "designed.3mf"
  68. _designed_3mf(path)
  69. lib_file = LibraryFile(
  70. filename="designed.3mf",
  71. file_path=str(path),
  72. file_type="3mf",
  73. file_size=path.stat().st_size,
  74. )
  75. db_session.add(lib_file)
  76. await db_session.commit()
  77. await db_session.refresh(lib_file)
  78. response = await async_client.get(f"/api/v1/library/files/{lib_file.id}/plates")
  79. assert response.status_code == 200
  80. assert [o["key"] for o in response.json()["design_overrides"]] == ["outer_wall_speed", "wall_loops"]