test_urls.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. import pytest
  2. import unittest
  3. from ast import literal_eval
  4. from datetime import timedelta
  5. from django.urls import reverse
  6. from django.test import Client
  7. from django.test.utils import override_settings
  8. from django.utils import timezone
  9. from wagtail.models import Site, Page
  10. from wagtail.images.tests.utils import Image, get_test_image_file
  11. from wagtailcrx.models import LayoutSettings
  12. from wagtailcrx.tests.testapp.models import EventPage, EventIndexPage, EventOccurrence
  13. @pytest.mark.django_db
  14. class TestSiteURLs(unittest.TestCase):
  15. def setUp(self):
  16. self.client = Client()
  17. @override_settings(DEBUG=False)
  18. def test_404(self):
  19. response = self.client.get("/testing/404/page/", follow=True)
  20. self.assertEqual(response.status_code, 404)
  21. def test_sitemap(self):
  22. response = self.client.get("/sitemap.xml")
  23. self.assertEqual(response.status_code, 200)
  24. self.assertEqual(response['content-type'], 'application/xml')
  25. def test_robots(self):
  26. response = self.client.get("/robots.txt")
  27. self.assertEqual(response.status_code, 200)
  28. self.assertEqual(response['content-type'], 'text/plain')
  29. def test_search(self):
  30. response = self.client.get(reverse(
  31. 'codered_search'),
  32. {'s': 'Test Search Query'},
  33. follow=True
  34. )
  35. self.assertEqual(response.status_code, 200)
  36. self.assertNotEqual(response.context['results'], None)
  37. response = self.client.get(reverse(
  38. 'codered_search'),
  39. {
  40. 's': 'keyword',
  41. 't': 't',
  42. },
  43. follow=False
  44. )
  45. self.assertEqual(response.status_code, 200)
  46. self.assertEqual(response.context['results'], None)
  47. @pytest.mark.django_db
  48. class TestEventURLs(unittest.TestCase):
  49. def setUp(self):
  50. self.client = Client()
  51. self.root_page = Page.get_root_nodes()[0]
  52. def test_generate_single_event(self):
  53. event_page = EventPage(
  54. path='/single-event/',
  55. depth=1,
  56. title='Single Event',
  57. slug='single-event'
  58. )
  59. self.root_page.add_child(instance=event_page)
  60. occurrence = EventOccurrence(
  61. event=event_page,
  62. start=timezone.now(),
  63. end=timezone.now() + timedelta(hours=1),
  64. )
  65. occurrence.save()
  66. ajax_url = reverse("event_generate_single_ical")
  67. response = self.client.post(
  68. ajax_url,
  69. {
  70. 'event_pk': event_page.pk,
  71. 'datetime_start': occurrence.start.strftime("%Y-%m-%dT%H:%M:%S%z"),
  72. 'datetime_end': occurrence.end.strftime("%Y-%m-%dT%H:%M:%S%z"),
  73. },
  74. follow=True
  75. )
  76. self.assertEqual(response.status_code, 200)
  77. self.assertEqual(response['Filename'], "{0}.ics".format(event_page.slug))
  78. self.assertEqual(
  79. response['Content-Disposition'],
  80. 'attachment; filename={0}.ics'.format(event_page.slug)
  81. )
  82. self.assertEqual(response['content-type'], 'text/calendar')
  83. # Get datetimes from response and compare them to datetimes on page
  84. # startswith() is used because older versions of Python
  85. # use different datetime formatting, specifically for timezones
  86. split_content = str(response._container[0]).split('VALUE=DATE-TIME:')
  87. start = split_content[1].split('\\')[0]
  88. end = split_content[2].split('\\')[0]
  89. self.assertTrue(
  90. start.startswith(
  91. EventOccurrence.objects.get(event=event_page).start.strftime("%Y%m%dT%H%M%S")
  92. )
  93. )
  94. self.assertTrue(
  95. end.startswith(
  96. EventOccurrence.objects.get(event=event_page).end.strftime("%Y%m%dT%H%M%S")
  97. )
  98. )
  99. # Test that garbage requests are handled appropriately.
  100. response = self.client.post(ajax_url)
  101. self.assertEqual(response.status_code, 400)
  102. response = self.client.post(ajax_url, {"event_pk": "junk"})
  103. self.assertEqual(response.status_code, 400)
  104. response = self.client.post(
  105. ajax_url,
  106. {
  107. "event_pk": "junk",
  108. "datetime_start": "junk",
  109. "datetime_end": "junk",
  110. }
  111. )
  112. self.assertEqual(response.status_code, 400)
  113. response = self.client.post(
  114. ajax_url,
  115. {
  116. "event_pk": "junk",
  117. "datetime_start": "2022-07-14T10:00:00+0000",
  118. "datetime_end": "2022-07-14T10:00:00+0000",
  119. }
  120. )
  121. self.assertEqual(response.status_code, 404)
  122. def test_generate_recurring_event(self):
  123. event_page = EventPage(
  124. path='/recurring-event/',
  125. depth=1,
  126. title='Recurring Event',
  127. slug='recurring-event'
  128. )
  129. self.root_page.add_child(instance=event_page)
  130. occurrence = EventOccurrence(
  131. event=event_page,
  132. start='2019-01-01T10:00:00+0000',
  133. end='2019-01-01T11:00:00+0000'
  134. )
  135. occurrence.save()
  136. ajax_url = reverse("event_generate_recurring_ical")
  137. response = self.client.post(
  138. ajax_url,
  139. {'event_pk': event_page.pk},
  140. follow=True
  141. )
  142. self.assertEqual(response.status_code, 200)
  143. self.assertEqual(response['Filename'], "{0}.ics".format(event_page.slug))
  144. self.assertEqual(
  145. response['Content-Disposition'],
  146. 'attachment; filename={0}.ics'.format(event_page.slug)
  147. )
  148. self.assertEqual(response['content-type'], 'text/calendar')
  149. # Get datetimes from response and compare them to datetimes on page
  150. # startswith() is used because older versions of Python
  151. # use different datetime formatting, specifically for timezones
  152. split_content = str(response._container[0]).split('VALUE=DATE-TIME:')
  153. start = split_content[1].split('\\')[0]
  154. end = split_content[2].split('\\')[0]
  155. self.assertTrue(
  156. start.startswith(
  157. EventOccurrence.objects.get(event=event_page).start.strftime("%Y%m%dT%H%M%S")
  158. )
  159. )
  160. self.assertTrue(
  161. end.startswith(
  162. EventOccurrence.objects.get(event=event_page).end.strftime("%Y%m%dT%H%M%S")
  163. )
  164. )
  165. # Test that garbage requests are handled appropriately.
  166. response = self.client.post(ajax_url)
  167. self.assertEqual(response.status_code, 400)
  168. response = self.client.post(ajax_url, {"event_pk": "junk"})
  169. self.assertEqual(response.status_code, 404)
  170. def test_generate_calendar(self):
  171. calendar_page = EventIndexPage(
  172. path='/event-index-page/',
  173. depth=1,
  174. title='Event Index Page',
  175. slug='event-index-page'
  176. )
  177. self.root_page.add_child(instance=calendar_page)
  178. event_page = EventPage(
  179. path='/eventpage/1/',
  180. depth=2,
  181. title='Event Page 1',
  182. slug='eventpage1'
  183. )
  184. calendar_page.add_child(instance=event_page)
  185. occurrence = EventOccurrence(
  186. event=event_page,
  187. start='2019-01-01T10:00:00+0000',
  188. end='2019-01-01T11:00:00+0000'
  189. )
  190. occurrence.save()
  191. ajax_url = reverse("event_generate_ical_for_calendar")
  192. response = self.client.post(
  193. ajax_url,
  194. {'page_id': calendar_page.pk},
  195. follow=True
  196. )
  197. self.assertEqual(response.status_code, 200)
  198. self.assertEqual(response['Filename'], 'calendar.ics')
  199. self.assertEqual(response['Content-Disposition'], 'attachment; filename=calendar.ics')
  200. self.assertEqual(response['content-type'], 'text/calendar')
  201. # Get datetimes from response and compare them to datetimes on page
  202. # startswith() is used because older versions of Python
  203. # use different datetime formatting, specifically for timezones
  204. split_content = str(response._container[0]).split('VALUE=DATE-TIME:')
  205. start = split_content[1].split('\\')[0]
  206. end = split_content[2].split('\\')[0]
  207. self.assertTrue(
  208. start.startswith(
  209. EventOccurrence.objects.get(event=event_page).start.strftime("%Y%m%dT%H%M%S")
  210. )
  211. )
  212. self.assertTrue(
  213. end.startswith(
  214. EventOccurrence.objects.get(event=event_page).end.strftime("%Y%m%dT%H%M%S")
  215. )
  216. )
  217. # Test that garbage requests are handled appropriately.
  218. response = self.client.post(ajax_url)
  219. self.assertEqual(response.status_code, 400)
  220. response = self.client.post(ajax_url, {"page_id": "junk"})
  221. self.assertEqual(response.status_code, 404)
  222. def test_ajax_calendar(self):
  223. calendar_page = EventIndexPage(
  224. path='/event-index-page/',
  225. depth=1,
  226. title='Event Index Page',
  227. slug='event-index-page'
  228. )
  229. self.root_page.add_child(instance=calendar_page)
  230. event_page = EventPage(
  231. path='/eventpage/1/',
  232. depth=2,
  233. title='Event Page 1',
  234. slug='eventpage1'
  235. )
  236. calendar_page.add_child(instance=event_page)
  237. occurrence_one = EventOccurrence(
  238. event=event_page,
  239. start='2019-01-01T10:00:00+0000',
  240. end='2019-01-01T11:00:00+0000'
  241. )
  242. occurrence_one.save()
  243. ajax_url = reverse("event_get_calendar_events")
  244. response = self.client.post(
  245. f"{ajax_url}?pid={calendar_page.pk}",
  246. follow=True,
  247. **{'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest'}
  248. )
  249. self.assertEqual(response.status_code, 200)
  250. # Get datetimes from response and compare them to datetimes on page
  251. start = literal_eval(response._container[0].decode()[1:-1])['start']
  252. end = literal_eval(response._container[0].decode()[1:-1])['end']
  253. event_local_start = timezone.localtime(
  254. EventOccurrence.objects.get(event=event_page).start
  255. )
  256. event_local_end = timezone.localtime(
  257. EventOccurrence.objects.get(event=event_page).end
  258. )
  259. self.assertEqual(
  260. start,
  261. event_local_start.strftime("%Y-%m-%dT%H:%M:%S%z")
  262. )
  263. self.assertEqual(
  264. end,
  265. event_local_end.strftime("%Y-%m-%dT%H:%M:%S%z")
  266. )
  267. # Test that garbage requests are handled appropriately.
  268. response = self.client.post(ajax_url)
  269. self.assertEqual(response.status_code, 400)
  270. response = self.client.post(f"{ajax_url}?pid=junk&start=junk&end=junk")
  271. self.assertEqual(response.status_code, 400)
  272. response = self.client.post(f"{ajax_url}?pid=junk")
  273. self.assertEqual(response.status_code, 404)
  274. @pytest.mark.django_db
  275. class TestFavicon(unittest.TestCase):
  276. def test_404(self):
  277. client = Client()
  278. # Get the default site
  279. site = Site.objects.filter(is_default_site=True)[0]
  280. # Ensure the favicon is blank
  281. layout = LayoutSettings.for_site(site)
  282. layout.favicon = None
  283. layout.save()
  284. # Expect a 404
  285. response = client.get("/favicon.ico")
  286. self.assertEqual(response.status_code, 404)
  287. def test_301(self):
  288. client = Client()
  289. # Get the default site
  290. site = Site.objects.filter(is_default_site=True)[0]
  291. # Set a dummy favicon
  292. layout = LayoutSettings.for_site(site)
  293. img = Image.objects.create(
  294. title="Test image",
  295. file=get_test_image_file(),
  296. )
  297. layout.favicon = img
  298. layout.save()
  299. # Expect a 301 redirect
  300. response = client.get("/favicon.ico")
  301. self.assertEqual(response.status_code, 301)