Auf Nutzerwunsch findet ohne bewusste Entscheidung kein Übertrag statt. Modell-Default, beide Checkboxen (Lizenz-Modal, Org-Modal) und der Modell-Test stehen jetzt auf aus, der Übertrag bleibt pro Kunde zuschaltbar. Der DB-Spalten-Default stand ohnehin schon auf 0. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
106 Zeilen
3.5 KiB
Python
106 Zeilen
3.5 KiB
Python
"""Tests fuer src/models.py - Pydantic-Validierung."""
|
|
import pytest
|
|
from pydantic import ValidationError
|
|
from models import (
|
|
MagicLinkRequest, MagicLinkResponse,
|
|
VerifyTokenRequest, TokenResponse,
|
|
OrgCreate, LicenseCreate, LicenseParams, LicenseResponse, UserCreate,
|
|
)
|
|
|
|
|
|
def test_magic_link_request_accepts_email():
|
|
r = MagicLinkRequest(email="info@aegis-sight.de")
|
|
assert r.email == "info@aegis-sight.de"
|
|
|
|
|
|
def test_magic_link_request_rejects_too_short():
|
|
with pytest.raises(ValidationError):
|
|
MagicLinkRequest(email="a")
|
|
|
|
|
|
def test_verify_token_min_length():
|
|
with pytest.raises(ValidationError):
|
|
VerifyTokenRequest(token="abc")
|
|
|
|
|
|
def test_token_response_default_email_empty():
|
|
r = TokenResponse(access_token="x" * 40, username="info")
|
|
assert r.email == ""
|
|
assert r.token_type == "bearer"
|
|
|
|
|
|
def test_org_create_slug_pattern():
|
|
"""Slug muss lowercase mit Bindestrichen sein."""
|
|
OrgCreate(name="Test", slug="abc-123")
|
|
with pytest.raises(ValidationError):
|
|
OrgCreate(name="Test", slug="Wrong Case")
|
|
with pytest.raises(ValidationError):
|
|
OrgCreate(name="Test", slug="under_score")
|
|
|
|
|
|
def test_license_create_type_pattern():
|
|
LicenseCreate(organization_id=1, license_type="trial")
|
|
LicenseCreate(organization_id=1, license_type="annual")
|
|
LicenseCreate(organization_id=1, license_type="permanent")
|
|
with pytest.raises(ValidationError):
|
|
LicenseCreate(organization_id=1, license_type="lifetime")
|
|
|
|
|
|
def test_license_params_credits_defaults():
|
|
"""Monatskontingent OHNE Übertrag ist die Voreinstellung."""
|
|
p = LicenseParams(license_type="trial")
|
|
assert p.credits_period == "monthly"
|
|
assert p.credits_rollover is False
|
|
assert p.budget_warning_percent == 80
|
|
|
|
|
|
def test_license_params_period_pattern():
|
|
LicenseParams(license_type="trial", credits_period="monthly")
|
|
LicenseParams(license_type="trial", credits_period="total")
|
|
with pytest.raises(ValidationError):
|
|
LicenseParams(license_type="trial", credits_period="weekly")
|
|
|
|
|
|
def test_license_create_inherits_credits_fields():
|
|
lic = LicenseCreate(
|
|
organization_id=1, license_type="annual",
|
|
credits_total=10000, credits_period="monthly", credits_rollover=False,
|
|
)
|
|
assert lic.credits_total == 10000
|
|
assert lic.credits_rollover is False
|
|
|
|
|
|
def test_org_create_without_license_still_valid():
|
|
"""Rückwärtskompatibilität, das Lizenz-Objekt ist optional."""
|
|
org = OrgCreate(name="Test", slug="test")
|
|
assert org.license is None
|
|
|
|
|
|
def test_org_create_with_nested_license():
|
|
org = OrgCreate(
|
|
name="Test", slug="test",
|
|
license={"license_type": "trial", "credits_total": 10000},
|
|
)
|
|
assert org.license.credits_total == 10000
|
|
assert org.license.credits_period == "monthly"
|
|
with pytest.raises(ValidationError):
|
|
OrgCreate(name="Test", slug="test", license={"license_type": "trial", "credits_period": "weekly"})
|
|
|
|
|
|
def test_license_response_without_new_columns():
|
|
"""Responses müssen auch von einer noch nicht migrierten DB validieren."""
|
|
r = LicenseResponse(
|
|
id=1, organization_id=1, license_type="trial", max_users=5,
|
|
valid_from="2026-07-25", valid_until=None, status="active",
|
|
notes=None, created_at="2026-07-25",
|
|
)
|
|
assert r.credits_period == "monthly"
|
|
assert r.credits_carried == 0
|
|
|
|
|
|
def test_user_create_role_pattern():
|
|
UserCreate(email="a@b.de", role="member")
|
|
UserCreate(email="a@b.de", role="org_admin")
|
|
with pytest.raises(ValidationError):
|
|
UserCreate(email="a@b.de", role="superuser")
|