274 lines
12 KiB
Python
274 lines
12 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_category(client, staff: dict[str, str]) -> None:
|
|
listed = client.get("/api/admin/about/articles/institution_directories", 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_institution_directory_publish_filter_placeholder_and_attachment(client):
|
|
if not _minio_ready():
|
|
pytest.skip("MinIO 不可达")
|
|
staff = _headers("staff")
|
|
article_ids: list[int] = []
|
|
file_ids: list[int] = []
|
|
try:
|
|
_clear_category(client, staff)
|
|
|
|
empty = client.get("/api/site/about/articles/institution_directories")
|
|
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\nroster", "application/pdf")},
|
|
)
|
|
assert pdf.status_code == 200, pdf.text
|
|
file_ids.append(pdf.json()["id"])
|
|
|
|
created = client.post(
|
|
"/api/admin/home/articles",
|
|
headers=staff,
|
|
json={
|
|
"category": "institution_directories",
|
|
"title": "甘肃省房地产价格评估行业协会单位会员名录(2025年6月)",
|
|
"publishedAt": "2025-06-05T08:00:00",
|
|
"published": True,
|
|
"bodyHtml": (
|
|
"<p>兰州市</p><table><tr><td>甘肃中瑞房地产资产评估有限公司</td></tr></table>"
|
|
"<script>alert(1)</script>"
|
|
),
|
|
"attachmentFileIds": [file_ids[0]],
|
|
},
|
|
)
|
|
assert created.status_code == 200, created.text
|
|
article_ids.append(created.json()["id"])
|
|
|
|
draft = client.post(
|
|
"/api/admin/home/articles",
|
|
headers=staff,
|
|
json={
|
|
"category": "institution_directories",
|
|
"title": "未发布名录",
|
|
"publishedAt": "2025-06-06T08:00:00",
|
|
"published": False,
|
|
"bodyHtml": "<p>未发布名录</p>",
|
|
"attachmentFileIds": [],
|
|
},
|
|
)
|
|
assert draft.status_code == 200, draft.text
|
|
article_ids.append(draft.json()["id"])
|
|
|
|
listed = client.get("/api/site/about/articles/institution_directories")
|
|
assert listed.status_code == 200, listed.text
|
|
assert "甘肃省房地产价格评估行业协会单位会员名录(2025年6月)" in listed.text
|
|
assert "未发布名录" not in listed.text
|
|
assert "暂无机构名录" not in listed.text
|
|
|
|
detail = client.get(f"/api/site/home/articles/{article_ids[0]}")
|
|
assert detail.status_code == 200, detail.text
|
|
body = detail.json()["bodyHtml"]
|
|
assert "甘肃中瑞房地产资产评估有限公司" in body
|
|
assert "table" in body.lower()
|
|
lowered = body.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/home/articles/{article_ids[1]}")
|
|
assert hidden.status_code == 404
|
|
|
|
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 "institution_directories" not in categories
|
|
|
|
before = client.get("/api/site/about/articles/institution_directories").text
|
|
rejected = client.post(
|
|
"/api/admin/home/articles",
|
|
headers=_headers("member"),
|
|
json={
|
|
"category": "institution_directories",
|
|
"title": "会员不得发布名录",
|
|
"published": True,
|
|
"bodyHtml": "<p>会员不得发布名录</p>",
|
|
"attachmentFileIds": [],
|
|
},
|
|
)
|
|
assert rejected.status_code in (401, 403)
|
|
after = client.get("/api/site/about/articles/institution_directories")
|
|
assert after.text == before
|
|
assert "会员不得发布名录" not in after.text
|
|
|
|
renamed = client.put(
|
|
f"/api/admin/home/articles/{article_ids[0]}",
|
|
headers=staff,
|
|
json={
|
|
"category": "institution_directories",
|
|
"title": "甘肃省房地产价格评估行业协会单位会员名录(2025年6月修订)",
|
|
"publishedAt": "2025-06-05T08:00:00",
|
|
"published": True,
|
|
"bodyHtml": "<p>兰州市</p><table><tr><td>甘肃中瑞房地产资产评估有限公司</td></tr></table>",
|
|
"attachmentFileIds": [file_ids[0]],
|
|
},
|
|
)
|
|
assert renamed.status_code == 200, renamed.text
|
|
revised = client.get("/api/site/about/articles/institution_directories")
|
|
assert "单位会员名录(2025年6月修订)" in revised.text
|
|
assert "单位会员名录(2025年6月)" not in revised.text.replace("单位会员名录(2025年6月修订)", "")
|
|
|
|
deleted = client.delete(f"/api/admin/home/articles/{article_ids[0]}", headers=staff)
|
|
assert deleted.status_code in (200, 204), deleted.text
|
|
article_ids.remove(article_ids[0])
|
|
gone = client.get("/api/site/about/articles/institution_directories")
|
|
assert "单位会员名录(2025年6月修订)" not in gone.text
|
|
assert "暂无机构名录" in gone.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_institution_directory_public_pagination(client):
|
|
if not _minio_ready():
|
|
pytest.skip("MinIO 不可达")
|
|
staff = _headers("staff")
|
|
article_ids: list[int] = []
|
|
try:
|
|
_clear_category(client, staff)
|
|
for index in range(11):
|
|
created = client.post(
|
|
"/api/admin/home/articles",
|
|
headers=staff,
|
|
json={
|
|
"category": "institution_directories",
|
|
"title": f"名录分页样例-{index:02d}",
|
|
"publishedAt": f"2026-03-{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/institution_directories?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/institution_directories?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/institution_directories?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/institution_directories?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)
|
|
|
|
|
|
PUBLISHED_TITLES = [
|
|
"甘肃省房地产价格评估行业协会单位会员名录(2025年6月)",
|
|
"甘肃省房地产价格评估行业协会个人会员名录(2025年5月)",
|
|
"甘肃省房地产价格评估行业协会个人会员名录(2023年6月)",
|
|
"甘肃省房地产价格评估行业协会单位会员名录(2023年6月)",
|
|
"甘肃省房地产价格评估行业协会估价师个人会员名录(2022年4月)",
|
|
"甘肃省房地产价格评估行业协会单位会员名录(2022年4月)",
|
|
"甘肃省房地产价格评估行业协会估价师个人会员名录(2021年7月)",
|
|
"甘肃省房地产价格评估行业协会估价师单位会员名录(2021年7月)",
|
|
"甘肃省房地产价格评估行业协会估价师个人会员名录(2021年5月)",
|
|
"甘肃省房地产价格评估行业协会单位会员名录(2021年5月)",
|
|
"甘肃省房地产价格评估行业协会估价师个人会员名录(2020年)",
|
|
"甘肃省房地产价格评估行业协会单位会员名录(2020年)",
|
|
"甘肃省最低收费备案标准名单",
|
|
"甘肃省住房和城乡建设厅关于公布甘肃省房地产估价机构名录的通知",
|
|
"甘肃省房地产价格评估行业协会单位会员名录",
|
|
"甘肃省房地产价格评估行业协会估价师个人会员名录(2019年)",
|
|
]
|
|
|
|
|
|
def test_institution_directory_import_keeps_titles_and_is_idempotent(client):
|
|
staff = _headers("staff")
|
|
from app.commands.import_institution_directories import import_institution_directories
|
|
from app.db import SessionLocal
|
|
|
|
db = SessionLocal()
|
|
try:
|
|
_clear_category(client, staff)
|
|
import_institution_directories(db)
|
|
listed = client.get("/api/site/about/articles/institution_directories?current=1&size=20")
|
|
assert listed.status_code == 200, listed.text
|
|
body = listed.json()
|
|
assert body["total"] == 16
|
|
assert [item["title"] for item in body["items"]] == PUBLISHED_TITLES
|
|
detail = client.get(f"/api/site/home/articles/{body['items'][0]['id']}")
|
|
assert detail.status_code == 200, detail.text
|
|
assert "甘肃中瑞房地产资产评估有限公司" in detail.json()["bodyHtml"]
|
|
assert "table" in detail.json()["bodyHtml"].lower()
|
|
|
|
import_institution_directories(db)
|
|
again = client.get("/api/site/about/articles/institution_directories?current=1&size=20")
|
|
assert again.status_code == 200, again.text
|
|
titles = [item["title"] for item in again.json()["items"]]
|
|
assert titles == PUBLISHED_TITLES
|
|
assert len(titles) == len(set(titles))
|
|
finally:
|
|
db.close()
|
|
_clear_category(client, staff)
|