149 lines
5.3 KiB
Python
149 lines
5.3 KiB
Python
"""专家委员会:工作人员写入 → 门户公开读取。"""
|
|
|
|
import pytest
|
|
from fastapi.testclient import TestClient
|
|
|
|
from app.core.config import get_settings
|
|
from app.core.security import create_access_token
|
|
|
|
|
|
@pytest.fixture
|
|
def client(monkeypatch):
|
|
monkeypatch.setenv("JWT_SECRET", "test-secret-must-be-32-characters!")
|
|
monkeypatch.setenv("API_PAYLOAD_ENCRYPT", "false")
|
|
get_settings.cache_clear()
|
|
if not get_settings().database_url.strip():
|
|
pytest.skip("DATABASE_URL 为空")
|
|
from app.main import create_app
|
|
|
|
with TestClient(create_app()) as api:
|
|
yield api
|
|
get_settings.cache_clear()
|
|
|
|
|
|
def _headers(token_type: str) -> dict[str, str]:
|
|
return {"Authorization": f"Bearer {create_access_token('1', token_type)}"}
|
|
|
|
|
|
def _minio_ready() -> bool:
|
|
try:
|
|
from app.services.storage import ensure_buckets
|
|
|
|
ensure_buckets()
|
|
return True
|
|
except Exception:
|
|
return False
|
|
|
|
|
|
def test_expert_committees_list_detail_delete_and_placeholder(client):
|
|
if not _minio_ready():
|
|
pytest.skip("MinIO 不可达")
|
|
staff = _headers("staff")
|
|
ids: list[int] = []
|
|
file_id = None
|
|
try:
|
|
empty = client.get("/api/site/about/experts")
|
|
assert empty.status_code == 200, empty.text
|
|
assert "暂无专家委员会信息" in empty.text
|
|
|
|
pdf = client.post(
|
|
"/api/admin/files",
|
|
headers=staff,
|
|
data={"bucket": "public"},
|
|
files={"file": ("专家名录.pdf", b"%PDF-1.4\nexperts", "application/pdf")},
|
|
)
|
|
assert pdf.status_code == 200, pdf.text
|
|
file_id = pdf.json()["id"]
|
|
|
|
first = client.post(
|
|
"/api/admin/about/experts",
|
|
headers=staff,
|
|
json={
|
|
"name": "房地产估价专家委员会",
|
|
"bodyHtml": "<p>估价技术咨询</p><script>alert(1)</script>",
|
|
"sortOrder": 1,
|
|
"published": True,
|
|
"attachmentFileIds": [file_id],
|
|
},
|
|
)
|
|
assert first.status_code == 200, first.text
|
|
ids.append(first.json()["id"])
|
|
|
|
second = client.post(
|
|
"/api/admin/about/experts",
|
|
headers=staff,
|
|
json={
|
|
"name": "行业自律专家委员会",
|
|
"bodyHtml": "<p>自律意见</p>",
|
|
"sortOrder": 2,
|
|
"published": True,
|
|
"attachmentFileIds": [],
|
|
},
|
|
)
|
|
assert second.status_code == 200, second.text
|
|
ids.append(second.json()["id"])
|
|
|
|
draft = client.post(
|
|
"/api/admin/about/experts",
|
|
headers=staff,
|
|
json={
|
|
"name": "内部筹备组",
|
|
"bodyHtml": "<p>内部</p>",
|
|
"sortOrder": 0,
|
|
"published": False,
|
|
"attachmentFileIds": [],
|
|
},
|
|
)
|
|
assert draft.status_code == 200, draft.text
|
|
ids.append(draft.json()["id"])
|
|
|
|
listing = client.get("/api/site/about/experts")
|
|
assert listing.status_code == 200, listing.text
|
|
names = [item["name"] for item in listing.json()["items"]]
|
|
assert names == ["房地产估价专家委员会", "行业自律专家委员会"]
|
|
assert "内部筹备组" not in listing.text
|
|
|
|
detail = client.get(f"/api/site/about/experts/{ids[0]}")
|
|
assert detail.status_code == 200, detail.text
|
|
assert "估价技术咨询" in detail.json()["bodyHtml"]
|
|
lowered = detail.json()["bodyHtml"].lower()
|
|
assert "script" not in lowered
|
|
assert "alert" not in lowered
|
|
assert [item["filename"] for item in detail.json()["attachments"]] == ["专家名录.pdf"]
|
|
|
|
hidden = client.get(f"/api/site/about/experts/{ids[2]}")
|
|
assert hidden.status_code == 404
|
|
|
|
deleted = client.delete(f"/api/admin/about/experts/{ids[1]}", headers=staff)
|
|
assert deleted.status_code == 200, deleted.text
|
|
ids.remove(ids[1])
|
|
after = client.get("/api/site/about/experts")
|
|
assert "行业自律专家委员会" not in after.text
|
|
assert "房地产估价专家委员会" in after.text
|
|
|
|
rejected = client.post(
|
|
"/api/admin/about/experts",
|
|
headers=_headers("member"),
|
|
json={
|
|
"name": "会员委员会",
|
|
"bodyHtml": "<p>x</p>",
|
|
"sortOrder": 9,
|
|
"published": True,
|
|
"attachmentFileIds": [],
|
|
},
|
|
)
|
|
assert rejected.status_code in (401, 403)
|
|
assert "会员委员会" not in client.get("/api/site/about/experts").text
|
|
finally:
|
|
for expert_id in list(ids):
|
|
client.delete(f"/api/admin/about/experts/{expert_id}", headers=staff)
|
|
leftover = client.get("/api/site/about/experts")
|
|
# clean any published leftovers from failed runs
|
|
admin_list = client.get("/api/admin/about/experts", headers=staff)
|
|
if admin_list.status_code == 200:
|
|
for item in admin_list.json().get("items", []):
|
|
client.delete(f"/api/admin/about/experts/{item['id']}", headers=staff)
|
|
assert "暂无专家委员会信息" in client.get("/api/site/about/experts").text
|
|
if file_id is not None:
|
|
client.delete(f"/api/admin/files/{file_id}", headers=staff)
|