From e25da86acf1dd2a0988fd2d6cc2c8f9760d6594a Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Fri, 14 Feb 2014 15:01:37 +0000 Subject: [PATCH 1/5] Added embed chooser unit test --- wagtail/wagtailembeds/tests.py | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/wagtail/wagtailembeds/tests.py b/wagtail/wagtailembeds/tests.py index a57469295..c5c74f7c1 100644 --- a/wagtail/wagtailembeds/tests.py +++ b/wagtail/wagtailembeds/tests.py @@ -1,5 +1,5 @@ from django.test import TestCase -from unittest import skip +from django.test.client import Client from wagtail.wagtailembeds import get_embed @@ -42,4 +42,27 @@ class TestEmbeds(TestCase): 'width': max_width if max_width else 640, 'height': 480, 'html': "

Blah blah blah

", - } \ No newline at end of file + } + + +def get_default_host(): + from wagtail.wagtailcore.models import Site + return Site.objects.filter(is_default_site=True).first().root_url.split('://')[1] + + +class TestChooser(TestCase): + def setUp(self): + # Create a user + from django.contrib.auth.models import User + User.objects.create_superuser(username='test', email='test@email.com', password='password') + + # Setup client + self.c = Client() + login = self.c.login(username='test', password='password') + self.assertEqual(login, True) + + def test_chooser(self): + r = self.c.get('/admin/embeds/chooser/', HTTP_HOST=get_default_host()) + self.assertEqual(r.status_code, 200) + + # TODO: Test submitting From 6c33ce02124cb3f5a903fdc8c3100a68f0c71cfb Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Fri, 14 Feb 2014 16:33:04 +0000 Subject: [PATCH 2/5] Fixed temporary redirects --- wagtail/wagtailredirects/middleware.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wagtail/wagtailredirects/middleware.py b/wagtail/wagtailredirects/middleware.py index 588814aa3..6fdd6fa27 100644 --- a/wagtail/wagtailredirects/middleware.py +++ b/wagtail/wagtailredirects/middleware.py @@ -20,7 +20,7 @@ class RedirectMiddleware(object): if redirect.is_permanent: return http.HttpResponsePermanentRedirect(redirect.link) else: - return http.HttpResponseTemporaryRedirect(redirect.link) + return http.HttpResponseRedirect(redirect.link) except: pass From 115e20a3c4a78850c7bc338665892f95f89e8bb3 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Fri, 14 Feb 2014 16:33:38 +0000 Subject: [PATCH 3/5] Rewrote redirect normalisation function --- wagtail/wagtailredirects/models.py | 37 +++++++++++++++--------------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/wagtail/wagtailredirects/models.py b/wagtail/wagtailredirects/models.py index 5c05d8960..2a3d5d71b 100644 --- a/wagtail/wagtailredirects/models.py +++ b/wagtail/wagtailredirects/models.py @@ -2,6 +2,8 @@ from django.db import models from wagtail.wagtailadmin.edit_handlers import FieldPanel, MultiFieldPanel, PageChooserPanel +from urlparse import urlparse + class Redirect(models.Model): old_path = models.CharField("Redirect from", max_length=255, unique=True, db_index=True) @@ -35,29 +37,28 @@ class Redirect(models.Model): return cls.objects.all() @staticmethod - def normalise_path(full_path): - # Split full_path into path and query_string - try: - question_mark = full_path.index('?') - path = full_path[:question_mark] - query_string = full_path[question_mark:] - except ValueError: - path = full_path - query_string = '' + def normalise_path(url): + # Parse url + url_parsed = urlparse(url) - # Check that the path has content before normalising - if path is None or path == '': - return query_string - - # Make sure theres a '/' at the beginning - if path[0] != '/': + # Path must start with / but not end with / + path = url_parsed[2] + if not path.startswith('/'): path = '/' + path - # Make sure theres not a '/' at the end - if path[-1] == '/': + if path.endswith('/'): path = path[:-1] - return path + query_string + # Query string components must be sorted alphabetically + query_string = url_parsed[4] + query_string_components = query_string.split('&') + query_string = '&'.join(sorted(query_string_components)) + + # Add query string to path + if query_string: + path = path + '?' + query_string + + return path def clean(self): # Normalise old path From fda1602595e9ec494849b99b4faf5576233e7dfe Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Fri, 14 Feb 2014 16:33:52 +0000 Subject: [PATCH 4/5] Added unit tests to wagtailredirects --- wagtail/wagtailredirects/tests.py | 82 ++++++++++++++++++++++++++----- 1 file changed, 69 insertions(+), 13 deletions(-) diff --git a/wagtail/wagtailredirects/tests.py b/wagtail/wagtailredirects/tests.py index 501deb776..1a34da329 100644 --- a/wagtail/wagtailredirects/tests.py +++ b/wagtail/wagtailredirects/tests.py @@ -1,16 +1,72 @@ -""" -This file demonstrates writing tests using the unittest module. These will pass -when you run "manage.py test". - -Replace this with more appropriate tests for your application. -""" - from django.test import TestCase +from django.test.client import Client +from wagtail.wagtailredirects import models -class SimpleTest(TestCase): - def test_basic_addition(self): - """ - Tests that 1 + 1 always equals 2. - """ - self.assertEqual(1 + 1, 2) +def get_default_site(): + from wagtail.wagtailcore.models import Site + return Site.objects.filter(is_default_site=True).first() + + +def get_default_host(): + return get_default_site().root_url.split('://')[1] + + +class TestRedirects(TestCase): + def test_path_normalisation(self): + # Shortcut to normalise function (to keep things tidy) + normalise_path = models.Redirect.normalise_path + + # Create a path + path = normalise_path('/Hello/world.html?foo=Bar&Baz=quux2') + + # Test against equivilant paths + self.assertEqual(path, normalise_path('/Hello/world.html?foo=Bar&Baz=quux2')) # The exact same URL + self.assertEqual(path, normalise_path('Hello/world.html?foo=Bar&Baz=quux2')) # Leading slash can be omitted + self.assertEqual(path, normalise_path('Hello/world.html/?foo=Bar&Baz=quux2')) # Trailing slashes are ignored + self.assertEqual(path, normalise_path('/Hello/world.html?foo=Bar&Baz=quux2#cool')) # Fragments are ignored + self.assertEqual(path, normalise_path('/Hello/world.html?Baz=quux2&foo=Bar')) # Order of query string paramters are ignored + + # Test against different paths + self.assertNotEqual(path, normalise_path('/hello/world.html?foo=Bar&Baz=quux2')) # 'hello' is lowercase + self.assertNotEqual(path, normalise_path('/Hello/world?foo=Bar&Baz=quux2')) # No '.html' + self.assertNotEqual(path, normalise_path('/Hello/world.html?foo=bar&Baz=Quux2')) # Query string parameters have wrong case + self.assertNotEqual(path, normalise_path('/Hello/world.html?foo=Bar&baz=quux2')) # ditto + self.assertNotEqual(path, normalise_path('/Hello/WORLD.html?foo=Bar&Baz=quux2')) # 'WORLD' is uppercase + self.assertNotEqual(path, normalise_path('/Hello/world.htm?foo=Bar&Baz=quux2')) # '.htm' is not the same as '.html' + + # Normalise some rubbish to make sure it doesn't crash + normalise_path('This is not a URL') + normalise_path('//////hello/world') + normalise_path('!#@%$*') + normalise_path('C:\\Program Files (x86)\\Some random program\\file.txt') + + def test_basic_redirect(self): + # Get a client + c = Client() + + # Create a redirect + redirect = models.Redirect(old_path='/redirectme', redirect_link='/redirectto', site=get_default_site()) + redirect.save() + + # Navigate to it + r = c.get('/redirectme/', HTTP_HOST=get_default_host()) + + # Check that we were redirected + self.assertEqual(r.status_code, 301) + self.assertTrue(r.has_header('Location')) + + def test_temporary_redirect(self): + # Get a client + c = Client() + + # Create a redirect + redirect = models.Redirect(old_path='/redirectme', redirect_link='/redirectto', site=get_default_site(), is_permanent=False) + redirect.save() + + # Navigate to it + r = c.get('/redirectme/', HTTP_HOST=get_default_host()) + + # Check that we were redirected temporarily + self.assertEqual(r.status_code, 302) + self.assertTrue(r.has_header('Location')) \ No newline at end of file From a9d4a70275e1dededfddd65fffe66ef06efc42d8 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Fri, 14 Feb 2014 17:17:31 +0000 Subject: [PATCH 5/5] Added MIDDLEWARE_CLASSES to runtests.py settings --- runtests.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/runtests.py b/runtests.py index e27f67aa8..17319cee9 100755 --- a/runtests.py +++ b/runtests.py @@ -26,6 +26,18 @@ if not settings.configured: TEMPLATE_CONTEXT_PROCESSORS=global_settings.TEMPLATE_CONTEXT_PROCESSORS + ( 'django.core.context_processors.request', ), + MIDDLEWARE_CLASSES=( + 'django.middleware.common.CommonMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', + + 'wagtail.wagtailcore.middleware.SiteMiddleware', + + 'wagtail.wagtailredirects.middleware.RedirectMiddleware', + ), INSTALLED_APPS=[ 'django.contrib.contenttypes', 'django.contrib.sessions',