baton/tests/test_models.py
Gros Frumos 04f7bd79e2 auth: replace UUID-based login with JWT credential verification
Login now requires login/email + password verified against DB via
/api/auth/login. Only approved registrations can access the app.
Signal endpoint accepts JWT Bearer tokens alongside legacy api_key auth.
Old UUID-only registration flow removed from frontend.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 14:14:12 +02:00

146 lines
4.5 KiB
Python

"""
Tests for backend/models.py (Pydantic v2 validation).
No DB or network calls — pure unit tests.
"""
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 pydantic import ValidationError
from backend.models import GeoData, RegisterRequest, SignalRequest
# ---------------------------------------------------------------------------
# RegisterRequest
# ---------------------------------------------------------------------------
def test_register_request_valid():
req = RegisterRequest(uuid="550e8400-e29b-41d4-a716-446655440000", name="Alice")
assert req.uuid == "550e8400-e29b-41d4-a716-446655440000"
assert req.name == "Alice"
def test_register_request_empty_name():
with pytest.raises(ValidationError):
RegisterRequest(uuid="550e8400-e29b-41d4-a716-446655440000", name="")
def test_register_request_missing_uuid():
with pytest.raises(ValidationError):
RegisterRequest(name="Alice") # type: ignore[call-arg]
def test_register_request_empty_uuid():
with pytest.raises(ValidationError):
RegisterRequest(uuid="", name="Alice")
def test_register_request_name_max_length():
"""name longer than 100 chars raises ValidationError."""
with pytest.raises(ValidationError):
RegisterRequest(uuid="550e8400-e29b-41d4-a716-446655440000", name="x" * 101)
def test_register_request_name_exactly_100():
req = RegisterRequest(uuid="550e8400-e29b-41d4-a716-446655440000", name="x" * 100)
assert len(req.name) == 100
# ---------------------------------------------------------------------------
# GeoData
# ---------------------------------------------------------------------------
def test_geo_data_valid():
geo = GeoData(lat=55.7558, lon=37.6173, accuracy=15.0)
assert geo.lat == 55.7558
assert geo.lon == 37.6173
assert geo.accuracy == 15.0
def test_geo_data_lat_out_of_range_high():
with pytest.raises(ValidationError):
GeoData(lat=90.1, lon=0.0, accuracy=10.0)
def test_geo_data_lat_out_of_range_low():
with pytest.raises(ValidationError):
GeoData(lat=-90.1, lon=0.0, accuracy=10.0)
def test_geo_data_lon_out_of_range_high():
with pytest.raises(ValidationError):
GeoData(lat=0.0, lon=180.1, accuracy=10.0)
def test_geo_data_lon_out_of_range_low():
with pytest.raises(ValidationError):
GeoData(lat=0.0, lon=-180.1, accuracy=10.0)
def test_geo_data_accuracy_zero():
"""accuracy must be strictly > 0."""
with pytest.raises(ValidationError):
GeoData(lat=0.0, lon=0.0, accuracy=0.0)
def test_geo_data_boundary_values():
"""Boundary values -90/90 lat and -180/180 lon are valid."""
geo = GeoData(lat=90.0, lon=180.0, accuracy=1.0)
assert geo.lat == 90.0
assert geo.lon == 180.0
# ---------------------------------------------------------------------------
# SignalRequest
# ---------------------------------------------------------------------------
def test_signal_request_valid():
req = SignalRequest(
user_id="550e8400-e29b-41d4-a716-446655440000",
timestamp=1742478000000,
geo={"lat": 55.7558, "lon": 37.6173, "accuracy": 15.0},
)
assert req.user_id == "550e8400-e29b-41d4-a716-446655440000"
assert req.timestamp == 1742478000000
assert req.geo is not None
assert req.geo.lat == 55.7558
def test_signal_request_no_geo():
req = SignalRequest(
user_id="550e8400-e29b-41d4-a716-446655440000",
timestamp=1742478000000,
geo=None,
)
assert req.geo is None
def test_signal_request_without_user_id():
"""user_id is optional (JWT auth sends signals without it)."""
req = SignalRequest(timestamp=1742478000000)
assert req.user_id is None
def test_signal_request_empty_user_id():
"""Empty string user_id is accepted (treated as None at endpoint level)."""
req = SignalRequest(user_id="", timestamp=1742478000000)
assert req.user_id == ""
def test_signal_request_timestamp_zero():
"""timestamp must be > 0."""
with pytest.raises(ValidationError):
SignalRequest(user_id="550e8400-e29b-41d4-a716-446655440000", timestamp=0)
def test_signal_request_timestamp_negative():
with pytest.raises(ValidationError):
SignalRequest(user_id="550e8400-e29b-41d4-a716-446655440000", timestamp=-1)