import pytest from httpx import ASGITransport, AsyncClient from app.main import app @pytest.mark.asyncio async def test_invite_and_accept_flow(client, auth_headers): # Invite a new user r = await client.post( "/api/users/invite", headers=auth_headers, json={"email": "mecanic@service.ro", "rol": "mecanic"}, ) assert r.status_code == 200 data = r.json() assert "token" in data assert data["email"] == "mecanic@service.ro" invite_token = data["token"] # Accept invite (creates user + returns JWT) r = await client.post( "/api/auth/accept-invite", json={"token": invite_token, "password": "mecanic123"}, ) assert r.status_code == 200 data = r.json() assert "access_token" in data assert data["token_type"] == "bearer" # New user can access /me new_headers = {"Authorization": f"Bearer {data['access_token']}"} r = await client.get("/api/auth/me", headers=new_headers) assert r.status_code == 200 me = r.json() assert me["email"] == "mecanic@service.ro" assert me["rol"] == "mecanic" @pytest.mark.asyncio async def test_list_users(client, auth_headers): r = await client.get("/api/users", headers=auth_headers) assert r.status_code == 200 users = r.json() assert len(users) >= 1 assert users[0]["rol"] == "owner" @pytest.mark.asyncio async def test_deactivate_user(client, auth_headers): # Invite and accept a user first r = await client.post( "/api/users/invite", headers=auth_headers, json={"email": "delete@service.ro", "rol": "mecanic"}, ) invite_token = r.json()["token"] await client.post( "/api/auth/accept-invite", json={"token": invite_token, "password": "pass123"}, ) # List users to get the new user's id r = await client.get("/api/users", headers=auth_headers) users = r.json() mecanic = next(u for u in users if u["email"] == "delete@service.ro") # Deactivate r = await client.delete( f"/api/users/{mecanic['id']}", headers=auth_headers ) assert r.status_code == 200 assert r.json()["ok"] is True @pytest.mark.asyncio async def test_cannot_deactivate_owner(client, auth_headers): r = await client.get("/api/users", headers=auth_headers) users = r.json() owner = next(u for u in users if u["rol"] == "owner") r = await client.delete( f"/api/users/{owner['id']}", headers=auth_headers ) assert r.status_code == 422 @pytest.mark.asyncio async def test_invalid_invite_token(client): r = await client.post( "/api/auth/accept-invite", json={"token": "invalid-token", "password": "pass123"}, ) assert r.status_code == 422 @pytest.mark.asyncio async def test_duplicate_invite(client, auth_headers): # Invite same email twice - first should succeed, second may fail if user exists await client.post( "/api/users/invite", headers=auth_headers, json={"email": "dup@service.ro", "rol": "mecanic"}, ) # Second invite for same email is allowed (user not created yet) r = await client.post( "/api/users/invite", headers=auth_headers, json={"email": "dup@service.ro", "rol": "admin"}, ) assert r.status_code == 200