"""Unit tests for /push routes (patched service, no real container)."""
import pytest
from fastapi.testclient import TestClient
import navi.api.routes.push as push_mod
class FakeService:
def __init__(self, enabled=True, public_key="PUBKEY"):
self.enabled = enabled
self.public_key = public_key
self.subs: list[dict] = []
self.deleted: list[str] = []
async def subscribe(self, user_id, endpoint, p256dh, auth, user_agent=None):
self.subs.append(dict(user_id=user_id, endpoint=endpoint,
p256dh=p256dh, auth=auth, user_agent=user_agent))
return "sub-1"
async def unsubscribe(self, endpoint):
self.deleted.append(endpoint)
@pytest.fixture
def client(monkeypatch):
service = FakeService()
monkeypatch.setattr(push_mod, "get_push_service", lambda: service)
from navi.main import app
from navi.auth.deps import require_user, _ANONYMOUS_USER
# require_user reads global settings; other tests (integration conftest)
# leave dependency_overrides on the shared app — pin the anonymous user
# so these tests don't depend on evaluation order.
app.dependency_overrides[require_user] = lambda: _ANONYMOUS_USER.model_copy()
try:
yield TestClient(app), service
finally:
app.dependency_overrides.pop(require_user, None)
def test_vapid_key_ok(client):
c, service = client
resp = c.get("/push/vapid-key")
assert resp.status_code == 200
assert resp.json() == {"public_key": "PUBKEY"}
def test_vapid_key_503_when_disabled(client):
c, service = client
service.enabled = False
assert c.get("/push/vapid-key").status_code == 503
assert c.post("/push/subscribe", json={"endpoint": "e", "keys": {"p256dh": "p", "auth": "a"}}).status_code == 503
def test_subscribe_upserts(client):
c, service = client
resp = c.post("/push/subscribe", json={
"endpoint": "https://push.example/ep1",
"keys": {"p256dh": "P256DH", "auth": "AUTH"},
"user_agent": "pytest",
})
assert resp.status_code == 200
assert resp.json() == {"id": "sub-1", "status": "subscribed"}
assert service.subs == [dict(
user_id="anonymous", endpoint="https://push.example/ep1",
p256dh="P256DH", auth="AUTH", user_agent="pytest",
)]
def test_subscribe_rejects_missing_keys(client):
c, _ = client
resp = c.post("/push/subscribe", json={"endpoint": "e", "keys": {}})
assert resp.status_code == 422
resp = c.post("/push/subscribe", json={"endpoint": "e", "keys": {"p256dh": "p"}})
assert resp.status_code == 422
def test_delete_subscribe_idempotent(client):
c, service = client
payload = {"endpoint": "https://push.example/ep1", "keys": {"p256dh": "p", "auth": "a"}}
assert c.request("DELETE", "/push/subscribe", json=payload).status_code == 200
assert c.request("DELETE", "/push/subscribe", json=payload).status_code == 200
assert service.deleted == ["https://push.example/ep1"] * 2