Merge branch 'master' into edit-handlers-unit-tests

This commit is contained in:
Tom Talbot 2014-06-20 10:16:25 +01:00
commit 342699839b
23 changed files with 699 additions and 248 deletions

View file

@ -9,6 +9,11 @@ Changelog
* Removed the "More" section from the admin menu
* Added pagination to page listings in admin
* Support for setting a subpage_types property on page models, to define which page types are allowed as subpages
* Added a new datetime picker widget
* Added styleguide (mainly for wagtail developers)
* Aesthetic improvements to preview experience
* 'image' tag now accepts extra keyword arguments to be output as attributes on the img tag
* Added an 'attrs' property to image rendition objects to output src, width, height and alt attributes all in one go
* Fix: Animated GIFs are now coalesced before resizing
* Fix: Wand backend clones images before modifying them
* Fix: Admin breadcrumb now positioned correctly on mobile

View file

@ -1,8 +1,8 @@
Original Authors
================
* Matthew Westcott matthew.westcott@torchbox.com
* David Cranwell david.cranwell@torchbox.com
* Matthew Westcott matthew.westcott@torchbox.com twitter: @gasmanic
* David Cranwell david.cranwell@torchbox.com twitter: @davecranwell
* Karl Hobley karl.hobley@torchbox.com
* Helen Chapman helen.chapman@torchbox.com

View file

@ -1,7 +1,7 @@
.. image:: https://travis-ci.org/torchbox/wagtail.png?branch=master
:target: https://travis-ci.org/torchbox/wagtail
.. image:: https://coveralls.io/repos/torchbox/wagtail/badge.png?branch=master&zxcv
.. image:: https://coveralls.io/repos/torchbox/wagtail/badge.png?branch=master&zxcv1
:target: https://coveralls.io/r/torchbox/wagtail?branch=master
.. image:: https://pypip.in/v/wagtail/badge.png?zxcv

View file

@ -197,6 +197,11 @@ In some cases greater control over the ``img`` tag is required, for example to a
<img src="{{ tmp_photo.src }}" width="{{ tmp_photo.width }}"
height="{{ tmp_photo.height }}" alt="{{ tmp_photo.alt }}" class="my-custom-class" />
You can also use the ``attrs`` property as a shorthand to output the ``src``, ``width``, ``height`` and ``alt`` attributes in one go:
.. code-block:: django
<img {{ tmp_photo.attrs }} class="my-custom-class" />
.. _rich-text-filter:

View file

