mirror of
https://github.com/jazzband/django-admin2.git
synced 2026-03-16 22:20:24 +00:00
Fixes for compatibility with python3.
This commit is contained in:
parent
dda1211f43
commit
a6e7755a55
9 changed files with 198 additions and 85 deletions
|
|
@ -18,7 +18,7 @@ class Admin2APISerializer(serializers.HyperlinkedModelSerializer):
|
|||
_default_view_name = 'admin2:%(app_label)s_%(model_name)s_api_detail'
|
||||
|
||||
pk = fields.Field(source='pk')
|
||||
__str__ = fields.Field(source='__unicode__')
|
||||
__unicode__ = fields.Field(source='__str__')
|
||||
|
||||
|
||||
class Admin2APIMixin(Admin2Mixin):
|
||||
|
|
|
|||
|
|
@ -7,13 +7,14 @@ from django.utils.encoding import python_2_unicode_compatible
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class Post(models.Model):
|
||||
title = models.CharField(max_length=255, verbose_name=_('title'))
|
||||
body = models.TextField(verbose_name=_('body'))
|
||||
published = models.BooleanField(default=False, verbose_name=_('published'))
|
||||
published_date = models.DateField(blank=True, null=True)
|
||||
|
||||
def __unicode__(self):
|
||||
def __str__(self):
|
||||
return self.title
|
||||
|
||||
class Meta:
|
||||
|
|
@ -21,11 +22,13 @@ class Post(models.Model):
|
|||
verbose_name_plural = _('posts')
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class Comment(models.Model):
|
||||
post = models.ForeignKey(Post, verbose_name=_('post'), related_name="comments")
|
||||
post = models.ForeignKey(
|
||||
Post, verbose_name=_('post'), related_name="comments")
|
||||
body = models.TextField(verbose_name=_('body'))
|
||||
|
||||
def __unicode__(self):
|
||||
def __str__(self):
|
||||
return self.body
|
||||
|
||||
class Meta:
|
||||
|
|
@ -33,7 +36,7 @@ class Comment(models.Model):
|
|||
verbose_name_plural = _('comments')
|
||||
|
||||
|
||||
#### Models needed for testing NestedObjects
|
||||
# Models needed for testing NestedObjects
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class Count(models.Model):
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
from __future__ import unicode_literals
|
||||
from django.contrib.auth.models import AnonymousUser, User
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.test import TestCase
|
||||
from django.test.client import RequestFactory
|
||||
from django.utils.encoding import force_text
|
||||
import json
|
||||
|
||||
|
||||
|
|
@ -69,7 +71,7 @@ class ListCreateAPIViewTest(APITestCase):
|
|||
response.render()
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertIn('"__str__": "Foo"', response.content)
|
||||
self.assertIn('"__unicode__": "Foo"', force_text(response.content))
|
||||
|
||||
def test_pagination(self):
|
||||
request = self.factory.get(reverse('admin2:blog_post_api_list'))
|
||||
|
|
@ -81,7 +83,7 @@ class ListCreateAPIViewTest(APITestCase):
|
|||
response.render()
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
data = json.loads(response.content)
|
||||
data = json.loads(force_text(response.content))
|
||||
self.assertEqual(data['count'], 0)
|
||||
# next and previous fields exist, but are null because we have no
|
||||
# content
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
from django import forms
|
||||
from django.test import TestCase
|
||||
|
||||
|
|
@ -8,6 +10,7 @@ from ..models import Post
|
|||
|
||||
|
||||
class ModelFormFactoryTest(TestCase):
|
||||
|
||||
def test_modelform_factory(self):
|
||||
form_class = modelform_factory(Post)
|
||||
self.assertTrue(form_class)
|
||||
|
|
@ -16,8 +19,9 @@ class ModelFormFactoryTest(TestCase):
|
|||
|
||||
|
||||
class GetFloppyformWidgetTest(TestCase):
|
||||
|
||||
def assertExpectWidget(self, instance, new_class_,
|
||||
equal_attributes=None, new_attributes=None):
|
||||
equal_attributes=None, new_attributes=None):
|
||||
new_instance = floppify_widget(instance)
|
||||
self.assertEqual(new_instance.__class__, new_class_)
|
||||
if equal_attributes:
|
||||
|
|
@ -33,8 +37,8 @@ class GetFloppyformWidgetTest(TestCase):
|
|||
old_attr = getattr(instance, attribute)
|
||||
new_attr = getattr(new_instance, attribute)
|
||||
self.assertEqual(old_attr, new_attr,
|
||||
'Original widget\'s attribute was not copied: %r != %r' %
|
||||
(old_attr, new_attr))
|
||||
'Original widget\'s attribute was not copied: %r != %r' %
|
||||
(old_attr, new_attr))
|
||||
if new_attributes:
|
||||
for attribute, value in new_attributes.items():
|
||||
self.assertTrue(
|
||||
|
|
@ -43,8 +47,8 @@ class GetFloppyformWidgetTest(TestCase):
|
|||
'generated widget %r' % (attribute, new_instance))
|
||||
new_attr = getattr(new_instance, attribute)
|
||||
self.assertEqual(new_attr, value,
|
||||
'Generated widget\'s attribute is not as expected: '
|
||||
'%r != %r' % (new_attr, value))
|
||||
'Generated widget\'s attribute is not as expected: '
|
||||
'%r != %r' % (new_attr, value))
|
||||
|
||||
def test_created_widget_doesnt_leak_attributes_into_original_widget(self):
|
||||
widget = forms.TextInput()
|
||||
|
|
@ -146,7 +150,7 @@ class GetFloppyformWidgetTest(TestCase):
|
|||
widget,
|
||||
floppyforms.widgets.ClearableFileInput,
|
||||
['initial_text', 'input_text', 'clear_checkbox_label',
|
||||
'template_with_initial', 'template_with_clear'])
|
||||
'template_with_initial', 'template_with_clear'])
|
||||
|
||||
def test_textarea_widget(self):
|
||||
self.assertExpectWidget(
|
||||
|
|
@ -222,7 +226,7 @@ class GetFloppyformWidgetTest(TestCase):
|
|||
forms.widgets.NullBooleanSelect(),
|
||||
floppyforms.widgets.NullBooleanSelect,
|
||||
('choices', 'allow_multiple_selected',))
|
||||
|
||||
|
||||
widget = forms.widgets.NullBooleanSelect()
|
||||
widget.choices = list(widget.choices)
|
||||
|
||||
|
|
@ -349,6 +353,7 @@ class GetFloppyformWidgetTest(TestCase):
|
|||
|
||||
|
||||
class ModelFormTest(TestCase):
|
||||
|
||||
def test_custom_base_form(self):
|
||||
class MyForm(forms.ModelForm):
|
||||
pass
|
||||
|
|
@ -410,6 +415,7 @@ class ModelFormTest(TestCase):
|
|||
|
||||
|
||||
class FieldWidgetTest(TestCase):
|
||||
|
||||
def test_dont_overwrite_none_default_widget(self):
|
||||
# we don't create the floppyform EmailInput for the email field here
|
||||
# since we have overwritten the default widget. However we replace the
|
||||
|
|
|
|||
|
|
@ -1,18 +1,22 @@
|
|||
# -*- 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,
|
||||
|
|
@ -23,12 +27,14 @@ class BaseIntegrationTest(TestCase):
|
|||
|
||||
|
||||
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")
|
||||
|
|
@ -40,6 +46,7 @@ class UserListTest(BaseIntegrationTest):
|
|||
|
||||
|
||||
class CommentListTest(BaseIntegrationTest):
|
||||
|
||||
def test_search_comments(self):
|
||||
# Test search across Foriegn Keys
|
||||
post_1 = Post.objects.create(title="post_1_title", body="body")
|
||||
|
|
@ -49,7 +56,8 @@ class CommentListTest(BaseIntegrationTest):
|
|||
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)
|
||||
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")
|
||||
|
|
@ -62,6 +70,7 @@ class CommentListTest(BaseIntegrationTest):
|
|||
|
||||
|
||||
class PostListTest(BaseIntegrationTest):
|
||||
|
||||
def _create_posts(self):
|
||||
Post.objects.bulk_create([
|
||||
Post(
|
||||
|
|
@ -129,7 +138,8 @@ class PostListTest(BaseIntegrationTest):
|
|||
|
||||
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>', response.content)
|
||||
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
|
||||
|
|
@ -139,27 +149,33 @@ class PostListTest(BaseIntegrationTest):
|
|||
|
||||
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)}
|
||||
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>', response.content)
|
||||
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'}
|
||||
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.")
|
||||
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")
|
||||
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")
|
||||
|
|
@ -167,12 +183,14 @@ class PostListTest(BaseIntegrationTest):
|
|||
self.assertNotContains(response, "A Post Title")
|
||||
|
||||
def test_renderer_title(self):
|
||||
Post.objects.create(title='a lowercase title', body='body', published=False)
|
||||
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)
|
||||
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')
|
||||
|
||||
|
|
@ -311,7 +329,8 @@ 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>', response.content)
|
||||
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",
|
||||
|
|
@ -329,7 +348,8 @@ class PostListTestCustomAction(BaseIntegrationTest):
|
|||
|
||||
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>', response.content)
|
||||
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",
|
||||
|
|
@ -346,6 +366,7 @@ class PostListTestCustomAction(BaseIntegrationTest):
|
|||
|
||||
|
||||
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",
|
||||
|
|
@ -354,9 +375,11 @@ class PostDetailViewTest(BaseIntegrationTest):
|
|||
|
||||
|
||||
class PostCreateViewTest(BaseIntegrationTest):
|
||||
|
||||
def test_view_ok(self):
|
||||
response = self.client.get(reverse("admin2:blog_post_create"))
|
||||
self.assertNotIn('''enctype="multipart/form-data"''', response.content)
|
||||
self.assertNotIn(
|
||||
'''enctype="multipart/form-data"''', force_text(response.content))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_create_post(self):
|
||||
|
|
@ -422,6 +445,7 @@ class PostCreateViewTest(BaseIntegrationTest):
|
|||
|
||||
|
||||
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",
|
||||
|
|
@ -437,9 +461,11 @@ class PostDeleteViewTest(BaseIntegrationTest):
|
|||
|
||||
|
||||
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")
|
||||
|
|
|
|||
|
|
@ -2,14 +2,17 @@
|
|||
from __future__ import division, absolute_import, unicode_literals
|
||||
|
||||
from django.db import models
|
||||
from django.utils.encoding import python_2_unicode_compatible
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class CaptionedFile(models.Model):
|
||||
caption = models.CharField(max_length=200, verbose_name=_('caption'))
|
||||
publication = models.FileField(upload_to='media', verbose_name=_('Uploaded File'))
|
||||
publication = models.FileField(
|
||||
upload_to='media', verbose_name=_('Uploaded File'))
|
||||
|
||||
def __unicode__(self):
|
||||
def __str__(self):
|
||||
return self.caption
|
||||
|
||||
class Meta:
|
||||
|
|
@ -17,11 +20,13 @@ class CaptionedFile(models.Model):
|
|||
verbose_name_plural = _('Captioned Files')
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class UncaptionedFile(models.Model):
|
||||
publication = models.FileField(upload_to='media', verbose_name=_('Uploaded File'))
|
||||
publication = models.FileField(
|
||||
upload_to='media', verbose_name=_('Uploaded File'))
|
||||
|
||||
def __unicode__(self):
|
||||
return unicode(self.publication)
|
||||
def __str__(self):
|
||||
return self.publication
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('Uncaptioned File')
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ from django.contrib.auth import get_user_model
|
|||
from django.core.urlresolvers import reverse
|
||||
from django.test import TestCase, Client
|
||||
from django.utils import timezone
|
||||
from django.utils.encoding import force_text
|
||||
|
||||
from ..models import CaptionedFile
|
||||
|
||||
|
|
@ -12,9 +13,11 @@ fixture_file = path.join(fixture_dir, 'pubtest.txt')
|
|||
|
||||
|
||||
class BaseIntegrationTest(TestCase):
|
||||
|
||||
"""
|
||||
Base TestCase for integration tests.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.client = Client()
|
||||
self.user = get_user_model()(username='user', is_staff=True,
|
||||
|
|
@ -25,55 +28,77 @@ class BaseIntegrationTest(TestCase):
|
|||
|
||||
|
||||
class AdminIndexTest(BaseIntegrationTest):
|
||||
|
||||
def test_view_ok(self):
|
||||
response = self.client.get(reverse("admin2:dashboard"))
|
||||
self.assertContains(response, reverse("admin2:files_captionedfile_index"))
|
||||
self.assertContains(
|
||||
response, reverse("admin2:files_captionedfile_index"))
|
||||
|
||||
|
||||
class CaptionedFileListTest(BaseIntegrationTest):
|
||||
|
||||
def test_view_ok(self):
|
||||
captioned_file = CaptionedFile.objects.create(caption="some file", publication=fixture_file)
|
||||
captioned_file = CaptionedFile.objects.create(
|
||||
caption="some file", publication=fixture_file)
|
||||
response = self.client.get(reverse("admin2:files_captionedfile_index"))
|
||||
self.assertContains(response, captioned_file.caption)
|
||||
|
||||
def test_actions_displayed(self):
|
||||
response = self.client.get(reverse("admin2:files_captionedfile_index"))
|
||||
self.assertInHTML('<a tabindex="-1" href="#" data-name="action" data-value="DeleteSelectedAction">Delete selected items</a>', response.content)
|
||||
self.assertInHTML(
|
||||
'<a tabindex="-1" href="#" data-name="action" data-value="DeleteSelectedAction">Delete selected items</a>', force_text(response.content))
|
||||
|
||||
def test_delete_selected_captioned_file(self):
|
||||
captioned_file = CaptionedFile.objects.create(caption="some file", publication=fixture_file)
|
||||
params = {'action': 'DeleteSelectedAction', 'selected_model_pk': str(captioned_file.pk)}
|
||||
response = self.client.post(reverse("admin2:files_captionedfile_index"), params)
|
||||
self.assertInHTML('<p>Are you sure you want to delete the selected Captioned File? The following item will be deleted:</p>', response.content)
|
||||
captioned_file = CaptionedFile.objects.create(
|
||||
caption="some file", publication=fixture_file)
|
||||
params = {'action': 'DeleteSelectedAction',
|
||||
'selected_model_pk': str(captioned_file.pk)}
|
||||
response = self.client.post(
|
||||
reverse("admin2:files_captionedfile_index"), params)
|
||||
self.assertInHTML(
|
||||
'<p>Are you sure you want to delete the selected Captioned File? The following item will be deleted:</p>', force_text(response.content))
|
||||
|
||||
def test_delete_selected_captioned_file_confirmation(self):
|
||||
captioned_file = CaptionedFile.objects.create(caption="some file", publication=fixture_file)
|
||||
params = {'action': 'DeleteSelectedAction', 'selected_model_pk': str(captioned_file.pk), 'confirmed': 'yes'}
|
||||
response = self.client.post(reverse("admin2:files_captionedfile_index"), params)
|
||||
self.assertRedirects(response, reverse("admin2:files_captionedfile_index"))
|
||||
captioned_file = CaptionedFile.objects.create(
|
||||
caption="some file", publication=fixture_file)
|
||||
params = {'action': 'DeleteSelectedAction', 'selected_model_pk': str(
|
||||
captioned_file.pk), 'confirmed': 'yes'}
|
||||
response = self.client.post(
|
||||
reverse("admin2:files_captionedfile_index"), params)
|
||||
self.assertRedirects(
|
||||
response, reverse("admin2:files_captionedfile_index"))
|
||||
|
||||
def test_delete_selected_captioned_file_none_selected(self):
|
||||
CaptionedFile.objects.create(caption="some file", publication=fixture_file)
|
||||
CaptionedFile.objects.create(
|
||||
caption="some file", publication=fixture_file)
|
||||
params = {'action': 'DeleteSelectedAction'}
|
||||
response = self.client.post(reverse("admin2:files_captionedfile_index"), params, follow=True)
|
||||
self.assertContains(response, "Items must be selected in order to perform actions on them. No items have been changed.")
|
||||
response = self.client.post(
|
||||
reverse("admin2:files_captionedfile_index"), params, follow=True)
|
||||
self.assertContains(
|
||||
response, "Items must be selected in order to perform actions on them. No items have been changed.")
|
||||
|
||||
|
||||
class CaptionedFileDetailViewTest(BaseIntegrationTest):
|
||||
|
||||
def test_view_ok(self):
|
||||
captioned_file = CaptionedFile.objects.create(caption="some file", publication=fixture_file)
|
||||
response = self.client.get(reverse("admin2:files_captionedfile_detail", args=(captioned_file.pk, )))
|
||||
captioned_file = CaptionedFile.objects.create(
|
||||
caption="some file", publication=fixture_file)
|
||||
response = self.client.get(
|
||||
reverse("admin2:files_captionedfile_detail", args=(captioned_file.pk, )))
|
||||
self.assertContains(response, captioned_file.caption)
|
||||
|
||||
|
||||
class CaptionedFileCreateViewTest(BaseIntegrationTest):
|
||||
|
||||
def test_view_ok(self):
|
||||
response = self.client.get(reverse("admin2:files_captionedfile_create"))
|
||||
self.assertIn('enctype="multipart/form-data"', response.content)
|
||||
response = self.client.get(
|
||||
reverse("admin2:files_captionedfile_create"))
|
||||
self.assertIn(
|
||||
'enctype="multipart/form-data"', force_text(response.content))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_create_captioned_file(self):
|
||||
with open(fixture_file, 'r') as fp:
|
||||
with open(fixture_file, 'rb') as fp:
|
||||
params = {
|
||||
"caption": "some file",
|
||||
"publication": fp,
|
||||
|
|
@ -81,15 +106,17 @@ class CaptionedFileCreateViewTest(BaseIntegrationTest):
|
|||
response = self.client.post(reverse("admin2:files_captionedfile_create"),
|
||||
params,
|
||||
follow=True)
|
||||
self.assertTrue(CaptionedFile.objects.filter(caption="some file").exists())
|
||||
self.assertRedirects(response, reverse("admin2:files_captionedfile_index"))
|
||||
self.assertTrue(
|
||||
CaptionedFile.objects.filter(caption="some file").exists())
|
||||
self.assertRedirects(
|
||||
response, reverse("admin2:files_captionedfile_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.
|
||||
"""
|
||||
with open(fixture_file, 'r') as fp:
|
||||
with open(fixture_file, 'rb') as fp:
|
||||
params = {
|
||||
"caption": "some file",
|
||||
"publication": fp,
|
||||
|
|
@ -97,15 +124,17 @@ class CaptionedFileCreateViewTest(BaseIntegrationTest):
|
|||
}
|
||||
response = self.client.post(reverse("admin2:files_captionedfile_create"),
|
||||
params)
|
||||
self.assertTrue(CaptionedFile.objects.filter(caption="some file").exists())
|
||||
self.assertRedirects(response, reverse("admin2:files_captionedfile_create"))
|
||||
self.assertTrue(
|
||||
CaptionedFile.objects.filter(caption="some file").exists())
|
||||
self.assertRedirects(
|
||||
response, reverse("admin2:files_captionedfile_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.
|
||||
"""
|
||||
with open(fixture_file, 'r') as fp:
|
||||
with open(fixture_file, 'rb') as fp:
|
||||
params = {
|
||||
"caption": "some file",
|
||||
"publication": fp,
|
||||
|
|
@ -119,27 +148,36 @@ class CaptionedFileCreateViewTest(BaseIntegrationTest):
|
|||
|
||||
|
||||
class CaptionedFileDeleteViewTest(BaseIntegrationTest):
|
||||
|
||||
def test_view_ok(self):
|
||||
captioned_file = CaptionedFile.objects.create(caption="some file", publication=fixture_file)
|
||||
captioned_file = CaptionedFile.objects.create(
|
||||
caption="some file", publication=fixture_file)
|
||||
response = self.client.get(reverse("admin2:files_captionedfile_delete",
|
||||
args=(captioned_file.pk, )))
|
||||
self.assertContains(response, captioned_file.caption)
|
||||
|
||||
def test_delete_captioned_file(self):
|
||||
captioned_file = CaptionedFile.objects.create(caption="some file", publication=fixture_file)
|
||||
captioned_file = CaptionedFile.objects.create(
|
||||
caption="some file", publication=fixture_file)
|
||||
response = self.client.post(reverse("admin2:files_captionedfile_delete",
|
||||
args=(captioned_file.pk, )))
|
||||
self.assertRedirects(response, reverse("admin2:files_captionedfile_index"))
|
||||
self.assertFalse(CaptionedFile.objects.filter(pk=captioned_file.pk).exists())
|
||||
self.assertRedirects(
|
||||
response, reverse("admin2:files_captionedfile_index"))
|
||||
self.assertFalse(
|
||||
CaptionedFile.objects.filter(pk=captioned_file.pk).exists())
|
||||
|
||||
|
||||
class FileDeleteActionTest(BaseIntegrationTest):
|
||||
|
||||
"""
|
||||
Tests the behaviour of the 'Delete selected items' action.
|
||||
"""
|
||||
|
||||
def test_confirmation_page(self):
|
||||
cf1 = captioned_file = CaptionedFile.objects.create(caption="some file", publication=fixture_file)
|
||||
cf2 = captioned_file = CaptionedFile.objects.create(caption="some file", publication=fixture_file)
|
||||
cf1 = CaptionedFile.objects.create(
|
||||
caption="some file", publication=fixture_file)
|
||||
cf2 = CaptionedFile.objects.create(
|
||||
caption="some file", publication=fixture_file)
|
||||
params = {
|
||||
'action': 'DeleteSelectedAction',
|
||||
'selected_model_pk': [cf1.pk, cf2.pk]
|
||||
|
|
@ -150,8 +188,10 @@ class FileDeleteActionTest(BaseIntegrationTest):
|
|||
self.assertContains(response, cf2.caption)
|
||||
|
||||
def test_results_page(self):
|
||||
cf1 = captioned_file = CaptionedFile.objects.create(caption="some file", publication=fixture_file)
|
||||
cf2 = captioned_file = CaptionedFile.objects.create(caption="some file", publication=fixture_file)
|
||||
cf1 = CaptionedFile.objects.create(
|
||||
caption="some file", publication=fixture_file)
|
||||
cf2 = CaptionedFile.objects.create(
|
||||
caption="some file", publication=fixture_file)
|
||||
params = {
|
||||
'action': 'DeleteSelectedAction',
|
||||
'selected_model_pk': [cf1.pk, cf2.pk],
|
||||
|
|
|
|||
|
|
@ -3,16 +3,18 @@ from __future__ import division, absolute_import, unicode_literals
|
|||
|
||||
import datetime
|
||||
|
||||
from django.utils.encoding import python_2_unicode_compatible
|
||||
from django.db import models
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class Poll(models.Model):
|
||||
question = models.CharField(max_length=200, verbose_name=_('question'))
|
||||
pub_date = models.DateTimeField(verbose_name=_('date published'))
|
||||
|
||||
def __unicode__(self):
|
||||
def __str__(self):
|
||||
return self.question
|
||||
|
||||
def was_published_recently(self):
|
||||
|
|
@ -26,12 +28,14 @@ class Poll(models.Model):
|
|||
verbose_name_plural = _('polls')
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class Choice(models.Model):
|
||||
poll = models.ForeignKey(Poll, verbose_name=_('poll'))
|
||||
choice_text = models.CharField(max_length=200, verbose_name=_('choice text'))
|
||||
choice_text = models.CharField(
|
||||
max_length=200, verbose_name=_('choice text'))
|
||||
votes = models.IntegerField(default=0, verbose_name=_('votes'))
|
||||
|
||||
def __unicode__(self):
|
||||
def __str__(self):
|
||||
return self.choice_text
|
||||
|
||||
class Meta:
|
||||
|
|
|
|||
|
|
@ -2,14 +2,17 @@ from django.contrib.auth import get_user_model
|
|||
from django.core.urlresolvers import reverse
|
||||
from django.test import TestCase, Client
|
||||
from django.utils import timezone
|
||||
from django.utils.encoding import force_text
|
||||
|
||||
from ..models import Poll
|
||||
|
||||
|
||||
class BaseIntegrationTest(TestCase):
|
||||
|
||||
"""
|
||||
Base TestCase for integration tests.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.client = Client()
|
||||
self.user = get_user_model()(username='user', is_staff=True,
|
||||
|
|
@ -20,48 +23,63 @@ class BaseIntegrationTest(TestCase):
|
|||
|
||||
|
||||
class AdminIndexTest(BaseIntegrationTest):
|
||||
|
||||
def test_view_ok(self):
|
||||
response = self.client.get(reverse("admin2:dashboard"))
|
||||
self.assertContains(response, reverse("admin2:polls_poll_index"))
|
||||
|
||||
|
||||
class PollListTest(BaseIntegrationTest):
|
||||
|
||||
def test_view_ok(self):
|
||||
poll = Poll.objects.create(question="some question", pub_date=timezone.now())
|
||||
poll = Poll.objects.create(
|
||||
question="some question", pub_date=timezone.now())
|
||||
response = self.client.get(reverse("admin2:polls_poll_index"))
|
||||
self.assertContains(response, poll.question)
|
||||
|
||||
def test_actions_displayed(self):
|
||||
response = self.client.get(reverse("admin2:polls_poll_index"))
|
||||
self.assertInHTML('<a tabindex="-1" href="#" data-name="action" data-value="DeleteSelectedAction">Delete selected items</a>', response.content)
|
||||
self.assertInHTML(
|
||||
'<a tabindex="-1" href="#" data-name="action" data-value="DeleteSelectedAction">Delete selected items</a>', force_text(response.content))
|
||||
|
||||
def test_delete_selected_poll(self):
|
||||
poll = Poll.objects.create(question="some question", pub_date=timezone.now())
|
||||
params = {'action': 'DeleteSelectedAction', 'selected_model_pk': str(poll.pk)}
|
||||
poll = Poll.objects.create(
|
||||
question="some question", pub_date=timezone.now())
|
||||
params = {'action': 'DeleteSelectedAction',
|
||||
'selected_model_pk': str(poll.pk)}
|
||||
response = self.client.post(reverse("admin2:polls_poll_index"), params)
|
||||
self.assertInHTML('<p>Are you sure you want to delete the selected poll? The following item will be deleted:</p>', response.content)
|
||||
self.assertInHTML(
|
||||
'<p>Are you sure you want to delete the selected poll? The following item will be deleted:</p>', force_text(response.content))
|
||||
|
||||
def test_delete_selected_poll_confirmation(self):
|
||||
poll = Poll.objects.create(question="some question", pub_date=timezone.now())
|
||||
params = {'action': 'DeleteSelectedAction', 'selected_model_pk': str(poll.pk), 'confirmed': 'yes'}
|
||||
poll = Poll.objects.create(
|
||||
question="some question", pub_date=timezone.now())
|
||||
params = {'action': 'DeleteSelectedAction',
|
||||
'selected_model_pk': str(poll.pk), 'confirmed': 'yes'}
|
||||
response = self.client.post(reverse("admin2:polls_poll_index"), params)
|
||||
self.assertRedirects(response, reverse("admin2:polls_poll_index"))
|
||||
|
||||
def test_delete_selected_poll_none_selected(self):
|
||||
Poll.objects.create(question="some question", pub_date=timezone.now())
|
||||
params = {'action': 'DeleteSelectedAction'}
|
||||
response = self.client.post(reverse("admin2:polls_poll_index"), params, follow=True)
|
||||
self.assertContains(response, "Items must be selected in order to perform actions on them. No items have been changed.")
|
||||
response = self.client.post(
|
||||
reverse("admin2:polls_poll_index"), params, follow=True)
|
||||
self.assertContains(
|
||||
response, "Items must be selected in order to perform actions on them. No items have been changed.")
|
||||
|
||||
|
||||
class PollDetailViewTest(BaseIntegrationTest):
|
||||
|
||||
def test_view_ok(self):
|
||||
poll = Poll.objects.create(question="some question", pub_date=timezone.now())
|
||||
response = self.client.get(reverse("admin2:polls_poll_detail", args=(poll.pk, )))
|
||||
poll = Poll.objects.create(
|
||||
question="some question", pub_date=timezone.now())
|
||||
response = self.client.get(
|
||||
reverse("admin2:polls_poll_detail", args=(poll.pk, )))
|
||||
self.assertContains(response, poll.question)
|
||||
|
||||
|
||||
class PollCreateViewTest(BaseIntegrationTest):
|
||||
|
||||
def test_view_ok(self):
|
||||
response = self.client.get(reverse("admin2:polls_poll_create"))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
|
@ -119,14 +137,17 @@ class PollCreateViewTest(BaseIntegrationTest):
|
|||
|
||||
|
||||
class PollDeleteViewTest(BaseIntegrationTest):
|
||||
|
||||
def test_view_ok(self):
|
||||
poll = Poll.objects.create(question="some question", pub_date=timezone.now())
|
||||
poll = Poll.objects.create(
|
||||
question="some question", pub_date=timezone.now())
|
||||
response = self.client.get(reverse("admin2:polls_poll_delete",
|
||||
args=(poll.pk, )))
|
||||
self.assertContains(response, poll.question)
|
||||
|
||||
def test_delete_poll(self):
|
||||
poll = Poll.objects.create(question="some question", pub_date=timezone.now())
|
||||
poll = Poll.objects.create(
|
||||
question="some question", pub_date=timezone.now())
|
||||
response = self.client.post(reverse("admin2:polls_poll_delete",
|
||||
args=(poll.pk, )))
|
||||
self.assertRedirects(response, reverse("admin2:polls_poll_index"))
|
||||
|
|
@ -134,12 +155,16 @@ class PollDeleteViewTest(BaseIntegrationTest):
|
|||
|
||||
|
||||
class PollDeleteActionTest(BaseIntegrationTest):
|
||||
|
||||
"""
|
||||
Tests the behaviour of the 'Delete selected items' action.
|
||||
"""
|
||||
|
||||
def test_confirmation_page(self):
|
||||
p1 = Poll.objects.create(question="some question", pub_date=timezone.now())
|
||||
p2 = Poll.objects.create(question="some question", pub_date=timezone.now())
|
||||
p1 = Poll.objects.create(
|
||||
question="some question", pub_date=timezone.now())
|
||||
p2 = Poll.objects.create(
|
||||
question="some question", pub_date=timezone.now())
|
||||
params = {
|
||||
'action': 'DeleteSelectedAction',
|
||||
'selected_model_pk': [p1.pk, p2.pk]
|
||||
|
|
@ -150,8 +175,10 @@ class PollDeleteActionTest(BaseIntegrationTest):
|
|||
self.assertContains(response, p2.question)
|
||||
|
||||
def test_results_page(self):
|
||||
p1 = Poll.objects.create(question="some question", pub_date=timezone.now())
|
||||
p2 = Poll.objects.create(question="some question", pub_date=timezone.now())
|
||||
p1 = Poll.objects.create(
|
||||
question="some question", pub_date=timezone.now())
|
||||
p2 = Poll.objects.create(
|
||||
question="some question", pub_date=timezone.now())
|
||||
params = {
|
||||
'action': 'DeleteSelectedAction',
|
||||
'selected_model_pk': [p1.pk, p2.pk],
|
||||
|
|
|
|||
Loading…
Reference in a new issue