Files
gsfdc/server/tests/test_about_column_articles.py
T

227 lines
8.8 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 _clear_column_category(client, staff: dict[str, str], category: str) -> None:
listed = client.get(f"/api/admin/about/articles/{category}", headers=staff)
assert listed.status_code == 200, listed.text
for item in listed.json().get("items") or []:
deleted = client.delete(f"/api/admin/home/articles/{item['id']}", headers=staff)
assert deleted.status_code in (200, 204), deleted.text
def test_column_articles_publish_filter_and_placeholders(client):
if not _minio_ready():
pytest.skip("MinIO 不可达")
staff = _headers("staff")
article_ids: list[int] = []
file_ids: list[int] = []
try:
for category in ("work_briefs", "annual_reports", "qualifications"):
_clear_column_category(client, staff, category)
empty_briefs = client.get("/api/site/about/articles/work_briefs")
assert empty_briefs.status_code == 200, empty_briefs.text
assert "暂无工作简报" in empty_briefs.text
assert "暂无年度报告或工作计划" in client.get("/api/site/about/articles/annual_reports").text
assert "暂无资质与荣誉" in client.get("/api/site/about/articles/qualifications").text
pdf = client.post(
"/api/admin/files",
headers=staff,
data={"bucket": "public"},
files={"file": ("批复扫描件.pdf", b"%PDF-1.4\nscan", "application/pdf")},
)
assert pdf.status_code == 200, pdf.text
file_ids.append(pdf.json()["id"])
report = client.post(
"/api/admin/home/articles",
headers=staff,
json={
"category": "annual_reports",
"title": "2025年协会工作报告",
"publishedAt": "2026-01-15T08:00:00",
"published": True,
"bodyHtml": "<p>公开公示版</p><script>alert(1)</script>",
"attachmentFileIds": [],
},
)
assert report.status_code == 200, report.text
article_ids.append(report.json()["id"])
draft = client.post(
"/api/admin/home/articles",
headers=staff,
json={
"category": "annual_reports",
"title": "内部财务稿",
"publishedAt": "2026-01-16T08:00:00",
"published": False,
"bodyHtml": "<p>内部财务稿</p>",
"attachmentFileIds": [],
},
)
assert draft.status_code == 200, draft.text
article_ids.append(draft.json()["id"])
honor = client.post(
"/api/admin/home/articles",
headers=staff,
json={
"category": "qualifications",
"title": "主管单位批复文件",
"publishedAt": "2024-03-01T08:00:00",
"published": True,
"bodyHtml": "<p>批复摘要</p>",
"attachmentFileIds": [file_ids[0]],
},
)
assert honor.status_code == 200, honor.text
article_ids.append(honor.json()["id"])
reports = client.get("/api/site/about/articles/annual_reports")
assert reports.status_code == 200, reports.text
assert "2025年协会工作报告" in reports.text
assert "内部财务稿" not in reports.text
assert "暂无年度报告或工作计划" not in reports.text
detail = client.get(f"/api/site/home/articles/{article_ids[0]}")
assert detail.status_code == 200, detail.text
body = detail.json()["bodyHtml"].lower()
assert "公开公示版" in detail.json()["bodyHtml"]
assert "script" not in body
assert "alert" not in body
hidden = client.get(f"/api/site/home/articles/{article_ids[1]}")
assert hidden.status_code == 404
honors = client.get("/api/site/about/articles/qualifications")
assert honors.status_code == 200, honors.text
assert "主管单位批复文件" in honors.text
honor_detail = client.get(f"/api/site/home/articles/{article_ids[2]}")
assert honor_detail.status_code == 200, honor_detail.text
assert [item["filename"] for item in honor_detail.json()["attachments"]] == ["批复扫描件.pdf"]
home = client.get("/api/site/home")
assert home.status_code == 200, home.text
home_json = home.json()
assert "annual_reports" not in home_json
assert "work_briefs" not in home_json
assert "qualifications" not in home_json
assert "2025年协会工作报告" not in home.text
editor = client.get("/api/admin/home", headers=staff)
assert editor.status_code == 200, editor.text
categories = {item["category"] for item in editor.json()["articles"]}
assert "annual_reports" not in categories
assert "work_briefs" not in categories
assert "qualifications" not in categories
rejected = client.post(
"/api/admin/home/articles",
headers=_headers("member"),
json={
"category": "work_briefs",
"title": "会员不得发布",
"published": True,
"bodyHtml": "<p>x</p>",
"attachmentFileIds": [],
},
)
assert rejected.status_code in (401, 403)
assert "会员不得发布" not in client.get("/api/site/about/articles/work_briefs").text
assert "暂无工作简报" in client.get("/api/site/about/articles/work_briefs").text
finally:
for article_id in article_ids:
client.delete(f"/api/admin/home/articles/{article_id}", headers=staff)
for file_id in file_ids:
client.delete(f"/api/admin/files/{file_id}", headers=staff)
def test_column_articles_public_pagination(client):
if not _minio_ready():
pytest.skip("MinIO 不可达")
staff = _headers("staff")
article_ids: list[int] = []
try:
_clear_column_category(client, staff, "work_briefs")
for index in range(11):
created = client.post(
"/api/admin/home/articles",
headers=staff,
json={
"category": "work_briefs",
"title": f"简报分页样例-{index:02d}",
"publishedAt": f"2026-02-{index + 1:02d}T08:00:00",
"published": True,
"bodyHtml": f"<p>简报分页样例-{index:02d}</p>",
"attachmentFileIds": [],
},
)
assert created.status_code == 200, created.text
article_ids.append(created.json()["id"])
page1 = client.get("/api/site/about/articles/work_briefs?current=1&size=10")
assert page1.status_code == 200, page1.text
body1 = page1.json()
assert body1["total"] == 11
assert body1["current"] == 1
assert body1["size"] == 10
assert len(body1["items"]) == 10
assert body1["items"][0]["title"] == "简报分页样例-10"
page2 = client.get("/api/site/about/articles/work_briefs?current=2&size=10")
assert page2.status_code == 200, page2.text
body2 = page2.json()
assert body2["total"] == 11
assert body2["current"] == 2
assert len(body2["items"]) == 1
assert body2["items"][0]["title"] == "简报分页样例-00"
size20 = client.get("/api/site/about/articles/work_briefs?current=1&size=20")
assert size20.status_code == 200, size20.text
assert size20.json()["size"] == 20
assert len(size20.json()["items"]) == 11
bad_size = client.get("/api/site/about/articles/work_briefs?current=1&size=15")
assert bad_size.status_code == 200, bad_size.text
assert bad_size.json()["size"] == 10
assert len(bad_size.json()["items"]) == 10
finally:
for article_id in article_ids:
client.delete(f"/api/admin/home/articles/{article_id}", headers=staff)