""" 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"