summaryrefslogtreecommitdiff
path: root/tests/regressiontests/admin_views/tests.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/regressiontests/admin_views/tests.py')
-rw-r--r--tests/regressiontests/admin_views/tests.py152
1 files changed, 118 insertions, 34 deletions
diff --git a/tests/regressiontests/admin_views/tests.py b/tests/regressiontests/admin_views/tests.py
index 39daf116ab..bf198bc9a2 100644
--- a/tests/regressiontests/admin_views/tests.py
+++ b/tests/regressiontests/admin_views/tests.py
@@ -1,5 +1,7 @@
# coding: utf-8
+import re
+
from django.test import TestCase
from django.contrib.auth.models import User, Permission
from django.contrib.contenttypes.models import ContentType
@@ -9,22 +11,27 @@ from django.contrib.admin.util import quote
from django.utils.html import escape
# local test models
-from models import Article, CustomArticle, Section, ModelWithStringPrimaryKey
+from models import Article, CustomArticle, Section, ModelWithStringPrimaryKey, Persona, FooAccount, BarAccount
+
+try:
+ set
+except NameError:
+ from sets import Set as set
class AdminViewBasicTest(TestCase):
fixtures = ['admin-views-users.xml', 'admin-views-colors.xml']
-
- # Store the bit of the URL where the admin is registered as a class
+
+ # Store the bit of the URL where the admin is registered as a class
# variable. That way we can test a second AdminSite just by subclassing
# this test case and changing urlbit.
urlbit = 'admin'
-
+
def setUp(self):
self.client.login(username='super', password='secret')
-
+
def tearDown(self):
self.client.logout()
-
+
def testTrailingSlashRequired(self):
"""
If you leave off the trailing slash, app should redirect and add it.
@@ -33,29 +40,29 @@ class AdminViewBasicTest(TestCase):
self.assertRedirects(request,
'/test_admin/%s/admin_views/article/add/' % self.urlbit, status_code=301
)
-
+
def testBasicAddGet(self):
"""
A smoke test to ensure GET on the add_view works.
"""
response = self.client.get('/test_admin/%s/admin_views/section/add/' % self.urlbit)
self.failUnlessEqual(response.status_code, 200)
-
+
def testAddWithGETArgs(self):
response = self.client.get('/test_admin/%s/admin_views/section/add/' % self.urlbit, {'name': 'My Section'})
self.failUnlessEqual(response.status_code, 200)
self.failUnless(
- 'value="My Section"' in response.content,
+ 'value="My Section"' in response.content,
"Couldn't find an input with the right value in the response."
)
-
+
def testBasicEditGet(self):
"""
A smoke test to ensureGET on the change_view works.
"""
response = self.client.get('/test_admin/%s/admin_views/section/1/' % self.urlbit)
self.failUnlessEqual(response.status_code, 200)
-
+
def testBasicAddPost(self):
"""
A smoke test to ensure POST on add_view works.
@@ -68,7 +75,7 @@ class AdminViewBasicTest(TestCase):
}
response = self.client.post('/test_admin/%s/admin_views/section/add/' % self.urlbit, post_data)
self.failUnlessEqual(response.status_code, 302) # redirect somewhere
-
+
def testBasicEditPost(self):
"""
A smoke test to ensure POST on edit_view works.
@@ -116,7 +123,7 @@ class AdminViewBasicTest(TestCase):
def testChangeListSortingCallable(self):
"""
- Ensure we can sort on a list_display field that is a callable
+ Ensure we can sort on a list_display field that is a callable
(column 2 is callable_year in ArticleAdmin)
"""
response = self.client.get('/test_admin/%s/admin_views/article/' % self.urlbit, {'ot': 'asc', 'o': 2})
@@ -126,10 +133,10 @@ class AdminViewBasicTest(TestCase):
response.content.index('Middle content') < response.content.index('Newest content'),
"Results of sorting on callable are out of order."
)
-
+
def testChangeListSortingModel(self):
"""
- Ensure we can sort on a list_display field that is a Model method
+ Ensure we can sort on a list_display field that is a Model method
(colunn 3 is 'model_year' in ArticleAdmin)
"""
response = self.client.get('/test_admin/%s/admin_views/article/' % self.urlbit, {'ot': 'dsc', 'o': 3})
@@ -139,37 +146,37 @@ class AdminViewBasicTest(TestCase):
response.content.index('Middle content') < response.content.index('Oldest content'),
"Results of sorting on Model method are out of order."
)
-
+
def testChangeListSortingModelAdmin(self):
"""
- Ensure we can sort on a list_display field that is a ModelAdmin method
+ Ensure we can sort on a list_display field that is a ModelAdmin method
(colunn 4 is 'modeladmin_year' in ArticleAdmin)
"""
response = self.client.get('/test_admin/%s/admin_views/article/' % self.urlbit, {'ot': 'asc', 'o': 4})
self.failUnlessEqual(response.status_code, 200)
self.failUnless(
- response.content.index('Oldest content') < response.content.index('Middle content') and
+ response.content.index('Oldest content') < response.content.index('Middle content') and
response.content.index('Middle content') < response.content.index('Newest content'),
"Results of sorting on ModelAdmin method are out of order."
)
-
+
def testLimitedFilter(self):
"""Ensure admin changelist filters do not contain objects excluded via limit_choices_to."""
response = self.client.get('/test_admin/%s/admin_views/thing/' % self.urlbit)
self.failUnlessEqual(response.status_code, 200)
self.failUnless(
- '<div id="changelist-filter">' in response.content,
+ '<div id="changelist-filter">' in response.content,
"Expected filter not found in changelist view."
)
self.failIf(
'<a href="?color__id__exact=3">Blue</a>' in response.content,
"Changelist filter not correctly limited by limit_choices_to."
)
-
+
def testIncorrectLookupParameters(self):
"""Ensure incorrect lookup parameters are handled gracefully."""
response = self.client.get('/test_admin/%s/admin_views/thing/' % self.urlbit, {'notarealfield': '5'})
- self.assertRedirects(response, '/test_admin/%s/admin_views/thing/?e=1' % self.urlbit)
+ self.assertRedirects(response, '/test_admin/%s/admin_views/thing/?e=1' % self.urlbit)
response = self.client.get('/test_admin/%s/admin_views/thing/' % self.urlbit, {'color__id__exact': 'StringNotInteger!'})
self.assertRedirects(response, '/test_admin/%s/admin_views/thing/?e=1' % self.urlbit)
@@ -186,7 +193,7 @@ class CustomModelAdminTest(AdminViewBasicTest):
request = self.client.get('/test_admin/admin2/')
self.assertTemplateUsed(request, 'custom_admin/index.html')
self.assert_('Hello from a custom index template *bar*' in request.content)
-
+
def testCustomAdminSiteView(self):
self.client.login(username='super', password='secret')
response = self.client.get('/test_admin/%s/my_view/' % self.urlbit)
@@ -411,7 +418,7 @@ class AdminViewPermissionsTest(TestCase):
post = self.client.post('/test_admin/admin/admin_views/article/1/', change_dict)
self.assertRedirects(post, '/test_admin/admin/admin_views/article/')
self.failUnlessEqual(Article.objects.get(pk=1).content, '<p>edited article</p>')
-
+
# one error in form should produce singular error message, multiple errors plural
change_dict['title'] = ''
post = self.client.post('/test_admin/admin/admin_views/article/1/', change_dict)
@@ -422,7 +429,7 @@ class AdminViewPermissionsTest(TestCase):
post = self.client.post('/test_admin/admin/admin_views/article/1/', change_dict)
self.failUnlessEqual(request.status_code, 200)
self.failUnless('Please correct the errors below.' in post.content,
- 'Plural error message not found in response to post with multiple errors.')
+ 'Plural error message not found in response to post with multiple errors.')
self.client.get('/test_admin/admin/logout/')
def testCustomModelAdminTemplates(self):
@@ -523,7 +530,7 @@ class AdminViewStringPrimaryKeyTest(TestCase):
response = self.client.get('/test_admin/admin/admin_views/modelwithstringprimarykey/%s/delete/' % quote(self.pk))
should_contain = """<a href="../../%s/">%s</a>""" % (quote(self.pk), escape(self.pk))
self.assertContains(response, should_contain)
-
+
def test_url_conflicts_with_add(self):
"A model with a primary key that ends with add should be visible"
add_model = ModelWithStringPrimaryKey(id="i have something to add")
@@ -531,7 +538,7 @@ class AdminViewStringPrimaryKeyTest(TestCase):
response = self.client.get('/test_admin/admin/admin_views/modelwithstringprimarykey/%s/' % quote(add_model.pk))
should_contain = """<h1>Change model with string primary key</h1>"""
self.assertContains(response, should_contain)
-
+
def test_url_conflicts_with_delete(self):
"A model with a primary key that ends with delete should be visible"
delete_model = ModelWithStringPrimaryKey(id="delete")
@@ -539,7 +546,7 @@ class AdminViewStringPrimaryKeyTest(TestCase):
response = self.client.get('/test_admin/admin/admin_views/modelwithstringprimarykey/%s/' % quote(delete_model.pk))
should_contain = """<h1>Change model with string primary key</h1>"""
self.assertContains(response, should_contain)
-
+
def test_url_conflicts_with_history(self):
"A model with a primary key that ends with history should be visible"
history_model = ModelWithStringPrimaryKey(id="history")
@@ -547,7 +554,7 @@ class AdminViewStringPrimaryKeyTest(TestCase):
response = self.client.get('/test_admin/admin/admin_views/modelwithstringprimarykey/%s/' % quote(history_model.pk))
should_contain = """<h1>Change model with string primary key</h1>"""
self.assertContains(response, should_contain)
-
+
class SecureViewTest(TestCase):
fixtures = ['admin-views-users.xml']
@@ -582,28 +589,28 @@ class SecureViewTest(TestCase):
LOGIN_FORM_KEY: 1,
'username': 'joepublic',
'password': 'secret'}
-
+
def tearDown(self):
self.client.logout()
-
+
def test_secure_view_shows_login_if_not_logged_in(self):
"Ensure that we see the login form"
response = self.client.get('/test_admin/admin/secure-view/' )
self.assertTemplateUsed(response, 'admin/login.html')
-
+
def test_secure_view_login_successfully_redirects_to_original_url(self):
request = self.client.get('/test_admin/admin/secure-view/')
self.failUnlessEqual(request.status_code, 200)
query_string = "the-answer=42"
login = self.client.post('/test_admin/admin/secure-view/', self.super_login, QUERY_STRING = query_string )
self.assertRedirects(login, '/test_admin/admin/secure-view/?%s' % query_string)
-
+
def test_staff_member_required_decorator_works_as_per_admin_login(self):
"""
Make sure only staff members can log in.
Successful posts to the login page will redirect to the orignal url.
- Unsuccessfull attempts will continue to render the login page with
+ Unsuccessfull attempts will continue to render the login page with
a 200 status code.
"""
# Super User
@@ -721,3 +728,80 @@ class AdminViewUnicodeTest(TestCase):
self.failUnlessEqual(response.status_code, 200)
response = self.client.post('/test_admin/admin/admin_views/book/1/delete/', delete_dict)
self.assertRedirects(response, '/test_admin/admin/admin_views/book/')
+
+class AdminInheritedInlinesTest(TestCase):
+ fixtures = ['admin-views-users.xml',]
+
+ def setUp(self):
+ self.client.login(username='super', password='secret')
+
+ def tearDown(self):
+ self.client.logout()
+
+ def testInline(self):
+ "Ensure that inline models which inherit from a common parent are correctly handled by admin."
+
+ foo_user = u"foo username"
+ bar_user = u"bar username"
+
+ name_re = re.compile('name="(.*?)"')
+
+ # test the add case
+ response = self.client.get('/test_admin/admin/admin_views/persona/add/')
+ names = name_re.findall(response.content)
+ # make sure we have no duplicate HTML names
+ self.failUnlessEqual(len(names), len(set(names)))
+
+ # test the add case
+ post_data = {
+ "name": u"Test Name",
+ # inline data
+ "accounts-TOTAL_FORMS": u"1",
+ "accounts-INITIAL_FORMS": u"0",
+ "accounts-0-username": foo_user,
+ "accounts-2-TOTAL_FORMS": u"1",
+ "accounts-2-INITIAL_FORMS": u"0",
+ "accounts-2-0-username": bar_user,
+ }
+
+ response = self.client.post('/test_admin/admin/admin_views/persona/add/', post_data)
+ self.failUnlessEqual(response.status_code, 302) # redirect somewhere
+ self.failUnlessEqual(Persona.objects.count(), 1)
+ self.failUnlessEqual(FooAccount.objects.count(), 1)
+ self.failUnlessEqual(BarAccount.objects.count(), 1)
+ self.failUnlessEqual(FooAccount.objects.all()[0].username, foo_user)
+ self.failUnlessEqual(BarAccount.objects.all()[0].username, bar_user)
+ self.failUnlessEqual(Persona.objects.all()[0].accounts.count(), 2)
+
+ # test the edit case
+
+ response = self.client.get('/test_admin/admin/admin_views/persona/1/')
+ names = name_re.findall(response.content)
+ # make sure we have no duplicate HTML names
+ self.failUnlessEqual(len(names), len(set(names)))
+
+ post_data = {
+ "name": u"Test Name",
+
+ "accounts-TOTAL_FORMS": "2",
+ "accounts-INITIAL_FORMS": u"1",
+
+ "accounts-0-username": "%s-1" % foo_user,
+ "accounts-0-account_ptr": "1",
+ "accounts-0-persona": "1",
+
+ "accounts-2-TOTAL_FORMS": u"2",
+ "accounts-2-INITIAL_FORMS": u"1",
+
+ "accounts-2-0-username": "%s-1" % bar_user,
+ "accounts-2-0-account_ptr": "2",
+ "accounts-2-0-persona": "1",
+ }
+ response = self.client.post('/test_admin/admin/admin_views/persona/1/', post_data)
+ self.failUnlessEqual(response.status_code, 302)
+ self.failUnlessEqual(Persona.objects.count(), 1)
+ self.failUnlessEqual(FooAccount.objects.count(), 1)
+ self.failUnlessEqual(BarAccount.objects.count(), 1)
+ self.failUnlessEqual(FooAccount.objects.all()[0].username, "%s-1" % foo_user)
+ self.failUnlessEqual(BarAccount.objects.all()[0].username, "%s-1" % bar_user)
+ self.failUnlessEqual(Persona.objects.all()[0].accounts.count(), 2)