test_webhook_endpoint_list.py 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. """The webhook endpoints listed in Settings are the ones that exist.
  2. The "Webhook Endpoints" card on the API keys settings page is the only place
  3. the UI tells an integrator what to call. It had drifted: it listed endpoints
  4. that never existed (status of all printers, pause, resume), gave two wrong
  5. paths, and left out start, cancel and the queue status. This compares the card
  6. with the webhook router, both ways.
  7. """
  8. import re
  9. from pathlib import Path
  10. from backend.app.api.routes.webhook import router
  11. from backend.app.core.config import settings
  12. SETTINGS_PAGE = Path(__file__).resolve().parents[3] / "frontend" / "src" / "pages" / "SettingsPage.tsx"
  13. # <span ...>POST</span>{' '}
  14. # <span className="text-white">/api/v1/webhook/printer/:id/stop</span>
  15. _LISTED = re.compile(
  16. r">(GET|POST|PUT|PATCH|DELETE)</span>\{' '\}\s*<span className=\"text-white\">(/api/v1/webhook/[^<\s]+)</span>"
  17. )
  18. def _listed() -> set[tuple[str, str]]:
  19. return {(method, path) for method, path in _LISTED.findall(SETTINGS_PAGE.read_text(encoding="utf-8"))}
  20. def _routed() -> set[tuple[str, str]]:
  21. found = set()
  22. for route in router.routes:
  23. path = settings.api_prefix + re.sub(r"\{[^}]+\}", ":id", route.path)
  24. for method in route.methods - {"HEAD", "OPTIONS"}:
  25. found.add((method, path))
  26. return found
  27. def test_every_webhook_path_on_the_page_is_read_by_this_test():
  28. """Otherwise an entry written in other markup would escape the comparison."""
  29. text = SETTINGS_PAGE.read_text(encoding="utf-8")
  30. occurrences = len(re.findall(r"/api/v1/webhook/", text))
  31. parsed = len(_LISTED.findall(text))
  32. assert occurrences == parsed, (
  33. f"{occurrences} webhook paths in SettingsPage.tsx but only {parsed} in the expected markup; "
  34. "write new entries like the existing ones (or extend _LISTED)"
  35. )
  36. def test_the_settings_card_lists_exactly_the_webhook_routes():
  37. listed, routed = _listed(), _routed()
  38. assert listed, "no webhook endpoints found on the settings card; has its markup changed?"
  39. assert listed - routed == set(), f"listed in Settings but no such route: {sorted(listed - routed)}"
  40. assert routed - listed == set(), f"webhook route missing from the Settings card: {sorted(routed - listed)}"