test_notification_scope_without_printer.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. """An event about a job that has no printer yet reaches "All printers" channels only.
  2. A channel limited to one printer received every "job added" for an "Any
  3. <model>" or unassigned job, and every "job waiting": with no printer on the
  4. event, no printer filter applied. A wait for a job pinned to a printer names
  5. that printer and reaches its channels. It hears of such a
  6. job once it is assigned to or started on its printer. Events about the whole
  7. fleet -- the queue finishing, stock, app messages -- still reach every channel.
  8. """
  9. import pytest
  10. from backend.app.models.notification import NotificationProvider
  11. from backend.app.services.notification_service import NotificationService
  12. pytestmark = [pytest.mark.asyncio, pytest.mark.integration]
  13. async def _providers(db_session, printer_factory):
  14. printer = await printer_factory()
  15. rows = [
  16. NotificationProvider(
  17. name="everyone", provider_type="ntfy", config="{}", on_queue_job_added=True, on_queue_completed=True
  18. ),
  19. NotificationProvider(
  20. name="one printer",
  21. provider_type="ntfy",
  22. config="{}",
  23. printer_id=printer.id,
  24. on_queue_job_added=True,
  25. on_queue_completed=True,
  26. ),
  27. ]
  28. db_session.add_all(rows)
  29. await db_session.commit()
  30. return printer.id
  31. async def _names(service, db_session, event, printer_id=None, **kwargs):
  32. providers = await service._get_providers_for_event(db_session, event, printer_id, **kwargs)
  33. return sorted(p.name for p in providers)
  34. async def test_a_job_without_a_printer_reaches_all_printer_channels_only(db_session, printer_factory):
  35. await _providers(db_session, printer_factory)
  36. assert await _names(NotificationService(), db_session, "on_queue_job_added") == ["everyone"]
  37. async def test_a_job_on_the_printer_reaches_its_channel(db_session, printer_factory):
  38. printer_id = await _providers(db_session, printer_factory)
  39. assert await _names(NotificationService(), db_session, "on_queue_job_added", printer_id) == [
  40. "everyone",
  41. "one printer",
  42. ]
  43. async def test_a_fleet_event_reaches_every_channel(db_session, printer_factory):
  44. await _providers(db_session, printer_factory)
  45. assert await _names(NotificationService(), db_session, "on_queue_completed", fleet_wide=True) == [
  46. "everyone",
  47. "one printer",
  48. ]
  49. async def test_the_fleet_events_are_marked_so():
  50. """Their callers pass fleet_wide, or they would silently lose scoped channels."""
  51. import inspect
  52. from backend.app.services import notification_service, print_scheduler
  53. source = inspect.getsource(notification_service.NotificationService)
  54. for event in (
  55. "on_app_message",
  56. "on_location_ha_sensor_alert",
  57. "on_queue_completed",
  58. "on_stock_reorder_alert",
  59. "on_stock_break_alert",
  60. ):
  61. line = next(text for text in source.splitlines() if f'_get_providers_for_event(db, "{event}"' in text)
  62. assert "fleet_wide=True" in line, event
  63. scheduler = inspect.getsource(print_scheduler)
  64. for event in ("on_filament_low", "on_stock_reorder_alert", "on_stock_break_alert"):
  65. line = next(text for text in scheduler.splitlines() if f'_get_providers_for_event(db, "{event}"' in text)
  66. assert "fleet_wide=True" in line, event
  67. @pytest.mark.parametrize(("printer_bound", "reached"), [(True, ["everyone", "one printer"]), (False, ["everyone"])])
  68. async def test_a_job_waiting_on_its_printer_reaches_that_printers_channel(
  69. db_session, printer_factory, printer_bound, reached
  70. ):
  71. from unittest.mock import AsyncMock, patch
  72. printer = await printer_factory()
  73. db_session.add_all(
  74. [
  75. NotificationProvider(name="everyone", provider_type="ntfy", config="{}", on_queue_job_waiting=True),
  76. NotificationProvider(
  77. name="one printer",
  78. provider_type="ntfy",
  79. config="{}",
  80. printer_id=printer.id,
  81. on_queue_job_waiting=True,
  82. ),
  83. ]
  84. )
  85. await db_session.commit()
  86. service = NotificationService()
  87. send = AsyncMock()
  88. with patch.object(service, "_send_to_providers", send):
  89. await service.on_queue_job_waiting(
  90. job_name="Bracket",
  91. target_model="X1C",
  92. waiting_reason="filament_short",
  93. db=db_session,
  94. printer_id=printer.id if printer_bound else None,
  95. )
  96. assert sorted(p.name for p in send.await_args.args[0]) == reached