287 lines
9.9 KiB
Python
287 lines
9.9 KiB
Python
|
|
import datetime
|
||
|
|
|
||
|
|
from django.conf import settings
|
||
|
|
from django.contrib.contenttypes.models import ContentType
|
||
|
|
from django.contrib.sites.shortcuts import get_current_site
|
||
|
|
from django.test import RequestFactory, TestCase, override_settings
|
||
|
|
from django.utils import timezone
|
||
|
|
|
||
|
|
from wagtail.models import Page, PageViewRestriction, Site
|
||
|
|
from wagtail.test.testapp.models import EventIndex, SimplePage
|
||
|
|
|
||
|
|
from .sitemap_generator import Sitemap
|
||
|
|
|
||
|
|
|
||
|
|
class TestSitemapGenerator(TestCase):
|
||
|
|
def setUp(self):
|
||
|
|
self.home_page = Page.objects.get(id=2)
|
||
|
|
|
||
|
|
self.child_page = self.home_page.add_child(
|
||
|
|
instance=SimplePage(
|
||
|
|
title="Hello world!",
|
||
|
|
slug="hello-world",
|
||
|
|
content="hello",
|
||
|
|
live=True,
|
||
|
|
last_published_at=datetime.datetime(
|
||
|
|
2017, 1, 1, 12, 0, 0, tzinfo=datetime.timezone.utc
|
||
|
|
),
|
||
|
|
latest_revision_created_at=datetime.datetime(
|
||
|
|
2017, 2, 1, 12, 0, 0, tzinfo=datetime.timezone.utc
|
||
|
|
),
|
||
|
|
)
|
||
|
|
)
|
||
|
|
|
||
|
|
self.unpublished_child_page = self.home_page.add_child(
|
||
|
|
instance=SimplePage(
|
||
|
|
title="Unpublished",
|
||
|
|
slug="unpublished",
|
||
|
|
content="hello",
|
||
|
|
live=False,
|
||
|
|
)
|
||
|
|
)
|
||
|
|
|
||
|
|
self.protected_child_page = self.home_page.add_child(
|
||
|
|
instance=SimplePage(
|
||
|
|
title="Protected",
|
||
|
|
slug="protected",
|
||
|
|
content="hello",
|
||
|
|
live=True,
|
||
|
|
)
|
||
|
|
)
|
||
|
|
PageViewRestriction.objects.create(
|
||
|
|
page=self.protected_child_page, password="hello"
|
||
|
|
)
|
||
|
|
|
||
|
|
self.page_with_no_last_publish_date = self.home_page.add_child(
|
||
|
|
instance=SimplePage(
|
||
|
|
title="I have no last publish date :-(",
|
||
|
|
slug="no-last-publish-date",
|
||
|
|
content="hello",
|
||
|
|
live=True,
|
||
|
|
latest_revision_created_at=datetime.datetime(
|
||
|
|
2017, 2, 1, 12, 0, 0, tzinfo=datetime.timezone.utc
|
||
|
|
),
|
||
|
|
)
|
||
|
|
)
|
||
|
|
|
||
|
|
self.site = Site.objects.get(is_default_site=True)
|
||
|
|
|
||
|
|
root_page = Page.objects.get(depth=1)
|
||
|
|
self.other_site_homepage = root_page.add_child(
|
||
|
|
instance=SimplePage(
|
||
|
|
title="Another site", slug="another-site", content="bonjour", live=True
|
||
|
|
)
|
||
|
|
)
|
||
|
|
Site.objects.create(
|
||
|
|
hostname="other.example.com", port=80, root_page=self.other_site_homepage
|
||
|
|
)
|
||
|
|
|
||
|
|
# Clear the cache to that runs are deterministic regarding the sql count
|
||
|
|
ContentType.objects.clear_cache()
|
||
|
|
|
||
|
|
def get_request_and_django_site(self, url):
|
||
|
|
request = RequestFactory().get(url)
|
||
|
|
request.META["HTTP_HOST"] = self.site.hostname
|
||
|
|
request.META["SERVER_PORT"] = self.site.port
|
||
|
|
return request, get_current_site(request)
|
||
|
|
|
||
|
|
def assertDatesEqual(self, actual, expected):
|
||
|
|
# Compare dates as naive or timezone-aware according to USE_TZ
|
||
|
|
if not settings.USE_TZ:
|
||
|
|
expected = timezone.make_naive(expected)
|
||
|
|
return self.assertEqual(actual, expected)
|
||
|
|
|
||
|
|
def test_items(self):
|
||
|
|
request, django_site = self.get_request_and_django_site("/sitemap.xml")
|
||
|
|
|
||
|
|
sitemap = Sitemap(request)
|
||
|
|
pages = sitemap.items()
|
||
|
|
|
||
|
|
self.assertIn(self.child_page.page_ptr.specific, pages)
|
||
|
|
self.assertNotIn(self.unpublished_child_page.page_ptr.specific, pages)
|
||
|
|
self.assertNotIn(self.protected_child_page.page_ptr.specific, pages)
|
||
|
|
|
||
|
|
def test_get_urls_without_request(self):
|
||
|
|
request, django_site = self.get_request_and_django_site("/sitemap.xml")
|
||
|
|
req_protocol = request.scheme
|
||
|
|
|
||
|
|
sitemap = Sitemap()
|
||
|
|
with self.assertNumQueries(17):
|
||
|
|
urls = [
|
||
|
|
url["location"]
|
||
|
|
for url in sitemap.get_urls(1, django_site, req_protocol)
|
||
|
|
]
|
||
|
|
|
||
|
|
self.assertIn("http://localhost/", urls) # Homepage
|
||
|
|
self.assertIn("http://localhost/hello-world/", urls) # Child page
|
||
|
|
|
||
|
|
def test_get_urls_with_request_site_cache(self):
|
||
|
|
request, django_site = self.get_request_and_django_site("/sitemap.xml")
|
||
|
|
req_protocol = request.scheme
|
||
|
|
|
||
|
|
sitemap = Sitemap(request)
|
||
|
|
|
||
|
|
# pre-seed find_for_request cache, so that it's not counted towards the query count
|
||
|
|
Site.find_for_request(request)
|
||
|
|
|
||
|
|
with self.assertNumQueries(14):
|
||
|
|
urls = [
|
||
|
|
url["location"]
|
||
|
|
for url in sitemap.get_urls(1, django_site, req_protocol)
|
||
|
|
]
|
||
|
|
|
||
|
|
self.assertIn("http://localhost/", urls) # Homepage
|
||
|
|
self.assertIn("http://localhost/hello-world/", urls) # Child page
|
||
|
|
|
||
|
|
@override_settings(WAGTAIL_I18N_ENABLED=True)
|
||
|
|
def test_get_urls_without_request_with_i18n(self):
|
||
|
|
request, django_site = self.get_request_and_django_site("/sitemap.xml")
|
||
|
|
req_protocol = request.scheme
|
||
|
|
|
||
|
|
sitemap = Sitemap()
|
||
|
|
with self.assertNumQueries(19):
|
||
|
|
urls = [
|
||
|
|
url["location"]
|
||
|
|
for url in sitemap.get_urls(1, django_site, req_protocol)
|
||
|
|
]
|
||
|
|
|
||
|
|
self.assertIn("http://localhost/", urls) # Homepage
|
||
|
|
self.assertIn("http://localhost/hello-world/", urls) # Child page
|
||
|
|
|
||
|
|
@override_settings(WAGTAIL_I18N_ENABLED=True)
|
||
|
|
def test_get_urls_with_request_site_cache_with_i18n(self):
|
||
|
|
request, django_site = self.get_request_and_django_site("/sitemap.xml")
|
||
|
|
req_protocol = request.scheme
|
||
|
|
|
||
|
|
sitemap = Sitemap(request)
|
||
|
|
|
||
|
|
# pre-seed find_for_request cache, so that it's not counted towards the query count
|
||
|
|
Site.find_for_request(request)
|
||
|
|
|
||
|
|
with self.assertNumQueries(16):
|
||
|
|
urls = [
|
||
|
|
url["location"]
|
||
|
|
for url in sitemap.get_urls(1, django_site, req_protocol)
|
||
|
|
]
|
||
|
|
|
||
|
|
self.assertIn("http://localhost/", urls) # Homepage
|
||
|
|
self.assertIn("http://localhost/hello-world/", urls) # Child page
|
||
|
|
|
||
|
|
def test_get_urls_uses_specific(self):
|
||
|
|
request, django_site = self.get_request_and_django_site("/sitemap.xml")
|
||
|
|
req_protocol = request.scheme
|
||
|
|
|
||
|
|
# Add an event page which has an extra url in the sitemap
|
||
|
|
self.home_page.add_child(
|
||
|
|
instance=EventIndex(
|
||
|
|
title="Events",
|
||
|
|
slug="events",
|
||
|
|
live=True,
|
||
|
|
)
|
||
|
|
)
|
||
|
|
|
||
|
|
sitemap = Sitemap(request)
|
||
|
|
urls = [
|
||
|
|
url["location"] for url in sitemap.get_urls(1, django_site, req_protocol)
|
||
|
|
]
|
||
|
|
|
||
|
|
self.assertIn("http://localhost/events/", urls) # Main view
|
||
|
|
self.assertIn("http://localhost/events/past/", urls) # Sub view
|
||
|
|
|
||
|
|
def test_lastmod_uses_last_published_date(self):
|
||
|
|
request, django_site = self.get_request_and_django_site("/sitemap.xml")
|
||
|
|
req_protocol = request.scheme
|
||
|
|
|
||
|
|
sitemap = Sitemap(request)
|
||
|
|
urls = sitemap.get_urls(1, django_site, req_protocol)
|
||
|
|
|
||
|
|
child_page_lastmod = [
|
||
|
|
url["lastmod"]
|
||
|
|
for url in urls
|
||
|
|
if url["location"] == "http://localhost/hello-world/"
|
||
|
|
][0]
|
||
|
|
self.assertDatesEqual(
|
||
|
|
child_page_lastmod,
|
||
|
|
datetime.datetime(2017, 1, 1, 12, 0, 0, tzinfo=datetime.timezone.utc),
|
||
|
|
)
|
||
|
|
|
||
|
|
# if no last_publish_date is defined, use latest revision date
|
||
|
|
child_page_lastmod = [
|
||
|
|
url["lastmod"]
|
||
|
|
for url in urls
|
||
|
|
if url["location"] == "http://localhost/no-last-publish-date/"
|
||
|
|
][0]
|
||
|
|
self.assertDatesEqual(
|
||
|
|
child_page_lastmod,
|
||
|
|
datetime.datetime(2017, 2, 1, 12, 0, 0, tzinfo=datetime.timezone.utc),
|
||
|
|
)
|
||
|
|
|
||
|
|
def test_latest_lastmod(self):
|
||
|
|
# give the homepage a lastmod
|
||
|
|
self.home_page.last_published_at = datetime.datetime(
|
||
|
|
2017, 3, 1, 12, 0, 0, tzinfo=datetime.timezone.utc
|
||
|
|
)
|
||
|
|
self.home_page.save()
|
||
|
|
|
||
|
|
request, django_site = self.get_request_and_django_site("/sitemap.xml")
|
||
|
|
req_protocol = request.scheme
|
||
|
|
|
||
|
|
sitemap = Sitemap(request)
|
||
|
|
sitemap.get_urls(1, django_site, req_protocol)
|
||
|
|
|
||
|
|
self.assertDatesEqual(
|
||
|
|
sitemap.latest_lastmod,
|
||
|
|
datetime.datetime(2017, 3, 1, 12, 0, 0, tzinfo=datetime.timezone.utc),
|
||
|
|
)
|
||
|
|
|
||
|
|
def test_latest_lastmod_missing(self):
|
||
|
|
# ensure homepage does not have lastmod
|
||
|
|
self.home_page.last_published_at = None
|
||
|
|
self.home_page.save()
|
||
|
|
|
||
|
|
request, django_site = self.get_request_and_django_site("/sitemap.xml")
|
||
|
|
req_protocol = request.scheme
|
||
|
|
|
||
|
|
sitemap = Sitemap(request)
|
||
|
|
sitemap.get_urls(1, django_site, req_protocol)
|
||
|
|
|
||
|
|
self.assertFalse(hasattr(sitemap, "latest_lastmod"))
|
||
|
|
|
||
|
|
def test_non_default_site(self):
|
||
|
|
request = RequestFactory().get("/sitemap.xml")
|
||
|
|
request.META["HTTP_HOST"] = "other.example.com"
|
||
|
|
request.META["SERVER_PORT"] = 80
|
||
|
|
|
||
|
|
sitemap = Sitemap(request)
|
||
|
|
pages = sitemap.items()
|
||
|
|
|
||
|
|
self.assertIn(self.other_site_homepage.page_ptr.specific, pages)
|
||
|
|
self.assertNotIn(self.child_page.page_ptr.specific, pages)
|
||
|
|
|
||
|
|
|
||
|
|
class TestIndexView(TestCase):
|
||
|
|
def test_index_view(self):
|
||
|
|
response = self.client.get("/sitemap-index.xml")
|
||
|
|
|
||
|
|
self.assertEqual(response.status_code, 200)
|
||
|
|
self.assertEqual(response["Content-Type"], "application/xml")
|
||
|
|
|
||
|
|
|
||
|
|
class TestSitemapView(TestCase):
|
||
|
|
def test_sitemap_view(self):
|
||
|
|
response = self.client.get("/sitemap.xml")
|
||
|
|
|
||
|
|
self.assertEqual(response.status_code, 200)
|
||
|
|
self.assertEqual(response["Content-Type"], "application/xml")
|
||
|
|
|
||
|
|
def test_sitemap_view_with_current_site_middleware(self):
|
||
|
|
with self.modify_settings(
|
||
|
|
MIDDLEWARE={
|
||
|
|
"append": "django.contrib.sites.middleware.CurrentSiteMiddleware",
|
||
|
|
}
|
||
|
|
):
|
||
|
|
response = self.client.get("/sitemap.xml")
|
||
|
|
|
||
|
|
self.assertEqual(response.status_code, 200)
|
||
|
|
self.assertEqual(response["Content-Type"], "application/xml")
|