From 8c4c26864103890897ca63708867621f16938a25 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Tue, 20 May 2014 11:23:36 +0100 Subject: [PATCH 01/60] Added *args, *kwargs paramters to serve/get_context/get_template This makes it easier to pass parameters from the route method down to get_context/get_template --- wagtail/wagtailcore/models.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/wagtail/wagtailcore/models.py b/wagtail/wagtailcore/models.py index 441c74a28..fdf9e7b9a 100644 --- a/wagtail/wagtailcore/models.py +++ b/wagtail/wagtailcore/models.py @@ -394,23 +394,23 @@ class Page(MP_Node, ClusterableModel, Indexed): return revision.as_page_object() - def get_context(self, request): + def get_context(self, request, *args, **kwargs): return { 'self': self, 'request': request, } - def get_template(self, request): + def get_template(self, request, *args, **kwargs): if request.is_ajax(): return self.ajax_template or self.template else: return self.template - def serve(self, request): + def serve(self, request, *args, **kwargs): return TemplateResponse( request, - self.get_template(request), - self.get_context(request) + self.get_template(request, *args, **kwargs), + self.get_context(request, *args, **kwargs) ) def is_navigable(self): From d88a5e596bf2cd6cdf10600c70d23750d86840c4 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Mon, 2 Jun 2014 09:36:06 +0100 Subject: [PATCH 02/60] Cleanup wagtailimages backends code --- wagtail/wagtailimages/backends/base.py | 21 +++++++-------------- wagtail/wagtailimages/backends/pillow.py | 7 +++++-- wagtail/wagtailimages/backends/wand.py | 2 +- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/wagtail/wagtailimages/backends/base.py b/wagtail/wagtailimages/backends/base.py index 25b7e882d..43ea977c9 100644 --- a/wagtail/wagtailimages/backends/base.py +++ b/wagtail/wagtailimages/backends/base.py @@ -1,6 +1,7 @@ from django.conf import settings from django.core.exceptions import ImproperlyConfigured + class InvalidImageBackendError(ImproperlyConfigured): pass @@ -8,23 +9,22 @@ class InvalidImageBackendError(ImproperlyConfigured): class BaseImageBackend(object): def __init__(self, params): self.quality = getattr(settings, 'IMAGE_COMPRESSION_QUALITY', 85) - + def open_image(self, input_file): """ - Open an image and return the backend specific image object to pass - to other methods. The object return has to have a size attribute + Open an image and return the backend specific image object to pass + to other methods. The object return has to have a size attribute which is a tuple with the width and height of the image and a format attribute with the format of the image. """ raise NotImplementedError('subclasses of BaseImageBackend must provide an open_image() method') - - + def save_image(self, image, output): """ Save the image to the output """ raise NotImplementedError('subclasses of BaseImageBackend must provide a save_image() method') - + def resize(self, image, size): """ resize image to the requested size, using highest quality settings @@ -32,11 +32,9 @@ class BaseImageBackend(object): """ raise NotImplementedError('subclasses of BaseImageBackend must provide an resize() method') - def crop_to_centre(self, image, size): raise NotImplementedError('subclasses of BaseImageBackend must provide a crop_to_centre() method') - def resize_to_max(self, image, size): """ Resize image down to fit within the given dimensions, preserving aspect ratio. @@ -58,10 +56,8 @@ class BaseImageBackend(object): final_size = (target_width, int(original_height * horz_scale)) else: final_size = (int(original_width * vert_scale), target_height) - - return self.resize(image, final_size) - + return self.resize(image, final_size) def resize_to_min(self, image, size): """ @@ -87,7 +83,6 @@ class BaseImageBackend(object): return self.resize(image, final_size) - def resize_to_width(self, image, target_width): """ Resize image down to the given width, preserving aspect ratio. @@ -104,7 +99,6 @@ class BaseImageBackend(object): return self.resize(image, final_size) - def resize_to_height(self, image, target_height): """ Resize image down to the given height, preserving aspect ratio. @@ -121,7 +115,6 @@ class BaseImageBackend(object): return self.resize(image, final_size) - def resize_to_fill(self, image, size): """ Resize down and crop image to fill the given dimensions. Most suitable for thumbnails. diff --git a/wagtail/wagtailimages/backends/pillow.py b/wagtail/wagtailimages/backends/pillow.py index 05d12d291..96976c277 100644 --- a/wagtail/wagtailimages/backends/pillow.py +++ b/wagtail/wagtailimages/backends/pillow.py @@ -1,6 +1,9 @@ -from base import BaseImageBackend +from __future__ import absolute_import + +from .base import BaseImageBackend import PIL.Image + class PillowBackend(BaseImageBackend): def __init__(self, params): super(PillowBackend, self).__init__(params) @@ -32,4 +35,4 @@ class PillowBackend(BaseImageBackend): top = (original_height - final_height) / 2 return image.crop( (left, top, left + final_width, top + final_height) - ) \ No newline at end of file + ) diff --git a/wagtail/wagtailimages/backends/wand.py b/wagtail/wagtailimages/backends/wand.py index 36e352715..0c493eb52 100644 --- a/wagtail/wagtailimages/backends/wand.py +++ b/wagtail/wagtailimages/backends/wand.py @@ -1,9 +1,9 @@ from __future__ import absolute_import from .base import BaseImageBackend - from wand.image import Image + class WandBackend(BaseImageBackend): def __init__(self, params): super(WandBackend, self).__init__(params) From 351b74c94b547b70902bab4a0e6e028738021349 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Mon, 2 Jun 2014 09:52:33 +0100 Subject: [PATCH 03/60] Wand image backend: Always clone images before performing oprations on them --- wagtail/wagtailimages/backends/wand.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/wagtail/wagtailimages/backends/wand.py b/wagtail/wagtailimages/backends/wand.py index 0c493eb52..d1a877436 100644 --- a/wagtail/wagtailimages/backends/wand.py +++ b/wagtail/wagtailimages/backends/wand.py @@ -18,8 +18,9 @@ class WandBackend(BaseImageBackend): image.save(file=output) def resize(self, image, size): - image.resize(size[0], size[1]) - return image + new_image = image.clone() + new_image.resize(size[0], size[1]) + return new_image def crop_to_centre(self, image, size): (original_width, original_height) = image.size @@ -34,7 +35,9 @@ class WandBackend(BaseImageBackend): left = (original_width - final_width) / 2 top = (original_height - final_height) / 2 - image.crop( + + new_image = image.clone() + new_image.crop( left=left, top=top, right=left + final_width, bottom=top + final_height ) - return image + return new_image From e438a6d99b9d936c2a7ea730a3d09da102dc9d85 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Mon, 2 Jun 2014 10:51:47 +0100 Subject: [PATCH 04/60] Minor wagtailimages cleanup --- wagtail/wagtailimages/models.py | 11 ++++------- wagtail/wagtailimages/tests.py | 16 ++++++++-------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/wagtail/wagtailimages/models.py b/wagtail/wagtailimages/models.py index 24fd1f0bf..a2be29486 100644 --- a/wagtail/wagtailimages/models.py +++ b/wagtail/wagtailimages/models.py @@ -180,27 +180,25 @@ class Filter(models.Model): generate an output image with this filter applied, returning it as another django.core.files.File object """ - backend = get_image_backend(backend_name) - + if not self.method: self._parse_spec_string() - + # If file is closed, open it input_file.open('rb') image = backend.open_image(input_file) file_format = image.format - + method = getattr(backend, self.method_name) image = method(image, self.method_arg) output = StringIO.StringIO() backend.save_image(image, output, file_format) - + # and then close the input file input_file.close() - # generate new filename derived from old one, inserting the filter spec string before the extension input_filename_parts = os.path.basename(input_file.name).split('.') @@ -210,7 +208,6 @@ class Filter(models.Model): output_filename = '.'.join(output_filename_parts) output_file = File(output, name=output_filename) - return output_file diff --git a/wagtail/wagtailimages/tests.py b/wagtail/wagtailimages/tests.py index 00d1245e6..1bc2acc93 100644 --- a/wagtail/wagtailimages/tests.py +++ b/wagtail/wagtailimages/tests.py @@ -84,10 +84,10 @@ class TestRenditions(TestCase): # default backend should be pillow backend = get_image_backend() self.assertTrue(isinstance(backend, PillowBackend)) - + def test_minification(self): rendition = self.image.get_rendition('width-400') - + # Check size self.assertEqual(rendition.width, 400) self.assertEqual(rendition.height, 300) @@ -114,7 +114,7 @@ class TestRenditions(TestCase): # Check that they are the same object self.assertEqual(first_rendition, second_rendition) - + class TestRenditionsWand(TestCase): def setUp(self): @@ -134,18 +134,18 @@ class TestRenditionsWand(TestCase): def test_minification(self): rendition = self.image.get_rendition('width-400') - + # Check size self.assertEqual(rendition.width, 400) self.assertEqual(rendition.height, 300) - + def test_resize_to_max(self): rendition = self.image.get_rendition('max-100x100') - + # Check size self.assertEqual(rendition.width, 100) self.assertEqual(rendition.height, 75) - + def test_resize_to_min(self): rendition = self.image.get_rendition('min-120x120') @@ -160,7 +160,7 @@ class TestRenditionsWand(TestCase): # Check that they are the same object self.assertEqual(first_rendition, second_rendition) - + class TestImageTag(TestCase): def setUp(self): From b5586102ed5ae4bb3f56c33f2dc9de56628fdd2b Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Mon, 2 Jun 2014 10:52:34 +0100 Subject: [PATCH 05/60] Cleanup Filter.process_image a bit --- wagtail/wagtailimages/models.py | 37 ++++++++++++++++----------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/wagtail/wagtailimages/models.py b/wagtail/wagtailimages/models.py index a2be29486..ddde18d29 100644 --- a/wagtail/wagtailimages/models.py +++ b/wagtail/wagtailimages/models.py @@ -161,15 +161,17 @@ class Filter(models.Model): # and save the results to self.method_name and self.method_arg try: (method_name_simple, method_arg_string) = self.spec.split('-') - self.method_name = Filter.OPERATION_NAMES[method_name_simple] + method_name = Filter.OPERATION_NAMES[method_name_simple] if method_name_simple in ('max', 'min', 'fill'): # method_arg_string is in the form 640x480 (width, height) = [int(i) for i in method_arg_string.split('x')] - self.method_arg = (width, height) + method_arg = (width, height) else: # method_arg_string is a single number - self.method_arg = int(method_arg_string) + method_arg = int(method_arg_string) + + return method_name, method_arg except (ValueError, KeyError): raise ValueError("Invalid image filter spec: %r" % self.spec) @@ -180,36 +182,33 @@ class Filter(models.Model): generate an output image with this filter applied, returning it as another django.core.files.File object """ + # Get image backend backend = get_image_backend(backend_name) - if not self.method: - self._parse_spec_string() - - # If file is closed, open it + # Open image file input_file.open('rb') image = backend.open_image(input_file) file_format = image.format - method = getattr(backend, self.method_name) + # Parse filter spec string + method_name, method_arg = self._parse_spec_string() - image = method(image, self.method_arg) + # Run filter + method_f = getattr(backend, method_name) + image = method_f(image, method_arg) + # Save output = StringIO.StringIO() backend.save_image(image, output, file_format) - # and then close the input file + # Close input file input_file.close() - # generate new filename derived from old one, inserting the filter spec string before the extension - input_filename_parts = os.path.basename(input_file.name).split('.') - filename_without_extension = '.'.join(input_filename_parts[:-1]) - filename_without_extension = filename_without_extension[:60] # trim filename base so that we're well under 100 chars - output_filename_parts = [filename_without_extension, self.spec] + input_filename_parts[-1:] - output_filename = '.'.join(output_filename_parts) + # Generate new filename derived from old one, inserting the filter spec string before the extension + filename_noext, ext = os.path.splitext(input_file.name) + output_filename = '.'.join([filename_noext[:60], self.spec]) + ext - output_file = File(output, name=output_filename) - - return output_file + return File(output, name=output_filename) class AbstractRendition(models.Model): From 7ba7ded7c6cf2183f7ba4dbee80c86ede90d00cb Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Mon, 2 Jun 2014 13:40:34 +0100 Subject: [PATCH 06/60] Added WagtailTestCase class with a couple of useful methods --- wagtail/tests/utils.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/wagtail/tests/utils.py b/wagtail/tests/utils.py index 6590e6dcc..8e18c661d 100644 --- a/wagtail/tests/utils.py +++ b/wagtail/tests/utils.py @@ -1,4 +1,6 @@ +from django.test import TestCase from django.contrib.auth.models import User +from django.utils.six.moves.urllib.parse import urlparse, ParseResult # We need to make sure that we're using the same unittest library that Django uses internally # Otherwise, we get issues with the "SkipTest" and "ExpectedFailure" exceptions being recognised as errors @@ -20,3 +22,26 @@ def login(client): client.login(username='test', password='password') return user + + +class WagtailTestCase(TestCase): + def login(self): + login(self.client) + + # From: https://github.com/django/django/blob/255449c1ee61c14778658caae8c430fa4d76afd6/django/contrib/auth/tests/test_views.py#L70-L85 + def assertURLEqual(self, url, expected, parse_qs=False): + """ + Given two URLs, make sure all their components (the ones given by + urlparse) are equal, only comparing components that are present in both + URLs. + If `parse_qs` is True, then the querystrings are parsed with QueryDict. + This is useful if you don't want the order of parameters to matter. + Otherwise, the query strings are compared as-is. + """ + fields = ParseResult._fields + + for attr, x, y in zip(fields, urlparse(url), urlparse(expected)): + if parse_qs and attr == 'query': + x, y = QueryDict(x), QueryDict(y) + if x and y and x != y: + self.fail("%r != %r (%s doesn't match)" % (url, expected, attr)) From 7e7910ba3b68e524683f4bafda08983805f11708 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Mon, 2 Jun 2014 13:41:00 +0100 Subject: [PATCH 07/60] Added LOGIN_REDIRECT_URL to runtests.py settings --- runtests.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/runtests.py b/runtests.py index 6fd37ebeb..346729653 100755 --- a/runtests.py +++ b/runtests.py @@ -101,7 +101,8 @@ if not settings.configured: ), COMPRESS_ENABLED=False, # disable compression so that we can run tests on the content of the compress tag WAGTAILSEARCH_BACKENDS=WAGTAILSEARCH_BACKENDS, - WAGTAIL_SITE_NAME='Test Site' + WAGTAIL_SITE_NAME='Test Site', + LOGIN_REDIRECT_URL = 'wagtailadmin_home', ) From 765f90746a6fac9e3a0caff025e0d668aed23a5d Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Mon, 2 Jun 2014 13:41:28 +0100 Subject: [PATCH 08/60] Use new WagtailTestCase class for checking redirect URLs in account management tests --- .../tests/test_account_management.py | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/wagtail/wagtailadmin/tests/test_account_management.py b/wagtail/wagtailadmin/tests/test_account_management.py index 95d54d7d9..0b71d55fb 100644 --- a/wagtail/wagtailadmin/tests/test_account_management.py +++ b/wagtail/wagtailadmin/tests/test_account_management.py @@ -1,17 +1,16 @@ -from django.test import TestCase -from wagtail.tests.utils import login, unittest +from wagtail.tests.utils import unittest, WagtailTestCase 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(WagtailTestCase): """ 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,6 +43,7 @@ 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) @@ -61,6 +61,7 @@ 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): """ @@ -71,17 +72,18 @@ class TestAuthentication(TestCase): # 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) -class TestAccountSection(TestCase): +class TestAccountSection(WagtailTestCase): """ This tests that the accounts section is working """ def setUp(self): - login(self.client) + self.login() def test_account_view(self): """ @@ -117,8 +119,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 +149,7 @@ class TestAccountSection(TestCase): self.assertTrue(User.objects.get(username='test').check_password('password')) -class TestPasswordReset(TestCase): +class TestPasswordReset(WagtailTestCase): """ This tests that the password reset is working """ @@ -176,8 +179,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 +271,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')) From a8ca4f14daefd980b402d987cd6fb7c496d991c4 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Mon, 2 Jun 2014 13:56:19 +0100 Subject: [PATCH 09/60] Return user object from login method --- wagtail/tests/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wagtail/tests/utils.py b/wagtail/tests/utils.py index 8e18c661d..44e612555 100644 --- a/wagtail/tests/utils.py +++ b/wagtail/tests/utils.py @@ -26,7 +26,7 @@ def login(client): class WagtailTestCase(TestCase): def login(self): - login(self.client) + return login(self.client) # From: https://github.com/django/django/blob/255449c1ee61c14778658caae8c430fa4d76afd6/django/contrib/auth/tests/test_views.py#L70-L85 def assertURLEqual(self, url, expected, parse_qs=False): From 00a06856a8fba6ef838ac41e4a261d9e03d4698a Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Mon, 2 Jun 2014 13:56:54 +0100 Subject: [PATCH 10/60] Use WagtailTestCase class in admin page views tests --- .../wagtailadmin/tests/test_pages_views.py | 59 +++++++++++-------- 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/wagtail/wagtailadmin/tests/test_pages_views.py b/wagtail/wagtailadmin/tests/test_pages_views.py index ccaa67dae..f97c26581 100644 --- a/wagtail/wagtailadmin/tests/test_pages_views.py +++ b/wagtail/wagtailadmin/tests/test_pages_views.py @@ -1,13 +1,12 @@ -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, WagtailTestCase 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(WagtailTestCase): def setUp(self): # Find root page self.root_page = Page.objects.get(id=2) @@ -19,7 +18,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 +27,13 @@ class TestPageExplorer(TestCase): self.assertTrue(response.context['pages'].filter(id=self.child_page.id).exists()) -class TestPageCreation(TestCase): +class TestPageCreation(WagtailTestCase): 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 +85,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 +104,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 +127,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 @@ -186,7 +188,7 @@ class TestPageCreation(TestCase): self.assertContains(response, "New page!") -class TestPageEdit(TestCase): +class TestPageEdit(WagtailTestCase): def setUp(self): # Find root page self.root_page = Page.objects.get(id=2) @@ -206,7 +208,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 +240,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 +258,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 +282,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 +311,7 @@ class TestPageEdit(TestCase): self.assertContains(response, "I've been edited!") -class TestPageDelete(TestCase): +class TestPageDelete(WagtailTestCase): def setUp(self): # Find root page self.root_page = Page.objects.get(id=2) @@ -318,7 +323,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 +349,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(WagtailTestCase): 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 +396,7 @@ class TestPageSearch(TestCase): self.assertTrue(any([r.slug == 'root' for r in results])) -class TestPageMove(TestCase): +class TestPageMove(WagtailTestCase): def setUp(self): # Find root page self.root_page = Page.objects.get(id=2) @@ -413,7 +419,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 +448,18 @@ class TestPageMove(TestCase): self.assertEqual(response.status_code, 200) -class TestPageUnpublish(TestCase): +class TestPageUnpublish(WagtailTestCase): 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 +508,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(WagtailTestCase): def setUp(self): self.submitter = User.objects.create_superuser( username='submitter', @@ -517,7 +524,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 +547,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 +599,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 +654,11 @@ class TestApproveRejectModeration(TestCase): self.assertContains(response, "Hello world!") -class TestContentTypeUse(TestCase): +class TestContentTypeUse(WagtailTestCase): 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 From 301fd6ec3c5e37b8f9b092fade08e49c7bde949c Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Mon, 2 Jun 2014 13:59:06 +0100 Subject: [PATCH 11/60] Made WagtailTestCase a mixin and renamed to WagtailTestUtils. --- wagtail/tests/utils.py | 2 +- .../tests/test_account_management.py | 9 ++++---- .../wagtailadmin/tests/test_pages_views.py | 21 ++++++++++--------- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/wagtail/tests/utils.py b/wagtail/tests/utils.py index 44e612555..4b22b000c 100644 --- a/wagtail/tests/utils.py +++ b/wagtail/tests/utils.py @@ -24,7 +24,7 @@ def login(client): return user -class WagtailTestCase(TestCase): +class WagtailTestUtils(object): def login(self): return login(self.client) diff --git a/wagtail/wagtailadmin/tests/test_account_management.py b/wagtail/wagtailadmin/tests/test_account_management.py index 0b71d55fb..499cd9554 100644 --- a/wagtail/wagtailadmin/tests/test_account_management.py +++ b/wagtail/wagtailadmin/tests/test_account_management.py @@ -1,11 +1,12 @@ -from wagtail.tests.utils import unittest, WagtailTestCase +from django.test import TestCase +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(WagtailTestCase): +class TestAuthentication(TestCase, WagtailTestUtils): """ This tests that users can login and logout of the admin interface """ @@ -78,7 +79,7 @@ class TestAuthentication(WagtailTestCase): self.assertFalse('_auth_user_id' in self.client.session) -class TestAccountSection(WagtailTestCase): +class TestAccountSection(TestCase, WagtailTestUtils): """ This tests that the accounts section is working """ @@ -149,7 +150,7 @@ class TestAccountSection(WagtailTestCase): self.assertTrue(User.objects.get(username='test').check_password('password')) -class TestPasswordReset(WagtailTestCase): +class TestPasswordReset(TestCase, WagtailTestUtils): """ This tests that the password reset is working """ diff --git a/wagtail/wagtailadmin/tests/test_pages_views.py b/wagtail/wagtailadmin/tests/test_pages_views.py index f97c26581..a34b29fd8 100644 --- a/wagtail/wagtailadmin/tests/test_pages_views.py +++ b/wagtail/wagtailadmin/tests/test_pages_views.py @@ -1,12 +1,13 @@ +from django.test import TestCase from wagtail.tests.models import SimplePage, EventPage -from wagtail.tests.utils import unittest, WagtailTestCase +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(WagtailTestCase): +class TestPageExplorer(TestCase, WagtailTestUtils): def setUp(self): # Find root page self.root_page = Page.objects.get(id=2) @@ -27,7 +28,7 @@ class TestPageExplorer(WagtailTestCase): self.assertTrue(response.context['pages'].filter(id=self.child_page.id).exists()) -class TestPageCreation(WagtailTestCase): +class TestPageCreation(TestCase, WagtailTestUtils): def setUp(self): # Find root page self.root_page = Page.objects.get(id=2) @@ -188,7 +189,7 @@ class TestPageCreation(WagtailTestCase): self.assertContains(response, "New page!") -class TestPageEdit(WagtailTestCase): +class TestPageEdit(TestCase, WagtailTestUtils): def setUp(self): # Find root page self.root_page = Page.objects.get(id=2) @@ -311,7 +312,7 @@ class TestPageEdit(WagtailTestCase): self.assertContains(response, "I've been edited!") -class TestPageDelete(WagtailTestCase): +class TestPageDelete(TestCase, WagtailTestUtils): def setUp(self): # Find root page self.root_page = Page.objects.get(id=2) @@ -355,7 +356,7 @@ class TestPageDelete(WagtailTestCase): self.assertEqual(Page.objects.filter(path__startswith=self.root_page.path, slug='hello-world').count(), 0) -class TestPageSearch(WagtailTestCase): +class TestPageSearch(TestCase, WagtailTestUtils): def setUp(self): # Login self.login() @@ -396,7 +397,7 @@ class TestPageSearch(WagtailTestCase): self.assertTrue(any([r.slug == 'root' for r in results])) -class TestPageMove(WagtailTestCase): +class TestPageMove(TestCase, WagtailTestUtils): def setUp(self): # Find root page self.root_page = Page.objects.get(id=2) @@ -448,7 +449,7 @@ class TestPageMove(WagtailTestCase): self.assertEqual(response.status_code, 200) -class TestPageUnpublish(WagtailTestCase): +class TestPageUnpublish(TestCase, WagtailTestUtils): def setUp(self): self.user = self.login() @@ -516,7 +517,7 @@ class TestPageUnpublish(WagtailTestCase): self.assertFalse(SimplePage.objects.get(id=self.page.id).live) -class TestApproveRejectModeration(WagtailTestCase): +class TestApproveRejectModeration(TestCase, WagtailTestUtils): def setUp(self): self.submitter = User.objects.create_superuser( username='submitter', @@ -654,7 +655,7 @@ class TestApproveRejectModeration(WagtailTestCase): self.assertContains(response, "Hello world!") -class TestContentTypeUse(WagtailTestCase): +class TestContentTypeUse(TestCase, WagtailTestUtils): fixtures = ['test.json'] def setUp(self): From d9825e9531c3067c3261bdc7ac04042c50e92148 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Mon, 2 Jun 2014 14:03:02 +0100 Subject: [PATCH 12/60] Fixed missing import --- wagtail/tests/utils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/wagtail/tests/utils.py b/wagtail/tests/utils.py index 4b22b000c..0497b239a 100644 --- a/wagtail/tests/utils.py +++ b/wagtail/tests/utils.py @@ -1,6 +1,7 @@ from django.test import TestCase from django.contrib.auth.models import User from django.utils.six.moves.urllib.parse import urlparse, ParseResult +from django.http import QueryDict # We need to make sure that we're using the same unittest library that Django uses internally # Otherwise, we get issues with the "SkipTest" and "ExpectedFailure" exceptions being recognised as errors From 106b27a5a5699fe369f841141bbf3cc219da6864 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Mon, 2 Jun 2014 15:23:32 +0100 Subject: [PATCH 13/60] Added template used assertions into many tests --- wagtail/wagtailadmin/tests/tests.py | 2 +- wagtail/wagtaildocs/tests.py | 54 ++++++++++++++----- wagtail/wagtailimages/tests.py | 48 ++++++++++++----- wagtail/wagtailredirects/tests.py | 24 ++++++--- .../wagtailsearch/tests/test_editorspicks.py | 24 ++++++--- wagtail/wagtailsearch/tests/test_frontend.py | 12 +++-- wagtail/wagtailsearch/tests/test_queries.py | 7 ++- wagtail/wagtailsnippets/tests.py | 24 ++++++--- wagtail/wagtailusers/tests.py | 18 ++++--- 9 files changed, 148 insertions(+), 65 deletions(-) diff --git a/wagtail/wagtailadmin/tests/tests.py b/wagtail/wagtailadmin/tests/tests.py index 12aa28a0b..b0c0896e2 100644 --- a/wagtail/wagtailadmin/tests/tests.py +++ b/wagtail/wagtailadmin/tests/tests.py @@ -12,7 +12,7 @@ class TestHome(TestCase): # Login login(self.client) - def test_status_code(self): + def test_simple(self): response = self.client.get(reverse('wagtailadmin_home')) self.assertEqual(response.status_code, 200) diff --git a/wagtail/wagtaildocs/tests.py b/wagtail/wagtaildocs/tests.py index d068f9a27..33da3e33a 100644 --- a/wagtail/wagtaildocs/tests.py +++ b/wagtail/wagtaildocs/tests.py @@ -46,8 +46,10 @@ class TestDocumentIndexView(TestCase): 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"}) @@ -74,8 +76,12 @@ class TestDocumentAddView(TestCase): 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): @@ -88,8 +94,12 @@ 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): @@ -102,8 +112,12 @@ 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): @@ -113,8 +127,11 @@ class TestDocumentChooserView(TestCase): 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"}) @@ -138,8 +155,12 @@ 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): @@ -149,8 +170,13 @@ class TestDocumentChooserUploadView(TestCase): 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/wagtailimages/tests.py b/wagtail/wagtailimages/tests.py index 00d1245e6..fdadc3704 100644 --- a/wagtail/wagtailimages/tests.py +++ b/wagtail/wagtailimages/tests.py @@ -194,8 +194,10 @@ class TestImageIndexView(TestCase): 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"}) @@ -225,8 +227,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({ @@ -263,8 +267,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({ @@ -295,8 +301,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({ @@ -318,8 +326,11 @@ class TestImageChooserView(TestCase): 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"}) @@ -346,8 +357,12 @@ 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): @@ -357,5 +372,10 @@ class TestImageChooserUploadView(TestCase): 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..f23ea63c9 100644 --- a/wagtail/wagtailredirects/tests.py +++ b/wagtail/wagtailredirects/tests.py @@ -73,8 +73,10 @@ class TestRedirectsIndexView(TestCase): 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"}) @@ -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({ @@ -142,8 +146,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) @@ -188,8 +194,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) diff --git a/wagtail/wagtailsearch/tests/test_editorspicks.py b/wagtail/wagtailsearch/tests/test_editorspicks.py index e0b49153f..2af0df625 100644 --- a/wagtail/wagtailsearch/tests/test_editorspicks.py +++ b/wagtail/wagtailsearch/tests/test_editorspicks.py @@ -52,8 +52,10 @@ class TestEditorsPicksIndexView(TestCase): 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"}) @@ -74,8 +76,10 @@ class TestEditorsPicksAddView(TestCase): 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') class TestEditorsPicksEditView(TestCase): @@ -89,8 +93,10 @@ 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') class TestEditorsPicksDeleteView(TestCase): @@ -104,5 +110,7 @@ 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') 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 7086d46f4..67325104d 100644 --- a/wagtail/wagtailsearch/tests/test_queries.py +++ b/wagtail/wagtailsearch/tests/test_queries.py @@ -146,8 +146,11 @@ class TestQueryChooserView(TestCase): 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/wagtailsnippets/tests.py b/wagtail/wagtailsnippets/tests.py index fd283f7f5..f68062319 100644 --- a/wagtail/wagtailsnippets/tests.py +++ b/wagtail/wagtailsnippets/tests.py @@ -13,8 +13,10 @@ class TestSnippetIndexView(TestCase): 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") @@ -29,8 +31,10 @@ class TestSnippetListView(TestCase): 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") @@ -50,8 +54,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'}) @@ -87,8 +93,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', diff --git a/wagtail/wagtailusers/tests.py b/wagtail/wagtailusers/tests.py index bfe0fe4ef..d60d33d47 100644 --- a/wagtail/wagtailusers/tests.py +++ b/wagtail/wagtailusers/tests.py @@ -11,8 +11,10 @@ class TestUserIndexView(TestCase): 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"}) @@ -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({ @@ -72,8 +76,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) From f4ee926ffaa17f318cca5ec226a4685866811be7 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Mon, 2 Jun 2014 15:56:03 +0100 Subject: [PATCH 14/60] Added URL assertions to tests which test redirecting --- wagtail/wagtailimages/tests.py | 11 +++++++---- wagtail/wagtailredirects/tests.py | 11 +++++++---- wagtail/wagtailsnippets/tests.py | 11 +++++++---- wagtail/wagtailusers/tests.py | 8 +++++--- 4 files changed, 26 insertions(+), 15 deletions(-) diff --git a/wagtail/wagtailimages/tests.py b/wagtail/wagtailimages/tests.py index fdadc3704..c8f0194c0 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 login, unittest, WagtailTestUtils from wagtail.wagtailimages.models import get_image_model from wagtail.wagtailimages.templatetags import image_tags @@ -217,7 +217,7 @@ class TestImageIndexView(TestCase): self.assertEqual(response.status_code, 200) -class TestImageAddView(TestCase): +class TestImageAddView(TestCase, WagtailTestUtils): def setUp(self): login(self.client) @@ -240,6 +240,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") @@ -251,7 +252,7 @@ class TestImageAddView(TestCase): self.assertEqual(image.height, 480) -class TestImageEditView(TestCase): +class TestImageEditView(TestCase, WagtailTestUtils): def setUp(self): login(self.client) @@ -279,13 +280,14 @@ 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) @@ -313,6 +315,7 @@ 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") diff --git a/wagtail/wagtailredirects/tests.py b/wagtail/wagtailredirects/tests.py index f23ea63c9..543a8dd70 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 login, WagtailTestUtils from django.core.urlresolvers import reverse @@ -90,7 +90,7 @@ class TestRedirectsIndexView(TestCase): self.assertEqual(response.status_code, 200) -class TestRedirectsAddView(TestCase): +class TestRedirectsAddView(TestCase, WagtailTestUtils): def setUp(self): login(self.client) @@ -114,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') @@ -131,7 +132,7 @@ 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/') @@ -163,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') @@ -179,7 +181,7 @@ 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/') @@ -209,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/wagtailsnippets/tests.py b/wagtail/wagtailsnippets/tests.py index f68062319..3adaf5a3b 100644 --- a/wagtail/wagtailsnippets/tests.py +++ b/wagtail/wagtailsnippets/tests.py @@ -2,7 +2,7 @@ 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 login, unittest, WagtailTestUtils from wagtail.tests.models import Advert @@ -40,7 +40,7 @@ class TestSnippetListView(TestCase): self.assertContains(self.get(), "Add advert") -class TestSnippetCreateView(TestCase): +class TestSnippetCreateView(TestCase, WagtailTestUtils): def setUp(self): login(self.client) @@ -68,13 +68,14 @@ 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' @@ -117,13 +118,14 @@ 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' @@ -142,6 +144,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 d60d33d47..c9105e3c0 100644 --- a/wagtail/wagtailusers/tests.py +++ b/wagtail/wagtailusers/tests.py @@ -1,7 +1,7 @@ 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 login, WagtailTestUtils class TestUserIndexView(TestCase): @@ -28,7 +28,7 @@ class TestUserIndexView(TestCase): self.assertEqual(response.status_code, 200) -class TestUserCreateView(TestCase): +class TestUserCreateView(TestCase, WagtailTestUtils): def setUp(self): login(self.client) @@ -55,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') @@ -62,7 +63,7 @@ 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') @@ -96,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) From eddc3fc917791c80c3bad250721bbb30ace9238e Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Mon, 2 Jun 2014 16:07:31 +0100 Subject: [PATCH 15/60] Always use login method from WagtailTestUtils --- wagtail/tests/utils.py | 18 +++++------ wagtail/wagtailadmin/tests/tests.py | 10 +++---- wagtail/wagtaildocs/tests.py | 30 +++++++++---------- wagtail/wagtailembeds/tests.py | 6 ++-- wagtail/wagtailimages/tests.py | 24 +++++++-------- wagtail/wagtailredirects/tests.py | 12 ++++---- .../wagtailsearch/tests/test_editorspicks.py | 24 +++++++++------ wagtail/wagtailsearch/tests/test_queries.py | 6 ++-- wagtail/wagtailsnippets/tests.py | 16 +++++----- wagtail/wagtailusers/tests.py | 10 +++---- 10 files changed, 79 insertions(+), 77 deletions(-) diff --git a/wagtail/tests/utils.py b/wagtail/tests/utils.py index 0497b239a..0b13e5932 100644 --- a/wagtail/tests/utils.py +++ b/wagtail/tests/utils.py @@ -15,19 +15,15 @@ except ImportError: import unittest -def login(client): - # Create a user - user = User.objects.create_superuser(username='test', email='test@email.com', password='password') - - # Login - client.login(username='test', password='password') - - return user - - class WagtailTestUtils(object): def login(self): - return login(self.client) + # Create a user + user = User.objects.create_superuser(username='test', email='test@email.com', password='password') + + # Login + self.client.login(username='test', password='password') + + return user # From: https://github.com/django/django/blob/255449c1ee61c14778658caae8c430fa4d76afd6/django/contrib/auth/tests/test_views.py#L70-L85 def assertURLEqual(self, url, expected, parse_qs=False): diff --git a/wagtail/wagtailadmin/tests/tests.py b/wagtail/wagtailadmin/tests/tests.py index b0c0896e2..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_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/wagtaildocs/tests.py b/wagtail/wagtaildocs/tests.py index 33da3e33a..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,9 +39,9 @@ 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) @@ -69,9 +69,9 @@ 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) @@ -84,9 +84,9 @@ class TestDocumentAddView(TestCase): # 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") @@ -102,9 +102,9 @@ class TestDocumentEditView(TestCase): # 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") @@ -120,9 +120,9 @@ class TestDocumentDeleteView(TestCase): # 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) @@ -145,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") @@ -163,9 +163,9 @@ class TestDocumentChooserChosenView(TestCase): # 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) diff --git a/wagtail/wagtailembeds/tests.py b/wagtail/wagtailembeds/tests.py index b1eefdb17..b1268729e 100644 --- a/wagtail/wagtailembeds/tests.py +++ b/wagtail/wagtailembeds/tests.py @@ -1,7 +1,7 @@ from django.test import TestCase from django.test.client import Client -from wagtail.tests.utils import login from wagtail.wagtailembeds import get_embed +from wagtail.tests.utils import WagtailTestUtils class TestEmbeds(TestCase): @@ -63,10 +63,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/wagtailimages/tests.py b/wagtail/wagtailimages/tests.py index c8f0194c0..d01535eda 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, WagtailTestUtils +from wagtail.tests.utils import unittest, WagtailTestUtils from wagtail.wagtailimages.models import get_image_model from wagtail.wagtailimages.templatetags import image_tags @@ -187,9 +187,9 @@ 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) @@ -219,7 +219,7 @@ class TestImageIndexView(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) @@ -254,7 +254,7 @@ class TestImageAddView(TestCase, WagtailTestUtils): class TestImageEditView(TestCase, WagtailTestUtils): def setUp(self): - login(self.client) + self.login() # Create an image to edit self.image = Image.objects.create( @@ -289,7 +289,7 @@ class TestImageEditView(TestCase, WagtailTestUtils): class TestImageDeleteView(TestCase, WagtailTestUtils): def setUp(self): - login(self.client) + self.login() # Create an image to edit self.image = Image.objects.create( @@ -322,9 +322,9 @@ class TestImageDeleteView(TestCase, WagtailTestUtils): 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) @@ -347,9 +347,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( @@ -368,9 +368,9 @@ class TestImageChooserChosenView(TestCase): # 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) diff --git a/wagtail/wagtailredirects/tests.py b/wagtail/wagtailredirects/tests.py index 543a8dd70..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, WagtailTestUtils +from wagtail.tests.utils import WagtailTestUtils from django.core.urlresolvers import reverse @@ -66,9 +66,9 @@ 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) @@ -92,7 +92,7 @@ class TestRedirectsIndexView(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) @@ -139,7 +139,7 @@ class TestRedirectsEditView(TestCase, WagtailTestUtils): 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) @@ -188,7 +188,7 @@ class TestRedirectsDeleteView(TestCase, WagtailTestUtils): 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) diff --git a/wagtail/wagtailsearch/tests/test_editorspicks.py b/wagtail/wagtailsearch/tests/test_editorspicks.py index 2af0df625..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,9 +45,9 @@ 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) @@ -69,9 +69,9 @@ 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) @@ -81,10 +81,12 @@ class TestEditorsPicksAddView(TestCase): 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") @@ -98,10 +100,12 @@ class TestEditorsPicksEditView(TestCase): 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") @@ -114,3 +118,5 @@ class TestEditorsPicksDeleteView(TestCase): 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_queries.py b/wagtail/wagtailsearch/tests/test_queries.py index 67325104d..ee5382db4 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 @@ -139,9 +139,9 @@ 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) diff --git a/wagtail/wagtailsnippets/tests.py b/wagtail/wagtailsnippets/tests.py index 3adaf5a3b..bf9d62731 100644 --- a/wagtail/wagtailsnippets/tests.py +++ b/wagtail/wagtailsnippets/tests.py @@ -2,13 +2,13 @@ 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, WagtailTestUtils +from wagtail.tests.utils import unittest, WagtailTestUtils from wagtail.tests.models import Advert -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) @@ -22,9 +22,9 @@ class TestSnippetIndexView(TestCase): 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', @@ -42,7 +42,7 @@ class TestSnippetListView(TestCase): class TestSnippetCreateView(TestCase, WagtailTestUtils): def setUp(self): - login(self.client) + self.login() def get(self, params={}): return self.client.get(reverse('wagtailsnippets_create', @@ -82,7 +82,7 @@ class TestSnippetEditView(TestCase, WagtailTestUtils): 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', @@ -132,7 +132,7 @@ class TestSnippetDelete(TestCase, WagtailTestUtils): 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, ))) diff --git a/wagtail/wagtailusers/tests.py b/wagtail/wagtailusers/tests.py index c9105e3c0..6de97f202 100644 --- a/wagtail/wagtailusers/tests.py +++ b/wagtail/wagtailusers/tests.py @@ -1,12 +1,12 @@ from django.test import TestCase from django.core.urlresolvers import reverse from django.contrib.auth.models import User -from wagtail.tests.utils import login, WagtailTestUtils +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) @@ -30,7 +30,7 @@ class TestUserIndexView(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) @@ -69,7 +69,7 @@ class TestUserEditView(TestCase, WagtailTestUtils): 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) From 1be56484b410cca6f50b5534b48fba400272f46e Mon Sep 17 00:00:00 2001 From: Jeffrey Hearn Date: Mon, 2 Jun 2014 13:47:30 -0400 Subject: [PATCH 16/60] Updated hallo.js library to 1.0.4 from unknown version --- .../static/wagtailadmin/js/vendor/hallo.js | 3975 +++++++++-------- 1 file changed, 2116 insertions(+), 1859 deletions(-) diff --git a/wagtail/wagtailadmin/static/wagtailadmin/js/vendor/hallo.js b/wagtail/wagtailadmin/static/wagtailadmin/js/vendor/hallo.js index 7ba3ff2c0..af5950fdb 100644 --- a/wagtail/wagtailadmin/static/wagtailadmin/js/vendor/hallo.js +++ b/wagtail/wagtailadmin/static/wagtailadmin/js/vendor/hallo.js @@ -1,671 +1,607 @@ -// Generated by CoffeeScript 1.3.3 -(function() { - - $.widget("ncri.hallohtml", { - options: { - editable: null, +/* Hallo 1.0.4 - rich text editor for jQuery UI +* by Henri Bergius and contributors. Available under the MIT license. +* See http://hallojs.org for more information +*/(function() { + (function(jQuery) { + return jQuery.widget('IKS.hallo', { toolbar: null, - uuid: "", - lang: 'en', - dialogOpts: { - autoOpen: false, - width: 600, - height: 'auto', - modal: false, - resizable: true, - draggable: true, - dialogClass: 'htmledit-dialog' + bound: false, + originalContent: '', + previousContent: '', + uuid: '', + selection: null, + _keepActivated: false, + originalHref: null, + options: { + editable: true, + plugins: {}, + toolbar: 'halloToolbarContextual', + parentElement: 'body', + buttonCssClass: null, + toolbarCssClass: null, + toolbarPositionAbove: false, + toolbarOptions: {}, + placeholder: '', + forceStructured: true, + checkTouch: true, + touchScreen: null }, - dialog: null, - buttonCssClass: null - }, - translations: { - en: { - title: 'Edit HTML', - update: 'Update' + _create: function() { + var options, plugin, _ref, + _this = this; + this.id = this._generateUUID(); + if (this.options.checkTouch && this.options.touchScreen === null) { + this.checkTouch(); + } + _ref = this.options.plugins; + for (plugin in _ref) { + options = _ref[plugin]; + if (!jQuery.isPlainObject(options)) { + options = {}; + } + jQuery.extend(options, { + editable: this, + uuid: this.id, + buttonCssClass: this.options.buttonCssClass + }); + jQuery(this.element)[plugin](options); + } + this.element.one('halloactivated', function() { + return _this._prepareToolbar(); + }); + return this.originalContent = this.getContents(); }, - de: { - title: 'HTML bearbeiten', - update: 'Aktualisieren' - } - }, - texts: null, - populateToolbar: function($toolbar) { - var $buttonHolder, $buttonset, id, widget; - widget = this; - this.texts = this.translations[this.options.lang]; - this.options.toolbar = $toolbar; - this.options.dialog = $("
").attr('id', "" + this.options.uuid + "-htmledit-dialog"); - $buttonset = $("").addClass(widget.widgetName); - id = "" + this.options.uuid + "-htmledit"; - $buttonHolder = $(''); - $buttonHolder.hallobutton({ - label: this.texts.title, - icon: 'icon-list-alt', - editable: this.options.editable, - command: null, - queryState: false, - uuid: this.options.uuid, - cssClass: this.options.buttonCssClass - }); - $buttonset.append($buttonHolder); - this.button = $buttonHolder; - this.button.click(function() { - if (widget.options.dialog.dialog("isOpen")) { - widget._closeDialog(); + _init: function() { + if (this.options.editable) { + return this.enable(); } else { - widget._openDialog(); + return this.disable(); + } + }, + destroy: function() { + var options, plugin, _ref; + this.disable(); + if (this.toolbar) { + this.toolbar.remove(); + this.element[this.options.toolbar]('destroy'); + } + _ref = this.options.plugins; + for (plugin in _ref) { + options = _ref[plugin]; + jQuery(this.element)[plugin]('destroy'); + } + return jQuery.Widget.prototype.destroy.call(this); + }, + disable: function() { + var _this = this; + this.element.attr("contentEditable", false); + this.element.off("focus", this._activated); + this.element.off("blur", this._deactivated); + this.element.off("keyup paste change", this._checkModified); + this.element.off("keyup", this._keys); + this.element.off("keyup mouseup", this._checkSelection); + this.bound = false; + jQuery(this.element).removeClass('isModified'); + jQuery(this.element).removeClass('inEditMode'); + this.element.parents('a').addBack().each(function(idx, elem) { + var element; + element = jQuery(elem); + if (!element.is('a')) { + return; + } + if (!_this.originalHref) { + return; + } + return element.attr('href', _this.originalHref); + }); + return this._trigger("disabled", null); + }, + enable: function() { + var _this = this; + this.element.parents('a[href]').addBack().each(function(idx, elem) { + var element; + element = jQuery(elem); + if (!element.is('a[href]')) { + return; + } + _this.originalHref = element.attr('href'); + return element.removeAttr('href'); + }); + this.element.attr("contentEditable", true); + if (!jQuery.parseHTML(this.element.html())) { + this.element.html(this.options.placeholder); + jQuery(this.element).addClass('inPlaceholderMode'); + this.element.css({ + 'min-width': this.element.innerWidth(), + 'min-height': this.element.innerHeight() + }); + } + if (!this.bound) { + this.element.on("focus", this, this._activated); + this.element.on("blur", this, this._deactivated); + this.element.on("keyup paste change", this, this._checkModified); + this.element.on("keyup", this, this._keys); + this.element.on("keyup mouseup", this, this._checkSelection); + this.bound = true; + } + if (this.options.forceStructured) { + this._forceStructured(); + } + return this._trigger("enabled", null); + }, + activate: function() { + return this.element.focus(); + }, + containsSelection: function() { + var range; + range = this.getSelection(); + return this.element.has(range.startContainer).length > 0; + }, + getSelection: function() { + var range, sel; + sel = rangy.getSelection(); + range = null; + if (sel.rangeCount > 0) { + range = sel.getRangeAt(0); + } else { + range = rangy.createRange(); + } + return range; + }, + restoreSelection: function(range) { + var sel; + sel = rangy.getSelection(); + return sel.setSingleRange(range); + }, + replaceSelection: function(cb) { + var newTextNode, r, range, sel, t; + if (navigator.appName === 'Microsoft Internet Explorer') { + t = document.selection.createRange().text; + r = document.selection.createRange(); + return r.pasteHTML(cb(t)); + } else { + sel = window.getSelection(); + range = sel.getRangeAt(0); + newTextNode = document.createTextNode(cb(range.extractContents())); + range.insertNode(newTextNode); + range.setStartAfter(newTextNode); + sel.removeAllRanges(); + return sel.addRange(range); + } + }, + removeAllSelections: function() { + if (navigator.appName === 'Microsoft Internet Explorer') { + return range.empty(); + } else { + return window.getSelection().removeAllRanges(); + } + }, + getPluginInstance: function(plugin) { + var instance; + instance = jQuery(this.element).data("IKS-" + plugin); + if (instance) { + return instance; + } + instance = jQuery(this.element).data(plugin); + if (instance) { + return instance; + } + throw new Error("Plugin " + plugin + " not found"); + }, + getContents: function() { + var cleanup, instance, plugin; + for (plugin in this.options.plugins) { + instance = this.getPluginInstance(plugin); + if (!instance) { + continue; + } + cleanup = instance.cleanupContentClone; + if (!jQuery.isFunction(cleanup)) { + continue; + } + jQuery(this.element)[plugin]('cleanupContentClone', this.element); + } + return this.element.html(); + }, + setContents: function(contents) { + return this.element.html(contents); + }, + isModified: function() { + if (!this.previousContent) { + this.previousContent = this.originalContent; + } + return this.previousContent !== this.getContents(); + }, + setUnmodified: function() { + jQuery(this.element).removeClass('isModified'); + return this.previousContent = this.getContents(); + }, + setModified: function() { + jQuery(this.element).addClass('isModified'); + return this._trigger('modified', null, { + editable: this, + content: this.getContents() + }); + }, + restoreOriginalContent: function() { + return this.element.html(this.originalContent); + }, + execute: function(command, value) { + if (document.execCommand(command, false, value)) { + return this.element.trigger("change"); + } + }, + protectFocusFrom: function(el) { + var _this = this; + return el.on("mousedown", function(event) { + event.preventDefault(); + _this._protectToolbarFocus = true; + return setTimeout(function() { + return _this._protectToolbarFocus = false; + }, 300); + }); + }, + keepActivated: function(_keepActivated) { + this._keepActivated = _keepActivated; + }, + _generateUUID: function() { + var S4; + S4 = function() { + return ((1 + Math.random()) * 0x10000 | 0).toString(16).substring(1); + }; + return "" + (S4()) + (S4()) + "-" + (S4()) + "-" + (S4()) + "-" + (S4()) + "-" + (S4()) + (S4()) + (S4()); + }, + _prepareToolbar: function() { + var defaults, instance, plugin, populate, toolbarOptions; + this.toolbar = jQuery('
').hide(); + if (this.options.toolbarCssClass) { + this.toolbar.addClass(this.options.toolbarCssClass); + } + defaults = { + editable: this, + parentElement: this.options.parentElement, + toolbar: this.toolbar, + positionAbove: this.options.toolbarPositionAbove + }; + toolbarOptions = jQuery.extend({}, defaults, this.options.toolbarOptions); + this.element[this.options.toolbar](toolbarOptions); + for (plugin in this.options.plugins) { + instance = this.getPluginInstance(plugin); + if (!instance) { + continue; + } + populate = instance.populateToolbar; + if (!jQuery.isFunction(populate)) { + continue; + } + this.element[plugin]('populateToolbar', this.toolbar); + } + this.element[this.options.toolbar]('setPosition'); + return this.protectFocusFrom(this.toolbar); + }, + changeToolbar: function(element, toolbar, hide) { + var originalToolbar; + if (hide == null) { + hide = false; + } + originalToolbar = this.options.toolbar; + this.options.parentElement = element; + if (toolbar) { + this.options.toolbar = toolbar; + } + if (!this.toolbar) { + return; + } + this.element[originalToolbar]('destroy'); + this.toolbar.remove(); + this._prepareToolbar(); + if (hide) { + return this.toolbar.hide(); + } + }, + _checkModified: function(event) { + var widget; + widget = event.data; + if (widget.isModified()) { + return widget.setModified(); + } + }, + _keys: function(event) { + var old, widget; + widget = event.data; + if (event.keyCode === 27) { + old = widget.getContents(); + widget.restoreOriginalContent(event); + widget._trigger("restored", null, { + editable: widget, + content: widget.getContents(), + thrown: old + }); + return widget.turnOff(); + } + }, + _rangesEqual: function(r1, r2) { + if (r1.startContainer !== r2.startContainer) { + return false; + } + if (r1.startOffset !== r2.startOffset) { + return false; + } + if (r1.endContainer !== r2.endContainer) { + return false; + } + if (r1.endOffset !== r2.endOffset) { + return false; + } + return true; + }, + _checkSelection: function(event) { + var widget; + if (event.keyCode === 27) { + return; + } + widget = event.data; + return setTimeout(function() { + var sel; + sel = widget.getSelection(); + if (widget._isEmptySelection(sel) || widget._isEmptyRange(sel)) { + if (widget.selection) { + widget.selection = null; + widget._trigger("unselected", null, { + editable: widget, + originalEvent: event + }); + } + return; + } + if (!widget.selection || !widget._rangesEqual(sel, widget.selection)) { + widget.selection = sel.cloneRange(); + return widget._trigger("selected", null, { + editable: widget, + selection: widget.selection, + ranges: [widget.selection], + originalEvent: event + }); + } + }, 0); + }, + _isEmptySelection: function(selection) { + if (selection.type === "Caret") { + return true; } return false; - }); - this.options.editable.element.on("hallodeactivated", function() { - return widget._closeDialog(); - }); - $toolbar.append($buttonset); - this.options.dialog.dialog(this.options.dialogOpts); - return this.options.dialog.dialog("option", "title", this.texts.title); - }, - _openDialog: function() { - var $editableEl, html, widget, xposition, yposition, - _this = this; - widget = this; - $editableEl = $(this.options.editable.element); - xposition = $editableEl.offset().left + $editableEl.outerWidth() + 10; - yposition = this.options.toolbar.offset().top - $(document).scrollTop(); - this.options.dialog.dialog("option", "position", [xposition, yposition]); - this.options.editable.keepActivated(true); - this.options.dialog.dialog("open"); - this.options.dialog.on('dialogclose', function() { - $('label', _this.button).removeClass('ui-state-active'); - _this.options.editable.element.focus(); - return _this.options.editable.keepActivated(false); - }); - this.options.dialog.html($("