diff --git a/wagtail/wagtailadmin/templatetags/localize.py b/wagtail/wagtailadmin/templatetags/localize.py
deleted file mode 100644
index 026dbe878..000000000
--- a/wagtail/wagtailadmin/templatetags/localize.py
+++ /dev/null
@@ -1,62 +0,0 @@
-from django import template
-from django.conf import settings
-from django.templatetags.static import static
-from django.utils import formats
-from django.utils.translation import get_language
-
-register = template.Library()
-
-# For reasons unkown, the el (greek) locale in django/conf/locale/el/formats.py
-# *did not* contain a DATE_INPUT_FORMATS -- so it fell back to using the US
-# date format (mm/dd/yy) which is not the correct one for Greece (dd/mm/yy).
-# This means that if we used a localized datepicker django *won't* be able to
-# parse the dates! So a test here checks if DATE_INPUT_FORMATS is actually
-# defined in a format module. If yes then it will just return an empty string
-# so that the normal, localized date format from datepicker will be used.
-# If DATE_INPUT_FORMATS is not defined then it will return
-@register.assignment_tag
-def get_date_format_override():
- if hasattr(settings, 'USE_I18N') and settings.USE_I18N==True:
-
- for m in formats.get_format_modules():
- if hasattr(m, 'DATE_INPUT_FORMATS'):
- return ''
- else: # fall back to the ISO to be sure date will be parsed
- return 'yy-mm-dd'
- else: # Fall back to ISO if I18N is *not* used
- return 'yy-mm-dd'
-
-# This is a list of all supported langs for jquery-ui datepicker which exist in
-# wagtailadmin/js/venor/i18n/. In case any new translations are added there the
-# language code should also be added in this list.
-SUPPORTED_DATEPICKER_LANGS = ['af', 'ar-DZ', 'ar', 'az', 'be', 'bg', 'bs', 'ca', 'cs', 'cy-GB', 'da', 'de',
- 'el', 'en-AU', 'en-GB', 'en-NZ', 'eo', 'es', 'et', 'eu', 'fa', 'fi', 'fo', 'fr-CA', 'fr-CH', 'fr', 'gl',
- 'he', 'hi', 'hr', 'hu', 'hy', 'id', 'is', 'it', 'ja', 'ka', 'kk', 'km', 'ko', 'ky', 'lb', 'lt', 'lv',
- 'mk', 'ml', 'ms', 'nb', 'nl-BE', 'nl', 'nn', 'no', 'pl', 'pt-BR', 'pt', 'rm', 'ro', 'ru', 'sk', 'sl', 'sq',
- 'sr-SR', 'sr', 'sv', 'ta', 'th', 'tj', 'tr', 'uk', 'vi', 'zh-CN', 'zh-HK', 'zh-TW'
-]
-# Get the correct i18n + l10n settings for datepicker depending on current
-# thread language
-@register.simple_tag
-def get_localized_datepicker_js():
- if hasattr(settings, 'USE_I18N') and settings.USE_I18N==True and \
- hasattr(settings, 'USE_L10N') and settings.USE_L10N==True:
-
- lang = get_language()
-
- if '-' in lang:
- lang_parts = lang.split('-')
- lang = lang_parts[0].lower() +'-'+ lang_parts[1].upper()
- else:
- lang=lang.lower()
- if lang in SUPPORTED_DATEPICKER_LANGS:
- translation_file = static("wagtailadmin/js/vendor/i18n/jquery.ui.datepicker-{0}.js".format(
- lang
- ))
- return ''.format(translation_file)
- else: # Don't return anything if language is not supported
- return ''
-
- else: # Don't return anything if we don't use I18N and L10N
- return ''
-
\ No newline at end of file
diff --git a/wagtail/wagtailadmin/tests/test_account_management.py b/wagtail/wagtailadmin/tests/test_account_management.py
index 95d54d7d9..3553b8fba 100644
--- a/wagtail/wagtailadmin/tests/test_account_management.py
+++ b/wagtail/wagtailadmin/tests/test_account_management.py
@@ -1,17 +1,17 @@
from django.test import TestCase
-from wagtail.tests.utils import login, unittest
+from wagtail.tests.utils import unittest, WagtailTestUtils
from django.core.urlresolvers import reverse
from django.contrib.auth.models import User
from django.contrib.auth.tokens import PasswordResetTokenGenerator
from django.core import mail
-class TestAuthentication(TestCase):
+class TestAuthentication(TestCase, WagtailTestUtils):
"""
This tests that users can login and logout of the admin interface
"""
def setUp(self):
- login(self.client)
+ self.login()
def test_login_view(self):
"""
@@ -44,12 +44,12 @@ class TestAuthentication(TestCase):
# Check that the user was redirected to the dashboard
self.assertEqual(response.status_code, 302)
+ self.assertURLEqual(response.url, reverse('wagtailadmin_home'))
# Check that the user was logged in
self.assertTrue('_auth_user_id' in self.client.session)
self.assertEqual(self.client.session['_auth_user_id'], User.objects.get(username='test').id)
- @unittest.expectedFailure # See: https://github.com/torchbox/wagtail/issues/25
def test_already_logged_in_redirect(self):
"""
This tests that a user who is already logged in is automatically
@@ -61,27 +61,63 @@ class TestAuthentication(TestCase):
# Check that the user was redirected to the dashboard
self.assertEqual(response.status_code, 302)
+ self.assertURLEqual(response.url, reverse('wagtailadmin_home'))
def test_logout(self):
"""
This tests that the user can logout
"""
- # Get logout page page
+ # Get logout page
response = self.client.get(reverse('wagtailadmin_logout'))
# Check that the user was redirected to the login page
self.assertEqual(response.status_code, 302)
+ self.assertURLEqual(response.url, reverse('wagtailadmin_login'))
# Check that the user was logged out
self.assertFalse('_auth_user_id' in self.client.session)
+ def test_not_logged_in_redirect(self):
+ """
+ This tests that a not logged in user is redirected to the
+ login page
+ """
+ # Logout
+ self.client.logout()
-class TestAccountSection(TestCase):
+ # Get dashboard
+ response = self.client.get(reverse('wagtailadmin_home'))
+
+ # Check that the user was redirected to the login page and that next was set correctly
+ self.assertEqual(response.status_code, 302)
+ self.assertURLEqual(response.url, reverse('wagtailadmin_login') + '?next=' + reverse('wagtailadmin_home'))
+
+ def test_not_logged_in_redirect_default_settings(self):
+ """
+ This does the same as the above test but checks that it
+ redirects to the correct place when the user has not set
+ the LOGIN_URL setting correctly
+ """
+ # Logout
+ self.client.logout()
+
+ # Get dashboard with default LOGIN_URL setting
+ with self.settings(LOGIN_URL='django.contrib.auth.views.login'):
+ response = self.client.get(reverse('wagtailadmin_home'))
+
+ # Check that the user was redirected to the login page and that next was set correctly
+ # Note: The user will be redirected to 'django.contrib.auth.views.login' but
+ # this must be the same URL as 'wagtailadmin_login'
+ self.assertEqual(response.status_code, 302)
+ self.assertURLEqual(response.url, reverse('wagtailadmin_login') + '?next=' + reverse('wagtailadmin_home'))
+
+
+class TestAccountSection(TestCase, WagtailTestUtils):
"""
This tests that the accounts section is working
"""
def setUp(self):
- login(self.client)
+ self.login()
def test_account_view(self):
"""
@@ -117,8 +153,9 @@ class TestAccountSection(TestCase):
}
response = self.client.post(reverse('wagtailadmin_account_change_password'), post_data)
- # Check that the user was redirected
+ # Check that the user was redirected to the account page
self.assertEqual(response.status_code, 302)
+ self.assertURLEqual(response.url, reverse('wagtailadmin_account'))
# Check that the password was changed
self.assertTrue(User.objects.get(username='test').check_password('newpassword'))
@@ -146,7 +183,7 @@ class TestAccountSection(TestCase):
self.assertTrue(User.objects.get(username='test').check_password('password'))
-class TestPasswordReset(TestCase):
+class TestPasswordReset(TestCase, WagtailTestUtils):
"""
This tests that the password reset is working
"""
@@ -176,8 +213,9 @@ class TestPasswordReset(TestCase):
}
response = self.client.post(reverse('password_reset'), post_data)
- # Check that the user was redirected
+ # Check that the user was redirected to the done page
self.assertEqual(response.status_code, 302)
+ self.assertURLEqual(response.url, reverse('password_reset_done'))
# Check that a password reset email was sent to the user
self.assertEqual(len(mail.outbox), 1)
@@ -267,8 +305,9 @@ class TestPasswordReset(TestCase):
}
response = self.client.post(reverse('password_reset_confirm', kwargs=self.url_kwargs), post_data)
- # Check that the user was redirected
+ # Check that the user was redirected to the complete page
self.assertEqual(response.status_code, 302)
+ self.assertURLEqual(response.url, reverse('password_reset_complete'))
# Check that the password was changed
self.assertTrue(User.objects.get(username='test').check_password('newpassword'))
diff --git a/wagtail/wagtailadmin/tests/test_edit_handlers.py b/wagtail/wagtailadmin/tests/test_edit_handlers.py
index 45db35c5b..8e0e4a7c5 100644
--- a/wagtail/wagtailadmin/tests/test_edit_handlers.py
+++ b/wagtail/wagtailadmin/tests/test_edit_handlers.py
@@ -1,15 +1,8 @@
from mock import MagicMock
from django.test import TestCase
-from django.core.exceptions import ValidationError
from wagtail.wagtailadmin.edit_handlers import (
- FriendlyDateInput,
- FriendlyTimeInput,
- FriendlyTimeField,
- LocalizedTimeInput,
- LocalizedDateInput,
- LocalizedTimeField,
get_form_for_model,
extract_panel_definitions_from_model_class,
BaseFieldPanel,
@@ -27,148 +20,6 @@ from wagtail.wagtailadmin.edit_handlers import (
from wagtail.wagtailcore.models import Page, Site
-class TestFriendlyDateInput(TestCase):
- def test_attrs(self):
- """
- When the attrs argument is passed to FriendlyDateInput's
- constructor, they should be set on the FriendlyDateInput
- object along with the default attrs
- """
- friendly = FriendlyDateInput(attrs={'awesome': 'sauce'})
- self.assertEqual(friendly.attrs, {'class': 'friendly_date',
- 'awesome': 'sauce'})
-
-
-class TestFriendlyTimeInput(TestCase):
- def test_attrs(self):
- """
- When the attrs argument is passed to FriendlyDateInput's
- constructor, they should be set on the FriendlyDateInput
- object along with the default attrs
- """
- friendly = FriendlyTimeInput(attrs={'awesome': 'sauce'})
- self.assertEqual(friendly.attrs, {'class': 'friendly_time',
- 'awesome': 'sauce'})
-
-
-class TestFriendlyTimeField(TestCase):
- def setUp(self):
- self.friendly = FriendlyTimeField()
-
- def test_no_time_string(self):
- """
- to_python() should return None if it is passed an empty
- string
- """
- result = self.friendly.to_python('')
- self.assertEqual(result, None)
-
- def test_invalid_time_string(self):
- """
- to_python() should raise a ValidationError if it is passed
- an invalid time string
- """
- self.assertRaises(ValidationError, self.friendly.to_python, 'bacon')
-
- def test_afternoon_time_string(self):
- """
- to_python() should convert a time string that ends with 'pm'
- to a 24-hour time in the afternoon
- """
- python_time = self.friendly.to_python('3:49pm')
- self.assertEqual(str(python_time), '15:49:00')
-
- def test_morning_time_string(self):
- """
- to_python() should convert a time string that ends with 'am'
- to a 24-hour time in the morning
- """
- python_time = self.friendly.to_python('3:49am')
- self.assertEqual(str(python_time), '03:49:00')
-
- def test_no_minutes_time_string(self):
- """
- If minutes are not specified in the time string, they should
- default to zero
- """
- python_time = self.friendly.to_python('3am')
- self.assertEqual(str(python_time), '03:00:00')
-
-
-class TestLocalizedDateInput(TestCase):
- def test_attrs(self):
- """
- When the attrs argument is passed to LocalizedDateInput's
- constructor, they should be set on the LocalizedDateInput
- object along with the default attrs
- """
- localized = LocalizedDateInput(attrs={'awesome': 'sauce'})
- self.assertEqual(localized.attrs, {'class': 'localized_date',
- 'localize': True,
- 'awesome': 'sauce'})
-
-
-class TestLocalizedTimeInput(TestCase):
- def test_attrs(self):
- """
- When the attrs argument is passed to LocalizedTimeInput's
- constructor, they should be set on the LocalizedTimeInput
- object along with the default attrs
- """
- localized = LocalizedTimeInput(attrs={'awesome': 'sauce'})
- self.assertEqual(localized.attrs, {'class': 'localized_time',
- 'awesome': 'sauce'})
-
-
-class TestLocalizedTimeField(TestCase):
- def setUp(self):
- self.localized = LocalizedTimeField()
-
- def test_no_time_string(self):
- """
- to_python() should return None if it is passed an empty
- string
- """
- result = self.localized.to_python('')
- self.assertEqual(result, None)
-
- def test_non_time_string(self):
- """
- to_python() should raise a ValidationError if it is passed
- a string that does not represent a time
- """
- self.assertRaises(ValidationError, self.localized.to_python, 'bacon')
-
- def test_invalid_time_string(self):
- """
- to_python() should raise a ValidationError if it is passed
- an invalid time string
- """
- self.assertRaises(ValidationError, self.localized.to_python, '99:99')
-
- def test_afternoon_time_string(self):
- """
- to_python() should understand 24-hour time
- """
- python_time = self.localized.to_python('15:49')
- self.assertEqual(str(python_time), '15:49:00')
-
- def test_morning_time_string(self):
- """
- to_python() should understand 24-hour time
- """
- python_time = self.localized.to_python('3:49')
- self.assertEqual(str(python_time), '03:49:00')
-
- def test_no_minutes_time_string(self):
- """
- If minutes are not specified in the time string, they should
- default to zero
- """
- python_time = self.localized.to_python('3')
- self.assertEqual(str(python_time), '03:00:00')
-
-
class TestGetFormForModel(TestCase):
class FakeClass(object):
_meta = MagicMock()
diff --git a/wagtail/wagtailadmin/tests/test_page_chooser.py b/wagtail/wagtailadmin/tests/test_page_chooser.py
index b5add3f15..475e4f7b1 100644
--- a/wagtail/wagtailadmin/tests/test_page_chooser.py
+++ b/wagtail/wagtailadmin/tests/test_page_chooser.py
@@ -3,9 +3,10 @@ from django.core.urlresolvers import reverse
from wagtail.wagtailcore.models import Page
from wagtail.tests.models import SimplePage
-from wagtail.tests.utils import login
+from wagtail.tests.utils import WagtailTestUtils
-class TestChooserBrowse(TestCase):
+
+class TestChooserBrowse(TestCase, WagtailTestUtils):
def setUp(self):
self.root_page = Page.objects.get(id=2)
@@ -15,13 +16,15 @@ class TestChooserBrowse(TestCase):
self.child_page.slug = "foobarbaz"
self.root_page.add_child(instance=self.child_page)
- login(self.client)
+ self.login()
def get(self, params={}):
return self.client.get(reverse('wagtailadmin_choose_page'), params)
- def test_status_code(self):
- self.assertEqual(self.get().status_code, 200)
+ def test_simple(self):
+ response = self.get()
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, 'wagtailadmin/chooser/browse.html')
def test_search(self):
response = self.get({'q': "foobarbaz"})
@@ -39,7 +42,7 @@ class TestChooserBrowse(TestCase):
self.assertEqual(response.status_code, 404)
-class TestChooserBrowseChild(TestCase):
+class TestChooserBrowseChild(TestCase, WagtailTestUtils):
def setUp(self):
self.root_page = Page.objects.get(id=2)
@@ -49,7 +52,7 @@ class TestChooserBrowseChild(TestCase):
self.child_page.slug = "foobarbaz"
self.root_page.add_child(instance=self.child_page)
- login(self.client)
+ self.login()
def get(self, params={}):
return self.client.get(reverse('wagtailadmin_choose_page_child',
@@ -59,8 +62,10 @@ class TestChooserBrowseChild(TestCase):
return self.client.get(reverse('wagtailadmin_choose_page_child',
args=(9999999,)), params)
- def test_status_code(self):
- self.assertEqual(self.get().status_code, 200)
+ def test_simple(self):
+ response = self.get()
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, 'wagtailadmin/chooser/browse.html')
def test_search(self):
response = self.get({'q': "foobarbaz"})
@@ -77,9 +82,9 @@ class TestChooserBrowseChild(TestCase):
self.assertEqual(self.get_invalid().status_code, 404)
-class TestChooserExternalLink(TestCase):
+class TestChooserExternalLink(TestCase, WagtailTestUtils):
def setUp(self):
- login(self.client)
+ self.login()
def get(self, params={}):
return self.client.get(reverse('wagtailadmin_choose_page_external_link'), params)
@@ -87,8 +92,10 @@ class TestChooserExternalLink(TestCase):
def post(self, post_data={}):
return self.client.post(reverse('wagtailadmin_choose_page_external_link'), post_data)
- def test_status_code(self):
- self.assertEqual(self.get().status_code, 200)
+ def test_simple(self):
+ response = self.get()
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, 'wagtailadmin/chooser/external_link.html')
def test_get_with_param(self):
self.assertEqual(self.get({'prompt_for_link_text': 'foo'}).status_code, 200)
@@ -99,9 +106,9 @@ class TestChooserExternalLink(TestCase):
self.assertContains(request, "'title': 'http://www.example.com/'")
-class TestChooserEmailLink(TestCase):
+class TestChooserEmailLink(TestCase, WagtailTestUtils):
def setUp(self):
- login(self.client)
+ self.login()
def get(self, params={}):
return self.client.get(reverse('wagtailadmin_choose_page_email_link'), params)
@@ -109,8 +116,10 @@ class TestChooserEmailLink(TestCase):
def post(self, post_data={}):
return self.client.post(reverse('wagtailadmin_choose_page_email_link'), post_data)
- def test_status_code(self):
- self.assertEqual(self.get().status_code, 200)
+ def test_simple(self):
+ response = self.get()
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, 'wagtailadmin/chooser/email_link.html')
def test_get_with_param(self):
self.assertEqual(self.get({'prompt_for_link_text': 'foo'}).status_code, 200)
diff --git a/wagtail/wagtailadmin/tests/test_pages_views.py b/wagtail/wagtailadmin/tests/test_pages_views.py
index 14e57a35e..09e6b6f5c 100644
--- a/wagtail/wagtailadmin/tests/test_pages_views.py
+++ b/wagtail/wagtailadmin/tests/test_pages_views.py
@@ -1,13 +1,13 @@
from django.test import TestCase
-from wagtail.tests.models import SimplePage, EventPage
-from wagtail.tests.utils import login, unittest
+from wagtail.tests.models import SimplePage, EventPage, StandardIndex, StandardChild, BusinessIndex, BusinessChild
+from wagtail.tests.utils import unittest, WagtailTestUtils
from wagtail.wagtailcore.models import Page, PageRevision
from django.core.urlresolvers import reverse
from django.contrib.auth.models import User, Permission
from django.core import mail
-class TestPageExplorer(TestCase):
+class TestPageExplorer(TestCase, WagtailTestUtils):
def setUp(self):
# Find root page
self.root_page = Page.objects.get(id=2)
@@ -19,7 +19,7 @@ class TestPageExplorer(TestCase):
self.root_page.add_child(instance=self.child_page)
# Login
- login(self.client)
+ self.login()
def test_explore(self):
response = self.client.get(reverse('wagtailadmin_explore', args=(self.root_page.id, )))
@@ -28,13 +28,13 @@ class TestPageExplorer(TestCase):
self.assertTrue(response.context['pages'].paginator.object_list.filter(id=self.child_page.id).exists())
-class TestPageCreation(TestCase):
+class TestPageCreation(TestCase, WagtailTestUtils):
def setUp(self):
# Find root page
self.root_page = Page.objects.get(id=2)
# Login
- self.user = login(self.client)
+ self.user = self.login()
def test_add_subpage(self):
response = self.client.get(reverse('wagtailadmin_pages_add_subpage', args=(self.root_page.id, )))
@@ -86,6 +86,7 @@ class TestPageCreation(TestCase):
# Should be redirected to explorer page
self.assertEqual(response.status_code, 302)
+ self.assertURLEqual(response.url, reverse('wagtailadmin_explore', args=(self.root_page.id, )))
# Find the page and check it
page = Page.objects.get(path__startswith=self.root_page.path, slug='hello-world').specific
@@ -104,6 +105,7 @@ class TestPageCreation(TestCase):
# Should be redirected to explorer page
self.assertEqual(response.status_code, 302)
+ self.assertURLEqual(response.url, reverse('wagtailadmin_explore', args=(self.root_page.id, )))
# Find the page and check it
page = Page.objects.get(path__startswith=self.root_page.path, slug='hello-world').specific
@@ -126,6 +128,7 @@ class TestPageCreation(TestCase):
# Should be redirected to explorer page
self.assertEqual(response.status_code, 302)
+ self.assertURLEqual(response.url, reverse('wagtailadmin_explore', args=(self.root_page.id, )))
# Find the page and check it
page = Page.objects.get(path__startswith=self.root_page.path, slug='hello-world').specific
@@ -185,8 +188,13 @@ class TestPageCreation(TestCase):
self.assertTemplateUsed(response, 'tests/simple_page.html')
self.assertContains(response, "New page!")
+ # Check that the treebeard attributes were set correctly on the page object
+ self.assertEqual(response.context['self'].depth, self.root_page.depth + 1)
+ self.assertTrue(response.context['self'].path.startswith(self.root_page.path))
+ self.assertEqual(response.context['self'].get_parent(), self.root_page)
-class TestPageEdit(TestCase):
+
+class TestPageEdit(TestCase, WagtailTestUtils):
def setUp(self):
# Find root page
self.root_page = Page.objects.get(id=2)
@@ -206,7 +214,7 @@ class TestPageEdit(TestCase):
self.root_page.add_child(instance=self.event_page)
# Login
- self.user = login(self.client)
+ self.user = self.login()
def test_page_edit(self):
# Tests that the edit page loads
@@ -238,6 +246,7 @@ class TestPageEdit(TestCase):
# Should be redirected to explorer page
self.assertEqual(response.status_code, 302)
+ self.assertURLEqual(response.url, reverse('wagtailadmin_explore', args=(self.root_page.id, )))
# The page should have "has_unpublished_changes" flag set
child_page_new = SimplePage.objects.get(id=self.child_page.id)
@@ -255,6 +264,7 @@ class TestPageEdit(TestCase):
# Should be redirected to explorer page
self.assertEqual(response.status_code, 302)
+ self.assertURLEqual(response.url, reverse('wagtailadmin_explore', args=(self.root_page.id, )))
# Check that the page was edited
child_page_new = SimplePage.objects.get(id=self.child_page.id)
@@ -278,6 +288,7 @@ class TestPageEdit(TestCase):
# Should be redirected to explorer page
self.assertEqual(response.status_code, 302)
+ self.assertURLEqual(response.url, reverse('wagtailadmin_explore', args=(self.root_page.id, )))
# The page should have "has_unpublished_changes" flag set
child_page_new = SimplePage.objects.get(id=self.child_page.id)
@@ -306,7 +317,7 @@ class TestPageEdit(TestCase):
self.assertContains(response, "I've been edited!")
-class TestPageDelete(TestCase):
+class TestPageDelete(TestCase, WagtailTestUtils):
def setUp(self):
# Find root page
self.root_page = Page.objects.get(id=2)
@@ -318,7 +329,7 @@ class TestPageDelete(TestCase):
self.root_page.add_child(instance=self.child_page)
# Login
- self.user = login(self.client)
+ self.user = self.login()
def test_page_delete(self):
response = self.client.get(reverse('wagtailadmin_pages_delete', args=(self.child_page.id, )))
@@ -344,15 +355,16 @@ class TestPageDelete(TestCase):
# Should be redirected to explorer page
self.assertEqual(response.status_code, 302)
+ self.assertURLEqual(response.url, reverse('wagtailadmin_explore', args=(self.root_page.id, )))
# Check that the page is gone
self.assertEqual(Page.objects.filter(path__startswith=self.root_page.path, slug='hello-world').count(), 0)
-class TestPageSearch(TestCase):
+class TestPageSearch(TestCase, WagtailTestUtils):
def setUp(self):
# Login
- login(self.client)
+ self.login()
def get(self, params=None, **extra):
return self.client.get(reverse('wagtailadmin_pages_search'), params or {}, **extra)
@@ -390,7 +402,7 @@ class TestPageSearch(TestCase):
self.assertTrue(any([r.slug == 'root' for r in results]))
-class TestPageMove(TestCase):
+class TestPageMove(TestCase, WagtailTestUtils):
def setUp(self):
# Find root page
self.root_page = Page.objects.get(id=2)
@@ -413,7 +425,7 @@ class TestPageMove(TestCase):
self.section_a.add_child(instance=self.test_page)
# Login
- self.user = login(self.client)
+ self.user = self.login()
def test_page_move(self):
response = self.client.get(reverse('wagtailadmin_pages_move', args=(self.test_page.id, )))
@@ -442,18 +454,18 @@ class TestPageMove(TestCase):
self.assertEqual(response.status_code, 200)
-class TestPageUnpublish(TestCase):
+class TestPageUnpublish(TestCase, WagtailTestUtils):
def setUp(self):
- self.user = login(self.client)
+ self.user = self.login()
# Create a page to unpublish
- root_page = Page.objects.get(id=2)
+ self.root_page = Page.objects.get(id=2)
self.page = SimplePage(
title="Hello world!",
slug='hello-world',
live=True,
)
- root_page.add_child(instance=self.page)
+ self.root_page.add_child(instance=self.page)
def test_unpublish_view(self):
"""
@@ -502,14 +514,15 @@ class TestPageUnpublish(TestCase):
'foo': "Must post something or the view won't see this as a POST request",
})
- # Check that the user was redirected
+ # Check that the user was redirected to the explore page
self.assertEqual(response.status_code, 302)
+ self.assertURLEqual(response.url, reverse('wagtailadmin_explore', args=(self.root_page.id, )))
# Check that the page was unpublished
self.assertFalse(SimplePage.objects.get(id=self.page.id).live)
-class TestApproveRejectModeration(TestCase):
+class TestApproveRejectModeration(TestCase, WagtailTestUtils):
def setUp(self):
self.submitter = User.objects.create_superuser(
username='submitter',
@@ -517,7 +530,7 @@ class TestApproveRejectModeration(TestCase):
password='password',
)
- self.user = login(self.client)
+ self.user = self.login()
# Create a page and submit it for moderation
root_page = Page.objects.get(id=2)
@@ -540,8 +553,9 @@ class TestApproveRejectModeration(TestCase):
'foo': "Must post something or the view won't see this as a POST request",
})
- # Check that the user was redirected
+ # Check that the user was redirected to the dashboard
self.assertEqual(response.status_code, 302)
+ self.assertURLEqual(response.url, reverse('wagtailadmin_home'))
# Page must be live
self.assertTrue(Page.objects.get(id=self.page.id).live)
@@ -591,8 +605,9 @@ class TestApproveRejectModeration(TestCase):
'foo': "Must post something or the view won't see this as a POST request",
})
- # Check that the user was redirected
+ # Check that the user was redirected to the dashboard
self.assertEqual(response.status_code, 302)
+ self.assertURLEqual(response.url, reverse('wagtailadmin_home'))
# Page must not be live
self.assertFalse(Page.objects.get(id=self.page.id).live)
@@ -645,11 +660,11 @@ class TestApproveRejectModeration(TestCase):
self.assertContains(response, "Hello world!")
-class TestContentTypeUse(TestCase):
+class TestContentTypeUse(TestCase, WagtailTestUtils):
fixtures = ['test.json']
def setUp(self):
- self.user = login(self.client)
+ self.user = self.login()
def test_content_type_use(self):
# Get use of event page
@@ -659,3 +674,48 @@ class TestContentTypeUse(TestCase):
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailadmin/pages/content_type_use.html')
self.assertContains(response, "Christmas")
+
+
+class TestSubpageBusinessRules(TestCase, WagtailTestUtils):
+ def setUp(self):
+ # Find root page
+ self.root_page = Page.objects.get(id=2)
+
+ # Add standard page
+ self.standard_index = StandardIndex()
+ self.standard_index.title = "Standard Index"
+ self.standard_index.slug = "standard-index"
+ self.root_page.add_child(instance=self.standard_index)
+
+ # Add business page
+ self.business_index = BusinessIndex()
+ self.business_index.title = "Business Index"
+ self.business_index.slug = "business-index"
+ self.root_page.add_child(instance=self.business_index)
+
+ # Add business child
+ self.business_child = BusinessChild()
+ self.business_child.title = "Business Child"
+ self.business_child.slug = "business-child"
+ self.business_index.add_child(instance=self.business_child)
+
+ # Login
+ self.login()
+
+ def test_standard_subpage(self):
+ response = self.client.get(reverse('wagtailadmin_pages_add_subpage', args=(self.standard_index.id, )))
+ self.assertEqual(response.status_code, 200)
+ self.assertContains(response, 'Standard Child')
+ self.assertContains(response, 'Business Child')
+
+ def test_business_subpage(self):
+ response = self.client.get(reverse('wagtailadmin_pages_add_subpage', args=(self.business_index.id, )))
+ self.assertEqual(response.status_code, 200)
+ self.assertNotContains(response, 'Standard Child')
+ self.assertContains(response, 'Business Child')
+
+ def test_business_child_subpage(self):
+ response = self.client.get(reverse('wagtailadmin_pages_add_subpage', args=(self.business_child.id, )))
+ self.assertEqual(response.status_code, 200)
+ self.assertNotContains(response, 'Standard Child')
+ self.assertEqual(0, len(response.context['page_types']))
diff --git a/wagtail/wagtailadmin/tests/tests.py b/wagtail/wagtailadmin/tests/tests.py
index 12aa28a0b..f014c026d 100644
--- a/wagtail/wagtailadmin/tests/tests.py
+++ b/wagtail/wagtailadmin/tests/tests.py
@@ -1,26 +1,26 @@
from django.test import TestCase
from wagtail.tests.models import SimplePage, EventPage
-from wagtail.tests.utils import login, unittest
+from wagtail.tests.utils import unittest, WagtailTestUtils
from wagtail.wagtailcore.models import Page
from wagtail.wagtailadmin.tasks import send_email_task
from django.core.urlresolvers import reverse
from django.core import mail
-class TestHome(TestCase):
+class TestHome(TestCase, WagtailTestUtils):
def setUp(self):
# Login
- login(self.client)
+ self.login()
- def test_status_code(self):
+ def test_simple(self):
response = self.client.get(reverse('wagtailadmin_home'))
self.assertEqual(response.status_code, 200)
-class TestEditorHooks(TestCase):
+class TestEditorHooks(TestCase, WagtailTestUtils):
def setUp(self):
self.homepage = Page.objects.get(id=2)
- login(self.client)
+ self.login()
def test_editor_css_and_js_hooks_on_add(self):
response = self.client.get(reverse('wagtailadmin_pages_create', args=('tests', 'simplepage', self.homepage.id)))
diff --git a/wagtail/wagtailadmin/urls.py b/wagtail/wagtailadmin/urls.py
index 8fbf2f6e7..21f127c1d 100644
--- a/wagtail/wagtailadmin/urls.py
+++ b/wagtail/wagtailadmin/urls.py
@@ -5,15 +5,8 @@ from wagtail.wagtailadmin.forms import LoginForm, PasswordResetForm
from wagtail.wagtailadmin.views import account, chooser, home, pages, tags, userbar
from wagtail.wagtailadmin import hooks
-urlpatterns = [
- url(
- r'^login/$', 'django.contrib.auth.views.login', {
- 'template_name': 'wagtailadmin/login.html',
- 'authentication_form': LoginForm,
- 'extra_context': {'show_password_reset': getattr(settings, 'WAGTAIL_PASSWORD_MANAGEMENT_ENABLED', True)},
- }, name='wagtailadmin_login'
- ),
+urlpatterns = [
# Password reset
url(
r'^password_reset/$', 'django.contrib.auth.views.password_reset', {
@@ -56,7 +49,8 @@ urlpatterns += [
url(r'^pages/(\d+)/edit/$', pages.edit, name='wagtailadmin_pages_edit'),
url(r'^pages/(\d+)/edit/preview/$', pages.preview_on_edit, name='wagtailadmin_pages_preview_on_edit'),
- url(r'^pages/preview_placeholder/$', pages.preview_placeholder, name='wagtailadmin_pages_preview_placeholder'),
+ url(r'^pages/preview/$', pages.preview, name='wagtailadmin_pages_preview'),
+ url(r'^pages/preview_loading/$', pages.preview_loading, name='wagtailadmin_pages_preview_loading'),
url(r'^pages/(\d+)/view_draft/$', pages.view_draft, name='wagtailadmin_pages_view_draft'),
url(r'^pages/(\d+)/add_subpage/$', pages.add_subpage, name='wagtailadmin_pages_add_subpage'),
@@ -81,6 +75,7 @@ urlpatterns += [
url(r'^tag-autocomplete/$', tags.autocomplete, name='wagtailadmin_tag_autocomplete'),
+ url(r'^login/$', account.login, name='wagtailadmin_login'),
url(r'^account/$', account.account, name='wagtailadmin_account'),
url(r'^account/change_password/$', account.change_password, name='wagtailadmin_account_change_password'),
url(r'^logout/$', account.logout, name='wagtailadmin_logout'),
@@ -90,6 +85,13 @@ urlpatterns += [
]
+# This is here to make sure that 'django.contrib.auth.views.login' is reversed correctly
+# It must be placed after 'wagtailadmin_login' to prevent this from being used
+urlpatterns += [
+ url(r'^login/$', 'django.contrib.auth.views.login'),
+]
+
+
# Import additional urlpatterns from any apps that define a register_admin_urls hook
for fn in hooks.get_hooks('register_admin_urls'):
urls = fn()
diff --git a/wagtail/wagtailadmin/views/account.py b/wagtail/wagtailadmin/views/account.py
index 8479ea6b0..c5e461f55 100644
--- a/wagtail/wagtailadmin/views/account.py
+++ b/wagtail/wagtailadmin/views/account.py
@@ -3,8 +3,13 @@ from django.shortcuts import render, redirect
from django.contrib import messages
from django.contrib.auth.forms import SetPasswordForm
from django.contrib.auth.decorators import permission_required
-from django.contrib.auth.views import logout as auth_logout
+from django.contrib.auth.views import logout as auth_logout, login as auth_login
from django.utils.translation import ugettext as _
+from django.views.decorators.debug import sensitive_post_parameters
+from django.views.decorators.cache import never_cache
+
+from wagtail.wagtailadmin import forms
+
@permission_required('wagtailadmin.access_admin')
def account(request):
@@ -37,6 +42,21 @@ def change_password(request):
})
+@sensitive_post_parameters()
+@never_cache
+def login(request):
+ if request.user.is_authenticated():
+ return redirect('wagtailadmin_home')
+ else:
+ return auth_login(request,
+ template_name='wagtailadmin/login.html',
+ authentication_form=forms.LoginForm,
+ extra_context={
+ 'show_password_reset': getattr(settings, 'WAGTAIL_PASSWORD_MANAGEMENT_ENABLED', True),
+ },
+ )
+
+
def logout(request):
response = auth_logout(request, next_page = 'wagtailadmin_login')
diff --git a/wagtail/wagtailadmin/views/pages.py b/wagtail/wagtailadmin/views/pages.py
index 69e6b7f4f..c3eb24e9e 100644
--- a/wagtail/wagtailadmin/views/pages.py
+++ b/wagtail/wagtailadmin/views/pages.py
@@ -57,13 +57,11 @@ def add_subpage(request, parent_page_id):
if not parent_page.permissions_for_user(request.user).can_add_subpage():
raise PermissionDenied
- page_types = sorted([ContentType.objects.get_for_model(model_class) for model_class in parent_page.clean_subpage_types()], key=lambda pagetype: pagetype.name.lower())
- all_page_types = sorted(get_page_types(), key=lambda pagetype: pagetype.name.lower())
+ page_types = sorted(parent_page.clean_subpage_types(), key=lambda pagetype: pagetype.name.lower())
return render(request, 'wagtailadmin/pages/add_subpage.html', {
'parent_page': parent_page,
'page_types': page_types,
- 'all_page_types': all_page_types,
})
@@ -364,6 +362,10 @@ def preview_on_create(request, content_type_app_name, content_type_model_name, p
parent_page = get_object_or_404(Page, id=parent_page_id).specific
page.set_url_path(parent_page)
+ # Set treebeard attributes
+ page.depth = parent_page.depth + 1
+ page.path = Page._get_children_path_interval(parent_page.path)[1]
+
# This view will generally be invoked as an AJAX request; as such, in the case of
# an error Django will return a plaintext response. This isn't what we want, since
# we will be writing the response back to an HTML page regardless of success or
@@ -395,7 +397,7 @@ def preview_on_create(request, content_type_app_name, content_type_model_name, p
return response
-def preview_placeholder(request):
+def preview(request):
"""
The HTML of a previewed page is written to the destination browser window using document.write.
This overwrites any previous content in the window, while keeping its URL intact. This in turn
@@ -416,8 +418,13 @@ def preview_placeholder(request):
Since we're going to this trouble, we'll also take the opportunity to display a spinner on the
placeholder page, providing some much-needed visual feedback.
"""
- return render(request, 'wagtailadmin/pages/preview_placeholder.html')
+ return render(request, 'wagtailadmin/pages/preview.html')
+def preview_loading(request):
+ """
+ This page is blank, but must be real HTML so its DOM can be written to once the preview of the page has rendered
+ """
+ return HttpResponse("
")
@permission_required('wagtailadmin.access_admin')
def unpublish(request, page_id):
diff --git a/wagtail/wagtailadmin/views/userbar.py b/wagtail/wagtailadmin/views/userbar.py
index 6e6ef3492..2b3749da0 100644
--- a/wagtail/wagtailadmin/views/userbar.py
+++ b/wagtail/wagtailadmin/views/userbar.py
@@ -1,9 +1,12 @@
from django.shortcuts import render
+from django.contrib.auth.decorators import permission_required
from wagtail.wagtailadmin.userbar import EditPageItem, AddPageItem, ApproveModerationEditPageItem, RejectModerationEditPageItem
from wagtail.wagtailadmin import hooks
from wagtail.wagtailcore.models import Page, PageRevision
+
+@permission_required('wagtailadmin.access_admin', raise_exception=True)
def for_frontend(request, page_id):
items = [
EditPageItem(Page.objects.get(id=page_id)),
@@ -24,6 +27,8 @@ def for_frontend(request, page_id):
'items': rendered_items,
})
+
+@permission_required('wagtailadmin.access_admin', raise_exception=True)
def for_moderation(request, revision_id):
items = [
EditPageItem(PageRevision.objects.get(id=revision_id).page),
@@ -44,4 +49,4 @@ def for_moderation(request, revision_id):
# Render the edit bird
return render(request, 'wagtailadmin/userbar/base.html', {
'items': rendered_items,
- })
\ No newline at end of file
+ })
diff --git a/wagtail/wagtailcore/models.py b/wagtail/wagtailcore/models.py
index b7e3d349e..5c3f9d1c5 100644
--- a/wagtail/wagtailcore/models.py
+++ b/wagtail/wagtailcore/models.py
@@ -1,7 +1,6 @@
-import sys
-import os
from StringIO import StringIO
from urlparse import urlparse
+import warnings
from modelcluster.models import ClusterableModel
@@ -101,30 +100,29 @@ def get_page_types():
return _PAGE_CONTENT_TYPES
-LEAF_PAGE_MODEL_CLASSES = []
-_LEAF_PAGE_CONTENT_TYPE_IDS = []
-
-
def get_leaf_page_content_type_ids():
- global _LEAF_PAGE_CONTENT_TYPE_IDS
- if len(_LEAF_PAGE_CONTENT_TYPE_IDS) != len(LEAF_PAGE_MODEL_CLASSES):
- _LEAF_PAGE_CONTENT_TYPE_IDS = [
- ContentType.objects.get_for_model(cls).id for cls in LEAF_PAGE_MODEL_CLASSES
- ]
- return _LEAF_PAGE_CONTENT_TYPE_IDS
-
-
-NAVIGABLE_PAGE_MODEL_CLASSES = []
-_NAVIGABLE_PAGE_CONTENT_TYPE_IDS = []
-
+ warnings.warn("""
+ get_leaf_page_content_type_ids is deprecated, as it treats pages without an explicit subpage_types
+ setting as 'leaf' pages. Code that calls get_leaf_page_content_type_ids must be rewritten to avoid
+ this incorrect assumption.
+ """, DeprecationWarning)
+ return [
+ content_type.id
+ for content_type in get_page_types()
+ if not getattr(content_type.model_class(), 'subpage_types', None)
+ ]
def get_navigable_page_content_type_ids():
- global _NAVIGABLE_PAGE_CONTENT_TYPE_IDS
- if len(_NAVIGABLE_PAGE_CONTENT_TYPE_IDS) != len(NAVIGABLE_PAGE_MODEL_CLASSES):
- _NAVIGABLE_PAGE_CONTENT_TYPE_IDS = [
- ContentType.objects.get_for_model(cls).id for cls in NAVIGABLE_PAGE_MODEL_CLASSES
- ]
- return _NAVIGABLE_PAGE_CONTENT_TYPE_IDS
+ warnings.warn("""
+ get_navigable_page_content_type_ids is deprecated, as it treats pages without an explicit subpage_types
+ setting as 'leaf' pages. Code that calls get_navigable_page_content_type_ids must be rewritten to avoid
+ this incorrect assumption.
+ """, DeprecationWarning)
+ return [
+ content_type.id
+ for content_type in get_page_types()
+ if getattr(content_type.model_class(), 'subpage_types', None)
+ ]
class PageManager(models.Manager):
@@ -209,10 +207,6 @@ class PageBase(models.base.ModelBase):
if not cls.is_abstract:
# register this type in the list of page content types
PAGE_MODEL_CLASSES.append(cls)
- if cls.subpage_types:
- NAVIGABLE_PAGE_MODEL_CLASSES.append(cls)
- else:
- LEAF_PAGE_MODEL_CLASSES.append(cls)
class Page(MP_Node, ClusterableModel, Indexed):
@@ -259,9 +253,6 @@ class Page(MP_Node, ClusterableModel, Indexed):
def __unicode__(self):
return self.title
- # by default pages do not allow any kind of subpages
- subpage_types = []
-
is_abstract = True # don't offer Page in the list of page types a superuser can create
def set_url_path(self, parent):
@@ -416,10 +407,10 @@ class Page(MP_Node, ClusterableModel, Indexed):
def is_navigable(self):
"""
Return true if it's meaningful to browse subpages of this page -
- i.e. it currently has subpages, or its page type indicates that sub-pages are supported,
+ i.e. it currently has subpages,
or it's at the top level (this rule necessary for empty out-of-the-box sites to have working navigation)
"""
- return (not self.is_leaf()) or (self.content_type_id not in get_leaf_page_content_type_ids()) or self.depth == 2
+ return (not self.is_leaf()) or self.depth == 2
def get_other_siblings(self):
# get sibling pages excluding self
@@ -484,25 +475,30 @@ class Page(MP_Node, ClusterableModel, Indexed):
where required
"""
if cls._clean_subpage_types is None:
- res = []
- for page_type in cls.subpage_types:
- if isinstance(page_type, basestring):
- try:
- app_label, model_name = page_type.split(".")
- except ValueError:
- # If we can't split, assume a model in current app
- app_label = cls._meta.app_label
- model_name = page_type
+ subpage_types = getattr(cls, 'subpage_types', None)
+ if subpage_types is None:
+ # if subpage_types is not specified on the Page class, allow all page types as subpages
+ res = get_page_types()
+ else:
+ res = []
+ for page_type in cls.subpage_types:
+ if isinstance(page_type, basestring):
+ try:
+ app_label, model_name = page_type.split(".")
+ except ValueError:
+ # If we can't split, assume a model in current app
+ app_label = cls._meta.app_label
+ model_name = page_type
+
+ model = get_model(app_label, model_name)
+ if model:
+ res.append(ContentType.objects.get_for_model(model))
+ else:
+ raise NameError(_("name '{0}' (used in subpage_types list) is not defined.").format(page_type))
- model = get_model(app_label, model_name)
- if model:
- res.append(model)
else:
- raise NameError(_("name '{0}' (used in subpage_types list) is not defined.").format(page_type))
-
- else:
- # assume it's already a model class
- res.append(page_type)
+ # assume it's already a model class
+ res.append(ContentType.objects.get_for_model(page_type))
cls._clean_subpage_types = res
@@ -652,13 +648,8 @@ class Page(MP_Node, ClusterableModel, Indexed):
def get_navigation_menu_items():
# Get all pages that appear in the navigation menu: ones which have children,
- # or are a non-leaf type (indicating that they *could* have children),
# or are at the top-level (this rule required so that an empty site out-of-the-box has a working menu)
- navigable_content_type_ids = get_navigable_page_content_type_ids()
- if navigable_content_type_ids:
- pages = Page.objects.filter(Q(content_type__in=navigable_content_type_ids)|Q(depth=2)|Q(numchild__gt=0)).order_by('path')
- else:
- pages = Page.objects.filter(Q(depth=2)|Q(numchild__gt=0)).order_by('path')
+ pages = Page.objects.filter(Q(depth=2)|Q(numchild__gt=0)).order_by('path')
# Turn this into a tree structure:
# tree_node = (page, children)
diff --git a/wagtail/wagtaildocs/tests.py b/wagtail/wagtaildocs/tests.py
index d068f9a27..3353ce39e 100644
--- a/wagtail/wagtaildocs/tests.py
+++ b/wagtail/wagtaildocs/tests.py
@@ -1,6 +1,6 @@
from django.test import TestCase
from wagtail.wagtaildocs import models
-from wagtail.tests.utils import login
+from wagtail.tests.utils import WagtailTestUtils
from django.contrib.auth.models import User, Group, Permission
from django.core.urlresolvers import reverse
from django.core.files.base import ContentFile
@@ -39,15 +39,17 @@ class TestDocumentPermissions(TestCase):
## ===== ADMIN VIEWS =====
-class TestDocumentIndexView(TestCase):
+class TestDocumentIndexView(TestCase, WagtailTestUtils):
def setUp(self):
- login(self.client)
+ self.login()
def get(self, params={}):
return self.client.get(reverse('wagtaildocs_index'), params)
- def test_status_code(self):
- self.assertEqual(self.get().status_code, 200)
+ def test_simple(self):
+ response = self.get()
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, 'wagtaildocs/documents/index.html')
def test_search(self):
response = self.get({'q': "Hello"})
@@ -67,20 +69,24 @@ class TestDocumentIndexView(TestCase):
self.assertEqual(response.status_code, 200)
-class TestDocumentAddView(TestCase):
+class TestDocumentAddView(TestCase, WagtailTestUtils):
def setUp(self):
- login(self.client)
+ self.login()
def get(self, params={}):
return self.client.get(reverse('wagtaildocs_add_document'), params)
- def test_status_code(self):
- self.assertEqual(self.get().status_code, 200)
+ def test_simple(self):
+ response = self.get()
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, 'wagtaildocs/documents/add.html')
+
+ # TODO: Test posting
-class TestDocumentEditView(TestCase):
+class TestDocumentEditView(TestCase, WagtailTestUtils):
def setUp(self):
- login(self.client)
+ self.login()
# Create a document to edit
self.document = models.Document.objects.create(title="Test document")
@@ -88,13 +94,17 @@ class TestDocumentEditView(TestCase):
def get(self, params={}):
return self.client.get(reverse('wagtaildocs_edit_document', args=(self.document.id,)), params)
- def test_status_code(self):
- self.assertEqual(self.get().status_code, 200)
+ def test_simple(self):
+ response = self.get()
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, 'wagtaildocs/documents/edit.html')
+
+ # TODO: Test posting
-class TestDocumentDeleteView(TestCase):
+class TestDocumentDeleteView(TestCase, WagtailTestUtils):
def setUp(self):
- login(self.client)
+ self.login()
# Create a document to delete
self.document = models.Document.objects.create(title="Test document")
@@ -102,19 +112,26 @@ class TestDocumentDeleteView(TestCase):
def get(self, params={}):
return self.client.get(reverse('wagtaildocs_delete_document', args=(self.document.id,)), params)
- def test_status_code(self):
- self.assertEqual(self.get().status_code, 200)
+ def test_simple(self):
+ response = self.get()
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, 'wagtaildocs/documents/confirm_delete.html')
+
+ # TODO: Test posting
-class TestDocumentChooserView(TestCase):
+class TestDocumentChooserView(TestCase, WagtailTestUtils):
def setUp(self):
- login(self.client)
+ self.login()
def get(self, params={}):
return self.client.get(reverse('wagtaildocs_chooser'), params)
- def test_status_code(self):
- self.assertEqual(self.get().status_code, 200)
+ def test_simple(self):
+ response = self.get()
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, 'wagtaildocs/chooser/chooser.html')
+ self.assertTemplateUsed(response, 'wagtaildocs/chooser/chooser.js')
def test_search(self):
response = self.get({'q': "Hello"})
@@ -128,9 +145,9 @@ class TestDocumentChooserView(TestCase):
self.assertEqual(response.status_code, 200)
-class TestDocumentChooserChosenView(TestCase):
+class TestDocumentChooserChosenView(TestCase, WagtailTestUtils):
def setUp(self):
- login(self.client)
+ self.login()
# Create a document to choose
self.document = models.Document.objects.create(title="Test document")
@@ -138,19 +155,28 @@ class TestDocumentChooserChosenView(TestCase):
def get(self, params={}):
return self.client.get(reverse('wagtaildocs_document_chosen', args=(self.document.id,)), params)
- def test_status_code(self):
- self.assertEqual(self.get().status_code, 200)
+ def test_simple(self):
+ response = self.get()
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, 'wagtaildocs/chooser/document_chosen.js')
+
+ # TODO: Test posting
-class TestDocumentChooserUploadView(TestCase):
+class TestDocumentChooserUploadView(TestCase, WagtailTestUtils):
def setUp(self):
- login(self.client)
+ self.login()
def get(self, params={}):
return self.client.get(reverse('wagtaildocs_chooser_upload'), params)
- def test_status_code(self):
- self.assertEqual(self.get().status_code, 200)
+ def test_simple(self):
+ response = self.get()
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, 'wagtaildocs/chooser/chooser.html')
+ self.assertTemplateUsed(response, 'wagtaildocs/chooser/chooser.js')
+
+ # TODO: Test document upload with chooser
class TestDocumentFilenameProperties(TestCase):
diff --git a/wagtail/wagtailembeds/tests.py b/wagtail/wagtailembeds/tests.py
index 0fbaf5baf..892dde5bd 100644
--- a/wagtail/wagtailembeds/tests.py
+++ b/wagtail/wagtailembeds/tests.py
@@ -8,10 +8,8 @@ except ImportError:
no_embedly = True
from django.test import TestCase
-from django.test.client import Client
-from wagtail.tests.utils import login
-from wagtail.tests.utils import unittest
+from wagtail.tests.utils import WagtailTestUtils, unittest
from wagtail.wagtailembeds import get_embed
from wagtail.wagtailembeds.embeds import (
@@ -19,8 +17,8 @@ from wagtail.wagtailembeds.embeds import (
EmbedlyException,
AccessDeniedEmbedlyException,
)
-from wagtail.wagtailembeds.embeds import embedly as wagtail_embedly
-from wagtail.wagtailembeds.embeds import oembed as wagtail_oembed
+from wagtail.wagtailembeds.embeds import embedly as wagtail_embedly, oembed as wagtail_oembed
+
class TestEmbeds(TestCase):
@@ -82,10 +80,10 @@ class TestEmbeds(TestCase):
self.assertEqual(embed.width, None)
-class TestChooser(TestCase):
+class TestChooser(TestCase, WagtailTestUtils):
def setUp(self):
# login
- login(self.client)
+ self.login()
def test_chooser(self):
r = self.client.get('/admin/embeds/chooser/')
diff --git a/wagtail/wagtailforms/templates/wagtailforms/index_submissions.html b/wagtail/wagtailforms/templates/wagtailforms/index_submissions.html
index a1b45f6d0..ae9572295 100644
--- a/wagtail/wagtailforms/templates/wagtailforms/index_submissions.html
+++ b/wagtail/wagtailforms/templates/wagtailforms/index_submissions.html
@@ -1,30 +1,28 @@
{% extends "wagtailadmin/base.html" %}
{% load i18n %}
-{% load localize %}
{% block titletag %}{% blocktrans with form_title=form_page.title|capfirst %}Submissions of {{ form_title }}{% endblocktrans %}{% endblock %}
{% block bodyclass %}menu-snippets{% endblock %}
{% block extra_js %}
- {% get_localized_datepicker_js %}
- {% get_date_format_override as format_override %}
-
+ {% include "wagtailadmin/shared/datetimepicker_translations.html" %}
+
{% endblock %}
diff --git a/wagtail/wagtailimages/templates/wagtailimages/chooser/chooser.js b/wagtail/wagtailimages/templates/wagtailimages/chooser/chooser.js
index 18ff4c5c2..237b960f6 100644
--- a/wagtail/wagtailimages/templates/wagtailimages/chooser/chooser.js
+++ b/wagtail/wagtailimages/templates/wagtailimages/chooser/chooser.js
@@ -1,4 +1,6 @@
function(modal) {
+ var searchUrl = $('form.image-search', modal.body).attr('action');
+
function ajaxifyLinks (context) {
$('.listing a', context).click(function() {
modal.loadUrl(this.href);
@@ -12,7 +14,6 @@ function(modal) {
});
}
- var searchUrl = $('form.image-search', modal.body).attr('action');
function search() {
$.ajax({
url: searchUrl,
@@ -24,8 +25,8 @@ function(modal) {
});
return false;
}
- function setPage(page) {
+ function setPage(page) {
if($('#id_q').val().length){
dataObj = {q: $('#id_q').val(), p: page};
}else{
diff --git a/wagtail/wagtailimages/tests.py b/wagtail/wagtailimages/tests.py
index 9f05ccad9..b31e33745 100644
--- a/wagtail/wagtailimages/tests.py
+++ b/wagtail/wagtailimages/tests.py
@@ -4,7 +4,7 @@ from django.contrib.auth.models import User, Group, Permission
from django.core.urlresolvers import reverse
from django.core.files.uploadedfile import SimpleUploadedFile
-from wagtail.tests.utils import login, unittest
+from wagtail.tests.utils import unittest, WagtailTestUtils
from wagtail.wagtailimages.models import get_image_model
from wagtail.wagtailimages.templatetags import image_tags
@@ -201,15 +201,17 @@ class TestImageTag(TestCase):
## ===== ADMIN VIEWS =====
-class TestImageIndexView(TestCase):
+class TestImageIndexView(TestCase, WagtailTestUtils):
def setUp(self):
- login(self.client)
+ self.login()
def get(self, params={}):
return self.client.get(reverse('wagtailimages_index'), params)
- def test_status_code(self):
- self.assertEqual(self.get().status_code, 200)
+ def test_simple(self):
+ response = self.get()
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, 'wagtailimages/images/index.html')
def test_search(self):
response = self.get({'q': "Hello"})
@@ -229,9 +231,9 @@ class TestImageIndexView(TestCase):
self.assertEqual(response.status_code, 200)
-class TestImageAddView(TestCase):
+class TestImageAddView(TestCase, WagtailTestUtils):
def setUp(self):
- login(self.client)
+ self.login()
def get(self, params={}):
return self.client.get(reverse('wagtailimages_add_image'), params)
@@ -239,8 +241,10 @@ class TestImageAddView(TestCase):
def post(self, post_data={}):
return self.client.post(reverse('wagtailimages_add_image'), post_data)
- def test_status_code(self):
- self.assertEqual(self.get().status_code, 200)
+ def test_simple(self):
+ response = self.get()
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, 'wagtailimages/images/add.html')
def test_add(self):
response = self.post({
@@ -250,6 +254,7 @@ class TestImageAddView(TestCase):
# Should redirect back to index
self.assertEqual(response.status_code, 302)
+ self.assertURLEqual(response.url, reverse('wagtailimages_index'))
# Check that the image was created
images = Image.objects.filter(title="Test image")
@@ -261,9 +266,9 @@ class TestImageAddView(TestCase):
self.assertEqual(image.height, 480)
-class TestImageEditView(TestCase):
+class TestImageEditView(TestCase, WagtailTestUtils):
def setUp(self):
- login(self.client)
+ self.login()
# Create an image to edit
self.image = Image.objects.create(
@@ -277,8 +282,10 @@ class TestImageEditView(TestCase):
def post(self, post_data={}):
return self.client.post(reverse('wagtailimages_edit_image', args=(self.image.id,)), post_data)
- def test_status_code(self):
- self.assertEqual(self.get().status_code, 200)
+ def test_simple(self):
+ response = self.get()
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, 'wagtailimages/images/edit.html')
def test_edit(self):
response = self.post({
@@ -287,15 +294,16 @@ class TestImageEditView(TestCase):
# Should redirect back to index
self.assertEqual(response.status_code, 302)
+ self.assertURLEqual(response.url, reverse('wagtailimages_index'))
# Check that the image was edited
image = Image.objects.get(id=self.image.id)
self.assertEqual(image.title, "Edited")
-class TestImageDeleteView(TestCase):
+class TestImageDeleteView(TestCase, WagtailTestUtils):
def setUp(self):
- login(self.client)
+ self.login()
# Create an image to edit
self.image = Image.objects.create(
@@ -309,8 +317,10 @@ class TestImageDeleteView(TestCase):
def post(self, post_data={}):
return self.client.post(reverse('wagtailimages_delete_image', args=(self.image.id,)), post_data)
- def test_status_code(self):
- self.assertEqual(self.get().status_code, 200)
+ def test_simple(self):
+ response = self.get()
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, 'wagtailimages/images/confirm_delete.html')
def test_delete(self):
response = self.post({
@@ -319,21 +329,25 @@ class TestImageDeleteView(TestCase):
# Should redirect back to index
self.assertEqual(response.status_code, 302)
+ self.assertURLEqual(response.url, reverse('wagtailimages_index'))
# Check that the image was deleted
images = Image.objects.filter(title="Test image")
self.assertEqual(images.count(), 0)
-class TestImageChooserView(TestCase):
+class TestImageChooserView(TestCase, WagtailTestUtils):
def setUp(self):
- login(self.client)
+ self.login()
def get(self, params={}):
return self.client.get(reverse('wagtailimages_chooser'), params)
- def test_status_code(self):
- self.assertEqual(self.get().status_code, 200)
+ def test_simple(self):
+ response = self.get()
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, 'wagtailimages/chooser/chooser.html')
+ self.assertTemplateUsed(response, 'wagtailimages/chooser/chooser.js')
def test_search(self):
response = self.get({'q': "Hello"})
@@ -347,9 +361,9 @@ class TestImageChooserView(TestCase):
self.assertEqual(response.status_code, 200)
-class TestImageChooserChosenView(TestCase):
+class TestImageChooserChosenView(TestCase, WagtailTestUtils):
def setUp(self):
- login(self.client)
+ self.login()
# Create an image to edit
self.image = Image.objects.create(
@@ -360,16 +374,25 @@ class TestImageChooserChosenView(TestCase):
def get(self, params={}):
return self.client.get(reverse('wagtailimages_image_chosen', args=(self.image.id,)), params)
- def test_status_code(self):
- self.assertEqual(self.get().status_code, 200)
+ def test_simple(self):
+ response = self.get()
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, 'wagtailimages/chooser/image_chosen.js')
+
+ # TODO: Test posting
-class TestImageChooserUploadView(TestCase):
+class TestImageChooserUploadView(TestCase, WagtailTestUtils):
def setUp(self):
- login(self.client)
+ self.login()
def get(self, params={}):
return self.client.get(reverse('wagtailimages_chooser_upload'), params)
- def test_status_code(self):
- self.assertEqual(self.get().status_code, 200)
+ def test_simple(self):
+ response = self.get()
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, 'wagtailimages/chooser/chooser.html')
+ self.assertTemplateUsed(response, 'wagtailimages/chooser/chooser.js')
+
+ # TODO: Test uploading through chooser
diff --git a/wagtail/wagtailredirects/tests.py b/wagtail/wagtailredirects/tests.py
index a14a853fa..29ad7ec0b 100644
--- a/wagtail/wagtailredirects/tests.py
+++ b/wagtail/wagtailredirects/tests.py
@@ -1,7 +1,7 @@
from django.test import TestCase
from django.test.client import Client
from wagtail.wagtailredirects import models
-from wagtail.tests.utils import login
+from wagtail.tests.utils import WagtailTestUtils
from django.core.urlresolvers import reverse
@@ -66,15 +66,17 @@ class TestRedirects(TestCase):
self.assertTrue(r.has_header('Location'))
-class TestRedirectsIndexView(TestCase):
+class TestRedirectsIndexView(TestCase, WagtailTestUtils):
def setUp(self):
- login(self.client)
+ self.login()
def get(self, params={}):
return self.client.get(reverse('wagtailredirects_index'), params)
- def test_status_code(self):
- self.assertEqual(self.get().status_code, 200)
+ def test_simple(self):
+ response = self.get()
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, 'wagtailredirects/index.html')
def test_search(self):
response = self.get({'q': "Hello"})
@@ -88,9 +90,9 @@ class TestRedirectsIndexView(TestCase):
self.assertEqual(response.status_code, 200)
-class TestRedirectsAddView(TestCase):
+class TestRedirectsAddView(TestCase, WagtailTestUtils):
def setUp(self):
- login(self.client)
+ self.login()
def get(self, params={}):
return self.client.get(reverse('wagtailredirects_add_redirect'), params)
@@ -98,8 +100,10 @@ class TestRedirectsAddView(TestCase):
def post(self, post_data={}):
return self.client.post(reverse('wagtailredirects_add_redirect'), post_data)
- def test_status_code(self):
- self.assertEqual(self.get().status_code, 200)
+ def test_simple(self):
+ response = self.get()
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, 'wagtailredirects/add.html')
def test_add(self):
response = self.post({
@@ -110,6 +114,7 @@ class TestRedirectsAddView(TestCase):
# Should redirect back to index
self.assertEqual(response.status_code, 302)
+ self.assertURLEqual(response.url, reverse('wagtailredirects_index'))
# Check that the redirect was created
redirects = models.Redirect.objects.filter(old_path='/test')
@@ -127,14 +132,14 @@ class TestRedirectsAddView(TestCase):
self.assertEqual(response.status_code, 200)
-class TestRedirectsEditView(TestCase):
+class TestRedirectsEditView(TestCase, WagtailTestUtils):
def setUp(self):
# Create a redirect to edit
self.redirect = models.Redirect(old_path='/test', redirect_link='http://www.test.com/')
self.redirect.save()
# Login
- login(self.client)
+ self.login()
def get(self, params={}, redirect_id=None):
return self.client.get(reverse('wagtailredirects_edit_redirect', args=(redirect_id or self.redirect.id, )), params)
@@ -142,8 +147,10 @@ class TestRedirectsEditView(TestCase):
def post(self, post_data={}, redirect_id=None):
return self.client.post(reverse('wagtailredirects_edit_redirect', args=(redirect_id or self.redirect.id, )), post_data)
- def test_status_code(self):
- self.assertEqual(self.get().status_code, 200)
+ def test_simple(self):
+ response = self.get()
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, 'wagtailredirects/edit.html')
def test_nonexistant_redirect(self):
self.assertEqual(self.get(redirect_id=100000).status_code, 404)
@@ -157,6 +164,7 @@ class TestRedirectsEditView(TestCase):
# Should redirect back to index
self.assertEqual(response.status_code, 302)
+ self.assertURLEqual(response.url, reverse('wagtailredirects_index'))
# Check that the redirect was edited
redirects = models.Redirect.objects.filter(old_path='/test')
@@ -173,14 +181,14 @@ class TestRedirectsEditView(TestCase):
# Should not redirect to index
self.assertEqual(response.status_code, 200)
-class TestRedirectsDeleteView(TestCase):
+class TestRedirectsDeleteView(TestCase, WagtailTestUtils):
def setUp(self):
# Create a redirect to edit
self.redirect = models.Redirect(old_path='/test', redirect_link='http://www.test.com/')
self.redirect.save()
# Login
- login(self.client)
+ self.login()
def get(self, params={}, redirect_id=None):
return self.client.get(reverse('wagtailredirects_delete_redirect', args=(redirect_id or self.redirect.id, )), params)
@@ -188,8 +196,10 @@ class TestRedirectsDeleteView(TestCase):
def post(self, post_data={}, redirect_id=None):
return self.client.post(reverse('wagtailredirects_delete_redirect', args=(redirect_id or self.redirect.id, )), post_data)
- def test_status_code(self):
- self.assertEqual(self.get().status_code, 200)
+ def test_simple(self):
+ response = self.get()
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, 'wagtailredirects/confirm_delete.html')
def test_nonexistant_redirect(self):
self.assertEqual(self.get(redirect_id=100000).status_code, 404)
@@ -201,6 +211,7 @@ class TestRedirectsDeleteView(TestCase):
# Should redirect back to index
self.assertEqual(response.status_code, 302)
+ self.assertURLEqual(response.url, reverse('wagtailredirects_index'))
# Check that the redirect was deleted
redirects = models.Redirect.objects.filter(old_path='/test')
diff --git a/wagtail/wagtailsearch/forms.py b/wagtail/wagtailsearch/forms.py
index 03e4ecd45..9485e4619 100644
--- a/wagtail/wagtailsearch/forms.py
+++ b/wagtail/wagtailsearch/forms.py
@@ -31,6 +31,8 @@ EditorsPickFormSetBase = inlineformset_factory(models.Query, models.EditorsPick,
class EditorsPickFormSet(EditorsPickFormSetBase):
+ minimum_forms = 1
+ minimum_forms_message = _("Please specify at least one recommendation for this search term.")
def add_fields(self, form, *args, **kwargs):
super(EditorsPickFormSet, self).add_fields(form, *args, **kwargs)
@@ -40,3 +42,20 @@ class EditorsPickFormSet(EditorsPickFormSetBase):
# Remove query field
del form.fields['query']
+
+ def clean(self):
+ # Editors pick must have at least one recommended page to be valid
+ # Check there is at least one non-deleted form.
+ non_deleted_forms = self.total_form_count()
+ non_empty_forms = 0
+ for i in xrange(0, self.total_form_count()):
+ form = self.forms[i]
+ if self.can_delete and self._should_delete_form(form):
+ non_deleted_forms -= 1
+ if not (form.instance.id is None and not form.has_changed()):
+ non_empty_forms += 1
+ if (
+ non_deleted_forms < self.minimum_forms
+ or non_empty_forms < self.minimum_forms
+ ):
+ raise forms.ValidationError(self.minimum_forms_message)
diff --git a/wagtail/wagtailsearch/templates/wagtailsearch/editorspicks/add.html b/wagtail/wagtailsearch/templates/wagtailsearch/editorspicks/add.html
index 3c927d96c..f443d1a6a 100644
--- a/wagtail/wagtailsearch/templates/wagtailsearch/editorspicks/add.html
+++ b/wagtail/wagtailsearch/templates/wagtailsearch/editorspicks/add.html
@@ -6,7 +6,7 @@
{% include "wagtailadmin/shared/header.html" with title=add_str icon="pick" %}
- {% blocktrans %}s
+ {% blocktrans %}
Editors picks are a means of recommending specific pages that might not organically come high up in search results. E.g recommending your primary donation page to a user searching with a less common term like "giving".
{% endblocktrans %}
{% blocktrans %}
diff --git a/wagtail/wagtailsearch/tests/test_editorspicks.py b/wagtail/wagtailsearch/tests/test_editorspicks.py
index e0b49153f..7ee974fd0 100644
--- a/wagtail/wagtailsearch/tests/test_editorspicks.py
+++ b/wagtail/wagtailsearch/tests/test_editorspicks.py
@@ -1,5 +1,5 @@
from django.test import TestCase
-from wagtail.tests.utils import login
+from wagtail.tests.utils import unittest, WagtailTestUtils
from wagtail.wagtailsearch import models
@@ -45,15 +45,17 @@ class TestEditorsPicks(TestCase):
self.assertEqual(models.Query.get("root page").editors_picks.last().description, "Last editors pick")
-class TestEditorsPicksIndexView(TestCase):
+class TestEditorsPicksIndexView(TestCase, WagtailTestUtils):
def setUp(self):
- login(self.client)
+ self.login()
def get(self, params={}):
return self.client.get('/admin/search/editorspicks/', params)
- def test_status_code(self):
- self.assertEqual(self.get().status_code, 200)
+ def test_simple(self):
+ response = self.get()
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, 'wagtailsearch/editorspicks/index.html')
def test_search(self):
response = self.get({'q': "Hello"})
@@ -67,20 +69,24 @@ class TestEditorsPicksIndexView(TestCase):
self.assertEqual(response.status_code, 200)
-class TestEditorsPicksAddView(TestCase):
+class TestEditorsPicksAddView(TestCase, WagtailTestUtils):
def setUp(self):
- login(self.client)
+ self.login()
def get(self, params={}):
return self.client.get('/admin/search/editorspicks/add/', params)
- def test_status_code(self):
- self.assertEqual(self.get().status_code, 200)
+ def test_simple(self):
+ response = self.get()
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, 'wagtailsearch/editorspicks/add.html')
+
+ # TODO: Test posting
-class TestEditorsPicksEditView(TestCase):
+class TestEditorsPicksEditView(TestCase, WagtailTestUtils):
def setUp(self):
- login(self.client)
+ self.login()
# Create an editors pick to edit
self.query = models.Query.get("Hello")
@@ -89,13 +95,17 @@ class TestEditorsPicksEditView(TestCase):
def get(self, params={}):
return self.client.get('/admin/search/editorspicks/' + str(self.query.id) + '/', params)
- def test_status_code(self):
- self.assertEqual(self.get().status_code, 200)
+ def test_simple(self):
+ response = self.get()
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, 'wagtailsearch/editorspicks/edit.html')
+
+ # TODO: Test posting
-class TestEditorsPicksDeleteView(TestCase):
+class TestEditorsPicksDeleteView(TestCase, WagtailTestUtils):
def setUp(self):
- login(self.client)
+ self.login()
# Create an editors pick to delete
self.query = models.Query.get("Hello")
@@ -104,5 +114,9 @@ class TestEditorsPicksDeleteView(TestCase):
def get(self, params={}):
return self.client.get('/admin/search/editorspicks/' + str(self.query.id) + '/delete/', params)
- def test_status_code(self):
- self.assertEqual(self.get().status_code, 200)
+ def test_simple(self):
+ response = self.get()
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, 'wagtailsearch/editorspicks/confirm_delete.html')
+
+ # TODO: Test posting
diff --git a/wagtail/wagtailsearch/tests/test_frontend.py b/wagtail/wagtailsearch/tests/test_frontend.py
index 82189cfc9..8081c968d 100644
--- a/wagtail/wagtailsearch/tests/test_frontend.py
+++ b/wagtail/wagtailsearch/tests/test_frontend.py
@@ -5,8 +5,10 @@ class TestSearchView(TestCase):
def get(self, params={}):
return self.client.get('/search/', params)
- def test_status_code(self):
- self.assertEqual(self.get().status_code, 200)
+ def test_simple(self):
+ response = self.get()
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, 'wagtailsearch/search_results.html')
def test_search(self):
response = self.get({'q': "Hello"})
@@ -24,8 +26,10 @@ class TestSuggestionsView(TestCase):
def get(self, params={}):
return self.client.get('/search/suggest/', params)
- def test_status_code(self):
- self.assertEqual(self.get().status_code, 200)
+ def test_simple(self):
+ response = self.get()
+ self.assertEqual(response.status_code, 200)
+ # TODO: Check that a valid JSON document was returned
def test_search(self):
response = self.get({'q': "Hello"})
diff --git a/wagtail/wagtailsearch/tests/test_queries.py b/wagtail/wagtailsearch/tests/test_queries.py
index 7c65af6bf..5c341d7d6 100644
--- a/wagtail/wagtailsearch/tests/test_queries.py
+++ b/wagtail/wagtailsearch/tests/test_queries.py
@@ -1,7 +1,7 @@
from django.test import TestCase
from django.core import management
from wagtail.wagtailsearch import models
-from wagtail.tests.utils import login, unittest
+from wagtail.tests.utils import unittest, WagtailTestUtils
from StringIO import StringIO
@@ -149,15 +149,18 @@ class TestGarbageCollectCommand(TestCase):
# TODO: Test that this command is acctually doing its job
-class TestQueryChooserView(TestCase):
+class TestQueryChooserView(TestCase, WagtailTestUtils):
def setUp(self):
- login(self.client)
+ self.login()
def get(self, params={}):
return self.client.get('/admin/search/queries/chooser/', params)
- def test_status_code(self):
- self.assertEqual(self.get().status_code, 200)
+ def test_simple(self):
+ response = self.get()
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, 'wagtailsearch/queries/chooser/chooser.html')
+ self.assertTemplateUsed(response, 'wagtailsearch/queries/chooser/chooser.js')
def test_search(self):
response = self.get({'q': "Hello"})
diff --git a/wagtail/wagtailsearch/views/editorspicks.py b/wagtail/wagtailsearch/views/editorspicks.py
index 97332818e..bb39c02ba 100644
--- a/wagtail/wagtailsearch/views/editorspicks.py
+++ b/wagtail/wagtailsearch/views/editorspicks.py
@@ -45,12 +45,12 @@ def index(request):
def save_editorspicks(query, new_query, editors_pick_formset):
- # Set sort_order
- for i, form in enumerate(editors_pick_formset.ordered_forms):
- form.instance.sort_order = i
-
# Save
if editors_pick_formset.is_valid():
+ # Set sort_order
+ for i, form in enumerate(editors_pick_formset.ordered_forms):
+ form.instance.sort_order = i
+
editors_pick_formset.save()
# If query was changed, move all editors picks to the new query
@@ -72,10 +72,14 @@ def add(request):
# Save editors picks
editors_pick_formset = forms.EditorsPickFormSet(request.POST, instance=query)
-
if save_editorspicks(query, query, editors_pick_formset):
messages.success(request, _("Editor's picks for '{0}' created.").format(query))
return redirect('wagtailsearch_editorspicks_index')
+ else:
+ if len(editors_pick_formset.non_form_errors()):
+ messages.error(request, " ".join(error for error in editors_pick_formset.non_form_errors())) # formset level error (e.g. no forms submitted)
+ else:
+ messages.error(request, _("Recommendations have not been created due to errors")) # specific errors will be displayed within form fields
else:
editors_pick_formset = forms.EditorsPickFormSet()
else:
@@ -95,15 +99,22 @@ def edit(request, query_id):
if request.POST:
# Get query
query_form = forms.QueryForm(request.POST)
+ # and the recommendations
+ editors_pick_formset = forms.EditorsPickFormSet(request.POST, instance=query)
+
if query_form.is_valid():
new_query = models.Query.get(query_form['query_string'].value())
# Save editors picks
- editors_pick_formset = forms.EditorsPickFormSet(request.POST, instance=query)
-
if save_editorspicks(query, new_query, editors_pick_formset):
messages.success(request, _("Editor's picks for '{0}' updated.").format(new_query))
return redirect('wagtailsearch_editorspicks_index')
+ else:
+ if len(editors_pick_formset.non_form_errors()):
+ messages.error(request, " ".join(error for error in editors_pick_formset.non_form_errors())) # formset level error (e.g. no forms submitted)
+ else:
+ messages.error(request, _("Recommendations have not been saved due to errors")) # specific errors will be displayed within form fields
+
else:
query_form = forms.QueryForm(initial=dict(query_string=query.query_string))
editors_pick_formset = forms.EditorsPickFormSet(instance=query)
diff --git a/wagtail/wagtailsnippets/tests.py b/wagtail/wagtailsnippets/tests.py
index de5e60b9b..9e2587794 100644
--- a/wagtail/wagtailsnippets/tests.py
+++ b/wagtail/wagtailsnippets/tests.py
@@ -2,46 +2,50 @@ from django.test import TestCase
from django.core.urlresolvers import reverse
from django.contrib.auth.models import User
-from wagtail.tests.utils import login, unittest
+from wagtail.tests.utils import unittest, WagtailTestUtils
from wagtail.tests.models import Advert, AlphaSnippet, ZuluSnippet
from wagtail.wagtailsnippets.models import register_snippet, SNIPPET_MODELS
from wagtail.wagtailsnippets.views.snippets import get_content_type_from_url_params, get_snippet_edit_handler
from wagtail.wagtailsnippets.edit_handlers import SnippetChooserPanel
-class TestSnippetIndexView(TestCase):
+class TestSnippetIndexView(TestCase, WagtailTestUtils):
def setUp(self):
- login(self.client)
+ self.login()
def get(self, params={}):
return self.client.get(reverse('wagtailsnippets_index'), params)
- def test_status_code(self):
- self.assertEqual(self.get().status_code, 200)
+ def test_simple(self):
+ response = self.get()
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, 'wagtailsnippets/snippets/index.html')
def test_displays_snippet(self):
self.assertContains(self.get(), "Adverts")
-class TestSnippetListView(TestCase):
+class TestSnippetListView(TestCase, WagtailTestUtils):
def setUp(self):
- login(self.client)
+ self.login()
def get(self, params={}):
return self.client.get(reverse('wagtailsnippets_list',
args=('tests', 'advert')),
params)
- def test_status_code(self):
- self.assertEqual(self.get().status_code, 200)
+ def test_simple(self):
+ response = self.get()
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, 'wagtailsnippets/snippets/type_index.html')
def test_displays_add_button(self):
self.assertContains(self.get(), "Add advert")
-class TestSnippetCreateView(TestCase):
+class TestSnippetCreateView(TestCase, WagtailTestUtils):
def setUp(self):
- login(self.client)
+ self.login()
def get(self, params={}):
return self.client.get(reverse('wagtailsnippets_create',
@@ -53,8 +57,10 @@ class TestSnippetCreateView(TestCase):
args=('tests', 'advert')),
post_data)
- def test_status_code(self):
- self.assertEqual(self.get().status_code, 200)
+ def test_simple(self):
+ response = self.get()
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, 'wagtailsnippets/snippets/create.html')
def test_create_invalid(self):
response = self.post(post_data={'foo': 'bar'})
@@ -65,20 +71,21 @@ class TestSnippetCreateView(TestCase):
response = self.post(post_data={'text': 'test_advert',
'url': 'http://www.example.com/'})
self.assertEqual(response.status_code, 302)
+ self.assertURLEqual(response.url, reverse('wagtailsnippets_list', args=('tests', 'advert')))
snippets = Advert.objects.filter(text='test_advert')
self.assertEqual(snippets.count(), 1)
self.assertEqual(snippets.first().url, 'http://www.example.com/')
-class TestSnippetEditView(TestCase):
+class TestSnippetEditView(TestCase, WagtailTestUtils):
def setUp(self):
self.test_snippet = Advert()
self.test_snippet.text = 'test_advert'
self.test_snippet.url = 'http://www.example.com/'
self.test_snippet.save()
- login(self.client)
+ self.login()
def get(self, params={}):
return self.client.get(reverse('wagtailsnippets_edit',
@@ -90,8 +97,10 @@ class TestSnippetEditView(TestCase):
args=('tests', 'advert', self.test_snippet.id)),
post_data)
- def test_status_code(self):
- self.assertEqual(self.get().status_code, 200)
+ def test_simple(self):
+ response = self.get()
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, 'wagtailsnippets/snippets/edit.html')
def test_non_existant_model(self):
response = self.client.get(reverse('wagtailsnippets_edit',
@@ -112,20 +121,21 @@ class TestSnippetEditView(TestCase):
response = self.post(post_data={'text': 'edited_test_advert',
'url': 'http://www.example.com/edited'})
self.assertEqual(response.status_code, 302)
+ self.assertURLEqual(response.url, reverse('wagtailsnippets_list', args=('tests', 'advert')))
snippets = Advert.objects.filter(text='edited_test_advert')
self.assertEqual(snippets.count(), 1)
self.assertEqual(snippets.first().url, 'http://www.example.com/edited')
-class TestSnippetDelete(TestCase):
+class TestSnippetDelete(TestCase, WagtailTestUtils):
def setUp(self):
self.test_snippet = Advert()
self.test_snippet.text = 'test_advert'
self.test_snippet.url = 'http://www.example.com/'
self.test_snippet.save()
- login(self.client)
+ self.login()
def test_delete_get(self):
response = self.client.get(reverse('wagtailsnippets_delete', args=('tests', 'advert', self.test_snippet.id, )))
@@ -137,6 +147,7 @@ class TestSnippetDelete(TestCase):
# Should be redirected to explorer page
self.assertEqual(response.status_code, 302)
+ self.assertURLEqual(response.url, reverse('wagtailsnippets_list', args=('tests', 'advert')))
# Check that the page is gone
self.assertEqual(Advert.objects.filter(text='test_advert').count(), 0)
diff --git a/wagtail/wagtailusers/tests.py b/wagtail/wagtailusers/tests.py
index bfe0fe4ef..6de97f202 100644
--- a/wagtail/wagtailusers/tests.py
+++ b/wagtail/wagtailusers/tests.py
@@ -1,18 +1,20 @@
from django.test import TestCase
from django.core.urlresolvers import reverse
from django.contrib.auth.models import User
-from wagtail.tests.utils import login
+from wagtail.tests.utils import WagtailTestUtils
-class TestUserIndexView(TestCase):
+class TestUserIndexView(TestCase, WagtailTestUtils):
def setUp(self):
- login(self.client)
+ self.login()
def get(self, params={}):
return self.client.get(reverse('wagtailusers_index'), params)
- def test_status_code(self):
- self.assertEqual(self.get().status_code, 200)
+ def test_simple(self):
+ response = self.get()
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, 'wagtailusers/index.html')
def test_search(self):
response = self.get({'q': "Hello"})
@@ -26,9 +28,9 @@ class TestUserIndexView(TestCase):
self.assertEqual(response.status_code, 200)
-class TestUserCreateView(TestCase):
+class TestUserCreateView(TestCase, WagtailTestUtils):
def setUp(self):
- login(self.client)
+ self.login()
def get(self, params={}):
return self.client.get(reverse('wagtailusers_create'), params)
@@ -36,8 +38,10 @@ class TestUserCreateView(TestCase):
def post(self, post_data={}):
return self.client.post(reverse('wagtailusers_create'), post_data)
- def test_status_code(self):
- self.assertEqual(self.get().status_code, 200)
+ def test_simple(self):
+ response = self.get()
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, 'wagtailusers/create.html')
def test_create(self):
response = self.post({
@@ -51,6 +55,7 @@ class TestUserCreateView(TestCase):
# Should redirect back to index
self.assertEqual(response.status_code, 302)
+ self.assertURLEqual(response.url, reverse('wagtailusers_index'))
# Check that the user was created
users = User.objects.filter(username='testuser')
@@ -58,13 +63,13 @@ class TestUserCreateView(TestCase):
self.assertEqual(users.first().email, 'test@user.com')
-class TestUserEditView(TestCase):
+class TestUserEditView(TestCase, WagtailTestUtils):
def setUp(self):
# Create a user to edit
self.test_user = User.objects.create_user(username='testuser', email='testuser@email.com', password='password')
# Login
- login(self.client)
+ self.login()
def get(self, params={}, user_id=None):
return self.client.get(reverse('wagtailusers_edit', args=(user_id or self.test_user.id, )), params)
@@ -72,8 +77,10 @@ class TestUserEditView(TestCase):
def post(self, post_data={}, user_id=None):
return self.client.post(reverse('wagtailusers_edit', args=(user_id or self.test_user.id, )), post_data)
- def test_status_code(self):
- self.assertEqual(self.get().status_code, 200)
+ def test_simple(self):
+ response = self.get()
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, 'wagtailusers/edit.html')
def test_nonexistant_redirect(self):
self.assertEqual(self.get(user_id=100000).status_code, 404)
@@ -90,6 +97,7 @@ class TestUserEditView(TestCase):
# Should redirect back to index
self.assertEqual(response.status_code, 302)
+ self.assertURLEqual(response.url, reverse('wagtailusers_index'))
# Check that the user was edited
user = User.objects.get(id=self.test_user.id)