test(P14.1): add comprehensive backend API test suite

Add 134 tests as independent test project:
- test_auth.py (5): Login, JWT, protected endpoints
- test_users.py (8): User CRUD, permissions
- test_projects.py (8): Project CRUD, ownership
- test_milestones.py (7): Milestone CRUD, filtering
- test_tasks.py (8): Task CRUD, filtering
- test_comments.py (5): Comment CRUD, permissions
- test_roles.py (9): Role/permission management
- test_milestone_actions.py (17): Milestone state machine
- test_task_transitions.py (34): Task state machine
- test_propose.py (19): Propose CRUD, lifecycle
- test_misc.py (14): Notifications, activity, API keys, dashboard

Setup:
- conftest.py: SQLite in-memory DB, fixtures
- requirements.txt: Dependencies
- pyproject.toml: Pytest config
- README.md: Documentation
This commit is contained in:
zhi
2026-03-19 12:43:44 +00:00
parent 477419cb57
commit 5f6a3dffe4
29 changed files with 3117 additions and 0 deletions

100
tests/test_users.py Normal file
View File

@@ -0,0 +1,100 @@
"""P14.1 — Users API tests.
Covers:
- List users
- Get user by ID
- Create user
- Update user
- Delete user
- User self-service restrictions
"""
import pytest
class TestUsers:
"""User management endpoints."""
def test_list_users(self, client, db, make_user, auth_header, seed_roles_and_permissions):
"""Admin can list all users."""
seed_roles_and_permissions
admin = make_user(username="admin", is_admin=True)
make_user(username="user1")
make_user(username="user2")
resp = client.get("/users", headers=auth_header(admin))
assert resp.status_code == 200
data = resp.json()
assert len(data) >= 2
def test_get_user_by_id(self, client, db, make_user, auth_header, seed_roles_and_permissions):
"""Get specific user details."""
seed_roles_and_permissions
admin = make_user(username="admin", is_admin=True)
user = make_user(username="testuser")
resp = client.get(f"/users/{user.id}", headers=auth_header(admin))
assert resp.status_code == 200
data = resp.json()
assert data["id"] == user.id
assert data["username"] == "testuser"
def test_create_user(self, client, db, make_user, auth_header, seed_roles_and_permissions):
"""Admin can create new user."""
seed_roles_and_permissions
admin = make_user(username="admin", is_admin=True)
resp = client.post(
"/users",
json={
"username": "newuser",
"password": "newpass123",
"is_admin": False
},
headers=auth_header(admin)
)
assert resp.status_code == 201
data = resp.json()
assert data["username"] == "newuser"
assert "id" in data
def test_update_user(self, client, db, make_user, auth_header, seed_roles_and_permissions):
"""Admin can update user."""
seed_roles_and_permissions
admin = make_user(username="admin", is_admin=True)
user = make_user(username="testuser")
resp = client.patch(
f"/users/{user.id}",
json={"username": "updateduser"},
headers=auth_header(admin)
)
assert resp.status_code == 200
data = resp.json()
assert data["username"] == "updateduser"
def test_delete_user(self, client, db, make_user, auth_header, seed_roles_and_permissions):
"""Admin can delete user."""
seed_roles_and_permissions
admin = make_user(username="admin", is_admin=True)
user = make_user(username="testuser")
resp = client.delete(f"/users/{user.id}", headers=auth_header(admin))
assert resp.status_code == 204
def test_regular_user_cannot_list_all_users(self, client, db, make_user, auth_header, seed_roles_and_permissions):
"""Non-admin cannot list all users."""
seed_roles_and_permissions
user = make_user(username="regular")
resp = client.get("/users", headers=auth_header(user))
assert resp.status_code == 403
def test_user_can_view_self(self, client, db, make_user, auth_header, seed_roles_and_permissions):
"""User can view their own profile."""
seed_roles_and_permissions
user = make_user(username="testuser")
resp = client.get(f"/users/{user.id}", headers=auth_header(user))
assert resp.status_code == 200
data = resp.json()
assert data["id"] == user.id