@ -24,21 +24,3 @@ class WagtailTestUtils(object):
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):
"""
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))

View file

@ -17,7 +17,7 @@ from django.core.urlresolvers import reverse
from django.utils.translation import ugettext_lazy
from wagtail.wagtailcore.models import Page
from wagtail.wagtailcore.util import camelcase_to_underscore
from wagtail.wagtailcore.utils import camelcase_to_underscore
from wagtail.wagtailcore.fields import RichTextArea

View file

@ -6,7 +6,7 @@ from wagtail.wagtailadmin import hooks
from wagtail.wagtailadmin.menu import MenuItem
from wagtail.wagtailcore.models import get_navigation_menu_items, UserPagePermissionsProxy
from wagtail.wagtailcore.util import camelcase_to_underscore
from wagtail.wagtailcore.utils import camelcase_to_underscore
register = template.Library()

View file

@ -43,8 +43,7 @@ class TestAuthentication(TestCase, WagtailTestUtils):
response = self.client.post(reverse('wagtailadmin_login'), post_data)
# Check that the user was redirected to the dashboard
self.assertEqual(response.status_code, 302)
self.assertURLEqual(response.url, reverse('wagtailadmin_home'))
self.assertRedirects(response, reverse('wagtailadmin_home'))
# Check that the user was logged in
self.assertTrue('_auth_user_id' in self.client.session)
@ -60,8 +59,7 @@ class TestAuthentication(TestCase, WagtailTestUtils):
response = self.client.get(reverse('wagtailadmin_login'))
# Check that the user was redirected to the dashboard
self.assertEqual(response.status_code, 302)
self.assertURLEqual(response.url, reverse('wagtailadmin_home'))
self.assertRedirects(response, reverse('wagtailadmin_home'))
def test_logout(self):
"""
@ -71,8 +69,7 @@ class TestAuthentication(TestCase, WagtailTestUtils):
response = self.client.get(reverse('wagtailadmin_logout'))
# Check that the user was redirected to the login page
self.assertEqual(response.status_code, 302)
self.assertURLEqual(response.url, reverse('wagtailadmin_login'))
self.assertRedirects(response, reverse('wagtailadmin_login'))
# Check that the user was logged out
self.assertFalse('_auth_user_id' in self.client.session)
@ -89,8 +86,7 @@ class TestAuthentication(TestCase, WagtailTestUtils):
response = self.client.get(reverse('wagtailadmin_home'))
# Check that the user was redirected to the login page and that next was set correctly
self.assertEqual(response.status_code, 302)
self.assertURLEqual(response.url, reverse('wagtailadmin_login') + '?next=' + reverse('wagtailadmin_home'))
self.assertRedirects(response, reverse('wagtailadmin_login') + '?next=' + reverse('wagtailadmin_home'))
def test_not_logged_in_redirect_default_settings(self):
"""
@ -109,7 +105,7 @@ class TestAuthentication(TestCase, WagtailTestUtils):
# Note: The user will be redirected to 'django.contrib.auth.views.login' but
# this must be the same URL as 'wagtailadmin_login'
self.assertEqual(response.status_code, 302)
self.assertURLEqual(response.url, reverse('wagtailadmin_login') + '?next=' + reverse('wagtailadmin_home'))
self.assertRedirects(response, reverse('wagtailadmin_login') + '?next=' + reverse('wagtailadmin_home'))
class TestAccountSection(TestCase, WagtailTestUtils):
@ -154,8 +150,7 @@ class TestAccountSection(TestCase, WagtailTestUtils):
response = self.client.post(reverse('wagtailadmin_account_change_password'), post_data)
# Check that the user was redirected to the account page
self.assertEqual(response.status_code, 302)
self.assertURLEqual(response.url, reverse('wagtailadmin_account'))
self.assertRedirects(response, reverse('wagtailadmin_account'))
# Check that the password was changed
self.assertTrue(User.objects.get(username='test').check_password('newpassword'))
@ -214,8 +209,7 @@ class TestPasswordReset(TestCase, WagtailTestUtils):
response = self.client.post(reverse('password_reset'), post_data)
# Check that the user was redirected to the done page
self.assertEqual(response.status_code, 302)
self.assertURLEqual(response.url, reverse('password_reset_done'))
self.assertRedirects(response, reverse('password_reset_done'))
# Check that a password reset email was sent to the user
self.assertEqual(len(mail.outbox), 1)
@ -306,8 +300,7 @@ class TestPasswordReset(TestCase, WagtailTestUtils):
response = self.client.post(reverse('password_reset_confirm', kwargs=self.url_kwargs), post_data)
# Check that the user was redirected to the complete page
self.assertEqual(response.status_code, 302)
self.assertURLEqual(response.url, reverse('password_reset_complete'))
self.assertRedirects(response, reverse('password_reset_complete'))
# Check that the password was changed
self.assertTrue(User.objects.get(username='test').check_password('newpassword'))

View file

@ -5,6 +5,7 @@ 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
from django.core.paginator import Paginator
class TestPageExplorer(TestCase, WagtailTestUtils):
@ -13,9 +14,10 @@ class TestPageExplorer(TestCase, WagtailTestUtils):
self.root_page = Page.objects.get(id=2)
# Add child page
self.child_page = SimplePage()
self.child_page.title = "Hello world!"
self.child_page.slug = "hello-world"
self.child_page = SimplePage(
title="Hello world!",
slug="hello-world",
)
self.root_page.add_child(instance=self.child_page)
# Login
@ -24,9 +26,81 @@ class TestPageExplorer(TestCase, WagtailTestUtils):
def test_explore(self):
response = self.client.get(reverse('wagtailadmin_explore', args=(self.root_page.id, )))
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailadmin/pages/index.html')
self.assertEqual(self.root_page, response.context['parent_page'])
self.assertTrue(response.context['pages'].paginator.object_list.filter(id=self.child_page.id).exists())
def test_explore_root(self):
response = self.client.get(reverse('wagtailadmin_explore_root'))
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailadmin/pages/index.html')
self.assertEqual(Page.objects.get(id=1), response.context['parent_page'])
self.assertTrue(response.context['pages'].paginator.object_list.filter(id=self.root_page.id).exists())
def test_ordering(self):
response = self.client.get(reverse('wagtailadmin_explore_root'), {'ordering': 'content_type'})
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailadmin/pages/index.html')
self.assertEqual(response.context['ordering'], 'content_type')
def test_invalid_ordering(self):
response = self.client.get(reverse('wagtailadmin_explore_root'), {'ordering': 'invalid_order'})
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailadmin/pages/index.html')
self.assertEqual(response.context['ordering'], 'title')
def test_reordering(self):
response = self.client.get(reverse('wagtailadmin_explore_root'), {'ordering': 'ord'})
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailadmin/pages/index.html')
self.assertEqual(response.context['ordering'], 'ord')
# Pages must not be paginated
self.assertNotIsInstance(response.context['pages'], Paginator)
def make_pages(self):
for i in range(150):
self.root_page.add_child(instance=SimplePage(
title="Page " + str(i),
slug="page-" + str(i),
))
def test_pagination(self):
self.make_pages()
response = self.client.get(reverse('wagtailadmin_explore', args=(self.root_page.id, )), {'p': 2})
# Check response
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailadmin/pages/index.html')
# Check that we got the correct page
self.assertEqual(response.context['pages'].number, 2)
def test_pagination_invalid(self):
self.make_pages()
response = self.client.get(reverse('wagtailadmin_explore', args=(self.root_page.id, )), {'p': 'Hello World!'})
# Check response
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailadmin/pages/index.html')
# Check that we got page one
self.assertEqual(response.context['pages'].number, 1)
def test_pagination_out_of_range(self):
self.make_pages()
response = self.client.get(reverse('wagtailadmin_explore', args=(self.root_page.id, )), {'p': 99999})
# Check response
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailadmin/pages/index.html')
# Check that we got the last page
self.assertEqual(response.context['pages'].number, response.context['pages'].paginator.num_pages)
class TestPageCreation(TestCase, WagtailTestUtils):
def setUp(self):
@ -85,8 +159,7 @@ class TestPageCreation(TestCase, WagtailTestUtils):
response = self.client.post(reverse('wagtailadmin_pages_create', args=('tests', 'simplepage', self.root_page.id)), post_data)
# Should be redirected to explorer page
self.assertEqual(response.status_code, 302)
self.assertURLEqual(response.url, reverse('wagtailadmin_explore', args=(self.root_page.id, )))
self.assertRedirects(response, 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,8 +177,7 @@ class TestPageCreation(TestCase, WagtailTestUtils):
response = self.client.post(reverse('wagtailadmin_pages_create', args=('tests', 'simplepage', self.root_page.id)), post_data)
# Should be redirected to explorer page
self.assertEqual(response.status_code, 302)
self.assertURLEqual(response.url, reverse('wagtailadmin_explore', args=(self.root_page.id, )))
self.assertRedirects(response, 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
@ -127,8 +199,7 @@ class TestPageCreation(TestCase, WagtailTestUtils):
response = self.client.post(reverse('wagtailadmin_pages_create', args=('tests', 'simplepage', self.root_page.id)), post_data)
# Should be redirected to explorer page
self.assertEqual(response.status_code, 302)
self.assertURLEqual(response.url, reverse('wagtailadmin_explore', args=(self.root_page.id, )))
self.assertRedirects(response, 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
@ -144,7 +215,7 @@ class TestPageCreation(TestCase, WagtailTestUtils):
self.assertEqual(mail.outbox[0].to, ['moderator@email.com'])
self.assertEqual(mail.outbox[0].subject, 'The page "New page!" has been submitted for moderation')
def test_create_simplepage_post_existingslug(self):
def test_create_simplepage_post_existing_slug(self):
# This tests the existing slug checking on page save
# Create a page
@ -165,6 +236,9 @@ class TestPageCreation(TestCase, WagtailTestUtils):
# Should not be redirected (as the save should fail)
self.assertEqual(response.status_code, 200)
# Check that a form error was raised
self.assertFormError(response, 'form', 'slug', "This slug is already in use")
def test_create_nonexistantparent(self):
response = self.client.get(reverse('wagtailadmin_pages_create', args=('tests', 'simplepage', 100000)))
self.assertEqual(response.status_code, 404)
@ -245,8 +319,7 @@ class TestPageEdit(TestCase, WagtailTestUtils):
response = self.client.post(reverse('wagtailadmin_pages_edit', args=(self.child_page.id, )), post_data)
# Should be redirected to explorer page
self.assertEqual(response.status_code, 302)
self.assertURLEqual(response.url, reverse('wagtailadmin_explore', args=(self.root_page.id, )))
self.assertRedirects(response, 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)
@ -263,8 +336,7 @@ class TestPageEdit(TestCase, WagtailTestUtils):
response = self.client.post(reverse('wagtailadmin_pages_edit', args=(self.child_page.id, )), post_data)
# Should be redirected to explorer page
self.assertEqual(response.status_code, 302)
self.assertURLEqual(response.url, reverse('wagtailadmin_explore', args=(self.root_page.id, )))
self.assertRedirects(response, 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)
@ -287,8 +359,7 @@ class TestPageEdit(TestCase, WagtailTestUtils):
response = self.client.post(reverse('wagtailadmin_pages_edit', args=(self.child_page.id, )), post_data)
# Should be redirected to explorer page
self.assertEqual(response.status_code, 302)
self.assertURLEqual(response.url, reverse('wagtailadmin_explore', args=(self.root_page.id, )))
self.assertRedirects(response, 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)
@ -302,6 +373,29 @@ class TestPageEdit(TestCase, WagtailTestUtils):
self.assertEqual(mail.outbox[0].to, ['moderator@email.com'])
self.assertEqual(mail.outbox[0].subject, 'The page "Hello world!" has been submitted for moderation') # Note: should this be "I've been edited!"?
def test_page_edit_post_existing_slug(self):
# This tests the existing slug checking on page edit
# Create a page
self.child_page = SimplePage()
self.child_page.title = "Hello world 2"
self.child_page.slug = "hello-world2"
self.root_page.add_child(instance=self.child_page)
# Attempt to change the slug to one thats already in use
post_data = {
'title': "Hello world 2",
'slug': 'hello-world',
'action-submit': "Submit",
}
response = self.client.post(reverse('wagtailadmin_pages_edit', args=(self.child_page.id, )), post_data)
# Should not be redirected (as the save should fail)
self.assertEqual(response.status_code, 200)
# Check that a form error was raised
self.assertFormError(response, 'form', 'slug', "This slug is already in use")
def test_preview_on_edit(self):
post_data = {
'title': "I've been edited!",
@ -354,8 +448,7 @@ class TestPageDelete(TestCase, WagtailTestUtils):
response = self.client.post(reverse('wagtailadmin_pages_delete', args=(self.child_page.id, )), post_data)
# Should be redirected to explorer page
self.assertEqual(response.status_code, 302)
self.assertURLEqual(response.url, reverse('wagtailadmin_explore', args=(self.root_page.id, )))
self.assertRedirects(response, 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)
@ -514,9 +607,8 @@ class TestPageUnpublish(TestCase, WagtailTestUtils):
'foo': "Must post something or the view won't see this as a POST request",
})
# 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, )))
# Should be redirected to explorer page
self.assertRedirects(response, reverse('wagtailadmin_explore', args=(self.root_page.id, )))
# Check that the page was unpublished
self.assertFalse(SimplePage.objects.get(id=self.page.id).live)
@ -554,8 +646,7 @@ class TestApproveRejectModeration(TestCase, WagtailTestUtils):
})
# Check that the user was redirected to the dashboard
self.assertEqual(response.status_code, 302)
self.assertURLEqual(response.url, reverse('wagtailadmin_home'))
self.assertRedirects(response, reverse('wagtailadmin_home'))
# Page must be live
self.assertTrue(Page.objects.get(id=self.page.id).live)
@ -606,8 +697,7 @@ class TestApproveRejectModeration(TestCase, WagtailTestUtils):
})
# Check that the user was redirected to the dashboard
self.assertEqual(response.status_code, 302)
self.assertURLEqual(response.url, reverse('wagtailadmin_home'))
self.assertRedirects(response, reverse('wagtailadmin_home'))
# Page must not be live
self.assertFalse(Page.objects.get(id=self.page.id).live)

View file

@ -0,0 +1,82 @@
from django.test import TestCase
from django.test.client import RequestFactory
from django.core.urlresolvers import reverse
from django.template import Template, Context
from django.contrib.auth.models import User, AnonymousUser
from wagtail.tests.utils import WagtailTestUtils
from wagtail.wagtailcore.models import Page
class TestUserbarTag(TestCase):
def setUp(self):
self.user = User.objects.create_superuser(username='test', email='test@email.com', password='password')
self.homepage = Page.objects.get(id=2)
def dummy_request(self, user=None):
request = RequestFactory().get('/')
request.user = user or AnonymousUser()
return request
def test_userbar_tag(self):
template = Template("{% load wagtailuserbar %}{% wagtailuserbar %}")
content = template.render(Context({
'self': self.homepage,
'request': self.dummy_request(self.user),
}))
self.assertIn("<!-- Wagtail user bar embed code -->", content)
def test_userbar_tag_anonymous_user(self):
template = Template("{% load wagtailuserbar %}{% wagtailuserbar %}")
content = template.render(Context({
'self': self.homepage,
'request': self.dummy_request(),
}))
# Make sure nothing was rendered
self.assertEqual(content, '')
class TestUserbarFrontend(TestCase, WagtailTestUtils):
def setUp(self):
self.login()
self.homepage = Page.objects.get(id=2)
def test_userbar_frontend(self):
response = self.client.get(reverse('wagtailadmin_userbar_frontend', args=(self.homepage.id, )))
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailadmin/userbar/base.html')
def test_userbar_frontend_anonymous_user_cannot_see(self):
# Logout
self.client.logout()
response = self.client.get(reverse('wagtailadmin_userbar_frontend', args=(self.homepage.id, )))
# Check that the user recieved a forbidden message
self.assertEqual(response.status_code, 403)
class TestUserbarModeration(TestCase, WagtailTestUtils):
def setUp(self):
self.login()
self.homepage = Page.objects.get(id=2)
self.homepage.save_revision()
self.revision = self.homepage.get_latest_revision()
def test_userbar_moderation(self):
response = self.client.get(reverse('wagtailadmin_userbar_moderation', args=(self.revision.id, )))
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailadmin/userbar/base.html')
def test_userbar_moderation_anonymous_user_cannot_see(self):
# Logout
self.client.logout()
response = self.client.get(reverse('wagtailadmin_userbar_moderation', args=(self.revision.id, )))
# Check that the user recieved a forbidden message
self.assertEqual(response.status_code, 403)

View file

@ -25,16 +25,14 @@ def index(request, parent_page_id=None):
pages = parent_page.get_children().prefetch_related('content_type')
# Get page ordering
if 'ordering' in request.GET:
ordering = request.GET['ordering']
if ordering in ['title', '-title', 'content_type', '-content_type', 'live', '-live']:
pages = pages.order_by(ordering)
else:
ordering = request.GET.get('ordering', 'title')
if ordering not in ['title', '-title', 'content_type', '-content_type', 'live', '-live', 'ord']:
ordering = 'title'
# Pagination
if ordering != 'ord':
pages = pages.order_by(ordering)
p = request.GET.get('p', 1)
paginator = Paginator(pages, 50)
try:
@ -179,6 +177,7 @@ def create(request, content_type_app_name, content_type_model_name, parent_page_
'parent_page': parent_page,
'edit_handler': edit_handler,
'display_modes': page.get_page_modes(),
'form': form, # Used in unit tests
})
@ -264,6 +263,7 @@ def edit(request, page_id):
'edit_handler': edit_handler,
'errors_debug': errors_debug,
'display_modes': page.get_page_modes(),
'form': form, # Used in unit tests
})

View file

@ -18,7 +18,7 @@ from django.utils.translation import ugettext_lazy as _
from treebeard.mp_tree import MP_Node
from wagtail.wagtailcore.util import camelcase_to_underscore
from wagtail.wagtailcore.utils import camelcase_to_underscore
from wagtail.wagtailcore.query import PageQuerySet
from wagtail.wagtailsearch import Indexed, get_search_backend
@ -126,56 +126,56 @@ def get_navigable_page_content_type_ids():
class PageManager(models.Manager):
def get_query_set(self):
def get_queryset(self):
return PageQuerySet(self.model).order_by('path')
def live(self):
return self.get_query_set().live()
return self.get_queryset().live()
def not_live(self):
return self.get_query_set().not_live()
return self.get_queryset().not_live()
def page(self, other):
return self.get_query_set().page(other)
return self.get_queryset().page(other)
def not_page(self, other):
return self.get_query_set().not_page(other)
return self.get_queryset().not_page(other)
def descendant_of(self, other, inclusive=False):
return self.get_query_set().descendant_of(other, inclusive)
return self.get_queryset().descendant_of(other, inclusive)
def not_descendant_of(self, other, inclusive=False):
return self.get_query_set().not_descendant_of(other, inclusive)
return self.get_queryset().not_descendant_of(other, inclusive)
def child_of(self, other):
return self.get_query_set().child_of(other)
return self.get_queryset().child_of(other)
def not_child_of(self, other):
return self.get_query_set().not_child_of(other)
return self.get_queryset().not_child_of(other)
def ancestor_of(self, other, inclusive=False):
return self.get_query_set().ancestor_of(other, inclusive)
return self.get_queryset().ancestor_of(other, inclusive)
def not_ancestor_of(self, other, inclusive=False):
return self.get_query_set().not_ancestor_of(other, inclusive)
return self.get_queryset().not_ancestor_of(other, inclusive)
def parent_of(self, other):
return self.get_query_set().parent_of(other)
return self.get_queryset().parent_of(other)
def not_parent_of(self, other):
return self.get_query_set().not_parent_of(other)
return self.get_queryset().not_parent_of(other)
def sibling_of(self, other, inclusive=False):
return self.get_query_set().sibling_of(other, inclusive)
return self.get_queryset().sibling_of(other, inclusive)
def not_sibling_of(self, other, inclusive=False):
return self.get_query_set().not_sibling_of(other, inclusive)
return self.get_queryset().not_sibling_of(other, inclusive)
def type(self, model):
return self.get_query_set().type(model)
return self.get_queryset().type(model)
def not_type(self, model):
return self.get_query_set().not_type(model)
return self.get_queryset().not_type(model)
class PageBase(models.base.ModelBase):
@ -697,8 +697,8 @@ class Orderable(models.Model):
class SubmittedRevisionsManager(models.Manager):
def get_query_set(self):
return super(SubmittedRevisionsManager, self).get_query_set().filter(submitted_for_moderation=True)
def get_queryset(self):
return super(SubmittedRevisionsManager, self).get_queryset().filter(submitted_for_moderation=True)
class PageRevision(models.Model):

View file

@ -1,6 +1,7 @@
import re
import warnings
warnings.warn(
"The wagtail.wagtailcore.util module has been renamed. "
"Use wagtail.wagtailcore.utils instead.", DeprecationWarning)
def camelcase_to_underscore(str):
# http://djangosnippets.org/snippets/585/
return re.sub('(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|$)))', '_\\1', str).lower().strip('_')
from .utils import *

View file

@ -0,0 +1,6 @@
import re
def camelcase_to_underscore(str):
# http://djangosnippets.org/snippets/585/
return re.sub('(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|$)))', '_\\1', str).lower().strip('_')

View file

@ -43,29 +43,61 @@ class TestDocumentIndexView(TestCase, WagtailTestUtils):
def setUp(self):
self.login()
def get(self, params={}):
return self.client.get(reverse('wagtaildocs_index'), params)
def test_simple(self):
response = self.get()
response = self.client.get(reverse('wagtaildocs_index'))
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtaildocs/documents/index.html')
def test_search(self):
response = self.get({'q': "Hello"})
response = self.client.get(reverse('wagtaildocs_index'), {'q': "Hello"})
self.assertEqual(response.status_code, 200)
self.assertEqual(response.context['query_string'], "Hello")
def make_docs(self):
for i in range(50):
document = models.Document(title="Test " + str(i))
document.save()
def test_pagination(self):
pages = ['0', '1', '-1', '9999', 'Not a page']
for page in pages:
response = self.get({'p': page})
self.assertEqual(response.status_code, 200)
self.make_docs()
response = self.client.get(reverse('wagtaildocs_index'), {'p': 2})
# Check response
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtaildocs/documents/index.html')
# Check that we got the correct page
self.assertEqual(response.context['documents'].number, 2)
def test_pagination_invalid(self):
self.make_docs()
response = self.client.get(reverse('wagtaildocs_index'), {'p': 'Hello World!'})
# Check response
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtaildocs/documents/index.html')
# Check that we got page one
self.assertEqual(response.context['documents'].number, 1)
def test_pagination_out_of_range(self):
self.make_docs()
response = self.client.get(reverse('wagtaildocs_index'), {'p': 99999})
# Check response
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtaildocs/documents/index.html')
# Check that we got the last page
self.assertEqual(response.context['documents'].number, response.context['documents'].paginator.num_pages)
def test_ordering(self):
orderings = ['title', '-created_at']
for ordering in orderings:
response = self.get({'ordering': ordering})
response = self.client.get(reverse('wagtaildocs_index'), {'ordering': ordering})
self.assertEqual(response.status_code, 200)
@ -73,33 +105,63 @@ class TestDocumentAddView(TestCase, WagtailTestUtils):
def setUp(self):
self.login()
def get(self, params={}):
return self.client.get(reverse('wagtaildocs_add_document'), params)
def test_simple(self):
response = self.get()
response = self.client.get(reverse('wagtaildocs_add_document'))
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtaildocs/documents/add.html')
# TODO: Test posting
def test_post(self):
# Build a fake file
fake_file = ContentFile("A boring example document")
fake_file.name = 'test.txt'
# Submit
post_data = {
'title': "Test document",
'file': fake_file,
}
response = self.client.post(reverse('wagtaildocs_add_document'), post_data)
# User should be redirected back to the index
self.assertRedirects(response, reverse('wagtaildocs_index'))
# Document should be created
self.assertTrue(models.Document.objects.filter(title="Test document").exists())
class TestDocumentEditView(TestCase, WagtailTestUtils):
def setUp(self):
self.login()
# Create a document to edit
self.document = models.Document.objects.create(title="Test document")
# Build a fake file
fake_file = ContentFile("A boring example document")
fake_file.name = 'test.txt'
def get(self, params={}):
return self.client.get(reverse('wagtaildocs_edit_document', args=(self.document.id,)), params)
# Create a document to edit
self.document = models.Document.objects.create(title="Test document", file=fake_file)
def test_simple(self):
response = self.get()
response = self.client.get(reverse('wagtaildocs_edit_document', args=(self.document.id,)))
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtaildocs/documents/edit.html')
# TODO: Test posting
def test_post(self):
# Build a fake file
fake_file = ContentFile("A boring example document")
fake_file.name = 'test.txt'
# Submit title change
post_data = {
'title': "Test document changed!",
'file': fake_file,
}
response = self.client.post(reverse('wagtaildocs_edit_document', args=(self.document.id,)), post_data)
# User should be redirected back to the index
self.assertRedirects(response, reverse('wagtaildocs_index'))
# Document title should be changed
self.assertEqual(models.Document.objects.get(id=self.document.id).title, "Test document changed!")
class TestDocumentDeleteView(TestCase, WagtailTestUtils):
@ -109,40 +171,80 @@ class TestDocumentDeleteView(TestCase, WagtailTestUtils):
# Create a document to delete
self.document = models.Document.objects.create(title="Test document")
def get(self, params={}):
return self.client.get(reverse('wagtaildocs_delete_document', args=(self.document.id,)), params)
def test_simple(self):
response = self.get()
response = self.client.get(reverse('wagtaildocs_delete_document', args=(self.document.id,)))
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtaildocs/documents/confirm_delete.html')
# TODO: Test posting
def test_delete(self):
# Submit title change
post_data = {
'foo': 'bar'
}
response = self.client.post(reverse('wagtaildocs_delete_document', args=(self.document.id,)), post_data)
# User should be redirected back to the index
self.assertRedirects(response, reverse('wagtaildocs_index'))
# Document should be deleted
self.assertFalse(models.Document.objects.filter(id=self.document.id).exists())
class TestDocumentChooserView(TestCase, WagtailTestUtils):
def setUp(self):
self.login()
def get(self, params={}):
return self.client.get(reverse('wagtaildocs_chooser'), params)
def test_simple(self):
response = self.get()
response = self.client.get(reverse('wagtaildocs_chooser'))
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"})
response = self.client.get(reverse('wagtaildocs_chooser'), {'q': "Hello"})
self.assertEqual(response.status_code, 200)
self.assertEqual(response.context['query_string'], "Hello")
def make_docs(self):
for i in range(50):
document = models.Document(title="Test " + str(i))
document.save()
def test_pagination(self):
pages = ['0', '1', '-1', '9999', 'Not a page']
for page in pages:
response = self.get({'p': page})
self.assertEqual(response.status_code, 200)
self.make_docs()
response = self.client.get(reverse('wagtaildocs_chooser'), {'p': 2})
# Check response
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtaildocs/documents/list.html')
# Check that we got the correct page
self.assertEqual(response.context['documents'].number, 2)
def test_pagination_invalid(self):
self.make_docs()
response = self.client.get(reverse('wagtaildocs_chooser'), {'p': 'Hello World!'})
# Check response
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtaildocs/documents/list.html')
# Check that we got page one
self.assertEqual(response.context['documents'].number, 1)
def test_pagination_out_of_range(self):
self.make_docs()
response = self.client.get(reverse('wagtaildocs_chooser'), {'p': 99999})
# Check response
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtaildocs/documents/list.html')
# Check that we got the last page
self.assertEqual(response.context['documents'].number, response.context['documents'].paginator.num_pages)
class TestDocumentChooserChosenView(TestCase, WagtailTestUtils):
@ -152,31 +254,40 @@ class TestDocumentChooserChosenView(TestCase, WagtailTestUtils):
# Create a document to choose
self.document = models.Document.objects.create(title="Test document")
def get(self, params={}):
return self.client.get(reverse('wagtaildocs_document_chosen', args=(self.document.id,)), params)
def test_simple(self):
response = self.get()
response = self.client.get(reverse('wagtaildocs_document_chosen', args=(self.document.id,)))
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtaildocs/chooser/document_chosen.js')
# TODO: Test posting
class TestDocumentChooserUploadView(TestCase, WagtailTestUtils):
def setUp(self):
self.login()
def get(self, params={}):
return self.client.get(reverse('wagtaildocs_chooser_upload'), params)
def test_simple(self):
response = self.get()
response = self.client.get(reverse('wagtaildocs_chooser_upload'))
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
def test_post(self):
# Build a fake file
fake_file = ContentFile("A boring example document")
fake_file.name = 'test.txt'
# Submit
post_data = {
'title': "Test document",
'file': fake_file,
}
response = self.client.post(reverse('wagtaildocs_chooser_upload'), post_data)
# Check that the response is a javascript file saying the document was chosen
self.assertTemplateUsed(response, 'wagtaildocs/chooser/document_chosen.js')
self.assertContains(response, "modal.respond('documentChosen'")
# Document should be created
self.assertTrue(models.Document.objects.filter(title="Test document").exists())
class TestDocumentFilenameProperties(TestCase):

View file

@ -10,7 +10,7 @@ from django.db import models
from django.db.models.signals import pre_delete
from django.dispatch.dispatcher import receiver
from django.utils.safestring import mark_safe
from django.utils.html import escape
from django.utils.html import escape, format_html_join
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
@ -68,8 +68,8 @@ class AbstractImage(models.Model, TagSearchable):
except ObjectDoesNotExist:
file_field = self.file
# If we have a backend attribute then pass it to process
# image - else pass 'default'
# If we have a backend attribute then pass it to process
# image - else pass 'default'
backend_name = getattr(self, 'backend', 'default')
generated_image_file = filter.process_image(file_field.file, backend_name=backend_name)
@ -236,11 +236,19 @@ class AbstractRendition(models.Model):
def url(self):
return self.file.url
def img_tag(self):
@property
def attrs(self):
return mark_safe(
'<img src="%s" width="%d" height="%d" alt="%s">' % (escape(self.url), self.width, self.height, escape(self.image.title))
'src="%s" width="%d" height="%d" alt="%s"' % (escape(self.url), self.width, self.height, escape(self.image.title))
)
def img_tag(self, extra_attributes=None):
if extra_attributes:
extra_attributes_string = format_html_join(' ', '{0}="{1}"', extra_attributes.items())
return mark_safe('<img %s %s>' % (self.attrs, extra_attributes_string))
else:
return mark_safe('<img %s>' % self.attrs)
class Meta:
abstract = True

View file

@ -7,32 +7,36 @@ register = template.Library()
# Local cache of filters, avoid hitting the DB
filters = {}
@register.tag(name="image")
def image(parser, token):
args = token.split_contents()
bits = token.split_contents()[1:]
image_var = bits[0]
filter_spec = bits[1]
bits = bits[2:]
if len(args) == 3:
# token is of the form {% image self.photo max-320x200 %}
tag_name, image_var, filter_spec = args
return ImageNode(image_var, filter_spec)
elif len(args) == 5:
if len(bits) == 2 and bits[0] == 'as':
# token is of the form {% image self.photo max-320x200 as img %}
tag_name, image_var, filter_spec, as_token, out_var = args
if as_token != 'as':
raise template.TemplateSyntaxError("'image' tag should be of the form {%% image self.photo max-320x200 %%} or {%% image self.photo max-320x200 as img %%}")
return ImageNode(image_var, filter_spec, out_var)
return ImageNode(image_var, filter_spec, output_var_name=bits[1])
else:
raise template.TemplateSyntaxError("'image' tag should be of the form {%% image self.photo max-320x200 %%} or {%% image self.photo max-320x200 as img %%}")
# token is of the form {% image self.photo max-320x200 %} - all additional tokens
# should be kwargs, which become attributes
attrs = {}
for bit in bits:
try:
name, value = bit.split('=')
except ValueError:
raise template.TemplateSyntaxError("'image' tag should be of the form {% image self.photo max-320x200 [ custom-attr=\"value\" ... ] %} or {% image self.photo max-320x200 as img %}")
attrs[name] = parser.compile_filter(value) # setup to resolve context variables as value
return ImageNode(image_var, filter_spec, attrs=attrs)
class ImageNode(template.Node):
def __init__(self, image_var_name, filter_spec, output_var_name=None):
def __init__(self, image_var_name, filter_spec, output_var_name=None, attrs={}):
self.image_var = template.Variable(image_var_name)
self.output_var_name = output_var_name
self.attrs = attrs
if filter_spec not in filters:
filters[filter_spec], _ = Filter.objects.get_or_create(spec=filter_spec)
@ -66,4 +70,7 @@ class ImageNode(template.Node):
return ''
else:
# render the rendition's image tag now
return rendition.img_tag()
resolved_attrs = {}
for key in self.attrs:
resolved_attrs[key] = self.attrs[key].resolve(context)
return rendition.img_tag(resolved_attrs)

View file

@ -197,6 +197,32 @@ class TestImageTag(TestCase):
self.assertTrue('height="300"' in result)
self.assertTrue('alt="Test image"' in result)
def render_image_tag_as(self, image, filter_spec):
temp = template.Template('{% load image_tags %}{% image image_obj ' + filter_spec + ' as test_img %}<img {{ test_img.attrs }} />')
context = template.Context({'image_obj': image})
return temp.render(context)
def test_image_tag_attrs(self):
result = self.render_image_tag_as(self.image, 'width-400')
# Check that all the required HTML attributes are set
self.assertTrue('width="400"' in result)
self.assertTrue('height="300"' in result)
self.assertTrue('alt="Test image"' in result)
def render_image_tag_with_extra_attributes(self, image, title):
temp = template.Template('{% load image_tags %}{% image image_obj width-400 class="photo" title=title|lower %}')
context = template.Context({'image_obj': image, 'title': title})
return temp.render(context)
def test_image_tag_with_extra_attributes(self):
result = self.render_image_tag_with_extra_attributes(self.image, 'My Wonderful Title')
# Check that all the required HTML attributes are set
self.assertTrue('width="400"' in result)
self.assertTrue('height="300"' in result)
self.assertTrue('class="photo"' in result)
self.assertTrue('title="my wonderful title"' in result)
## ===== ADMIN VIEWS =====
@ -253,8 +279,7 @@ class TestImageAddView(TestCase, WagtailTestUtils):
})
# Should redirect back to index
self.assertEqual(response.status_code, 302)
self.assertURLEqual(response.url, reverse('wagtailimages_index'))
self.assertRedirects(response, reverse('wagtailimages_index'))
# Check that the image was created
images = Image.objects.filter(title="Test image")
@ -293,8 +318,7 @@ class TestImageEditView(TestCase, WagtailTestUtils):
})
# Should redirect back to index
self.assertEqual(response.status_code, 302)
self.assertURLEqual(response.url, reverse('wagtailimages_index'))
self.assertRedirects(response, reverse('wagtailimages_index'))
# Check that the image was edited
image = Image.objects.get(id=self.image.id)
@ -328,8 +352,7 @@ class TestImageDeleteView(TestCase, WagtailTestUtils):
})
# Should redirect back to index
self.assertEqual(response.status_code, 302)
self.assertURLEqual(response.url, reverse('wagtailimages_index'))
self.assertRedirects(response, reverse('wagtailimages_index'))
# Check that the image was deleted
images = Image.objects.filter(title="Test image")

View file

@ -113,8 +113,7 @@ class TestRedirectsAddView(TestCase, WagtailTestUtils):
})
# Should redirect back to index
self.assertEqual(response.status_code, 302)
self.assertURLEqual(response.url, reverse('wagtailredirects_index'))
self.assertRedirects(response, reverse('wagtailredirects_index'))
# Check that the redirect was created
redirects = models.Redirect.objects.filter(old_path='/test')
@ -163,8 +162,7 @@ class TestRedirectsEditView(TestCase, WagtailTestUtils):
})
# Should redirect back to index
self.assertEqual(response.status_code, 302)
self.assertURLEqual(response.url, reverse('wagtailredirects_index'))
self.assertRedirects(response, reverse('wagtailredirects_index'))
# Check that the redirect was edited
redirects = models.Redirect.objects.filter(old_path='/test')
@ -210,8 +208,7 @@ class TestRedirectsDeleteView(TestCase, WagtailTestUtils):
})
# Should redirect back to index
self.assertEqual(response.status_code, 302)
self.assertURLEqual(response.url, reverse('wagtailredirects_index'))
self.assertRedirects(response, reverse('wagtailredirects_index'))
# Check that the redirect was deleted
redirects = models.Redirect.objects.filter(old_path='/test')

View file

@ -1,4 +1,6 @@
from django.test import TestCase
from django.core.urlresolvers import reverse
from wagtail.tests.utils import unittest, WagtailTestUtils
from wagtail.wagtailsearch import models
@ -49,39 +51,104 @@ class TestEditorsPicksIndexView(TestCase, WagtailTestUtils):
def setUp(self):
self.login()
def get(self, params={}):
return self.client.get('/admin/search/editorspicks/', params)
def test_simple(self):
response = self.get()
response = self.client.get(reverse('wagtailsearch_editorspicks_index'))
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailsearch/editorspicks/index.html')
def test_search(self):
response = self.get({'q': "Hello"})
response = self.client.get(reverse('wagtailsearch_editorspicks_index'), {'q': "Hello"})
self.assertEqual(response.status_code, 200)
self.assertEqual(response.context['query_string'], "Hello")
def make_editors_picks(self):
for i in range(50):
models.EditorsPick.objects.create(
query=models.Query.get("query " + str(i)),
page_id=1,
sort_order=0,
description="First editors pick",
)
def test_pagination(self):
pages = ['0', '1', '-1', '9999', 'Not a page']
for page in pages:
response = self.get({'p': page})
self.assertEqual(response.status_code, 200)
self.make_editors_picks()
response = self.client.get(reverse('wagtailsearch_editorspicks_index'), {'p': 2})
# Check response
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailsearch/editorspicks/index.html')
# Check that we got the correct page
self.assertEqual(response.context['queries'].number, 2)
def test_pagination_invalid(self):
self.make_editors_picks()
response = self.client.get(reverse('wagtailsearch_editorspicks_index'), {'p': 'Hello World!'})
# Check response
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailsearch/editorspicks/index.html')
# Check that we got page one
self.assertEqual(response.context['queries'].number, 1)
def test_pagination_out_of_range(self):
self.make_editors_picks()
response = self.client.get(reverse('wagtailsearch_editorspicks_index'), {'p': 99999})
# Check response
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailsearch/editorspicks/index.html')
# Check that we got the last page
self.assertEqual(response.context['queries'].number, response.context['queries'].paginator.num_pages)
class TestEditorsPicksAddView(TestCase, WagtailTestUtils):
def setUp(self):
self.login()
def get(self, params={}):
return self.client.get('/admin/search/editorspicks/add/', params)
def test_simple(self):
response = self.get()
response = self.client.get(reverse('wagtailsearch_editorspicks_add'))
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailsearch/editorspicks/add.html')
# TODO: Test posting
def test_post(self):
# Submit
post_data = {
'query_string': "test",
'editors_picks-TOTAL_FORMS': 1,
'editors_picks-INITIAL_FORMS': 0,
'editors_picks-MAX_NUM_FORMS': 1000,
'editors_picks-0-DELETE': '',
'editors_picks-0-ORDER': 0,
'editors_picks-0-page': 1,
'editors_picks-0-description': "Hello",
}
response = self.client.post(reverse('wagtailsearch_editorspicks_add'), post_data)
# User should be redirected back to the index
self.assertRedirects(response, reverse('wagtailsearch_editorspicks_index'))
# Check that the editors pick was created
self.assertTrue(models.Query.get('test').editors_picks.filter(page_id=1).exists())
def test_post_without_recommendations(self):
# Submit
post_data = {
'query_string': "test",
'editors_picks-TOTAL_FORMS': 0,
'editors_picks-INITIAL_FORMS': 0,
'editors_picks-MAX_NUM_FORMS': 1000,
}
response = self.client.post(reverse('wagtailsearch_editorspicks_add'), post_data)
# User should be given an error
self.assertEqual(response.status_code, 200)
self.assertFormsetError(response, 'editors_pick_formset', None, None, "Please specify at least one recommendation for this search term.")
class TestEditorsPicksEditView(TestCase, WagtailTestUtils):
@ -90,17 +157,123 @@ class TestEditorsPicksEditView(TestCase, WagtailTestUtils):
# Create an editors pick to edit
self.query = models.Query.get("Hello")
self.query.editors_picks.create(page_id=1, description="Root page")
def get(self, params={}):
return self.client.get('/admin/search/editorspicks/' + str(self.query.id) + '/', params)
self.editors_pick = self.query.editors_picks.create(page_id=1, description="Root page")
self.editors_pick_2 = self.query.editors_picks.create(page_id=2, description="Homepage")
def test_simple(self):
response = self.get()
response = self.client.get(reverse('wagtailsearch_editorspicks_edit', args=(self.query.id, )))
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailsearch/editorspicks/edit.html')
# TODO: Test posting
def test_post(self):
# Submit
post_data = {
'query_string': "Hello",
'editors_picks-TOTAL_FORMS': 2,
'editors_picks-INITIAL_FORMS': 2,
'editors_picks-MAX_NUM_FORMS': 1000,
'editors_picks-0-id': self.editors_pick.id,
'editors_picks-0-DELETE': '',
'editors_picks-0-ORDER': 0,
'editors_picks-0-page': 1,
'editors_picks-0-description': "Description has changed", # Change
'editors_picks-1-id': self.editors_pick_2.id,
'editors_picks-1-DELETE': '',
'editors_picks-1-ORDER': 1,
'editors_picks-1-page': 2,
'editors_picks-1-description': "Homepage",
}
response = self.client.post(reverse('wagtailsearch_editorspicks_edit', args=(self.query.id, )), post_data)
# User should be redirected back to the index
self.assertRedirects(response, reverse('wagtailsearch_editorspicks_index'))
# Check that the editors pick description was edited
self.assertEqual(models.EditorsPick.objects.get(id=self.editors_pick.id).description, "Description has changed")
def test_post_reorder(self):
# Check order before reordering
self.assertEqual(models.Query.get("Hello").editors_picks.all()[0], self.editors_pick)
self.assertEqual(models.Query.get("Hello").editors_picks.all()[1], self.editors_pick_2)
# Submit
post_data = {
'query_string': "Hello",
'editors_picks-TOTAL_FORMS': 2,
'editors_picks-INITIAL_FORMS': 2,
'editors_picks-MAX_NUM_FORMS': 1000,
'editors_picks-0-id': self.editors_pick.id,
'editors_picks-0-DELETE': '',
'editors_picks-0-ORDER': 1, # Change
'editors_picks-0-page': 1,
'editors_picks-0-description': "Root page",
'editors_picks-1-id': self.editors_pick_2.id,
'editors_picks-1-DELETE': '',
'editors_picks-1-ORDER': 0, # Change
'editors_picks-1-page': 2,
'editors_picks-1-description': "Homepage",
}
response = self.client.post(reverse('wagtailsearch_editorspicks_edit', args=(self.query.id, )), post_data)
# User should be redirected back to the index
self.assertRedirects(response, reverse('wagtailsearch_editorspicks_index'))
# Check that the recommendations were reordered
self.assertEqual(models.Query.get("Hello").editors_picks.all()[0], self.editors_pick_2)
self.assertEqual(models.Query.get("Hello").editors_picks.all()[1], self.editors_pick)
def test_post_delete_recommendation(self):
# Submit
post_data = {
'query_string': "Hello",
'editors_picks-TOTAL_FORMS': 2,
'editors_picks-INITIAL_FORMS': 2,
'editors_picks-MAX_NUM_FORMS': 1000,
'editors_picks-0-id': self.editors_pick.id,
'editors_picks-0-DELETE': '',
'editors_picks-0-ORDER': 0,
'editors_picks-0-page': 1,
'editors_picks-0-description': "Root page",
'editors_picks-1-id': self.editors_pick_2.id,
'editors_picks-1-DELETE': 1,
'editors_picks-1-ORDER': 1,
'editors_picks-1-page': 2,
'editors_picks-1-description': "Homepage",
}
response = self.client.post(reverse('wagtailsearch_editorspicks_edit', args=(self.query.id, )), post_data)
# User should be redirected back to the index
self.assertRedirects(response, reverse('wagtailsearch_editorspicks_index'))
# Check that the recommendation was deleted
self.assertFalse(models.EditorsPick.objects.filter(id=self.editors_pick_2.id).exists())
# The other recommendation should still exist
self.assertTrue(models.EditorsPick.objects.filter(id=self.editors_pick.id).exists())
def test_post_without_recommendations(self):
# Submit
post_data = {
'query_string': "Hello",
'editors_picks-TOTAL_FORMS': 2,
'editors_picks-INITIAL_FORMS': 2,
'editors_picks-MAX_NUM_FORMS': 1000,
'editors_picks-0-id': self.editors_pick.id,
'editors_picks-0-DELETE': 1,
'editors_picks-0-ORDER': 0,
'editors_picks-0-page': 1,
'editors_picks-0-description': "Description has changed", # Change
'editors_picks-1-id': self.editors_pick_2.id,
'editors_picks-1-DELETE': 1,
'editors_picks-1-ORDER': 1,
'editors_picks-1-page': 2,
'editors_picks-1-description': "Homepage",
}
response = self.client.post(reverse('wagtailsearch_editorspicks_edit', args=(self.query.id, )), post_data)
# User should be given an error
self.assertEqual(response.status_code, 200)
self.assertFormsetError(response, 'editors_pick_formset', None, None, "Please specify at least one recommendation for this search term.")
class TestEditorsPicksDeleteView(TestCase, WagtailTestUtils):
@ -109,14 +282,26 @@ class TestEditorsPicksDeleteView(TestCase, WagtailTestUtils):
# Create an editors pick to delete
self.query = models.Query.get("Hello")
self.query.editors_picks.create(page_id=1, description="Root page")
def get(self, params={}):
return self.client.get('/admin/search/editorspicks/' + str(self.query.id) + '/delete/', params)
self.editors_pick = self.query.editors_picks.create(page_id=1, description="Root page")
self.editors_pick_2 = self.query.editors_picks.create(page_id=2, description="Homepage")
def test_simple(self):
response = self.get()
response = self.client.get(reverse('wagtailsearch_editorspicks_delete', args=(self.query.id, )))
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailsearch/editorspicks/confirm_delete.html')
# TODO: Test posting
def test_post(self):
# Submit
post_data = {
'foo': 'bar',
}
response = self.client.post(reverse('wagtailsearch_editorspicks_delete', args=(self.query.id, )), post_data)
# User should be redirected back to the index
self.assertRedirects(response, reverse('wagtailsearch_editorspicks_index'))
# Check that both recommendations were deleted
self.assertFalse(models.EditorsPick.objects.filter(id=self.editors_pick_2.id).exists())
# The other recommendation should still exist
self.assertFalse(models.EditorsPick.objects.filter(id=self.editors_pick.id).exists())

View file

@ -102,45 +102,6 @@ class TestQueryPopularity(TestCase):
self.assertEqual(popular_queries[1], models.Query.get("popular query"))
self.assertEqual(popular_queries[2], models.Query.get("little popular query"))
@unittest.expectedFailure # Time based popularity isn't implemented yet
def test_query_popularity_over_time(self):
today = timezone.now().date()
two_days_ago = today - datetime.timedelta(days=2)
a_week_ago = today - datetime.timedelta(days=7)
a_month_ago = today - datetime.timedelta(days=30)
# Add 10 hits to a query that was very popular query a month ago
for i in range(10):
models.Query.get("old popular query").add_hit(date=a_month_ago)
# Add 5 hits to a query that is was popular 2 days ago
for i in range(5):
models.Query.get("new popular query").add_hit(date=two_days_ago)
# Get most popular queries
popular_queries = models.Query.get_most_popular()
# Old popular query should be most popular
self.assertEqual(popular_queries.count(), 2)
self.assertEqual(popular_queries[0], models.Query.get("old popular query"))
self.assertEqual(popular_queries[1], models.Query.get("new popular query"))
# Get most popular queries for past week
past_week_popular_queries = models.Query.get_most_popular(date_since=a_week_ago)
# Only new popular query should be in this list
self.assertEqual(past_week_popular_queries.count(), 1)
self.assertEqual(past_week_popular_queries[0], models.Query.get("new popular query"))
# Old popular query gets a couple more hits!
for i in range(2):
models.Query.get("old popular query").add_hit()
# Old popular query should now be in the most popular queries
self.assertEqual(past_week_popular_queries.count(), 2)
self.assertEqual(past_week_popular_queries[0], models.Query.get("new popular query"))
self.assertEqual(past_week_popular_queries[1], models.Query.get("old popular query"))
class TestGarbageCollectCommand(TestCase):
def test_garbage_collect_command(self):

View file

@ -70,8 +70,7 @@ class TestSnippetCreateView(TestCase, WagtailTestUtils):
def test_create(self):
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')))
self.assertRedirects(response, reverse('wagtailsnippets_list', args=('tests', 'advert')))
snippets = Advert.objects.filter(text='test_advert')
self.assertEqual(snippets.count(), 1)
@ -120,8 +119,7 @@ class TestSnippetEditView(TestCase, WagtailTestUtils):
def test_edit(self):
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')))
self.assertRedirects(response, reverse('wagtailsnippets_list', args=('tests', 'advert')))
snippets = Advert.objects.filter(text='edited_test_advert')
self.assertEqual(snippets.count(), 1)
@ -146,8 +144,7 @@ class TestSnippetDelete(TestCase, WagtailTestUtils):
response = self.client.post(reverse('wagtailsnippets_delete', args=('tests', 'advert', self.test_snippet.id, )), post_data)
# Should be redirected to explorer page
self.assertEqual(response.status_code, 302)
self.assertURLEqual(response.url, reverse('wagtailsnippets_list', args=('tests', 'advert')))
self.assertRedirects(response, reverse('wagtailsnippets_list', args=('tests', 'advert')))
# Check that the page is gone
self.assertEqual(Advert.objects.filter(text='test_advert').count(), 0)

View file

@ -54,8 +54,7 @@ class TestUserCreateView(TestCase, WagtailTestUtils):
})
# Should redirect back to index
self.assertEqual(response.status_code, 302)
self.assertURLEqual(response.url, reverse('wagtailusers_index'))
self.assertRedirects(response, reverse('wagtailusers_index'))
# Check that the user was created
users = User.objects.filter(username='testuser')
@ -96,8 +95,7 @@ class TestUserEditView(TestCase, WagtailTestUtils):
})
# Should redirect back to index
self.assertEqual(response.status_code, 302)
self.assertURLEqual(response.url, reverse('wagtailusers_index'))
self.assertRedirects(response, reverse('wagtailusers_index'))
# Check that the user was edited
user = User.objects.get(id=self.test_user.id)