import uuid import pytest from fastapi.testclient import TestClient from tests.conftest import ( admin_token, approve_cloud, bearer, png_bytes, register_and_confirm, ) # --------------------------------------------------------------------------- # get profile # --------------------------------------------------------------------------- def test_get_profile(client: TestClient, monkeypatch) -> None: info = register_and_confirm( client, monkeypatch, f"prof-{uuid.uuid4().hex[:8]}@example.com", "profpass1", "资料展示", ) r = client.get(f"/api/v1/profiles/{info['user_id']}") assert r.status_code == 200 assert r.json()["username"] == "资料展示" def test_get_nonexistent_profile(client: TestClient) -> None: r = client.get(f"/api/v1/profiles/{uuid.uuid4()}") assert r.status_code == 404 # --------------------------------------------------------------------------- # update my profile # --------------------------------------------------------------------------- def test_update_me(client: TestClient, monkeypatch) -> None: info = register_and_confirm( client, monkeypatch, f"updme-{uuid.uuid4().hex[:8]}@example.com", "updmepass", "原昵称", ) r = client.patch( "/api/v1/profiles/me", headers=bearer(info["token"]), json={"username": "新昵称"}, ) assert r.status_code == 200 assert r.json()["username"] == "新昵称" def test_update_me_short_username(client: TestClient, monkeypatch) -> None: info = register_and_confirm( client, monkeypatch, f"shortname-{uuid.uuid4().hex[:8]}@example.com", "shortname", "短名字测试", ) r = client.patch( "/api/v1/profiles/me", headers=bearer(info["token"]), json={"username": "A"}, ) assert r.status_code == 422 def test_update_me_duplicate_username(client: TestClient, monkeypatch) -> None: register_and_confirm( client, monkeypatch, f"dupname-u1-{uuid.uuid4().hex[:8]}@example.com", "pass11112", "已占用的名字", ) info2 = register_and_confirm( client, monkeypatch, f"dupname-u2-{uuid.uuid4().hex[:8]}@example.com", "pass22223", "第二人", ) r = client.patch( "/api/v1/profiles/me", headers=bearer(info2["token"]), json={"username": "已占用的名字"}, ) assert r.status_code == 409 assert "昵称" in r.json()["detail"] # --------------------------------------------------------------------------- # get user clouds # --------------------------------------------------------------------------- def test_get_user_clouds_public(client: TestClient, monkeypatch) -> None: info = register_and_confirm( client, monkeypatch, f"pubcloud-{uuid.uuid4().hex[:8]}@example.com", "pubcloud1", "公开云主", ) ur = client.post( "/api/v1/clouds", headers=bearer(info["token"]), files={"image": ("cloud.png", png_bytes(), "image/png")}, data={"cloud_type_id": "1", "is_hidden": "false"}, ) approve_cloud(client, admin_token(client), ur.json()["cloud"]["id"]) r = client.get(f"/api/v1/profiles/{info['user_id']}/clouds") assert r.status_code == 200 assert r.json()["total"] >= 1 for item in r.json()["items"]: assert item["status"] == "approved" def test_get_user_clouds_as_owner(client: TestClient, monkeypatch) -> None: info = register_and_confirm( client, monkeypatch, f"owncloud-{uuid.uuid4().hex[:8]}@example.com", "owncloud1", "私有云主", ) ur = client.post( "/api/v1/clouds", headers=bearer(info["token"]), files={"image": ("cloud.png", png_bytes(), "image/png")}, data={"cloud_type_id": "1", "is_hidden": "false"}, ) approve_cloud(client, admin_token(client), ur.json()["cloud"]["id"]) r = client.get( f"/api/v1/profiles/{info['user_id']}/clouds", headers=bearer(info["token"]), ) assert r.status_code == 200 assert r.json()["total"] >= 1 def test_get_nonexistent_user_clouds(client: TestClient) -> None: r = client.get(f"/api/v1/profiles/{uuid.uuid4()}/clouds") assert r.status_code == 404 # --------------------------------------------------------------------------- # stats (admin only) # --------------------------------------------------------------------------- def test_get_user_stats_admin(client: TestClient, monkeypatch) -> None: info = register_and_confirm( client, monkeypatch, f"stats-{uuid.uuid4().hex[:8]}@example.com", "statspass", "统计用户", ) # upload one cloud and approve it, upload another pending ur1 = client.post( "/api/v1/clouds", headers=bearer(info["token"]), files={"image": ("cloud.png", png_bytes(), "image/png")}, data={"cloud_type_id": "1", "is_hidden": "false"}, ) approve_cloud(client, admin_token(client), ur1.json()["cloud"]["id"]) client.post( "/api/v1/clouds", headers=bearer(info["token"]), files={"image": ("cloud.png", png_bytes(), "image/png")}, data={"cloud_type_id": "2", "is_hidden": "false"}, ) r = client.get( f"/api/v1/profiles/{info['user_id']}/stats", headers=bearer(admin_token(client)), ) assert r.status_code == 200 body = r.json() assert body["cloud_count"] == 2 assert body["public_cloud_count"] == 1 assert body["collection_count"] == 2 assert body["username"] == "统计用户" def test_get_user_stats_non_admin(client: TestClient, monkeypatch) -> None: info = register_and_confirm( client, monkeypatch, f"stats-na-{uuid.uuid4().hex[:8]}@example.com", "statsnap", "非管理员统计", ) r = client.get( f"/api/v1/profiles/{info['user_id']}/stats", headers=bearer(info["token"]), ) assert r.status_code == 403 def test_get_user_stats_unauthenticated(client: TestClient) -> None: r = client.get(f"/api/v1/profiles/{uuid.uuid4()}/stats") assert r.status_code == 401 def test_get_user_stats_nonexistent(client: TestClient) -> None: r = client.get( f"/api/v1/profiles/{uuid.uuid4()}/stats", headers=bearer(admin_token(client)), ) assert r.status_code == 404