Files
wagtailcms/apps/core/test_site_setup.py

163 lines
7.2 KiB
Python

import pytest
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Permission
from django.core.exceptions import ValidationError
from django.test import Client
from django.urls import reverse
from wagtail.models import Page, Site
from apps.core.models import ContactPage, NavigationMenu, NavigationMenuItem, SimpleContentPage, SiteSettings
from apps.core.site_setup import setup_company_site
from apps.core.wagtail_hooks import register_company_setup_menu
from apps.forms.models import FormDefinition
from apps.home.models import HomePage
from apps.products.models import ProductIndexPage
pytestmark = pytest.mark.django_db
@pytest.fixture
def company_data():
return {"company_name": "测试软件公司", "contact_phone": "010-12345678", "contact_email": "hello@example.com", "address": "测试地址", "icp_number": ""}
@pytest.fixture
def admin_user():
return get_user_model().objects.create_superuser("site-admin", "admin@example.com", "test-password")
def test_setup_creates_full_site_and_public_api(client, company_data):
created = setup_company_site(company_data, create_demo=True)
site = Site.objects.get(is_default_site=True)
assert isinstance(site.root_page.specific, HomePage)
assert len(created) == 13
assert set(site.root_page.get_children().values_list("slug", flat=True)) == {
"products", "solutions", "cases", "blog", "about", "contact", "privacy-policy",
}
assert SiteSettings.for_site(site).company_name == company_data["company_name"]
assert site.site_name == company_data["company_name"]
assert NavigationMenu.objects.get(name="main").items.count() == 7
assert NavigationMenu.objects.get(name="footer").items.count() == 3
assert FormDefinition.objects.get(name="官网项目咨询").notification_email == company_data["contact_email"]
for type_name, slug in [("core.SimpleContentPage", "about"), ("products.ProductPage", "content-platform"), ("core.ContactPage", "contact")]:
response = client.get("/api/v2/pages/", {"type": type_name, "slug": slug, "fields": "body"})
assert response.status_code == 200
assert response.json()["meta"]["total_count"] == 1
assert "虚构" in Page.objects.get(slug="demo-content-project").title
def test_setup_is_idempotent_and_preserves_edits(company_data):
setup_company_site(company_data, True)
page = SimpleContentPage.objects.get(slug="about")
page.title = "客户自己的介绍"
page.body = "<p>客户自己的内容</p>"
page.save_revision().publish()
count = Page.objects.count()
forms = FormDefinition.objects.count()
assert setup_company_site(company_data, True) == []
page.refresh_from_db()
assert page.title == "客户自己的介绍"
assert str(page.body) == "<p>客户自己的内容</p>"
assert Page.objects.count() == count
assert FormDefinition.objects.count() == forms
def test_existing_home_contact_menu_and_draft_are_preserved(home_page, company_data):
site = Site.objects.get(is_default_site=True)
site.root_page = home_page
site.save()
original_body = home_page.body.get_prep_value()
contact = home_page.add_child(instance=ContactPage(title="原有联系页", slug="contact", body=[("richtext", "<p>自定义</p>")]))
contact.save_revision().publish()
products = home_page.add_child(instance=ProductIndexPage(title="草稿栏目", slug="products", live=False))
products.save_revision()
menu = NavigationMenu.objects.create(name="main")
NavigationMenuItem.objects.create(menu=menu, label="原有菜单", link_url="/custom/")
setup_company_site(company_data, True)
home_page.refresh_from_db()
contact.refresh_from_db()
products.refresh_from_db()
assert home_page.body.get_prep_value() == original_body
assert contact.title == "原有联系页"
assert "自定义" in str(contact.body)
assert not products.live
assert menu.items.count() == 1
assert menu.items.first().label == "原有菜单"
assert FormDefinition.objects.count() == 0
def test_company_only_does_not_create_pages_or_forms(company_data):
before = Page.objects.count()
setup_company_site(company_data)
assert Page.objects.count() == before
assert FormDefinition.objects.count() == 0
assert NavigationMenu.objects.count() == 0
def test_conflict_rolls_back_all_changes(home_page, company_data):
site = Site.objects.get(is_default_site=True)
site.root_page = home_page
site.save()
home_page.add_child(instance=SimpleContentPage(title="路径冲突", slug="solutions"))
before = Page.objects.count()
with pytest.raises(ValidationError, match="solutions"):
setup_company_site(company_data, True)
assert Page.objects.count() == before
assert not SiteSettings.objects.filter(company_name=company_data["company_name"]).exists()
site.refresh_from_db()
assert site.site_name != company_data["company_name"]
def test_incompatible_root_is_not_replaced(company_data):
site = Site.objects.get(is_default_site=True)
site.root_page.slug = "existing-business"
site.root_page.save()
with pytest.raises(ValidationError, match="根页面"):
setup_company_site(company_data, True)
site.refresh_from_db()
assert site.root_page.slug == "existing-business"
def test_company_html_is_escaped(company_data):
company_data["company_name"] = '<script>alert("test")</script>'
setup_company_site(company_data, True)
assert "<script>" not in str(SimpleContentPage.objects.get(slug="about").body)
def test_wizard_get_and_post(client, admin_user, company_data):
client.force_login(admin_user)
url = reverse("company_site_setup")
response = client.get(url)
assert response.status_code == 200
assert "新建页面会立即公开发布" in response.content.decode()
before = Page.objects.count()
assert client.post(url, company_data).status_code == 302
assert Page.objects.count() == before
response = client.post(url, {**company_data, "create_demo": "on"}, follow=True)
assert response.status_code == 200
assert "新增 13 个页面" in response.content.decode()
def test_wizard_requires_superuser_and_csrf(client, admin_user, company_data):
url = reverse("company_site_setup")
assert client.get(url).status_code == 302
user = get_user_model().objects.create_user("editor", password="test-password", is_staff=True)
user.user_permissions.add(Permission.objects.get(content_type__app_label="wagtailadmin", codename="access_admin"))
client.force_login(user)
assert client.post(url, {**company_data, "create_demo": "on"}).status_code == 403
item = register_company_setup_menu()
request = type("Request", (), {"user": user})()
assert not item.is_shown(request)
csrf_client = Client(enforce_csrf_checks=True)
csrf_client.force_login(admin_user)
assert csrf_client.post(url, company_data).status_code == 403
def test_invalid_form_does_not_write(client, admin_user, company_data):
client.force_login(admin_user)
before = Page.objects.count()
response = client.post(reverse("company_site_setup"), {**company_data, "company_name": "", "contact_email": "invalid", "create_demo": "on"})
assert response.status_code == 200
assert response.context["form"].errors
assert Page.objects.count() == before