import pytest @pytest.mark.asyncio async def test_register_creates_user(client): response = await client.post( "/auth/register", json={"username": "medium1", "password": "spookyspooky"}, ) assert response.status_code == 201 body = response.json() assert body["username"] == "medium1" assert "id" in body assert "password" not in body @pytest.mark.asyncio async def test_register_duplicate_username_rejected(client): await client.post("/auth/register", json={"username": "medium1", "password": "spookyspooky"}) response = await client.post("/auth/register", json={"username": "medium1", "password": "anotherpass"}) assert response.status_code == 409 @pytest.mark.asyncio async def test_login_sets_cookie_and_me_returns_user(client): await client.post("/auth/register", json={"username": "medium2", "password": "spookyspooky"}) login_resp = await client.post("/auth/login", json={"username": "medium2", "password": "spookyspooky"}) assert login_resp.status_code == 200 assert "qm_session" in login_resp.cookies # secure=True cookies are only auto-attached by httpx's cookie jar to https # requests; the test transport uses base_url="http://test", so re-inject # the cookie manually to simulate what a browser talking to the real # Cloudflare-Tunnel-terminated HTTPS endpoint would do automatically. client.cookies.set("qm_session", login_resp.cookies["qm_session"]) me_resp = await client.get("/auth/me") assert me_resp.status_code == 200 assert me_resp.json()["username"] == "medium2" @pytest.mark.asyncio async def test_login_wrong_password_rejected(client): await client.post("/auth/register", json={"username": "medium3", "password": "spookyspooky"}) response = await client.post("/auth/login", json={"username": "medium3", "password": "wrongpass"}) assert response.status_code == 401 @pytest.mark.asyncio async def test_me_without_cookie_rejected(client): response = await client.get("/auth/me") assert response.status_code == 401 @pytest.mark.asyncio async def test_login_nonexistent_username_rejected(client): response = await client.post("/auth/login", json={"username": "nosuchmedium", "password": "whatever123"}) assert response.status_code == 401 @pytest.mark.asyncio async def test_logout_revokes_session_server_side(client): await client.post("/auth/register", json={"username": "medium4", "password": "spookyspooky"}) login_resp = await client.post("/auth/login", json={"username": "medium4", "password": "spookyspooky"}) raw_token = login_resp.cookies["qm_session"] # secure=True cookies aren't auto-attached over the test transport's plain # http://test base_url (see note above), so re-inject the cookie before # the logout call itself, otherwise the server never sees a session to revoke. client.cookies.set("qm_session", raw_token) logout_resp = await client.post("/auth/logout") assert logout_resp.status_code == 204 me_resp = await client.get("/auth/me") assert me_resp.status_code == 401