b7e6f637a7
Consolidate API gateway service into monorepo. Squashed from https://github.com/cartsnitch/api main (89bacb1). Co-Authored-By: Paperclip <noreply@paperclip.ing>
210 lines
5.2 KiB
Python
210 lines
5.2 KiB
Python
"""Integration tests for auth endpoints."""
|
|
|
|
import pytest
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_register_success(client):
|
|
resp = await client.post(
|
|
"/auth/register",
|
|
json={
|
|
"email": "new@example.com",
|
|
"password": "securepass123",
|
|
"display_name": "New User",
|
|
},
|
|
)
|
|
assert resp.status_code == 201
|
|
data = resp.json()
|
|
assert "access_token" in data
|
|
assert "refresh_token" in data
|
|
assert data["token_type"] == "bearer"
|
|
assert data["expires_in"] == 900 # 15 min * 60
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_register_duplicate_email(client):
|
|
await client.post(
|
|
"/auth/register",
|
|
json={
|
|
"email": "dupe@example.com",
|
|
"password": "securepass123",
|
|
"display_name": "User One",
|
|
},
|
|
)
|
|
resp = await client.post(
|
|
"/auth/register",
|
|
json={
|
|
"email": "dupe@example.com",
|
|
"password": "securepass456",
|
|
"display_name": "User Two",
|
|
},
|
|
)
|
|
assert resp.status_code == 409
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_register_short_password(client):
|
|
resp = await client.post(
|
|
"/auth/register",
|
|
json={
|
|
"email": "short@example.com",
|
|
"password": "short",
|
|
"display_name": "Short Pass",
|
|
},
|
|
)
|
|
assert resp.status_code == 422
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_login_success(client):
|
|
await client.post(
|
|
"/auth/register",
|
|
json={
|
|
"email": "login@example.com",
|
|
"password": "securepass123",
|
|
"display_name": "Login User",
|
|
},
|
|
)
|
|
resp = await client.post(
|
|
"/auth/login",
|
|
json={
|
|
"email": "login@example.com",
|
|
"password": "securepass123",
|
|
},
|
|
)
|
|
assert resp.status_code == 200
|
|
assert "access_token" in resp.json()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_login_wrong_password(client):
|
|
await client.post(
|
|
"/auth/register",
|
|
json={
|
|
"email": "wrong@example.com",
|
|
"password": "securepass123",
|
|
"display_name": "Wrong Pass",
|
|
},
|
|
)
|
|
resp = await client.post(
|
|
"/auth/login",
|
|
json={
|
|
"email": "wrong@example.com",
|
|
"password": "badpassword1",
|
|
},
|
|
)
|
|
assert resp.status_code == 401
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_login_nonexistent_user(client):
|
|
resp = await client.post(
|
|
"/auth/login",
|
|
json={
|
|
"email": "ghost@example.com",
|
|
"password": "doesntmatter",
|
|
},
|
|
)
|
|
assert resp.status_code == 401
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_refresh_token(client):
|
|
reg = await client.post(
|
|
"/auth/register",
|
|
json={
|
|
"email": "refresh@example.com",
|
|
"password": "securepass123",
|
|
"display_name": "Refresh User",
|
|
},
|
|
)
|
|
refresh_token = reg.json()["refresh_token"]
|
|
|
|
resp = await client.post(
|
|
"/auth/refresh",
|
|
json={
|
|
"refresh_token": refresh_token,
|
|
},
|
|
)
|
|
assert resp.status_code == 200
|
|
assert "access_token" in resp.json()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_refresh_with_invalid_token(client):
|
|
resp = await client.post(
|
|
"/auth/refresh",
|
|
json={
|
|
"refresh_token": "invalid.token.here",
|
|
},
|
|
)
|
|
assert resp.status_code == 401
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_me(client, auth_headers):
|
|
resp = await client.get("/auth/me", headers=auth_headers)
|
|
assert resp.status_code == 200
|
|
data = resp.json()
|
|
assert data["email"] == "test@example.com"
|
|
assert data["display_name"] == "Test User"
|
|
assert "id" in data
|
|
assert "created_at" in data
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_me_unauthorized(client):
|
|
resp = await client.get("/auth/me")
|
|
assert resp.status_code in (401, 403) # No auth header
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_update_me(client, auth_headers):
|
|
resp = await client.patch(
|
|
"/auth/me",
|
|
headers=auth_headers,
|
|
json={
|
|
"display_name": "Updated Name",
|
|
},
|
|
)
|
|
assert resp.status_code == 200
|
|
assert resp.json()["display_name"] == "Updated Name"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_delete_me(client, auth_headers):
|
|
resp = await client.delete("/auth/me", headers=auth_headers)
|
|
assert resp.status_code == 204
|
|
|
|
# Verify user is gone (token still valid but user deleted)
|
|
resp = await client.get("/auth/me", headers=auth_headers)
|
|
assert resp.status_code == 404
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_refresh_after_delete_fails(client):
|
|
"""Refresh token for a deleted user must be rejected."""
|
|
reg = await client.post(
|
|
"/auth/register",
|
|
json={
|
|
"email": "ghost@example.com",
|
|
"password": "securepass123",
|
|
"display_name": "Ghost User",
|
|
},
|
|
)
|
|
tokens = reg.json()
|
|
headers = {"Authorization": f"Bearer {tokens['access_token']}"}
|
|
|
|
# Delete the user
|
|
resp = await client.delete("/auth/me", headers=headers)
|
|
assert resp.status_code == 204
|
|
|
|
# Refresh token should now fail
|
|
resp = await client.post(
|
|
"/auth/refresh",
|
|
json={
|
|
"refresh_token": tokens["refresh_token"],
|
|
},
|
|
)
|
|
assert resp.status_code == 401
|