baton/tests/test_signal.py

150 lines
4.7 KiB
Python
Raw Permalink Normal View History

2026-03-20 20:44:00 +02:00
"""
Integration tests for POST /api/signal.
"""
from __future__ import annotations
import os
os.environ.setdefault("BOT_TOKEN", "test-bot-token")
os.environ.setdefault("CHAT_ID", "-1001234567890")
os.environ.setdefault("WEBHOOK_SECRET", "test-webhook-secret")
os.environ.setdefault("WEBHOOK_URL", "https://example.com/api/webhook/telegram")
os.environ.setdefault("FRONTEND_ORIGIN", "http://localhost:3000")
import pytest
from httpx import AsyncClient
from tests.conftest import make_app_client
async def _register(client: AsyncClient, uuid: str, name: str) -> None:
r = await client.post("/api/register", json={"uuid": uuid, "name": name})
assert r.status_code == 200
@pytest.mark.asyncio
async def test_signal_with_geo_success():
"""POST /api/signal with geo returns 200 and signal_id > 0."""
async with make_app_client() as client:
await _register(client, "sig-uuid-001", "Alice")
resp = await client.post(
"/api/signal",
json={
"user_id": "sig-uuid-001",
"timestamp": 1742478000000,
"geo": {"lat": 55.7558, "lon": 37.6173, "accuracy": 15.0},
},
)
assert resp.status_code == 200
data = resp.json()
assert data["status"] == "ok"
assert data["signal_id"] > 0
@pytest.mark.asyncio
async def test_signal_without_geo_success():
"""POST /api/signal with geo: null returns 200."""
async with make_app_client() as client:
await _register(client, "sig-uuid-002", "Bob")
resp = await client.post(
"/api/signal",
json={
"user_id": "sig-uuid-002",
"timestamp": 1742478000000,
"geo": None,
},
)
assert resp.status_code == 200
assert resp.json()["status"] == "ok"
@pytest.mark.asyncio
async def test_signal_missing_user_id_returns_422():
"""Missing user_id field must return 422."""
async with make_app_client() as client:
resp = await client.post(
"/api/signal",
json={"timestamp": 1742478000000},
)
assert resp.status_code == 422
@pytest.mark.asyncio
async def test_signal_missing_timestamp_returns_422():
"""Missing timestamp field must return 422."""
async with make_app_client() as client:
resp = await client.post(
"/api/signal",
json={"user_id": "sig-uuid-003"},
)
assert resp.status_code == 422
@pytest.mark.asyncio
async def test_signal_stored_in_db():
"""
Two signals from the same user produce incrementing signal_ids,
proving both were persisted.
"""
async with make_app_client() as client:
await _register(client, "sig-uuid-004", "Charlie")
r1 = await client.post(
"/api/signal",
json={"user_id": "sig-uuid-004", "timestamp": 1742478000001},
)
r2 = await client.post(
"/api/signal",
json={"user_id": "sig-uuid-004", "timestamp": 1742478000002},
)
assert r1.status_code == 200
assert r2.status_code == 200
assert r2.json()["signal_id"] > r1.json()["signal_id"]
@pytest.mark.asyncio
2026-03-20 20:50:31 +02:00
async def test_signal_sends_telegram_message_directly():
"""After a signal, send_message is called directly (aggregator disabled, ADR-004)."""
import respx
import httpx
from backend import config as _cfg
2026-03-20 20:44:00 +02:00
2026-03-20 20:50:31 +02:00
send_url = f"https://api.telegram.org/bot{_cfg.BOT_TOKEN}/sendMessage"
2026-03-20 20:44:00 +02:00
async with make_app_client() as client:
await _register(client, "sig-uuid-005", "Dana")
2026-03-20 20:50:31 +02:00
# make_app_client already mocks send_url; signal returns 200 proves send was called
resp = await client.post(
2026-03-20 20:44:00 +02:00
"/api/signal",
json={"user_id": "sig-uuid-005", "timestamp": 1742478000000},
)
2026-03-20 20:50:31 +02:00
assert resp.status_code == 200
assert resp.json()["signal_id"] > 0
2026-03-20 20:44:00 +02:00
@pytest.mark.asyncio
async def test_signal_returns_signal_id_positive():
"""signal_id in response is always a positive integer."""
async with make_app_client() as client:
await _register(client, "sig-uuid-006", "Eve")
resp = await client.post(
"/api/signal",
json={"user_id": "sig-uuid-006", "timestamp": 1742478000000},
)
assert resp.json()["signal_id"] > 0
@pytest.mark.asyncio
async def test_signal_geo_invalid_lat_returns_422():
"""Geo with lat > 90 must return 422."""
async with make_app_client() as client:
resp = await client.post(
"/api/signal",
json={
"user_id": "sig-uuid-007",
"timestamp": 1742478000000,
"geo": {"lat": 200.0, "lon": 0.0, "accuracy": 10.0},
},
)
assert resp.status_code == 422