import pytest async def get_token(client, username="projuser", password="pass123"): await client.post("/api/v1/auth/register", json={"username": username, "password": password}) login = await client.post("/api/v1/auth/login", json={"username": username, "password": password}) return login.json()["access_token"] @pytest.mark.asyncio async def test_create_project(client): token = await get_token(client) response = await client.post( "/api/v1/projects", json={"name": "My Project", "description": "Description"}, headers={"Authorization": f"Bearer {token}"} ) assert response.status_code == 201 data = response.json() assert data["name"] == "My Project" assert data["description"] == "Description" @pytest.mark.asyncio async def test_list_projects(client): token = await get_token(client) await client.post("/api/v1/projects", json={"name": "Project 1"}, headers={"Authorization": f"Bearer {token}"}) await client.post("/api/v1/projects", json={"name": "Project 2"}, headers={"Authorization": f"Bearer {token}"}) response = await client.get("/api/v1/projects", headers={"Authorization": f"Bearer {token}"}) assert response.status_code == 200 assert len(response.json()["projects"]) == 2 @pytest.mark.asyncio async def test_get_project(client): token = await get_token(client) create_resp = await client.post( "/api/v1/projects", json={"name": "Get Test"}, headers={"Authorization": f"Bearer {token}"} ) proj_id = create_resp.json()["id"] response = await client.get( f"/api/v1/projects/{proj_id}", headers={"Authorization": f"Bearer {token}"} ) assert response.status_code == 200 assert response.json()["name"] == "Get Test" @pytest.mark.asyncio async def test_update_project(client): token = await get_token(client) create_resp = await client.post( "/api/v1/projects", json={"name": "Original"}, headers={"Authorization": f"Bearer {token}"} ) proj_id = create_resp.json()["id"] response = await client.put( f"/api/v1/projects/{proj_id}", json={"name": "Updated"}, headers={"Authorization": f"Bearer {token}"} ) assert response.status_code == 200 assert response.json()["name"] == "Updated" @pytest.mark.asyncio async def test_patch_project(client): """Test PATCH endpoint for partial project update.""" token = await get_token(client) create_resp = await client.post( "/api/v1/projects", json={"name": "Original", "description": "Original desc"}, headers={"Authorization": f"Bearer {token}"} ) proj_id = create_resp.json()["id"] # PATCH name only response = await client.patch( f"/api/v1/projects/{proj_id}", json={"name": "Patched Name"}, headers={"Authorization": f"Bearer {token}"} ) assert response.status_code == 200 data = response.json() assert data["name"] == "Patched Name" assert data["description"] == "Original desc" # PATCH description only response = await client.patch( f"/api/v1/projects/{proj_id}", json={"description": "Patched desc"}, headers={"Authorization": f"Bearer {token}"} ) assert response.status_code == 200 data = response.json() assert data["name"] == "Patched Name" assert data["description"] == "Patched desc" @pytest.mark.asyncio async def test_soft_delete_project(client): token = await get_token(client) create_resp = await client.post( "/api/v1/projects", json={"name": "To Delete"}, headers={"Authorization": f"Bearer {token}"} ) proj_id = create_resp.json()["id"] del_resp = await client.delete( f"/api/v1/projects/{proj_id}", headers={"Authorization": f"Bearer {token}"} ) assert del_resp.status_code == 204 # Should not appear in list list_resp = await client.get("/api/v1/projects", headers={"Authorization": f"Bearer {token}"}) assert len(list_resp.json()["projects"]) == 0 @pytest.mark.asyncio async def test_restore_project(client): token = await get_token(client) create_resp = await client.post( "/api/v1/projects", json={"name": "To Restore"}, headers={"Authorization": f"Bearer {token}"} ) proj_id = create_resp.json()["id"] await client.delete(f"/api/v1/projects/{proj_id}", headers={"Authorization": f"Bearer {token}"}) restore_resp = await client.post( f"/api/v1/projects/{proj_id}/restore", headers={"Authorization": f"Bearer {token}"} ) assert restore_resp.status_code == 200 assert restore_resp.json()["name"] == "To Restore"