test_preconfig_replay_failure.py 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. """A pre-assigned slot the printer could not be told about is retried (SA-3).
  2. SpoolBuddy assigns a spool to an empty slot with an empty fingerprint; the
  3. slot is configured on the printer once filament goes in. The fingerprint was
  4. recorded even when nothing could be sent (no MQTT client while the printer
  5. reconnects), and a recorded fingerprint ends the replay, so the slot was never
  6. configured.
  7. """
  8. from unittest.mock import AsyncMock, MagicMock, patch
  9. import pytest
  10. from backend.app.models.spool_assignment import SpoolAssignment
  11. from backend.tests.integration.test_inventory_assign import _make_mock_status, spool_factory # noqa: F401
  12. pytestmark = [pytest.mark.asyncio, pytest.mark.integration]
  13. async def _fingerprint_after_insert(db_session, printer_factory, spool_factory, apply: AsyncMock):
  14. from backend.app.main import on_ams_change
  15. printer = await printer_factory(name="H2D")
  16. spool = await spool_factory(slicer_filament="GFL05", material="PLA")
  17. assignment = SpoolAssignment(spool_id=spool.id, printer_id=printer.id, ams_id=2, tray_id=3)
  18. db_session.add(assignment)
  19. await db_session.commit()
  20. ams_data = [{"id": 2, "tray": [{"id": 3, "tray_type": "PLA", "tray_color": "FF0000FF", "state": 11}]}]
  21. status = _make_mock_status(ams_data=ams_data)
  22. with (
  23. patch("backend.app.api.routes.inventory.apply_spool_to_slot_via_mqtt", apply),
  24. patch("backend.app.main.printer_manager") as pm,
  25. patch("backend.app.main.mqtt_relay") as relay,
  26. patch("backend.app.main.ws_manager") as ws,
  27. ):
  28. pm.get_printer.return_value = MagicMock(name="H2D", serial_number="0948BB540200427")
  29. pm.get_status.return_value = status
  30. pm.get_client.return_value = MagicMock()
  31. pm.get_model.return_value = "H2D"
  32. relay.on_ams_change = AsyncMock()
  33. ws.send_printer_status = AsyncMock()
  34. ws.broadcast = AsyncMock()
  35. await on_ams_change(printer.id, ams_data)
  36. await db_session.refresh(assignment)
  37. apply.assert_awaited_once()
  38. return assignment.fingerprint_type, assignment.fingerprint_color
  39. async def test_a_slot_the_printer_could_not_be_told_about_is_retried(
  40. async_client, db_session, printer_factory, spool_factory
  41. ):
  42. """No MQTT client (reconnecting): nothing was sent."""
  43. apply = AsyncMock(return_value=False)
  44. assert await _fingerprint_after_insert(db_session, printer_factory, spool_factory, apply) == (None, None)
  45. async def test_a_configuration_that_raised_is_not_retried(async_client, db_session, printer_factory, spool_factory):
  46. """It may have sent part of the commands, and would raise again on every
  47. AMS change, mid-print included (remain% steps count as changes)."""
  48. apply = AsyncMock(side_effect=RuntimeError("preset lookup failed"))
  49. assert await _fingerprint_after_insert(db_session, printer_factory, spool_factory, apply) == ("PLA", "FF0000FF")
  50. async def test_a_configured_slot_records_its_fingerprint(async_client, db_session, printer_factory, spool_factory):
  51. apply = AsyncMock(return_value=True)
  52. assert await _fingerprint_after_insert(db_session, printer_factory, spool_factory, apply) == ("PLA", "FF0000FF")