test_plate_clear_notification.py 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. """Integration tests for the plate-clear-required notification (#2525).
  2. The event is opt-in: it fires after every print, at the same moment as the
  3. print-complete alert, so a provider only receives it when the toggle is
  4. explicitly enabled.
  5. """
  6. from unittest.mock import AsyncMock, patch
  7. import pytest
  8. from httpx import AsyncClient
  9. from backend.app.services.notification_service import notification_service
  10. class TestPlateClearNotificationDispatch:
  11. @pytest.mark.asyncio
  12. @pytest.mark.integration
  13. async def test_sends_to_a_provider_that_opted_in(self, notification_provider_factory, db_session):
  14. await notification_provider_factory(name="Opted In", on_plate_clear_required=True)
  15. send = AsyncMock()
  16. with patch.object(notification_service, "_send_to_providers", send):
  17. await notification_service.on_plate_clear_required(1, "Workshop", db_session)
  18. assert send.await_count == 1
  19. providers = send.await_args.args[0]
  20. assert [p.name for p in providers] == ["Opted In"]
  21. assert send.await_args.args[4] == "plate_clear_required"
  22. # _build_message_from_template folds in app_name/timestamp; the caller's
  23. # own variable is what matters here.
  24. assert send.await_args.kwargs["variables"]["printer"] == "Workshop"
  25. @pytest.mark.asyncio
  26. @pytest.mark.integration
  27. async def test_silent_for_a_provider_that_did_not_opt_in(self, notification_provider_factory, db_session):
  28. await notification_provider_factory(name="Default Off", on_plate_clear_required=False)
  29. send = AsyncMock()
  30. with patch.object(notification_service, "_send_to_providers", send):
  31. await notification_service.on_plate_clear_required(1, "Workshop", db_session)
  32. send.assert_not_awaited()
  33. @pytest.mark.asyncio
  34. @pytest.mark.integration
  35. async def test_skips_a_provider_scoped_to_a_different_printer(
  36. self, notification_provider_factory, printer_factory, db_session
  37. ):
  38. await printer_factory(name="Workshop")
  39. other = await printer_factory(name="Other")
  40. await notification_provider_factory(name="Other Printer", on_plate_clear_required=True, printer_id=other.id)
  41. send = AsyncMock()
  42. with patch.object(notification_service, "_send_to_providers", send):
  43. await notification_service.on_plate_clear_required(1, "Workshop", db_session)
  44. send.assert_not_awaited()
  45. class TestPlateClearProviderField:
  46. @pytest.mark.asyncio
  47. @pytest.mark.integration
  48. async def test_defaults_to_off_on_create_and_round_trips_on_update(self, async_client: AsyncClient):
  49. create = await async_client.post(
  50. "/api/v1/notifications/",
  51. json={
  52. "name": "Plate Clear Test",
  53. "provider_type": "ntfy",
  54. "enabled": True,
  55. "config": {"server": "https://ntfy.sh", "topic": "test-topic"},
  56. },
  57. )
  58. assert create.status_code in (200, 201), create.text
  59. provider_id = create.json()["id"]
  60. assert create.json()["on_plate_clear_required"] is False
  61. update = await async_client.patch(
  62. f"/api/v1/notifications/{provider_id}",
  63. json={"on_plate_clear_required": True},
  64. )
  65. assert update.status_code == 200, update.text
  66. assert update.json()["on_plate_clear_required"] is True