160 lines
4.9 KiB
Python
160 lines
4.9 KiB
Python
"""
|
|
Tests for authentication endpoints.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import timedelta
|
|
|
|
import pytest
|
|
from httpx import AsyncClient
|
|
|
|
from cpv3.infrastructure.security import create_token
|
|
from cpv3.modules.users.models import User
|
|
|
|
|
|
class TestRegisterEndpoint:
|
|
"""Tests for POST /auth/register."""
|
|
|
|
async def test_register_success(self, async_client: AsyncClient):
|
|
"""Test successful user registration."""
|
|
response = await async_client.post(
|
|
"/auth/register",
|
|
json={
|
|
"username": "newuser",
|
|
"email": "newuser@example.com",
|
|
"password": "securepassword123",
|
|
"first_name": "New",
|
|
"last_name": "User",
|
|
},
|
|
)
|
|
|
|
assert response.status_code == 201
|
|
data = response.json()
|
|
assert "access" in data
|
|
assert "refresh" in data
|
|
assert data["user"]["username"] == "newuser"
|
|
assert data["user"]["email"] == "newuser@example.com"
|
|
|
|
async def test_register_duplicate_username(
|
|
self, async_client: AsyncClient, test_user: User
|
|
):
|
|
"""Test registration fails with duplicate username."""
|
|
response = await async_client.post(
|
|
"/auth/register",
|
|
json={
|
|
"username": test_user.username, # existing username
|
|
"email": "another@example.com",
|
|
"password": "password123",
|
|
},
|
|
)
|
|
|
|
assert response.status_code == 400
|
|
|
|
async def test_register_missing_required_fields(self, async_client: AsyncClient):
|
|
"""Test registration fails with missing required fields."""
|
|
response = await async_client.post(
|
|
"/auth/register",
|
|
json={"username": "someuser"}, # missing email and password
|
|
)
|
|
|
|
assert response.status_code == 422
|
|
|
|
|
|
class TestLoginEndpoint:
|
|
"""Tests for POST /auth/login."""
|
|
|
|
async def test_login_success(self, async_client: AsyncClient, test_user: User):
|
|
"""Test successful login."""
|
|
response = await async_client.post(
|
|
"/auth/login",
|
|
json={
|
|
"username": "testuser",
|
|
"password": "testpassword",
|
|
},
|
|
)
|
|
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert "access" in data
|
|
assert "refresh" in data
|
|
assert data["user"]["username"] == "testuser"
|
|
|
|
async def test_login_invalid_password(
|
|
self, async_client: AsyncClient, test_user: User
|
|
):
|
|
"""Test login fails with wrong password."""
|
|
response = await async_client.post(
|
|
"/auth/login",
|
|
json={
|
|
"username": "testuser",
|
|
"password": "wrongpassword",
|
|
},
|
|
)
|
|
|
|
assert response.status_code == 401
|
|
assert response.json()["detail"] == "Invalid credentials"
|
|
|
|
async def test_login_nonexistent_user(self, async_client: AsyncClient):
|
|
"""Test login fails for nonexistent user."""
|
|
response = await async_client.post(
|
|
"/auth/login",
|
|
json={
|
|
"username": "nonexistent",
|
|
"password": "password123",
|
|
},
|
|
)
|
|
|
|
assert response.status_code == 401
|
|
assert response.json()["detail"] == "Invalid credentials"
|
|
|
|
|
|
class TestRefreshEndpoint:
|
|
"""Tests for POST /auth/refresh."""
|
|
|
|
async def test_refresh_success(self, async_client: AsyncClient, test_user: User):
|
|
"""Test successful token refresh."""
|
|
refresh_token = create_token(
|
|
subject=str(test_user.id),
|
|
token_type="refresh",
|
|
expires_in=timedelta(days=7),
|
|
)
|
|
|
|
response = await async_client.post(
|
|
"/auth/refresh",
|
|
json={"refresh": refresh_token},
|
|
)
|
|
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert "access" in data
|
|
assert "refresh" in data
|
|
|
|
async def test_refresh_with_access_token_fails(
|
|
self, async_client: AsyncClient, test_user: User
|
|
):
|
|
"""Test refresh fails when using access token instead of refresh token."""
|
|
access_token = create_token(
|
|
subject=str(test_user.id),
|
|
token_type="access",
|
|
expires_in=timedelta(minutes=15),
|
|
)
|
|
|
|
response = await async_client.post(
|
|
"/auth/refresh",
|
|
json={"refresh": access_token},
|
|
)
|
|
|
|
assert response.status_code == 401
|
|
assert response.json()["detail"] == "Invalid refresh token"
|
|
|
|
async def test_refresh_with_invalid_token(self, async_client: AsyncClient):
|
|
"""Test refresh fails with invalid token."""
|
|
response = await async_client.post(
|
|
"/auth/refresh",
|
|
json={"refresh": "invalid.token.here"},
|
|
)
|
|
|
|
assert response.status_code == 401
|
|
assert response.json()["detail"] == "Invalid refresh token"
|