feature: create multitasking
This commit is contained in:
@@ -0,0 +1,212 @@
|
||||
"""
|
||||
Tests for user management endpoints.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import uuid
|
||||
|
||||
import pytest
|
||||
from httpx import AsyncClient
|
||||
|
||||
from cpv3.modules.users.models import User
|
||||
|
||||
|
||||
class TestListUsersEndpoint:
|
||||
"""Tests for GET /api/users/."""
|
||||
|
||||
async def test_list_users_authenticated(
|
||||
self, auth_client: AsyncClient, test_user: User
|
||||
):
|
||||
"""Test listing users as authenticated user."""
|
||||
response = await auth_client.get("/api/users/")
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert isinstance(data, list)
|
||||
|
||||
async def test_list_users_unauthenticated(self, async_client: AsyncClient):
|
||||
"""Test listing users without auth returns 401."""
|
||||
response = await async_client.get("/api/users/")
|
||||
|
||||
assert response.status_code == 401
|
||||
|
||||
|
||||
class TestCreateUserEndpoint:
|
||||
"""Tests for POST /api/users/."""
|
||||
|
||||
async def test_create_user_as_staff(self, staff_client: AsyncClient):
|
||||
"""Test staff can create a new user."""
|
||||
response = await staff_client.post(
|
||||
"/api/users/",
|
||||
json={
|
||||
"username": "newcreateduser",
|
||||
"email": "newcreated@example.com",
|
||||
"password": "password123",
|
||||
"first_name": "New",
|
||||
"last_name": "Created",
|
||||
},
|
||||
)
|
||||
|
||||
assert response.status_code == 201
|
||||
data = response.json()
|
||||
assert data["username"] == "newcreateduser"
|
||||
assert data["email"] == "newcreated@example.com"
|
||||
|
||||
async def test_create_user_unauthenticated(self, async_client: AsyncClient):
|
||||
"""Test creating user without auth returns 401."""
|
||||
response = await async_client.post(
|
||||
"/api/users/",
|
||||
json={
|
||||
"username": "newuser",
|
||||
"email": "new@example.com",
|
||||
"password": "password123",
|
||||
},
|
||||
)
|
||||
|
||||
assert response.status_code == 401
|
||||
|
||||
|
||||
class TestMeEndpoint:
|
||||
"""Tests for GET /api/users/me/."""
|
||||
|
||||
async def test_me_returns_current_user(
|
||||
self, auth_client: AsyncClient, test_user: User
|
||||
):
|
||||
"""Test getting current user info."""
|
||||
response = await auth_client.get("/api/users/me/")
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["username"] == test_user.username
|
||||
assert data["email"] == test_user.email
|
||||
assert data["id"] == str(test_user.id)
|
||||
|
||||
async def test_me_unauthenticated(self, async_client: AsyncClient):
|
||||
"""Test getting current user without auth returns 401."""
|
||||
response = await async_client.get("/api/users/me/")
|
||||
|
||||
assert response.status_code == 401
|
||||
|
||||
|
||||
class TestRetrieveUserEndpoint:
|
||||
"""Tests for GET /api/users/{user_id}/."""
|
||||
|
||||
async def test_retrieve_own_user(self, auth_client: AsyncClient, test_user: User):
|
||||
"""Test user can retrieve their own info."""
|
||||
response = await auth_client.get(f"/api/users/{test_user.id}/")
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["id"] == str(test_user.id)
|
||||
assert data["username"] == test_user.username
|
||||
|
||||
async def test_retrieve_other_user_as_staff(
|
||||
self, staff_client: AsyncClient, test_user: User
|
||||
):
|
||||
"""Test staff can retrieve other user's info."""
|
||||
response = await staff_client.get(f"/api/users/{test_user.id}/")
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["id"] == str(test_user.id)
|
||||
|
||||
async def test_retrieve_nonexistent_user(self, auth_client: AsyncClient):
|
||||
"""Test retrieving nonexistent user returns 404."""
|
||||
fake_id = uuid.uuid4()
|
||||
response = await auth_client.get(f"/api/users/{fake_id}/")
|
||||
|
||||
assert response.status_code == 404
|
||||
assert response.json()["detail"] == "Not found"
|
||||
|
||||
async def test_retrieve_other_user_forbidden(
|
||||
self, auth_client: AsyncClient, other_user: User
|
||||
):
|
||||
"""Test regular user cannot retrieve other user's info."""
|
||||
response = await auth_client.get(f"/api/users/{other_user.id}/")
|
||||
|
||||
assert response.status_code == 403
|
||||
assert response.json()["detail"] == "Forbidden"
|
||||
|
||||
|
||||
class TestPatchUserEndpoint:
|
||||
"""Tests for PATCH /api/users/{user_id}/."""
|
||||
|
||||
async def test_patch_own_user(self, auth_client: AsyncClient, test_user: User):
|
||||
"""Test user can update their own info."""
|
||||
response = await auth_client.patch(
|
||||
f"/api/users/{test_user.id}/",
|
||||
json={"first_name": "Updated", "last_name": "Name"},
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["first_name"] == "Updated"
|
||||
assert data["last_name"] == "Name"
|
||||
|
||||
async def test_patch_other_user_as_staff(
|
||||
self, staff_client: AsyncClient, test_user: User
|
||||
):
|
||||
"""Test staff can update other user's info."""
|
||||
response = await staff_client.patch(
|
||||
f"/api/users/{test_user.id}/",
|
||||
json={"first_name": "StaffUpdated"},
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["first_name"] == "StaffUpdated"
|
||||
|
||||
async def test_patch_nonexistent_user(self, auth_client: AsyncClient):
|
||||
"""Test patching nonexistent user returns 404."""
|
||||
fake_id = uuid.uuid4()
|
||||
response = await auth_client.patch(
|
||||
f"/api/users/{fake_id}/",
|
||||
json={"first_name": "Test"},
|
||||
)
|
||||
|
||||
assert response.status_code == 404
|
||||
|
||||
async def test_patch_other_user_forbidden(
|
||||
self, auth_client: AsyncClient, other_user: User
|
||||
):
|
||||
"""Test regular user cannot update other user's info."""
|
||||
response = await auth_client.patch(
|
||||
f"/api/users/{other_user.id}/",
|
||||
json={"first_name": "Hacked"},
|
||||
)
|
||||
|
||||
assert response.status_code == 403
|
||||
|
||||
|
||||
class TestDeleteUserEndpoint:
|
||||
"""Tests for DELETE /api/users/{user_id}/."""
|
||||
|
||||
async def test_delete_own_user(self, auth_client: AsyncClient, test_user: User):
|
||||
"""Test user can delete (deactivate) their own account."""
|
||||
response = await auth_client.delete(f"/api/users/{test_user.id}/")
|
||||
|
||||
assert response.status_code == 204
|
||||
|
||||
async def test_delete_other_user_as_staff(
|
||||
self, staff_client: AsyncClient, test_user: User
|
||||
):
|
||||
"""Test staff can delete other user's account."""
|
||||
response = await staff_client.delete(f"/api/users/{test_user.id}/")
|
||||
|
||||
assert response.status_code == 204
|
||||
|
||||
async def test_delete_nonexistent_user(self, auth_client: AsyncClient):
|
||||
"""Test deleting nonexistent user returns 404."""
|
||||
fake_id = uuid.uuid4()
|
||||
response = await auth_client.delete(f"/api/users/{fake_id}/")
|
||||
|
||||
assert response.status_code == 404
|
||||
|
||||
async def test_delete_other_user_forbidden(
|
||||
self, auth_client: AsyncClient, other_user: User
|
||||
):
|
||||
"""Test regular user cannot delete other user's account."""
|
||||
response = await auth_client.delete(f"/api/users/{other_user.id}/")
|
||||
|
||||
assert response.status_code == 403
|
||||
Reference in New Issue
Block a user