mirror of
https://github.com/jazzband/django-admin2.git
synced 2026-03-16 22:20:24 +00:00
561 lines
21 KiB
Python
561 lines
21 KiB
Python
# -*- coding: utf-8 -*-
|
|
from __future__ import unicode_literals
|
|
from datetime import datetime
|
|
|
|
from django.contrib.auth import get_user_model
|
|
from django.contrib.auth.models import Group
|
|
from django.core.urlresolvers import reverse
|
|
from django.test import TestCase, Client
|
|
from django.utils.encoding import force_text
|
|
|
|
from ..models import Post, Comment
|
|
|
|
|
|
class BaseIntegrationTest(TestCase):
|
|
|
|
"""
|
|
Base TestCase for integration tests.
|
|
"""
|
|
|
|
def setUp(self):
|
|
self.client = Client()
|
|
self.user = get_user_model()(username='user', is_staff=True,
|
|
is_superuser=True)
|
|
self.user.set_password("password")
|
|
self.user.save()
|
|
self.client.login(username='user', password='password')
|
|
|
|
|
|
class AdminIndexTest(BaseIntegrationTest):
|
|
|
|
def test_view_ok(self):
|
|
response = self.client.get(reverse("admin2:dashboard"))
|
|
self.assertContains(response, reverse("admin2:blog_post_index"))
|
|
|
|
|
|
class UserListTest(BaseIntegrationTest):
|
|
|
|
def test_search_users_m2m_group(self):
|
|
# This test should cause the distinct search path to exectue
|
|
group = Group.objects.create(name="Test Group")
|
|
self.user.groups.add(group)
|
|
|
|
params = {"q": "group"}
|
|
response = self.client.get(reverse("admin2:auth_user_index"), params)
|
|
self.assertContains(response, 'user')
|
|
|
|
|
|
class CommentListTest(BaseIntegrationTest):
|
|
|
|
def test_search_comments(self):
|
|
# Test search across Foriegn Keys
|
|
post_1 = Post.objects.create(title="post_1_title", body="body")
|
|
post_2 = Post.objects.create(title="post_2_title", body="another body")
|
|
Comment.objects.create(body="comment_post_1_a", post=post_1)
|
|
Comment.objects.create(body="comment_post_1_b", post=post_1)
|
|
Comment.objects.create(body="comment_post_2", post=post_2)
|
|
|
|
params = {"q": "post_1_title"}
|
|
response = self.client.get(
|
|
reverse("admin2:blog_comment_index"), params)
|
|
self.assertContains(response, "comment_post_1_a")
|
|
self.assertContains(response, "comment_post_1_b")
|
|
self.assertNotContains(response, "comment_post_2")
|
|
|
|
def test_list_selected_hides(self):
|
|
post_1 = Post.objects.create(title="post_1_title", body="body")
|
|
Comment.objects.create(body="comment_post1_body", post=post_1)
|
|
response = self.client.get(reverse("admin2:blog_comment_index"))
|
|
self.assertNotContains(response, "of 1 selected")
|
|
|
|
|
|
class PostListTest(BaseIntegrationTest):
|
|
|
|
def _create_posts(self):
|
|
Post.objects.bulk_create([
|
|
Post(
|
|
title="post_1_title",
|
|
body="body",
|
|
published_date=datetime(
|
|
month=7,
|
|
day=22,
|
|
year=2013
|
|
)
|
|
),
|
|
Post(
|
|
title="post_2_title",
|
|
body="body",
|
|
published_date=datetime(
|
|
month=5,
|
|
day=20,
|
|
year=2012,
|
|
)
|
|
),
|
|
Post(
|
|
title="post_3_title",
|
|
body="body",
|
|
published_date=datetime(
|
|
month=5,
|
|
day=30,
|
|
year=2012,
|
|
),
|
|
),
|
|
Post(
|
|
title="post_4_title",
|
|
body="body",
|
|
published_date=datetime(
|
|
month=6,
|
|
day=20,
|
|
year=2012,
|
|
)
|
|
),
|
|
Post(
|
|
title="post_5_title",
|
|
body="body",
|
|
published_date=datetime(
|
|
month=6,
|
|
day=20,
|
|
year=2012,
|
|
)
|
|
),
|
|
])
|
|
|
|
def test_view_ok(self):
|
|
post = Post.objects.create(title="A Post Title", body="body")
|
|
response = self.client.get(reverse("admin2:blog_post_index"))
|
|
self.assertContains(response, post.title)
|
|
|
|
def test_list_filter_presence(self):
|
|
Post.objects.create(title="post_1_title", body="body")
|
|
Post.objects.create(title="post_2_title", body="another body")
|
|
response = self.client.get(reverse("admin2:blog_post_index"))
|
|
self.assertContains(response, 'id="list_filter_container"')
|
|
|
|
def test_list_selected_shows(self):
|
|
Post.objects.create(title="post_1_title", body="body")
|
|
response = self.client.get(reverse("admin2:blog_post_index"))
|
|
self.assertContains(response, 'class="selected-count"')
|
|
|
|
def test_actions_displayed(self):
|
|
response = self.client.get(reverse("admin2:blog_post_index"))
|
|
self.assertInHTML(
|
|
'<a tabindex="-1" href="#" data-name="action" data-value="DeleteSelectedAction">Delete selected items</a>', force_text(response.content))
|
|
|
|
def test_actions_displayed_twice(self):
|
|
# If actions_on_top and actions_on_bottom are both set
|
|
response = self.client.get(reverse("admin2:blog_comment_index"))
|
|
self.assertContains(response, '<div class="navbar actions-top">')
|
|
self.assertContains(response, '<div class="navbar actions-bottom">')
|
|
|
|
def test_delete_selected_post(self):
|
|
post = Post.objects.create(title="A Post Title", body="body")
|
|
params = {'action': 'DeleteSelectedAction',
|
|
'selected_model_pk': str(post.pk)}
|
|
response = self.client.post(reverse("admin2:blog_post_index"), params)
|
|
# caution : uses pluralization
|
|
self.assertInHTML(
|
|
'<p>Are you sure you want to delete the selected post? The following item will be deleted:</p>', force_text(response.content))
|
|
|
|
def test_delete_selected_post_confirmation(self):
|
|
post = Post.objects.create(title="A Post Title", body="body")
|
|
params = {'action': 'DeleteSelectedAction',
|
|
'selected_model_pk': str(post.pk), 'confirmed': 'yes'}
|
|
response = self.client.post(reverse("admin2:blog_post_index"), params)
|
|
self.assertRedirects(response, reverse("admin2:blog_post_index"))
|
|
|
|
def test_delete_selected_post_none_selected(self):
|
|
Post.objects.create(title="A Post Title", body="body")
|
|
params = {'action': 'DeleteSelectedAction'}
|
|
response = self.client.post(
|
|
reverse("admin2:blog_post_index"), params, follow=True)
|
|
self.assertContains(
|
|
response, "Items must be selected in order to perform actions on them. No items have been changed.")
|
|
|
|
def test_search_posts(self):
|
|
Post.objects.create(title="A Post Title", body="body")
|
|
Post.objects.create(title="Another Post Title", body="body")
|
|
Post.objects.create(
|
|
title="Post With Keyword In Body", body="another post body")
|
|
params = {"q": "another"}
|
|
response = self.client.get(reverse("admin2:blog_post_index"), params)
|
|
self.assertContains(response, "Another Post Title")
|
|
self.assertContains(response, "Post With Keyword In Body")
|
|
self.assertNotContains(response, "A Post Title")
|
|
|
|
def test_renderer_title(self):
|
|
Post.objects.create(
|
|
title='a lowercase title', body='body', published=False)
|
|
response = self.client.get(reverse('admin2:blog_post_index'))
|
|
self.assertContains(response, 'A Lowercase Title')
|
|
|
|
def test_renderer_body(self):
|
|
Post.objects.create(
|
|
title='title', body='a lowercase body', published=False)
|
|
response = self.client.get(reverse('admin2:blog_post_index'))
|
|
self.assertContains(response, 'a lowercase body')
|
|
|
|
def test_renderer_unpublished(self):
|
|
Post.objects.create(title='title', body='body', published=False)
|
|
response = self.client.get(reverse('admin2:blog_post_index'))
|
|
self.assertContains(response, 'icon-minus-sign')
|
|
|
|
def test_renderer_published(self):
|
|
Post.objects.create(title='title', body='body', published=True)
|
|
response = self.client.get(reverse('admin2:blog_post_index'))
|
|
self.assertContains(response, 'icon-ok-sign')
|
|
|
|
def test_drilldowns(self):
|
|
self._create_posts()
|
|
|
|
response = self.client.get(reverse('admin2:blog_post_index'))
|
|
self.assertContains(response, '<a href="?year=2012">2012</a>')
|
|
self.assertContains(response, "<tr>", 5)
|
|
|
|
response = self.client.get(
|
|
"%s?%s" % (
|
|
reverse('admin2:blog_post_index'),
|
|
"year=2012",
|
|
)
|
|
)
|
|
|
|
self.assertContains(
|
|
response,
|
|
'<a href="?year=2012&month=05">May 2012</a>',
|
|
)
|
|
self.assertContains(
|
|
response,
|
|
'All dates',
|
|
)
|
|
self.assertContains(response, "<tr>", 4)
|
|
|
|
response = self.client.get(
|
|
"%s?%s" % (
|
|
reverse('admin2:blog_post_index'),
|
|
"year=2012&month=5",
|
|
)
|
|
)
|
|
|
|
self.assertContains(response, "<tr>", 2)
|
|
self.assertContains(
|
|
response,
|
|
'<a href="?year=2012&month=05&day=20">May 20</a>',
|
|
)
|
|
self.assertContains(response, '<a href="?year=2012">')
|
|
|
|
response = self.client.get(
|
|
"%s?%s" % (
|
|
reverse('admin2:blog_post_index'),
|
|
"year=2012&month=05&day=20",
|
|
)
|
|
)
|
|
|
|
self.assertContains(response, "<tr>", 1)
|
|
self.assertContains(
|
|
response,
|
|
'<a href="?year=2012&month=05&day=20">May 20</a>',
|
|
)
|
|
self.assertContains(
|
|
response,
|
|
'<li class="active">'
|
|
)
|
|
self.assertContains(
|
|
response,
|
|
'May 2012'
|
|
)
|
|
|
|
def test_ordering(self):
|
|
self._create_posts()
|
|
|
|
response = self.client.get(reverse("admin2:blog_post_index"))
|
|
|
|
model_admin = response.context["view"].model_admin
|
|
response_queryset = response.context["object_list"]
|
|
manual_queryset = Post.objects.order_by("-published_date", "title")
|
|
|
|
zipped_queryset = zip(
|
|
list(response_queryset),
|
|
list(manual_queryset),
|
|
)
|
|
|
|
self.assertTrue(all([
|
|
model1.pk == model2.pk
|
|
for model1, model2 in zipped_queryset
|
|
]))
|
|
|
|
self.assertEqual(
|
|
model_admin.get_ordering(response.request),
|
|
model_admin.ordering,
|
|
)
|
|
|
|
def test_all_unselected_action(self):
|
|
self._create_posts()
|
|
|
|
response = self.client.get(reverse("admin2:blog_post_index"))
|
|
|
|
self.assertTrue(all([
|
|
not post.published
|
|
for post in response.context["object_list"]
|
|
]))
|
|
|
|
response = self.client.post(
|
|
reverse("admin2:blog_post_index"),
|
|
{
|
|
'action': 'PublishAllItemsAction',
|
|
},
|
|
follow=True
|
|
)
|
|
|
|
self.assertTrue(all([
|
|
post.published
|
|
for post in response.context["object_list"]
|
|
]))
|
|
|
|
# Test function-based view
|
|
response = self.client.post(
|
|
reverse("admin2:blog_post_index"),
|
|
{
|
|
'action': 'PublishAllItemsAction',
|
|
},
|
|
follow=True,
|
|
)
|
|
|
|
self.assertTrue(all([
|
|
post.published
|
|
for post in response.context["object_list"]
|
|
]))
|
|
|
|
|
|
class PostListTestCustomAction(BaseIntegrationTest):
|
|
|
|
def test_publish_action_displayed_in_list(self):
|
|
response = self.client.get(reverse("admin2:blog_post_index"))
|
|
self.assertInHTML(
|
|
'<a tabindex="-1" href="#" data-name="action" data-value="CustomPublishAction">Publish selected items</a>', force_text(response.content))
|
|
|
|
def test_publish_selected_items(self):
|
|
post = Post.objects.create(title="A Post Title",
|
|
body="body",
|
|
published=False)
|
|
self.assertEqual(Post.objects.filter(published=True).count(), 0)
|
|
|
|
params = {'action': 'CustomPublishAction',
|
|
'selected_model_pk': str(post.pk),
|
|
'confirmed': 'yes'}
|
|
response = self.client.post(reverse("admin2:blog_post_index"), params)
|
|
self.assertRedirects(response, reverse("admin2:blog_post_index"))
|
|
|
|
self.assertEqual(Post.objects.filter(published=True).count(), 1)
|
|
|
|
def test_unpublish_action_displayed_in_list(self):
|
|
response = self.client.get(reverse("admin2:blog_post_index"))
|
|
self.assertInHTML(
|
|
'<a tabindex="-1" href="#" data-name="action" data-value="unpublish_items">Unpublish selected items</a>', force_text(response.content))
|
|
|
|
def test_unpublish_selected_items(self):
|
|
post = Post.objects.create(title="A Post Title",
|
|
body="body",
|
|
published=True)
|
|
self.assertEqual(Post.objects.filter(published=True).count(), 1)
|
|
|
|
params = {'action': 'unpublish_items',
|
|
'selected_model_pk': str(post.pk)}
|
|
response = self.client.post(reverse("admin2:blog_post_index"), params)
|
|
self.assertRedirects(response, reverse("admin2:blog_post_index"))
|
|
|
|
self.assertEqual(Post.objects.filter(published=True).count(), 0)
|
|
|
|
|
|
class PostDetailViewTest(BaseIntegrationTest):
|
|
|
|
def test_view_ok(self):
|
|
post = Post.objects.create(title="A Post Title", body="body")
|
|
response = self.client.get(reverse("admin2:blog_post_detail",
|
|
args=(post.pk, )))
|
|
self.assertContains(response, post.title)
|
|
|
|
|
|
class PostCreateViewTest(BaseIntegrationTest):
|
|
|
|
def test_view_ok(self):
|
|
response = self.client.get(reverse("admin2:blog_post_create"))
|
|
self.assertNotIn(
|
|
'''enctype="multipart/form-data"''', force_text(response.content))
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
def test_create_post(self):
|
|
# Generated by inspecting the request with the pdb debugger
|
|
post_data = {
|
|
"comments-TOTAL_FORMS": u'2',
|
|
"comments-INITIAL_FORMS": u'0',
|
|
"comments-MAX_NUM_FORMS": u'',
|
|
"comments-0-body": u'Comment Body',
|
|
'comments-0-post': '',
|
|
'comments-0-id': '',
|
|
"title": "A Post Title",
|
|
"body": "a_post_body",
|
|
}
|
|
|
|
response = self.client.post(reverse("admin2:blog_post_create"),
|
|
post_data,
|
|
follow=True)
|
|
self.assertTrue(Post.objects.filter(title="A Post Title").exists())
|
|
Comment.objects.get(body="Comment Body")
|
|
self.assertRedirects(response, reverse("admin2:blog_post_index"))
|
|
|
|
def test_save_and_add_another_redirects_to_create(self):
|
|
"""
|
|
Tests that choosing 'Save and add another' from the model create
|
|
page redirects the user to the model create page.
|
|
"""
|
|
post_data = {
|
|
"comments-TOTAL_FORMS": u'2',
|
|
"comments-INITIAL_FORMS": u'0',
|
|
"comments-MAX_NUM_FORMS": u'',
|
|
"comments-0-body": u'Comment Body',
|
|
'comments-0-post': '',
|
|
'comments-0-id': '',
|
|
"title": "A Post Title",
|
|
"body": "a_post_body",
|
|
"_addanother": ""
|
|
}
|
|
self.client.login(username='admin', password='password')
|
|
response = self.client.post(reverse("admin2:blog_post_create"),
|
|
post_data)
|
|
Post.objects.get(title='A Post Title')
|
|
self.assertRedirects(response, reverse("admin2:blog_post_create"))
|
|
|
|
def test_save_and_continue_editing_redirects_to_update(self):
|
|
"""
|
|
Tests that choosing "Save and continue editing" redirects
|
|
the user to the model update form.
|
|
"""
|
|
post_data = {
|
|
"comments-TOTAL_FORMS": u'2',
|
|
"comments-INITIAL_FORMS": u'0',
|
|
"comments-MAX_NUM_FORMS": u'',
|
|
"title": "Unique",
|
|
"body": "a_post_body",
|
|
"_continue": ""
|
|
}
|
|
response = self.client.post(reverse("admin2:blog_post_create"),
|
|
post_data)
|
|
post = Post.objects.get(title="Unique")
|
|
self.assertRedirects(response, reverse("admin2:blog_post_update",
|
|
args=(post.pk, )))
|
|
|
|
|
|
class PostDeleteViewTest(BaseIntegrationTest):
|
|
|
|
def test_view_ok(self):
|
|
post = Post.objects.create(title="A Post Title", body="body")
|
|
response = self.client.get(reverse("admin2:blog_post_delete",
|
|
args=(post.pk, )))
|
|
self.assertContains(response, post.title)
|
|
|
|
def test_delete_post(self):
|
|
post = Post.objects.create(title="A Post Title", body="body")
|
|
response = self.client.post(reverse("admin2:blog_post_delete",
|
|
args=(post.pk, )))
|
|
self.assertRedirects(response, reverse("admin2:blog_post_index"))
|
|
self.assertFalse(Post.objects.filter(pk=post.pk).exists())
|
|
|
|
|
|
class PostDeleteActionTest(BaseIntegrationTest):
|
|
|
|
"""
|
|
Tests the behaviour of the 'Delete selected items' action.
|
|
"""
|
|
|
|
def test_confirmation_page(self):
|
|
p1 = Post.objects.create(title="A Post Title", body="body")
|
|
p2 = Post.objects.create(title="A Post Title", body="body")
|
|
post_data = {
|
|
'action': 'DeleteSelectedAction',
|
|
'selected_model_pk': [p1.pk, p2.pk]
|
|
}
|
|
response = self.client.post(reverse("admin2:blog_post_index"),
|
|
post_data)
|
|
self.assertContains(response, p1.title)
|
|
self.assertContains(response, p2.title)
|
|
|
|
def test_results_page(self):
|
|
p1 = Post.objects.create(title="A Post Title", body="body")
|
|
p2 = Post.objects.create(title="A Post Title", body="body")
|
|
post_data = {
|
|
'action': 'DeleteSelectedAction',
|
|
'selected_model_pk': [p1.pk, p2.pk],
|
|
'confirmed': 'yes'
|
|
}
|
|
response = self.client.post(reverse("admin2:blog_post_index"),
|
|
post_data, follow=True)
|
|
self.assertContains(response, "Successfully deleted 2 post")
|
|
|
|
|
|
class TestAuthViews(TestCase):
|
|
|
|
def setUp(self):
|
|
self.client = Client()
|
|
self.user = get_user_model()(username='user', is_staff=True,
|
|
is_superuser=True)
|
|
self.user.set_password("password")
|
|
self.user.save()
|
|
|
|
def test_login_required_redirect_to_index(self):
|
|
index_path = reverse('admin2:dashboard') + '?next=/admin2/blog/post/'
|
|
target_path = reverse('admin2:blog_post_index')
|
|
self.assertRedirects(self.client.get(target_path), index_path)
|
|
|
|
def test_login_required_logined_successful(self):
|
|
index_path = reverse('admin2:dashboard')
|
|
self.client.login(username=self.user.username,
|
|
password='password')
|
|
self.assertContains(self.client.get(index_path),
|
|
reverse('admin2:blog_post_index'))
|
|
|
|
def test_change_password_for_myself(self):
|
|
self.client.login(username=self.user.username,
|
|
password='password')
|
|
request = self.client.post(reverse('admin2:password_change',
|
|
kwargs={'pk': self.user.pk}),
|
|
{'old_password': 'password',
|
|
'new_password1': 'user',
|
|
'new_password2': 'user'})
|
|
self.assertRedirects(request, reverse('admin2:password_change_done'))
|
|
self.client.logout()
|
|
|
|
self.assertFalse(self.client.login(username=self.user.username,
|
|
password='password'))
|
|
self.assertTrue(self.client.login(username=self.user.username,
|
|
password='user'))
|
|
|
|
def test_change_password(self):
|
|
self.client.login(username=self.user.username,
|
|
password='password')
|
|
|
|
new_user = get_user_model()(username='new_user')
|
|
new_user.set_password("new_user")
|
|
new_user.save()
|
|
|
|
request = self.client.post(reverse('admin2:password_change',
|
|
kwargs={'pk': new_user.pk}),
|
|
{'old_password': 'new_user',
|
|
'password1': 'new_user_password',
|
|
'password2': 'new_user_password'})
|
|
self.assertRedirects(request, reverse('admin2:password_change_done'))
|
|
self.client.logout()
|
|
|
|
self.assertFalse(self.client.login(username=new_user.username,
|
|
password='new_user'))
|
|
self.assertTrue(self.client.login(username=new_user.username,
|
|
password='new_user_password'))
|
|
|
|
def test_logout(self):
|
|
self.client.login(username=self.user.username,
|
|
password='password')
|
|
logout_path = reverse('admin2:logout')
|
|
request = self.client.get(logout_path)
|
|
self.assertContains(request, 'Log in again')
|
|
|
|
index_path = reverse('admin2:dashboard') + '?next=/admin2/blog/post/'
|
|
target_path = reverse('admin2:blog_post_index')
|
|
self.assertRedirects(self.client.get(target_path), index_path)
|