Backend: - conftest with async SQLite DB, factory fixtures for all models - pytest-asyncio config in pyproject.toml - Tests: auth (JWT, dev login), RBAC (access service), audit (query, export), brand enforcement (colors, fonts, logos, contrast), retention (cleanup, purge), content intelligence (regex classifiers), slide mapping, review workflow, analytics data queries Frontend: - Cypress E2E config with baseUrl and viewport settings - Custom commands (devLogin, createPresentation) - E2E specs: login flow, wizard navigation, admin panel, review workflow - Test scripts in package.json Infrastructure: - Makefile: test-e2e and test-all targets Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
78 lines
2.6 KiB
Python
78 lines
2.6 KiB
Python
"""Tests for auth_service: JWT creation/validation, dev login, user creation."""
|
|
import uuid
|
|
|
|
import pytest
|
|
|
|
from services.auth_service import AuthService
|
|
|
|
|
|
@pytest.fixture
|
|
def auth_service():
|
|
return AuthService()
|
|
|
|
|
|
class TestJWT:
|
|
def test_create_and_validate_token(self, auth_service, make_user):
|
|
"""Token round-trip: create → validate → same payload."""
|
|
from models.sql.user import UserModel
|
|
|
|
user = UserModel(
|
|
id=uuid.uuid4(),
|
|
email="jwt@test.com",
|
|
display_name="JWT User",
|
|
role="user",
|
|
is_active=True,
|
|
)
|
|
token = auth_service.create_session_jwt(user)
|
|
payload = auth_service.validate_token(token)
|
|
|
|
assert payload is not None
|
|
assert payload["sub"] == str(user.id)
|
|
assert payload["email"] == "jwt@test.com"
|
|
assert payload["role"] == "user"
|
|
|
|
def test_validate_invalid_token(self, auth_service):
|
|
assert auth_service.validate_token("garbage.token.here") is None
|
|
|
|
def test_validate_tampered_token(self, auth_service):
|
|
from models.sql.user import UserModel
|
|
|
|
user = UserModel(
|
|
id=uuid.uuid4(),
|
|
email="tamper@test.com",
|
|
display_name="Tamper",
|
|
role="user",
|
|
is_active=True,
|
|
)
|
|
token = auth_service.create_session_jwt(user)
|
|
# Tamper with the token
|
|
tampered = token[:-5] + "XXXXX"
|
|
assert auth_service.validate_token(tampered) is None
|
|
|
|
|
|
class TestDevLogin:
|
|
async def test_dev_login_success(self, auth_service, session):
|
|
"""Dev mode: correct password creates user."""
|
|
user = await auth_service.dev_login("dev@test.com", "testpass", session)
|
|
assert user is not None
|
|
assert user.email == "dev@test.com"
|
|
|
|
async def test_dev_login_wrong_password(self, auth_service, session):
|
|
user = await auth_service.dev_login("dev@test.com", "wrongpass", session)
|
|
assert user is None
|
|
|
|
async def test_dev_login_idempotent(self, auth_service, session):
|
|
"""Logging in twice with same email returns same user."""
|
|
user1 = await auth_service.dev_login("dev@test.com", "testpass", session)
|
|
user2 = await auth_service.dev_login("dev@test.com", "testpass", session)
|
|
assert user1.id == user2.id
|
|
|
|
|
|
class TestDevMode:
|
|
def test_is_dev_mode_when_no_azure(self, auth_service):
|
|
"""Without AZURE_AD_TENANT_ID, service is in dev mode."""
|
|
assert auth_service.is_dev_mode is True
|
|
|
|
def test_get_authorization_url_raises_in_dev_mode(self, auth_service):
|
|
with pytest.raises(ValueError, match="dev login"):
|
|
auth_service.get_authorization_url()
|