Files

1016 lines
37 KiB
Python

import httpx
import pytest
from fastapi import HTTPException
from fastapi.testclient import TestClient
from minio.error import S3Error
import urllib3
from app.core.config import get_settings
from app.core.security import create_access_token
_PLACEHOLDERS = (
"协会定位整理中",
"价值主张整理中",
"轮播内容准备中",
"新闻动态即将发布",
"暂无新的通知公告",
"政策法规整理中",
"数据看板整理中",
"估价师、机构与公众入口即将开放",
"报告查询、报告审核与投诉举报入口即将开放",
"协会荣誉与资质整理中",
"会员单位名录整理中",
"办公地址整理中",
"联系电话整理中",
"联系邮箱整理中",
"地图位置整理中",
"主管部门链接整理中",
"相关部门链接整理中",
"合作协会链接整理中",
"隐私政策、使用条款与网站声明整理中",
)
@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 _template_state(api: TestClient, headers: dict[str, str]) -> dict:
body = api.get("/api/admin/home", headers=headers)
assert body.status_code == 200, body.text
data = body.json()
return {
"activeTemplate": data["activeTemplate"],
"templates": [
{
"name": item["name"],
"slogan": item["slogan"],
"valueProposition": item["valueProposition"],
}
for item in data["templates"]
],
}
def _restore_templates(api: TestClient, headers: dict[str, str], state: dict) -> None:
api.put("/api/admin/home", headers=headers, json=state)
def _headers(token_type: str) -> dict[str, str]:
token = create_access_token("1", token_type)
return {"Authorization": f"Bearer {token}"}
def _write(api: TestClient, headers: dict[str, str]):
return api.put(
"/api/admin/home",
headers=headers,
json={
"activeTemplate": "LOGO蓝",
"templates": [
{
"name": "科技蓝",
"slogan": "科技蓝模板标语",
"valueProposition": "科技蓝价值主张",
},
{
"name": "LOGO蓝",
"slogan": "服务甘肃房地产估价",
"valueProposition": "公开、专业、可核验",
},
],
},
)
def test_public_home_returns_only_the_active_template(client):
headers = _headers("staff")
previous = _template_state(client, headers)
saved = _write(client, headers)
assert saved.status_code == 200, saved.text
response = client.get("/api/site/home")
assert response.status_code == 200, response.text
body = response.json()
assert body["templateName"] == "LOGO蓝"
assert body["slogan"] == "服务甘肃房地产估价"
assert body["valueProposition"] == "公开、专业、可核验"
text = response.text
assert "科技蓝模板标语" not in text
assert "科技蓝价值主张" not in text
assert "陇ICP备19001227号" in text
assert "甘公网安备62010202001984号" in text
for sentence in _PLACEHOLDERS:
if sentence in ("协会定位整理中", "价值主张整理中"):
continue
assert sentence in text
before = client.get("/api/site/home").json()
rejected = _write(client, _headers("member"))
assert rejected.status_code == 403
after = client.get("/api/site/home").json()
assert after["slogan"] == before["slogan"] == "服务甘肃房地产估价"
assert "科技蓝模板标语" not in client.get("/api/site/home").text
settings = client.get("/api/site/settings")
assert settings.status_code == 200
assert "templateName" not in settings.json()
assert "服务甘肃房地产估价" not in settings.text
_restore_templates(client, headers, previous)
def _minio_ready() -> bool:
from app.services.storage import ensure_buckets
try:
ensure_buckets()
except (urllib3.exceptions.HTTPError, OSError, TimeoutError, HTTPException, S3Error):
return False
return True
def test_published_carousel_detail_is_public_and_draft_is_hidden(client):
if not _minio_ready():
pytest.skip("MinIO 不可达")
headers = _headers("staff")
previous = _template_state(client, headers)
saved = _write(client, headers)
assert saved.status_code == 200, saved.text
image_bytes = b"\x89PNG\r\n\x1a\ncarousel"
pdf_bytes = b"%PDF-1.4\nplan"
image_id = None
pdf_id = None
slide_id = None
draft_id = None
try:
image = client.post(
"/api/admin/files",
headers=headers,
data={"bucket": "public"},
files={"file": ("cover.png", image_bytes, "image/png")},
)
assert image.status_code == 200, image.text
image_id = image.json()["id"]
attachment = client.post(
"/api/admin/files",
headers=headers,
data={"bucket": "public"},
files={"file": ("计划.pdf", pdf_bytes, "application/pdf")},
)
assert attachment.status_code == 200, attachment.text
pdf_id = attachment.json()["id"]
created = client.post(
"/api/admin/home/slides",
headers=headers,
json={
"title": "估价师继续教育通知",
"imageFileId": image_id,
"sortOrder": 1,
"enabled": True,
"intervalSeconds": 6,
"published": True,
"bodyHtml": "<p>请按计划参加</p><script>alert(1)</script>",
"attachmentFileIds": [pdf_id],
},
)
assert created.status_code == 200, created.text
slide_id = created.json()["id"]
draft = client.post(
"/api/admin/home/slides",
headers=headers,
json={
"title": "内部草稿",
"imageFileId": image_id,
"sortOrder": 0,
"enabled": True,
"intervalSeconds": 6,
"published": False,
"bodyHtml": "<p>内部草稿</p>",
"attachmentFileIds": [],
},
)
assert draft.status_code == 200, draft.text
draft_id = draft.json()["id"]
home = client.get("/api/site/home")
assert home.status_code == 200, home.text
assert "内部草稿" not in home.text
assert "轮播内容准备中" not in home.text
items = home.json()["carousel"]["items"]
assert [item["title"] for item in items] == ["估价师继续教育通知"]
assert items[0]["intervalSeconds"] == 6
assert items[0]["id"] == slide_id
image_download = httpx.get(items[0]["imageUrl"], timeout=5.0, follow_redirects=True)
assert image_download.status_code == 200
assert image_download.content == image_bytes
detail = client.get(f"/api/site/home/slides/{slide_id}")
assert detail.status_code == 200, detail.text
body = detail.json()
assert "请按计划参加" in body["bodyHtml"]
lowered = body["bodyHtml"].lower()
assert "script" not in lowered
assert "alert" not in lowered
assert body["attachments"] == [
{"filename": "计划.pdf", "url": body["attachments"][0]["url"]}
]
downloaded = httpx.get(body["attachments"][0]["url"], timeout=5.0, follow_redirects=True)
assert downloaded.status_code == 200
assert downloaded.content == pdf_bytes
hidden = client.get(f"/api/site/home/slides/{draft_id}")
assert hidden.status_code == 404
assert "内部草稿" not in hidden.text
assert "内部草稿" not in client.get("/api/site/home").text
finally:
for slide in (slide_id, draft_id):
if slide is not None:
client.delete(f"/api/admin/home/slides/{slide}", headers=headers)
for file_id in (image_id, pdf_id):
if file_id is not None:
client.delete(f"/api/admin/files/{file_id}", headers=headers)
_restore_templates(client, headers, previous)
def test_slide_body_can_be_revised(client):
if not _minio_ready():
pytest.skip("MinIO 不可达")
headers = _headers("staff")
image_bytes = b"\x89PNG\r\n\x1a\nrevise"
image_id = None
pdf_id = None
slide_id = None
try:
image = client.post(
"/api/admin/files",
headers=headers,
data={"bucket": "public"},
files={"file": ("revise.png", image_bytes, "image/png")},
)
assert image.status_code == 200, image.text
image_id = image.json()["id"]
created = client.post(
"/api/admin/home/slides",
headers=headers,
json={
"title": "待改轮播",
"imageFileId": image_id,
"sortOrder": 9,
"enabled": True,
"intervalSeconds": 6,
"published": True,
"bodyHtml": "<p>原来的正文</p>",
"attachmentFileIds": [],
},
)
assert created.status_code == 200, created.text
slide_id = created.json()["id"]
pdf = client.post(
"/api/admin/files",
headers=headers,
data={"bucket": "public"},
files={"file": ("计划.pdf", b"%PDF-1.4\nplan", "application/pdf")},
)
assert pdf.status_code == 200, pdf.text
pdf_id = pdf.json()["id"]
updated = client.put(
f"/api/admin/home/slides/{slide_id}",
headers=headers,
json={
"title": "已改轮播",
"imageFileId": image_id,
"sortOrder": 3,
"enabled": True,
"intervalSeconds": 8,
"published": True,
"bodyHtml": "<p>报名已延期</p><script>alert(1)</script>",
"attachmentFileIds": [pdf_id],
},
)
assert updated.status_code == 200, updated.text
revised = client.get(f"/api/site/home/slides/{slide_id}")
assert revised.status_code == 200, revised.text
body = revised.json()["bodyHtml"]
assert "报名已延期" in body
assert "原来的正文" not in body
lowered = body.lower()
assert "script" not in lowered
assert "alert" not in lowered
assert [item["filename"] for item in revised.json()["attachments"]] == ["计划.pdf"]
home = client.get("/api/site/home").json()
listed = next(item for item in home["carousel"]["items"] if item["id"] == slide_id)
assert listed["title"] == "已改轮播"
assert listed["intervalSeconds"] == 8
editor = client.get("/api/admin/home", headers=headers)
saved = next(item for item in editor.json()["slides"] if item["id"] == slide_id)
assert "报名已延期" in saved["bodyHtml"]
assert [item["filename"] for item in saved["attachments"]] == ["计划.pdf"]
missing = client.put(
"/api/admin/home/slides/99999999",
headers=headers,
json={
"title": "不存在",
"imageFileId": image_id,
"sortOrder": 1,
"enabled": True,
"intervalSeconds": 6,
"published": False,
"bodyHtml": "<p>无</p>",
"attachmentFileIds": [],
},
)
assert missing.status_code == 404
finally:
if slide_id is not None:
client.delete(f"/api/admin/home/slides/{slide_id}", headers=headers)
for file_id in (image_id, pdf_id):
if file_id is not None:
client.delete(f"/api/admin/files/{file_id}", headers=headers)
def test_article_body_and_attachments_can_be_revised(client):
if not _minio_ready():
pytest.skip("MinIO 不可达")
headers = _headers("staff")
pdf_id = None
extra_id = None
article_id = None
try:
pdf = client.post(
"/api/admin/files",
headers=headers,
data={"bucket": "public"},
files={"file": ("办法.pdf", b"%PDF-1.4\nrule", "application/pdf")},
)
assert pdf.status_code == 200, pdf.text
pdf_id = pdf.json()["id"]
created = client.post(
"/api/admin/home/articles",
headers=headers,
json={
"category": "policies",
"title": "待改办法",
"publishedAt": "2024-03-01T09:00:00",
"published": True,
"bodyHtml": "<p>原办法</p>",
"imageFileId": None,
"attachmentFileIds": [pdf_id],
},
)
assert created.status_code == 200, created.text
article_id = created.json()["id"]
extra = client.post(
"/api/admin/files",
headers=headers,
data={"bucket": "public"},
files={"file": ("补充.docx", b"PK\x03\x04extra", "application/octet-stream")},
)
assert extra.status_code == 200, extra.text
extra_id = extra.json()["id"]
updated = client.put(
f"/api/admin/home/articles/{article_id}",
headers=headers,
json={
"category": "notices",
"title": "已改通知",
"publishedAt": "2024-04-02T10:00:00",
"published": True,
"bodyHtml": "<p>请下载附件</p><script>alert(1)</script>",
"imageFileId": None,
"attachmentFileIds": [pdf_id, extra_id],
},
)
assert updated.status_code == 200, updated.text
detail = client.get(f"/api/site/home/articles/{article_id}")
assert detail.status_code == 200, detail.text
body = detail.json()
assert body["title"] == "已改通知"
assert body["category"] == "notices"
assert "请下载附件" in body["bodyHtml"]
assert "原办法" not in body["bodyHtml"]
lowered = body["bodyHtml"].lower()
assert "script" not in lowered
assert "alert" not in lowered
assert [item["filename"] for item in body["attachments"]] == ["办法.pdf", "补充.docx"]
editor = client.get("/api/admin/home", headers=headers)
saved = next(item for item in editor.json()["articles"] if item["id"] == article_id)
assert [item["filename"] for item in saved["attachments"]] == ["办法.pdf", "补充.docx"]
missing = client.put(
"/api/admin/home/articles/99999999",
headers=headers,
json={
"category": "news",
"title": "不存在",
"published": False,
"bodyHtml": "<p>无</p>",
"attachmentFileIds": [],
},
)
assert missing.status_code == 404
finally:
if article_id is not None:
client.delete(f"/api/admin/home/articles/{article_id}", headers=headers)
for file_id in (pdf_id, extra_id):
if file_id is not None:
client.delete(f"/api/admin/files/{file_id}", headers=headers)
def _reset_home(client, headers, previous: dict | None = None) -> None:
if previous is not None:
_restore_templates(client, headers, previous)
def test_home_article_lists_keep_latest_published_only(client):
if not _minio_ready():
pytest.skip("MinIO 不可达")
headers = _headers("staff")
empty = client.get("/api/site/home")
assert empty.status_code == 200, empty.text
assert "新闻动态即将发布" in empty.text
assert "数据看板整理中" in empty.text
image_bytes = b"\x89PNG\r\n\x1a\nchart"
image_id = None
article_ids: list[int] = []
try:
limited = client.put(
"/api/admin/home/articles/display",
headers=headers,
json={"news": 2},
)
assert limited.status_code == 200, limited.text
image = client.post(
"/api/admin/files",
headers=headers,
data={"bucket": "public"},
files={"file": ("chart.png", image_bytes, "image/png")},
)
assert image.status_code == 200, image.text
image_id = image.json()["id"]
image_url = image.json()["url"]
def add(category: str, title: str, published_at: str, published: bool, body: str, image_file_id):
created = client.post(
"/api/admin/home/articles",
headers=headers,
json={
"category": category,
"title": title,
"publishedAt": published_at,
"published": published,
"bodyHtml": body,
"imageFileId": image_file_id,
"attachmentFileIds": [],
},
)
assert created.status_code == 200, created.text
article_ids.append(created.json()["id"])
return created.json()["id"]
news_id = add("news", "新闻", "2020-01-03T00:00:00", True, "<p>新闻</p>", None)
add("news", "中闻", "2020-01-02T00:00:00", True, "<p>中闻</p>", None)
add("news", "旧闻", "2020-01-01T00:00:00", True, "<p>旧闻</p>", None)
unpublished_news = add("news", "未发新闻", "2020-01-04T00:00:00", False, "<p>未发新闻</p>", None)
dashboard_id = add(
"dashboard",
"区域价格指数示意说明",
"2020-02-01T00:00:00",
True,
f'<p>本期示意,非实时采集</p><img src="{image_url}" alt="示意">',
image_id,
)
hidden_dashboard = add(
"dashboard",
"内部测算稿",
"2020-02-02T00:00:00",
False,
"<p>内部测算稿</p>",
image_id,
)
home = client.get("/api/site/home")
assert home.status_code == 200, home.text
text = home.text
assert "旧闻" not in text
assert "未发新闻" not in text
assert "内部测算稿" not in text
assert "新闻动态即将发布" not in text
assert "数据看板整理中" not in text
assert "暂无新的通知公告" in text
assert "政策法规整理中" in text
news_items = home.json()["news"]["items"]
assert [item["title"] for item in news_items] == ["新闻", "中闻"]
assert "imageUrl" not in news_items[0]
assert news_items[0]["id"] == news_id
dashboard_items = home.json()["dashboard"]["items"]
assert [item["title"] for item in dashboard_items] == ["区域价格指数示意说明"]
chart = httpx.get(dashboard_items[0]["imageUrl"], timeout=5.0, follow_redirects=True)
assert chart.status_code == 200
assert chart.content == image_bytes
detail = client.get(f"/api/site/home/articles/{dashboard_id}")
assert detail.status_code == 200, detail.text
assert "本期示意,非实时采集" in detail.json()["bodyHtml"]
assert image_url in detail.json()["bodyHtml"]
hidden = client.get(f"/api/site/home/articles/{unpublished_news}")
assert hidden.status_code == 404
assert "未发新闻" not in hidden.text
draft = client.get(f"/api/site/home/articles/{hidden_dashboard}")
assert draft.status_code == 404
assert "内部测算稿" not in draft.text
finally:
for article_id in article_ids:
client.delete(f"/api/admin/home/articles/{article_id}", headers=headers)
if image_id is not None:
client.delete(f"/api/admin/files/{image_id}", headers=headers)
client.put(
"/api/admin/home/articles/display",
headers=headers,
json={"news": 8},
)
def _clear_entries(client, headers) -> None:
client.put(
"/api/admin/home/audiences",
headers=headers,
json={
"categories": [
{"name": "估价师", "links": []},
{"name": "估价机构", "links": []},
{"name": "公众", "links": []},
]
},
)
client.put(
"/api/admin/home/hot-links",
headers=headers,
json={
"links": [
{"key": "reportQuery", "label": "报告查询", "url": "/reports/query", "visible": False, "sortOrder": 0},
{"key": "reportReview", "label": "报告审核", "url": "/reports/review", "visible": False, "sortOrder": 1},
{"key": "complaint", "label": "投诉举报", "url": "", "visible": False, "sortOrder": 2},
]
},
)
client.put(
"/api/admin/home/menu",
headers=headers,
json={
"items": [
{"key": "member", "label": "会员服务", "url": "", "visible": False, "sortOrder": 1},
]
},
)
def test_public_home_exposes_audience_hot_links_and_shortcut_menu(client):
headers = _headers("staff")
_clear_entries(client, headers)
empty = client.get("/api/site/home")
assert empty.status_code == 200, empty.text
assert "估价师、机构与公众入口即将开放" in empty.text
assert "报告查询、报告审核与投诉举报入口即将开放" in empty.text
assert empty.json()["shortcutMenu"]["items"] == [
{"label": "首页", "url": "/", "navigation": "sameWindow"}
]
try:
audiences = client.put(
"/api/admin/home/audiences",
headers=headers,
json={
"categories": [
{
"name": "估价师",
"links": [
{
"label": "估价师查询",
"url": "https://example.com/appraiser",
"visible": True,
"sortOrder": 1,
},
{
"label": "不展示的机构入口",
"url": "https://example.com/hidden",
"visible": False,
"sortOrder": 2,
},
],
},
{"name": "估价机构", "links": []},
{
"name": "公众",
"links": [
{
"label": "联系我们",
"url": "",
"visible": True,
"sortOrder": 1,
}
],
},
]
},
)
assert audiences.status_code == 200, audiences.text
hot = client.put(
"/api/admin/home/hot-links",
headers=headers,
json={
"links": [
{
"key": "reportQuery",
"label": "报告查询",
"url": "https://example.com/report-check",
"visible": True,
"sortOrder": 1,
},
{
"key": "reportReview",
"label": "报告审核",
"url": "https://example.com/review",
"visible": False,
"sortOrder": 2,
},
{
"key": "complaint",
"label": "投诉举报",
"url": "",
"visible": False,
"sortOrder": 3,
},
]
},
)
assert hot.status_code == 200, hot.text
menu = client.put(
"/api/admin/home/menu",
headers=headers,
json={
"items": [
{
"key": "member",
"label": "会员服务",
"url": "https://example.com/member",
"visible": True,
"sortOrder": 1,
}
]
},
)
assert menu.status_code == 200, menu.text
home = client.get("/api/site/home")
assert home.status_code == 200, home.text
body = home.json()
text = home.text
assert "估价师、机构与公众入口即将开放" not in text
assert "报告查询、报告审核与投诉举报入口即将开放" not in text
assert "不展示的机构入口" not in text
assert "真伪" not in text
assert "authenticity" not in text
categories = body["audiences"]["categories"]
assert [item["name"] for item in categories] == ["估价师", "估价机构", "公众"]
for category in categories:
assert "url" not in category
assert categories[0]["links"] == [
{
"label": "估价师查询",
"url": "https://example.com/appraiser",
"navigation": "newWindow",
}
]
assert categories[2]["links"] == [
{"label": "联系我们", "url": "", "navigation": "none"}
]
assert "报告查询" not in str(body["audiences"])
assert body["hotLinks"]["links"] == [
{
"label": "报告查询",
"url": "/reports/query",
"navigation": "sameWindow",
}
]
assert "https://example.com/report-check" not in text
assert [item["label"] for item in body["shortcutMenu"]["items"]] == ["首页", "会员服务"]
assert body["shortcutMenu"]["items"][1] == {
"label": "会员服务",
"url": "https://example.com/member",
"navigation": "newWindow",
}
assert "继续教育" not in [item["label"] for item in body["shortcutMenu"]["items"]]
hidden = client.put(
"/api/admin/home/menu",
headers=headers,
json={
"items": [
{
"key": "member",
"label": "会员服务",
"url": "https://example.com/member",
"visible": False,
"sortOrder": 1,
},
]
},
)
assert hidden.status_code == 200, hidden.text
menu_only = client.get("/api/site/home").json()["shortcutMenu"]["items"]
assert menu_only == [{"label": "首页", "url": "/", "navigation": "sameWindow"}]
assert "https://example.com/member" not in client.get("/api/site/home").text
finally:
_clear_entries(client, headers)
def test_public_home_lists_members_without_links_and_keeps_empty_honors(client):
if not _minio_ready():
pytest.skip("MinIO 不可达")
headers = _headers("staff")
empty = client.get("/api/site/home")
assert empty.status_code == 200, empty.text
assert "协会荣誉与资质整理中" in empty.text
assert "会员单位名录整理中" in empty.text
logo_bytes = b"\x89PNG\r\n\x1a\nmember"
honor_bytes = b"\x89PNG\r\n\x1a\nhonor"
logo_id = None
honor_id = None
try:
logo = client.post(
"/api/admin/files",
headers=headers,
data={"bucket": "public"},
files={"file": ("member.png", logo_bytes, "image/png")},
)
assert logo.status_code == 200, logo.text
logo_id = logo.json()["id"]
honor = client.post(
"/api/admin/files",
headers=headers,
data={"bucket": "public"},
files={"file": ("honor.png", honor_bytes, "image/png")},
)
assert honor.status_code == 200, honor.text
honor_id = honor.json()["id"]
shown = client.put(
"/api/admin/home/honors",
headers=headers,
json={
"intervalSeconds": 5,
"items": [{"imageFileId": honor_id, "sortOrder": 1}],
},
)
assert shown.status_code == 200, shown.text
with_honor = client.get("/api/site/home")
assert with_honor.status_code == 200, with_honor.text
assert "协会荣誉与资质整理中" not in with_honor.text
honor_items = with_honor.json()["honors"]["items"]
assert with_honor.json()["honors"]["intervalSeconds"] == 5
downloaded = httpx.get(honor_items[0]["imageUrl"], timeout=5.0, follow_redirects=True)
assert downloaded.status_code == 200
assert downloaded.content == honor_bytes
cleared = client.put(
"/api/admin/home/honors",
headers=headers,
json={"intervalSeconds": 5, "items": []},
)
assert cleared.status_code == 200, cleared.text
saved = client.put(
"/api/admin/home/members",
headers=headers,
json={
"intervalSeconds": 8,
"items": [
{
"name": "甘肃示例估价公司",
"url": "",
"imageFileId": logo_id,
"sortOrder": 1,
}
],
},
)
assert saved.status_code == 200, saved.text
home = client.get("/api/site/home")
assert home.status_code == 200, home.text
assert "协会荣誉与资质整理中" in home.text
assert "会员单位名录整理中" not in home.text
members = home.json()["members"]
assert members["intervalSeconds"] == 8
assert members["items"] == [
{
"name": "甘肃示例估价公司",
"url": "",
"navigation": "none",
"imageUrl": members["items"][0]["imageUrl"],
}
]
logo_download = httpx.get(members["items"][0]["imageUrl"], timeout=5.0, follow_redirects=True)
assert logo_download.status_code == 200
assert logo_download.content == logo_bytes
finally:
client.put(
"/api/admin/home/honors",
headers=headers,
json={"intervalSeconds": 5, "items": []},
)
client.put(
"/api/admin/home/members",
headers=headers,
json={"intervalSeconds": 8, "items": []},
)
for file_id in (logo_id, honor_id):
if file_id is not None:
client.delete(f"/api/admin/files/{file_id}", headers=headers)
def _empty_contact(name: str, address: str = "") -> dict:
return {
"name": name,
"address": address,
"phone": "",
"email": "",
"latitude": None,
"longitude": None,
}
def _related(template_name: str, supervisor: list[dict]) -> dict:
return {
"templateName": template_name,
"categories": [
{"name": "主管部门", "links": supervisor},
{"name": "相关部门", "links": []},
{"name": "合作协会", "links": []},
],
}
def test_staff_home_includes_map_picker_credentials(client, monkeypatch):
headers = _headers("staff")
monkeypatch.setenv("GAODE_KEY", "test-gaode-key")
monkeypatch.setenv("GAODE_SECURITY_JS_CODE", "test-gaode-secret")
get_settings.cache_clear()
try:
body = client.get("/api/admin/home", headers=headers)
assert body.status_code == 200, body.text
assert body.json()["mapPicker"] == {
"key": "test-gaode-key",
"securityJsCode": "test-gaode-secret",
}
monkeypatch.setenv("GAODE_SECURITY_JS_CODE", "")
get_settings.cache_clear()
hidden = client.get("/api/admin/home", headers=headers)
assert hidden.status_code == 200, hidden.text
assert hidden.json()["mapPicker"] is None
guest = client.get("/api/admin/home")
assert guest.status_code == 401
finally:
get_settings.cache_clear()
def test_public_footer_uses_the_active_template_and_hides_an_unplaced_map(client, monkeypatch):
headers = _headers("staff")
previous = _template_state(client, headers)
monkeypatch.setenv("GAODE_KEY", "test-gaode-key")
monkeypatch.setenv("GAODE_SECURITY_JS_CODE", "test-gaode-secret")
get_settings.cache_clear()
try:
activated = _write(client, headers)
assert activated.status_code == 200, activated.text
contact = client.put(
"/api/admin/home/contact",
headers=headers,
json={
"templates": [
_empty_contact("科技蓝", "科技蓝办公地址"),
_empty_contact("LOGO蓝"),
]
},
)
assert contact.status_code == 200, contact.text
related = client.put(
"/api/admin/home/related-links",
headers=headers,
json=_related(
"LOGO蓝",
[
{
"label": "甘肃省住建厅",
"url": "https://example.com/zjt",
"visible": True,
"sortOrder": 1,
}
],
),
)
assert related.status_code == 200, related.text
other = client.put(
"/api/admin/home/related-links",
headers=headers,
json=_related(
"科技蓝",
[
{
"label": "科技蓝主管部门",
"url": "https://example.com/tech",
"visible": True,
"sortOrder": 1,
}
],
),
)
assert other.status_code == 200, other.text
compliance = client.put(
"/api/admin/home/compliance",
headers=headers,
json={"templateName": "LOGO蓝", "links": []},
)
assert compliance.status_code == 200, compliance.text
home = client.get("/api/site/home")
assert home.status_code == 200, home.text
text = home.text
assert "科技蓝办公地址" not in text
assert "科技蓝主管部门" not in text
assert "办公地址整理中" in text
assert "联系电话整理中" in text
assert "联系邮箱整理中" in text
assert "地图位置整理中" in text
assert "主管部门链接整理中" not in text
assert "相关部门链接整理中" in text
assert "合作协会链接整理中" in text
assert "隐私政策" in text
assert "使用条款" in text
assert "网站声明" in text
assert home.json()["compliance"]["links"][0]["url"] == "/legal/privacy"
assert home.json()["relatedLinks"]["主管部门"]["links"] == [
{
"label": "甘肃省住建厅",
"url": "https://example.com/zjt",
"navigation": "newWindow",
}
]
placed = client.put(
"/api/admin/home/contact",
headers=headers,
json={
"templates": [
_empty_contact("科技蓝", "科技蓝办公地址"),
{
"name": "LOGO蓝",
"address": "",
"phone": "",
"email": "",
"latitude": 36.5,
"longitude": 103.5,
},
]
},
)
assert placed.status_code == 200, placed.text
mapped = client.get("/api/site/home")
assert mapped.status_code == 200, mapped.text
assert "地图位置整理中" not in mapped.text
assert mapped.json()["contact"]["map"] == {
"latitude": 36.5,
"longitude": 103.5,
"key": "test-gaode-key",
"securityJsCode": "test-gaode-secret",
}
finally:
client.put(
"/api/admin/home/contact",
headers=headers,
json={"templates": [_empty_contact("科技蓝"), _empty_contact("LOGO蓝")]},
)
for name in ("科技蓝", "LOGO蓝"):
client.put(
"/api/admin/home/related-links",
headers=headers,
json=_related(name, []),
)
client.put(
"/api/admin/home/compliance",
headers=headers,
json={"templateName": name, "links": []},
)
_reset_home(client, headers, previous)
get_settings.cache_clear()