From 8ce46375ae3927eec142a8689215ac5039123a03 Mon Sep 17 00:00:00 2001 From: Preston Timmons Date: Tue, 2 Apr 2013 19:00:55 -0600 Subject: [PATCH] Move last remaining tests out of models.py files; prep for test discovery. --- tests/conditional_processing/models.py | 129 ------ tests/conditional_processing/tests.py | 129 ++++++ tests/conditional_processing/views.py | 2 +- tests/forms_tests/tests/__init__.py | 2 +- tests/forms_tests/tests/models.py | 218 ----------- tests/forms_tests/tests/tests.py | 218 +++++++++++ tests/test_client/models.py | 508 ------------------------ tests/test_client/tests.py | 517 ++++++++++++++++++++++++- tests/test_client_override/__init__.py | 0 tests/test_client_override/models.py | 0 tests/test_client_override/tests.py | 21 + 11 files changed, 872 insertions(+), 872 deletions(-) create mode 100644 tests/conditional_processing/tests.py create mode 100644 tests/forms_tests/tests/tests.py create mode 100644 tests/test_client_override/__init__.py create mode 100644 tests/test_client_override/models.py create mode 100644 tests/test_client_override/tests.py diff --git a/tests/conditional_processing/models.py b/tests/conditional_processing/models.py index 77f1ff54ed..e69de29bb2 100644 --- a/tests/conditional_processing/models.py +++ b/tests/conditional_processing/models.py @@ -1,129 +0,0 @@ -# -*- coding:utf-8 -*- -from __future__ import unicode_literals - -from datetime import datetime - -from django.test import TestCase - - -FULL_RESPONSE = 'Test conditional get response' -LAST_MODIFIED = datetime(2007, 10, 21, 23, 21, 47) -LAST_MODIFIED_STR = 'Sun, 21 Oct 2007 23:21:47 GMT' -LAST_MODIFIED_NEWER_STR = 'Mon, 18 Oct 2010 16:56:23 GMT' -LAST_MODIFIED_INVALID_STR = 'Mon, 32 Oct 2010 16:56:23 GMT' -EXPIRED_LAST_MODIFIED_STR = 'Sat, 20 Oct 2007 23:21:47 GMT' -ETAG = 'b4246ffc4f62314ca13147c9d4f76974' -EXPIRED_ETAG = '7fae4cd4b0f81e7d2914700043aa8ed6' - -class ConditionalGet(TestCase): - urls = 'conditional_processing.urls' - - def assertFullResponse(self, response, check_last_modified=True, check_etag=True): - self.assertEqual(response.status_code, 200) - self.assertEqual(response.content, FULL_RESPONSE.encode()) - if check_last_modified: - self.assertEqual(response['Last-Modified'], LAST_MODIFIED_STR) - if check_etag: - self.assertEqual(response['ETag'], '"%s"' % ETAG) - - def assertNotModified(self, response): - self.assertEqual(response.status_code, 304) - self.assertEqual(response.content, b'') - - def testWithoutConditions(self): - response = self.client.get('/condition/') - self.assertFullResponse(response) - - def testIfModifiedSince(self): - self.client.defaults['HTTP_IF_MODIFIED_SINCE'] = LAST_MODIFIED_STR - response = self.client.get('/condition/') - self.assertNotModified(response) - self.client.defaults['HTTP_IF_MODIFIED_SINCE'] = LAST_MODIFIED_NEWER_STR - response = self.client.get('/condition/') - self.assertNotModified(response) - self.client.defaults['HTTP_IF_MODIFIED_SINCE'] = LAST_MODIFIED_INVALID_STR - response = self.client.get('/condition/') - self.assertFullResponse(response) - self.client.defaults['HTTP_IF_MODIFIED_SINCE'] = EXPIRED_LAST_MODIFIED_STR - response = self.client.get('/condition/') - self.assertFullResponse(response) - - def testIfNoneMatch(self): - self.client.defaults['HTTP_IF_NONE_MATCH'] = '"%s"' % ETAG - response = self.client.get('/condition/') - self.assertNotModified(response) - self.client.defaults['HTTP_IF_NONE_MATCH'] = '"%s"' % EXPIRED_ETAG - response = self.client.get('/condition/') - self.assertFullResponse(response) - - # Several etags in If-None-Match is a bit exotic but why not? - self.client.defaults['HTTP_IF_NONE_MATCH'] = '"%s", "%s"' % (ETAG, EXPIRED_ETAG) - response = self.client.get('/condition/') - self.assertNotModified(response) - - def testIfMatch(self): - self.client.defaults['HTTP_IF_MATCH'] = '"%s"' % ETAG - response = self.client.put('/condition/etag/') - self.assertEqual(response.status_code, 200) - self.client.defaults['HTTP_IF_MATCH'] = '"%s"' % EXPIRED_ETAG - response = self.client.put('/condition/etag/') - self.assertEqual(response.status_code, 412) - - def testBothHeaders(self): - self.client.defaults['HTTP_IF_MODIFIED_SINCE'] = LAST_MODIFIED_STR - self.client.defaults['HTTP_IF_NONE_MATCH'] = '"%s"' % ETAG - response = self.client.get('/condition/') - self.assertNotModified(response) - - self.client.defaults['HTTP_IF_MODIFIED_SINCE'] = EXPIRED_LAST_MODIFIED_STR - self.client.defaults['HTTP_IF_NONE_MATCH'] = '"%s"' % ETAG - response = self.client.get('/condition/') - self.assertFullResponse(response) - - self.client.defaults['HTTP_IF_MODIFIED_SINCE'] = LAST_MODIFIED_STR - self.client.defaults['HTTP_IF_NONE_MATCH'] = '"%s"' % EXPIRED_ETAG - response = self.client.get('/condition/') - self.assertFullResponse(response) - - def testSingleCondition1(self): - self.client.defaults['HTTP_IF_MODIFIED_SINCE'] = LAST_MODIFIED_STR - response = self.client.get('/condition/last_modified/') - self.assertNotModified(response) - response = self.client.get('/condition/etag/') - self.assertFullResponse(response, check_last_modified=False) - - def testSingleCondition2(self): - self.client.defaults['HTTP_IF_NONE_MATCH'] = '"%s"' % ETAG - response = self.client.get('/condition/etag/') - self.assertNotModified(response) - response = self.client.get('/condition/last_modified/') - self.assertFullResponse(response, check_etag=False) - - def testSingleCondition3(self): - self.client.defaults['HTTP_IF_MODIFIED_SINCE'] = EXPIRED_LAST_MODIFIED_STR - response = self.client.get('/condition/last_modified/') - self.assertFullResponse(response, check_etag=False) - - def testSingleCondition4(self): - self.client.defaults['HTTP_IF_NONE_MATCH'] = '"%s"' % EXPIRED_ETAG - response = self.client.get('/condition/etag/') - self.assertFullResponse(response, check_last_modified=False) - - def testSingleCondition5(self): - self.client.defaults['HTTP_IF_MODIFIED_SINCE'] = LAST_MODIFIED_STR - response = self.client.get('/condition/last_modified2/') - self.assertNotModified(response) - response = self.client.get('/condition/etag2/') - self.assertFullResponse(response, check_last_modified=False) - - def testSingleCondition6(self): - self.client.defaults['HTTP_IF_NONE_MATCH'] = '"%s"' % ETAG - response = self.client.get('/condition/etag2/') - self.assertNotModified(response) - response = self.client.get('/condition/last_modified2/') - self.assertFullResponse(response, check_etag=False) - - def testInvalidETag(self): - self.client.defaults['HTTP_IF_NONE_MATCH'] = r'"\"' - response = self.client.get('/condition/etag/') - self.assertFullResponse(response, check_last_modified=False) diff --git a/tests/conditional_processing/tests.py b/tests/conditional_processing/tests.py new file mode 100644 index 0000000000..77f1ff54ed --- /dev/null +++ b/tests/conditional_processing/tests.py @@ -0,0 +1,129 @@ +# -*- coding:utf-8 -*- +from __future__ import unicode_literals + +from datetime import datetime + +from django.test import TestCase + + +FULL_RESPONSE = 'Test conditional get response' +LAST_MODIFIED = datetime(2007, 10, 21, 23, 21, 47) +LAST_MODIFIED_STR = 'Sun, 21 Oct 2007 23:21:47 GMT' +LAST_MODIFIED_NEWER_STR = 'Mon, 18 Oct 2010 16:56:23 GMT' +LAST_MODIFIED_INVALID_STR = 'Mon, 32 Oct 2010 16:56:23 GMT' +EXPIRED_LAST_MODIFIED_STR = 'Sat, 20 Oct 2007 23:21:47 GMT' +ETAG = 'b4246ffc4f62314ca13147c9d4f76974' +EXPIRED_ETAG = '7fae4cd4b0f81e7d2914700043aa8ed6' + +class ConditionalGet(TestCase): + urls = 'conditional_processing.urls' + + def assertFullResponse(self, response, check_last_modified=True, check_etag=True): + self.assertEqual(response.status_code, 200) + self.assertEqual(response.content, FULL_RESPONSE.encode()) + if check_last_modified: + self.assertEqual(response['Last-Modified'], LAST_MODIFIED_STR) + if check_etag: + self.assertEqual(response['ETag'], '"%s"' % ETAG) + + def assertNotModified(self, response): + self.assertEqual(response.status_code, 304) + self.assertEqual(response.content, b'') + + def testWithoutConditions(self): + response = self.client.get('/condition/') + self.assertFullResponse(response) + + def testIfModifiedSince(self): + self.client.defaults['HTTP_IF_MODIFIED_SINCE'] = LAST_MODIFIED_STR + response = self.client.get('/condition/') + self.assertNotModified(response) + self.client.defaults['HTTP_IF_MODIFIED_SINCE'] = LAST_MODIFIED_NEWER_STR + response = self.client.get('/condition/') + self.assertNotModified(response) + self.client.defaults['HTTP_IF_MODIFIED_SINCE'] = LAST_MODIFIED_INVALID_STR + response = self.client.get('/condition/') + self.assertFullResponse(response) + self.client.defaults['HTTP_IF_MODIFIED_SINCE'] = EXPIRED_LAST_MODIFIED_STR + response = self.client.get('/condition/') + self.assertFullResponse(response) + + def testIfNoneMatch(self): + self.client.defaults['HTTP_IF_NONE_MATCH'] = '"%s"' % ETAG + response = self.client.get('/condition/') + self.assertNotModified(response) + self.client.defaults['HTTP_IF_NONE_MATCH'] = '"%s"' % EXPIRED_ETAG + response = self.client.get('/condition/') + self.assertFullResponse(response) + + # Several etags in If-None-Match is a bit exotic but why not? + self.client.defaults['HTTP_IF_NONE_MATCH'] = '"%s", "%s"' % (ETAG, EXPIRED_ETAG) + response = self.client.get('/condition/') + self.assertNotModified(response) + + def testIfMatch(self): + self.client.defaults['HTTP_IF_MATCH'] = '"%s"' % ETAG + response = self.client.put('/condition/etag/') + self.assertEqual(response.status_code, 200) + self.client.defaults['HTTP_IF_MATCH'] = '"%s"' % EXPIRED_ETAG + response = self.client.put('/condition/etag/') + self.assertEqual(response.status_code, 412) + + def testBothHeaders(self): + self.client.defaults['HTTP_IF_MODIFIED_SINCE'] = LAST_MODIFIED_STR + self.client.defaults['HTTP_IF_NONE_MATCH'] = '"%s"' % ETAG + response = self.client.get('/condition/') + self.assertNotModified(response) + + self.client.defaults['HTTP_IF_MODIFIED_SINCE'] = EXPIRED_LAST_MODIFIED_STR + self.client.defaults['HTTP_IF_NONE_MATCH'] = '"%s"' % ETAG + response = self.client.get('/condition/') + self.assertFullResponse(response) + + self.client.defaults['HTTP_IF_MODIFIED_SINCE'] = LAST_MODIFIED_STR + self.client.defaults['HTTP_IF_NONE_MATCH'] = '"%s"' % EXPIRED_ETAG + response = self.client.get('/condition/') + self.assertFullResponse(response) + + def testSingleCondition1(self): + self.client.defaults['HTTP_IF_MODIFIED_SINCE'] = LAST_MODIFIED_STR + response = self.client.get('/condition/last_modified/') + self.assertNotModified(response) + response = self.client.get('/condition/etag/') + self.assertFullResponse(response, check_last_modified=False) + + def testSingleCondition2(self): + self.client.defaults['HTTP_IF_NONE_MATCH'] = '"%s"' % ETAG + response = self.client.get('/condition/etag/') + self.assertNotModified(response) + response = self.client.get('/condition/last_modified/') + self.assertFullResponse(response, check_etag=False) + + def testSingleCondition3(self): + self.client.defaults['HTTP_IF_MODIFIED_SINCE'] = EXPIRED_LAST_MODIFIED_STR + response = self.client.get('/condition/last_modified/') + self.assertFullResponse(response, check_etag=False) + + def testSingleCondition4(self): + self.client.defaults['HTTP_IF_NONE_MATCH'] = '"%s"' % EXPIRED_ETAG + response = self.client.get('/condition/etag/') + self.assertFullResponse(response, check_last_modified=False) + + def testSingleCondition5(self): + self.client.defaults['HTTP_IF_MODIFIED_SINCE'] = LAST_MODIFIED_STR + response = self.client.get('/condition/last_modified2/') + self.assertNotModified(response) + response = self.client.get('/condition/etag2/') + self.assertFullResponse(response, check_last_modified=False) + + def testSingleCondition6(self): + self.client.defaults['HTTP_IF_NONE_MATCH'] = '"%s"' % ETAG + response = self.client.get('/condition/etag2/') + self.assertNotModified(response) + response = self.client.get('/condition/last_modified2/') + self.assertFullResponse(response, check_etag=False) + + def testInvalidETag(self): + self.client.defaults['HTTP_IF_NONE_MATCH'] = r'"\"' + response = self.client.get('/condition/etag/') + self.assertFullResponse(response, check_last_modified=False) diff --git a/tests/conditional_processing/views.py b/tests/conditional_processing/views.py index 2188c9b462..14a5a83a45 100644 --- a/tests/conditional_processing/views.py +++ b/tests/conditional_processing/views.py @@ -4,7 +4,7 @@ from __future__ import absolute_import from django.views.decorators.http import condition, etag, last_modified from django.http import HttpResponse -from .models import FULL_RESPONSE, LAST_MODIFIED, ETAG +from .tests import FULL_RESPONSE, LAST_MODIFIED, ETAG def index(request): diff --git a/tests/forms_tests/tests/__init__.py b/tests/forms_tests/tests/__init__.py index 6708e54c79..6b4771912f 100644 --- a/tests/forms_tests/tests/__init__.py +++ b/tests/forms_tests/tests/__init__.py @@ -12,7 +12,7 @@ from .input_formats import (LocalizedTimeTests, CustomTimeInputFormatsTests, SimpleDateFormatTests, LocalizedDateTimeTests, CustomDateTimeInputFormatsTests, SimpleDateTimeFormatTests) from .media import FormsMediaTestCase, StaticFormsMediaTestCase -from .models import (TestTicket12510, ModelFormCallableModelDefault, +from .tests import (TestTicket12510, ModelFormCallableModelDefault, FormsModelTestCase, RelatedModelFormTests) from .regressions import FormsRegressionsTestCase from .util import FormsUtilTestCase diff --git a/tests/forms_tests/tests/models.py b/tests/forms_tests/tests/models.py index be75643b28..e69de29bb2 100644 --- a/tests/forms_tests/tests/models.py +++ b/tests/forms_tests/tests/models.py @@ -1,218 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import, unicode_literals - -import datetime - -from django.core.files.uploadedfile import SimpleUploadedFile -from django.db import models -from django.forms import Form, ModelForm, FileField, ModelChoiceField -from django.forms.models import ModelFormMetaclass -from django.test import TestCase -from django.utils import six - -from ..models import (ChoiceOptionModel, ChoiceFieldModel, FileModel, Group, - BoundaryModel, Defaults, OptionalMultiChoiceModel) - - -class ChoiceFieldForm(ModelForm): - class Meta: - model = ChoiceFieldModel - - -class OptionalMultiChoiceModelForm(ModelForm): - class Meta: - model = OptionalMultiChoiceModel - - -class FileForm(Form): - file1 = FileField() - - -class TestTicket12510(TestCase): - ''' It is not necessary to generate choices for ModelChoiceField (regression test for #12510). ''' - def setUp(self): - self.groups = [Group.objects.create(name=name) for name in 'abc'] - - def test_choices_not_fetched_when_not_rendering(self): - # only one query is required to pull the model from DB - with self.assertNumQueries(1): - field = ModelChoiceField(Group.objects.order_by('-name')) - self.assertEqual('a', field.clean(self.groups[0].pk).name) - - -class TestTicket14567(TestCase): - """ - Check that the return values of ModelMultipleChoiceFields are QuerySets - """ - def test_empty_queryset_return(self): - "If a model's ManyToManyField has blank=True and is saved with no data, a queryset is returned." - form = OptionalMultiChoiceModelForm({'multi_choice_optional': '', 'multi_choice': ['1']}) - self.assertTrue(form.is_valid()) - # Check that the empty value is a QuerySet - self.assertTrue(isinstance(form.cleaned_data['multi_choice_optional'], models.query.QuerySet)) - # While we're at it, test whether a QuerySet is returned if there *is* a value. - self.assertTrue(isinstance(form.cleaned_data['multi_choice'], models.query.QuerySet)) - - -class ModelFormCallableModelDefault(TestCase): - def test_no_empty_option(self): - "If a model's ForeignKey has blank=False and a default, no empty option is created (Refs #10792)." - option = ChoiceOptionModel.objects.create(name='default') - - choices = list(ChoiceFieldForm().fields['choice'].choices) - self.assertEqual(len(choices), 1) - self.assertEqual(choices[0], (option.pk, six.text_type(option))) - - def test_callable_initial_value(self): - "The initial value for a callable default returning a queryset is the pk (refs #13769)" - obj1 = ChoiceOptionModel.objects.create(id=1, name='default') - obj2 = ChoiceOptionModel.objects.create(id=2, name='option 2') - obj3 = ChoiceOptionModel.objects.create(id=3, name='option 3') - self.assertHTMLEqual(ChoiceFieldForm().as_p(), """

-

-

Hold down "Control", or "Command" on a Mac, to select more than one.

-

Hold down "Control", or "Command" on a Mac, to select more than one.

""") - - def test_initial_instance_value(self): - "Initial instances for model fields may also be instances (refs #7287)" - obj1 = ChoiceOptionModel.objects.create(id=1, name='default') - obj2 = ChoiceOptionModel.objects.create(id=2, name='option 2') - obj3 = ChoiceOptionModel.objects.create(id=3, name='option 3') - self.assertHTMLEqual(ChoiceFieldForm(initial={ - 'choice': obj2, - 'choice_int': obj2, - 'multi_choice': [obj2,obj3], - 'multi_choice_int': ChoiceOptionModel.objects.exclude(name="default"), - }).as_p(), """

-

-

- Hold down "Control", or "Command" on a Mac, to select more than one.

-

- Hold down "Control", or "Command" on a Mac, to select more than one.

""") - - -class FormsModelTestCase(TestCase): - def test_unicode_filename(self): - # FileModel with unicode filename and data ######################### - f = FileForm(data={}, files={'file1': SimpleUploadedFile('我隻氣墊船裝滿晒鱔.txt', 'मेरी मँडराने वाली नाव सर्पमीनों से भरी ह'.encode('utf-8'))}, auto_id=False) - self.assertTrue(f.is_valid()) - self.assertTrue('file1' in f.cleaned_data) - m = FileModel.objects.create(file=f.cleaned_data['file1']) - self.assertEqual(m.file.name, 'tests/\u6211\u96bb\u6c23\u588a\u8239\u88dd\u6eff\u6652\u9c54.txt') - m.delete() - - def test_boundary_conditions(self): - # Boundary conditions on a PostitiveIntegerField ######################### - class BoundaryForm(ModelForm): - class Meta: - model = BoundaryModel - - f = BoundaryForm({'positive_integer': 100}) - self.assertTrue(f.is_valid()) - f = BoundaryForm({'positive_integer': 0}) - self.assertTrue(f.is_valid()) - f = BoundaryForm({'positive_integer': -100}) - self.assertFalse(f.is_valid()) - - def test_formfield_initial(self): - # Formfield initial values ######## - # If the model has default values for some fields, they are used as the formfield - # initial values. - class DefaultsForm(ModelForm): - class Meta: - model = Defaults - - self.assertEqual(DefaultsForm().fields['name'].initial, 'class default value') - self.assertEqual(DefaultsForm().fields['def_date'].initial, datetime.date(1980, 1, 1)) - self.assertEqual(DefaultsForm().fields['value'].initial, 42) - r1 = DefaultsForm()['callable_default'].as_widget() - r2 = DefaultsForm()['callable_default'].as_widget() - self.assertNotEqual(r1, r2) - - # In a ModelForm that is passed an instance, the initial values come from the - # instance's values, not the model's defaults. - foo_instance = Defaults(name='instance value', def_date=datetime.date(1969, 4, 4), value=12) - instance_form = DefaultsForm(instance=foo_instance) - self.assertEqual(instance_form.initial['name'], 'instance value') - self.assertEqual(instance_form.initial['def_date'], datetime.date(1969, 4, 4)) - self.assertEqual(instance_form.initial['value'], 12) - - from django.forms import CharField - - class ExcludingForm(ModelForm): - name = CharField(max_length=255) - - class Meta: - model = Defaults - exclude = ['name', 'callable_default'] - - f = ExcludingForm({'name': 'Hello', 'value': 99, 'def_date': datetime.date(1999, 3, 2)}) - self.assertTrue(f.is_valid()) - self.assertEqual(f.cleaned_data['name'], 'Hello') - obj = f.save() - self.assertEqual(obj.name, 'class default value') - self.assertEqual(obj.value, 99) - self.assertEqual(obj.def_date, datetime.date(1999, 3, 2)) - -class RelatedModelFormTests(TestCase): - def test_invalid_loading_order(self): - """ - Test for issue 10405 - """ - class A(models.Model): - ref = models.ForeignKey("B") - - class Meta: - model=A - - self.assertRaises(ValueError, ModelFormMetaclass, str('Form'), (ModelForm,), {'Meta': Meta}) - - class B(models.Model): - pass - - def test_valid_loading_order(self): - """ - Test for issue 10405 - """ - class A(models.Model): - ref = models.ForeignKey("B") - - class B(models.Model): - pass - - class Meta: - model=A - - self.assertTrue(issubclass(ModelFormMetaclass(str('Form'), (ModelForm,), {'Meta': Meta}), ModelForm)) diff --git a/tests/forms_tests/tests/tests.py b/tests/forms_tests/tests/tests.py new file mode 100644 index 0000000000..be75643b28 --- /dev/null +++ b/tests/forms_tests/tests/tests.py @@ -0,0 +1,218 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, unicode_literals + +import datetime + +from django.core.files.uploadedfile import SimpleUploadedFile +from django.db import models +from django.forms import Form, ModelForm, FileField, ModelChoiceField +from django.forms.models import ModelFormMetaclass +from django.test import TestCase +from django.utils import six + +from ..models import (ChoiceOptionModel, ChoiceFieldModel, FileModel, Group, + BoundaryModel, Defaults, OptionalMultiChoiceModel) + + +class ChoiceFieldForm(ModelForm): + class Meta: + model = ChoiceFieldModel + + +class OptionalMultiChoiceModelForm(ModelForm): + class Meta: + model = OptionalMultiChoiceModel + + +class FileForm(Form): + file1 = FileField() + + +class TestTicket12510(TestCase): + ''' It is not necessary to generate choices for ModelChoiceField (regression test for #12510). ''' + def setUp(self): + self.groups = [Group.objects.create(name=name) for name in 'abc'] + + def test_choices_not_fetched_when_not_rendering(self): + # only one query is required to pull the model from DB + with self.assertNumQueries(1): + field = ModelChoiceField(Group.objects.order_by('-name')) + self.assertEqual('a', field.clean(self.groups[0].pk).name) + + +class TestTicket14567(TestCase): + """ + Check that the return values of ModelMultipleChoiceFields are QuerySets + """ + def test_empty_queryset_return(self): + "If a model's ManyToManyField has blank=True and is saved with no data, a queryset is returned." + form = OptionalMultiChoiceModelForm({'multi_choice_optional': '', 'multi_choice': ['1']}) + self.assertTrue(form.is_valid()) + # Check that the empty value is a QuerySet + self.assertTrue(isinstance(form.cleaned_data['multi_choice_optional'], models.query.QuerySet)) + # While we're at it, test whether a QuerySet is returned if there *is* a value. + self.assertTrue(isinstance(form.cleaned_data['multi_choice'], models.query.QuerySet)) + + +class ModelFormCallableModelDefault(TestCase): + def test_no_empty_option(self): + "If a model's ForeignKey has blank=False and a default, no empty option is created (Refs #10792)." + option = ChoiceOptionModel.objects.create(name='default') + + choices = list(ChoiceFieldForm().fields['choice'].choices) + self.assertEqual(len(choices), 1) + self.assertEqual(choices[0], (option.pk, six.text_type(option))) + + def test_callable_initial_value(self): + "The initial value for a callable default returning a queryset is the pk (refs #13769)" + obj1 = ChoiceOptionModel.objects.create(id=1, name='default') + obj2 = ChoiceOptionModel.objects.create(id=2, name='option 2') + obj3 = ChoiceOptionModel.objects.create(id=3, name='option 3') + self.assertHTMLEqual(ChoiceFieldForm().as_p(), """

+

+

Hold down "Control", or "Command" on a Mac, to select more than one.

+

Hold down "Control", or "Command" on a Mac, to select more than one.

""") + + def test_initial_instance_value(self): + "Initial instances for model fields may also be instances (refs #7287)" + obj1 = ChoiceOptionModel.objects.create(id=1, name='default') + obj2 = ChoiceOptionModel.objects.create(id=2, name='option 2') + obj3 = ChoiceOptionModel.objects.create(id=3, name='option 3') + self.assertHTMLEqual(ChoiceFieldForm(initial={ + 'choice': obj2, + 'choice_int': obj2, + 'multi_choice': [obj2,obj3], + 'multi_choice_int': ChoiceOptionModel.objects.exclude(name="default"), + }).as_p(), """

+

+

+ Hold down "Control", or "Command" on a Mac, to select more than one.

+

+ Hold down "Control", or "Command" on a Mac, to select more than one.

""") + + +class FormsModelTestCase(TestCase): + def test_unicode_filename(self): + # FileModel with unicode filename and data ######################### + f = FileForm(data={}, files={'file1': SimpleUploadedFile('我隻氣墊船裝滿晒鱔.txt', 'मेरी मँडराने वाली नाव सर्पमीनों से भरी ह'.encode('utf-8'))}, auto_id=False) + self.assertTrue(f.is_valid()) + self.assertTrue('file1' in f.cleaned_data) + m = FileModel.objects.create(file=f.cleaned_data['file1']) + self.assertEqual(m.file.name, 'tests/\u6211\u96bb\u6c23\u588a\u8239\u88dd\u6eff\u6652\u9c54.txt') + m.delete() + + def test_boundary_conditions(self): + # Boundary conditions on a PostitiveIntegerField ######################### + class BoundaryForm(ModelForm): + class Meta: + model = BoundaryModel + + f = BoundaryForm({'positive_integer': 100}) + self.assertTrue(f.is_valid()) + f = BoundaryForm({'positive_integer': 0}) + self.assertTrue(f.is_valid()) + f = BoundaryForm({'positive_integer': -100}) + self.assertFalse(f.is_valid()) + + def test_formfield_initial(self): + # Formfield initial values ######## + # If the model has default values for some fields, they are used as the formfield + # initial values. + class DefaultsForm(ModelForm): + class Meta: + model = Defaults + + self.assertEqual(DefaultsForm().fields['name'].initial, 'class default value') + self.assertEqual(DefaultsForm().fields['def_date'].initial, datetime.date(1980, 1, 1)) + self.assertEqual(DefaultsForm().fields['value'].initial, 42) + r1 = DefaultsForm()['callable_default'].as_widget() + r2 = DefaultsForm()['callable_default'].as_widget() + self.assertNotEqual(r1, r2) + + # In a ModelForm that is passed an instance, the initial values come from the + # instance's values, not the model's defaults. + foo_instance = Defaults(name='instance value', def_date=datetime.date(1969, 4, 4), value=12) + instance_form = DefaultsForm(instance=foo_instance) + self.assertEqual(instance_form.initial['name'], 'instance value') + self.assertEqual(instance_form.initial['def_date'], datetime.date(1969, 4, 4)) + self.assertEqual(instance_form.initial['value'], 12) + + from django.forms import CharField + + class ExcludingForm(ModelForm): + name = CharField(max_length=255) + + class Meta: + model = Defaults + exclude = ['name', 'callable_default'] + + f = ExcludingForm({'name': 'Hello', 'value': 99, 'def_date': datetime.date(1999, 3, 2)}) + self.assertTrue(f.is_valid()) + self.assertEqual(f.cleaned_data['name'], 'Hello') + obj = f.save() + self.assertEqual(obj.name, 'class default value') + self.assertEqual(obj.value, 99) + self.assertEqual(obj.def_date, datetime.date(1999, 3, 2)) + +class RelatedModelFormTests(TestCase): + def test_invalid_loading_order(self): + """ + Test for issue 10405 + """ + class A(models.Model): + ref = models.ForeignKey("B") + + class Meta: + model=A + + self.assertRaises(ValueError, ModelFormMetaclass, str('Form'), (ModelForm,), {'Meta': Meta}) + + class B(models.Model): + pass + + def test_valid_loading_order(self): + """ + Test for issue 10405 + """ + class A(models.Model): + ref = models.ForeignKey("B") + + class B(models.Model): + pass + + class Meta: + model=A + + self.assertTrue(issubclass(ModelFormMetaclass(str('Form'), (ModelForm,), {'Meta': Meta}), ModelForm)) diff --git a/tests/test_client/models.py b/tests/test_client/models.py index 0f3cba7e88..e69de29bb2 100644 --- a/tests/test_client/models.py +++ b/tests/test_client/models.py @@ -1,508 +0,0 @@ -# coding: utf-8 -""" -39. Testing using the Test Client - -The test client is a class that can act like a simple -browser for testing purposes. - -It allows the user to compose GET and POST requests, and -obtain the response that the server gave to those requests. -The server Response objects are annotated with the details -of the contexts and templates that were rendered during the -process of serving the request. - -``Client`` objects are stateful - they will retain cookie (and -thus session) details for the lifetime of the ``Client`` instance. - -This is not intended as a replacement for Twill, Selenium, or -other browser automation frameworks - it is here to allow -testing against the contexts and templates produced by a view, -rather than the HTML rendered to the end-user. - -""" -from __future__ import absolute_import, unicode_literals - -from django.conf import settings -from django.core import mail -from django.test import Client, TestCase, RequestFactory -from django.test.utils import override_settings - -from .views import get_view - -@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',)) -class ClientTest(TestCase): - fixtures = ['testdata.json'] - - def test_get_view(self): - "GET a view" - # The data is ignored, but let's check it doesn't crash the system - # anyway. - data = {'var': '\xf2'} - response = self.client.get('/test_client/get_view/', data) - - # Check some response details - self.assertContains(response, 'This is a test') - self.assertEqual(response.context['var'], '\xf2') - self.assertEqual(response.templates[0].name, 'GET Template') - - def test_get_post_view(self): - "GET a view that normally expects POSTs" - response = self.client.get('/test_client/post_view/', {}) - - # Check some response details - self.assertEqual(response.status_code, 200) - self.assertEqual(response.templates[0].name, 'Empty GET Template') - self.assertTemplateUsed(response, 'Empty GET Template') - self.assertTemplateNotUsed(response, 'Empty POST Template') - - def test_empty_post(self): - "POST an empty dictionary to a view" - response = self.client.post('/test_client/post_view/', {}) - - # Check some response details - self.assertEqual(response.status_code, 200) - self.assertEqual(response.templates[0].name, 'Empty POST Template') - self.assertTemplateNotUsed(response, 'Empty GET Template') - self.assertTemplateUsed(response, 'Empty POST Template') - - def test_post(self): - "POST some data to a view" - post_data = { - 'value': 37 - } - response = self.client.post('/test_client/post_view/', post_data) - - # Check some response details - self.assertEqual(response.status_code, 200) - self.assertEqual(response.context['data'], '37') - self.assertEqual(response.templates[0].name, 'POST Template') - self.assertContains(response, 'Data received') - - def test_response_headers(self): - "Check the value of HTTP headers returned in a response" - response = self.client.get("/test_client/header_view/") - - self.assertEqual(response['X-DJANGO-TEST'], 'Slartibartfast') - - def test_raw_post(self): - "POST raw data (with a content type) to a view" - test_doc = """BlinkMalcolm Gladwell""" - response = self.client.post("/test_client/raw_post_view/", test_doc, - content_type="text/xml") - self.assertEqual(response.status_code, 200) - self.assertEqual(response.templates[0].name, "Book template") - self.assertEqual(response.content, b"Blink - Malcolm Gladwell") - - def test_redirect(self): - "GET a URL that redirects elsewhere" - response = self.client.get('/test_client/redirect_view/') - # Check that the response was a 302 (redirect) and that - # assertRedirect() understands to put an implicit http://testserver/ in - # front of non-absolute URLs. - self.assertRedirects(response, '/test_client/get_view/') - - host = 'django.testserver' - client_providing_host = Client(HTTP_HOST=host) - response = client_providing_host.get('/test_client/redirect_view/') - # Check that the response was a 302 (redirect) with absolute URI - self.assertRedirects(response, '/test_client/get_view/', host=host) - - def test_redirect_with_query(self): - "GET a URL that redirects with given GET parameters" - response = self.client.get('/test_client/redirect_view/', {'var': 'value'}) - - # Check if parameters are intact - self.assertRedirects(response, 'http://testserver/test_client/get_view/?var=value') - - def test_permanent_redirect(self): - "GET a URL that redirects permanently elsewhere" - response = self.client.get('/test_client/permanent_redirect_view/') - # Check that the response was a 301 (permanent redirect) - self.assertRedirects(response, 'http://testserver/test_client/get_view/', status_code=301) - - client_providing_host = Client(HTTP_HOST='django.testserver') - response = client_providing_host.get('/test_client/permanent_redirect_view/') - # Check that the response was a 301 (permanent redirect) with absolute URI - self.assertRedirects(response, 'http://django.testserver/test_client/get_view/', status_code=301) - - def test_temporary_redirect(self): - "GET a URL that does a non-permanent redirect" - response = self.client.get('/test_client/temporary_redirect_view/') - # Check that the response was a 302 (non-permanent redirect) - self.assertRedirects(response, 'http://testserver/test_client/get_view/', status_code=302) - - def test_redirect_to_strange_location(self): - "GET a URL that redirects to a non-200 page" - response = self.client.get('/test_client/double_redirect_view/') - - # Check that the response was a 302, and that - # the attempt to get the redirection location returned 301 when retrieved - self.assertRedirects(response, 'http://testserver/test_client/permanent_redirect_view/', target_status_code=301) - - def test_follow_redirect(self): - "A URL that redirects can be followed to termination." - response = self.client.get('/test_client/double_redirect_view/', follow=True) - self.assertRedirects(response, 'http://testserver/test_client/get_view/', status_code=302, target_status_code=200) - self.assertEqual(len(response.redirect_chain), 2) - - def test_redirect_http(self): - "GET a URL that redirects to an http URI" - response = self.client.get('/test_client/http_redirect_view/',follow=True) - self.assertFalse(response.test_was_secure_request) - - def test_redirect_https(self): - "GET a URL that redirects to an https URI" - response = self.client.get('/test_client/https_redirect_view/',follow=True) - self.assertTrue(response.test_was_secure_request) - - def test_notfound_response(self): - "GET a URL that responds as '404:Not Found'" - response = self.client.get('/test_client/bad_view/') - - # Check that the response was a 404, and that the content contains MAGIC - self.assertContains(response, 'MAGIC', status_code=404) - - def test_valid_form(self): - "POST valid data to a form" - post_data = { - 'text': 'Hello World', - 'email': 'foo@example.com', - 'value': 37, - 'single': 'b', - 'multi': ('b','c','e') - } - response = self.client.post('/test_client/form_view/', post_data) - self.assertEqual(response.status_code, 200) - self.assertTemplateUsed(response, "Valid POST Template") - - def test_valid_form_with_hints(self): - "GET a form, providing hints in the GET data" - hints = { - 'text': 'Hello World', - 'multi': ('b','c','e') - } - response = self.client.get('/test_client/form_view/', data=hints) - self.assertEqual(response.status_code, 200) - self.assertTemplateUsed(response, "Form GET Template") - # Check that the multi-value data has been rolled out ok - self.assertContains(response, 'Select a valid choice.', 0) - - def test_incomplete_data_form(self): - "POST incomplete data to a form" - post_data = { - 'text': 'Hello World', - 'value': 37 - } - response = self.client.post('/test_client/form_view/', post_data) - self.assertContains(response, 'This field is required.', 3) - self.assertEqual(response.status_code, 200) - self.assertTemplateUsed(response, "Invalid POST Template") - - self.assertFormError(response, 'form', 'email', 'This field is required.') - self.assertFormError(response, 'form', 'single', 'This field is required.') - self.assertFormError(response, 'form', 'multi', 'This field is required.') - - def test_form_error(self): - "POST erroneous data to a form" - post_data = { - 'text': 'Hello World', - 'email': 'not an email address', - 'value': 37, - 'single': 'b', - 'multi': ('b','c','e') - } - response = self.client.post('/test_client/form_view/', post_data) - self.assertEqual(response.status_code, 200) - self.assertTemplateUsed(response, "Invalid POST Template") - - self.assertFormError(response, 'form', 'email', 'Enter a valid email address.') - - def test_valid_form_with_template(self): - "POST valid data to a form using multiple templates" - post_data = { - 'text': 'Hello World', - 'email': 'foo@example.com', - 'value': 37, - 'single': 'b', - 'multi': ('b','c','e') - } - response = self.client.post('/test_client/form_view_with_template/', post_data) - self.assertContains(response, 'POST data OK') - self.assertTemplateUsed(response, "form_view.html") - self.assertTemplateUsed(response, 'base.html') - self.assertTemplateNotUsed(response, "Valid POST Template") - - def test_incomplete_data_form_with_template(self): - "POST incomplete data to a form using multiple templates" - post_data = { - 'text': 'Hello World', - 'value': 37 - } - response = self.client.post('/test_client/form_view_with_template/', post_data) - self.assertContains(response, 'POST data has errors') - self.assertTemplateUsed(response, 'form_view.html') - self.assertTemplateUsed(response, 'base.html') - self.assertTemplateNotUsed(response, "Invalid POST Template") - - self.assertFormError(response, 'form', 'email', 'This field is required.') - self.assertFormError(response, 'form', 'single', 'This field is required.') - self.assertFormError(response, 'form', 'multi', 'This field is required.') - - def test_form_error_with_template(self): - "POST erroneous data to a form using multiple templates" - post_data = { - 'text': 'Hello World', - 'email': 'not an email address', - 'value': 37, - 'single': 'b', - 'multi': ('b','c','e') - } - response = self.client.post('/test_client/form_view_with_template/', post_data) - self.assertContains(response, 'POST data has errors') - self.assertTemplateUsed(response, "form_view.html") - self.assertTemplateUsed(response, 'base.html') - self.assertTemplateNotUsed(response, "Invalid POST Template") - - self.assertFormError(response, 'form', 'email', 'Enter a valid email address.') - - def test_unknown_page(self): - "GET an invalid URL" - response = self.client.get('/test_client/unknown_view/') - - # Check that the response was a 404 - self.assertEqual(response.status_code, 404) - - def test_url_parameters(self): - "Make sure that URL ;-parameters are not stripped." - response = self.client.get('/test_client/unknown_view/;some-parameter') - - # Check that the path in the response includes it (ignore that it's a 404) - self.assertEqual(response.request['PATH_INFO'], '/test_client/unknown_view/;some-parameter') - - def test_view_with_login(self): - "Request a page that is protected with @login_required" - - # Get the page without logging in. Should result in 302. - response = self.client.get('/test_client/login_protected_view/') - self.assertRedirects(response, 'http://testserver/accounts/login/?next=/test_client/login_protected_view/') - - # Log in - login = self.client.login(username='testclient', password='password') - self.assertTrue(login, 'Could not log in') - - # Request a page that requires a login - response = self.client.get('/test_client/login_protected_view/') - self.assertEqual(response.status_code, 200) - self.assertEqual(response.context['user'].username, 'testclient') - - def test_view_with_method_login(self): - "Request a page that is protected with a @login_required method" - - # Get the page without logging in. Should result in 302. - response = self.client.get('/test_client/login_protected_method_view/') - self.assertRedirects(response, 'http://testserver/accounts/login/?next=/test_client/login_protected_method_view/') - - # Log in - login = self.client.login(username='testclient', password='password') - self.assertTrue(login, 'Could not log in') - - # Request a page that requires a login - response = self.client.get('/test_client/login_protected_method_view/') - self.assertEqual(response.status_code, 200) - self.assertEqual(response.context['user'].username, 'testclient') - - def test_view_with_login_and_custom_redirect(self): - "Request a page that is protected with @login_required(redirect_field_name='redirect_to')" - - # Get the page without logging in. Should result in 302. - response = self.client.get('/test_client/login_protected_view_custom_redirect/') - self.assertRedirects(response, 'http://testserver/accounts/login/?redirect_to=/test_client/login_protected_view_custom_redirect/') - - # Log in - login = self.client.login(username='testclient', password='password') - self.assertTrue(login, 'Could not log in') - - # Request a page that requires a login - response = self.client.get('/test_client/login_protected_view_custom_redirect/') - self.assertEqual(response.status_code, 200) - self.assertEqual(response.context['user'].username, 'testclient') - - def test_view_with_bad_login(self): - "Request a page that is protected with @login, but use bad credentials" - - login = self.client.login(username='otheruser', password='nopassword') - self.assertFalse(login) - - def test_view_with_inactive_login(self): - "Request a page that is protected with @login, but use an inactive login" - - login = self.client.login(username='inactive', password='password') - self.assertFalse(login) - - def test_logout(self): - "Request a logout after logging in" - # Log in - self.client.login(username='testclient', password='password') - - # Request a page that requires a login - response = self.client.get('/test_client/login_protected_view/') - self.assertEqual(response.status_code, 200) - self.assertEqual(response.context['user'].username, 'testclient') - - # Log out - self.client.logout() - - # Request a page that requires a login - response = self.client.get('/test_client/login_protected_view/') - self.assertRedirects(response, 'http://testserver/accounts/login/?next=/test_client/login_protected_view/') - - def test_view_with_permissions(self): - "Request a page that is protected with @permission_required" - - # Get the page without logging in. Should result in 302. - response = self.client.get('/test_client/permission_protected_view/') - self.assertRedirects(response, 'http://testserver/accounts/login/?next=/test_client/permission_protected_view/') - - # Log in - login = self.client.login(username='testclient', password='password') - self.assertTrue(login, 'Could not log in') - - # Log in with wrong permissions. Should result in 302. - response = self.client.get('/test_client/permission_protected_view/') - self.assertRedirects(response, 'http://testserver/accounts/login/?next=/test_client/permission_protected_view/') - - # TODO: Log in with right permissions and request the page again - - def test_view_with_permissions_exception(self): - "Request a page that is protected with @permission_required but raises a exception" - - # Get the page without logging in. Should result in 403. - response = self.client.get('/test_client/permission_protected_view_exception/') - self.assertEqual(response.status_code, 403) - - # Log in - login = self.client.login(username='testclient', password='password') - self.assertTrue(login, 'Could not log in') - - # Log in with wrong permissions. Should result in 403. - response = self.client.get('/test_client/permission_protected_view_exception/') - self.assertEqual(response.status_code, 403) - - def test_view_with_method_permissions(self): - "Request a page that is protected with a @permission_required method" - - # Get the page without logging in. Should result in 302. - response = self.client.get('/test_client/permission_protected_method_view/') - self.assertRedirects(response, 'http://testserver/accounts/login/?next=/test_client/permission_protected_method_view/') - - # Log in - login = self.client.login(username='testclient', password='password') - self.assertTrue(login, 'Could not log in') - - # Log in with wrong permissions. Should result in 302. - response = self.client.get('/test_client/permission_protected_method_view/') - self.assertRedirects(response, 'http://testserver/accounts/login/?next=/test_client/permission_protected_method_view/') - - # TODO: Log in with right permissions and request the page again - - def test_session_modifying_view(self): - "Request a page that modifies the session" - # Session value isn't set initially - try: - self.client.session['tobacconist'] - self.fail("Shouldn't have a session value") - except KeyError: - pass - - from django.contrib.sessions.models import Session - response = self.client.post('/test_client/session_view/') - - # Check that the session was modified - self.assertEqual(self.client.session['tobacconist'], 'hovercraft') - - def test_view_with_exception(self): - "Request a page that is known to throw an error" - self.assertRaises(KeyError, self.client.get, "/test_client/broken_view/") - - #Try the same assertion, a different way - try: - self.client.get('/test_client/broken_view/') - self.fail('Should raise an error') - except KeyError: - pass - - def test_mail_sending(self): - "Test that mail is redirected to a dummy outbox during test setup" - - response = self.client.get('/test_client/mail_sending_view/') - self.assertEqual(response.status_code, 200) - - self.assertEqual(len(mail.outbox), 1) - self.assertEqual(mail.outbox[0].subject, 'Test message') - self.assertEqual(mail.outbox[0].body, 'This is a test email') - self.assertEqual(mail.outbox[0].from_email, 'from@example.com') - self.assertEqual(mail.outbox[0].to[0], 'first@example.com') - self.assertEqual(mail.outbox[0].to[1], 'second@example.com') - - def test_mass_mail_sending(self): - "Test that mass mail is redirected to a dummy outbox during test setup" - - response = self.client.get('/test_client/mass_mail_sending_view/') - self.assertEqual(response.status_code, 200) - - self.assertEqual(len(mail.outbox), 2) - self.assertEqual(mail.outbox[0].subject, 'First Test message') - self.assertEqual(mail.outbox[0].body, 'This is the first test email') - self.assertEqual(mail.outbox[0].from_email, 'from@example.com') - self.assertEqual(mail.outbox[0].to[0], 'first@example.com') - self.assertEqual(mail.outbox[0].to[1], 'second@example.com') - - self.assertEqual(mail.outbox[1].subject, 'Second Test message') - self.assertEqual(mail.outbox[1].body, 'This is the second test email') - self.assertEqual(mail.outbox[1].from_email, 'from@example.com') - self.assertEqual(mail.outbox[1].to[0], 'second@example.com') - self.assertEqual(mail.outbox[1].to[1], 'third@example.com') - -class CSRFEnabledClientTests(TestCase): - def setUp(self): - # Enable the CSRF middleware for this test - self.old_MIDDLEWARE_CLASSES = settings.MIDDLEWARE_CLASSES - csrf_middleware_class = 'django.middleware.csrf.CsrfViewMiddleware' - if csrf_middleware_class not in settings.MIDDLEWARE_CLASSES: - settings.MIDDLEWARE_CLASSES += (csrf_middleware_class,) - - def tearDown(self): - settings.MIDDLEWARE_CLASSES = self.old_MIDDLEWARE_CLASSES - - def test_csrf_enabled_client(self): - "A client can be instantiated with CSRF checks enabled" - csrf_client = Client(enforce_csrf_checks=True) - - # The normal client allows the post - response = self.client.post('/test_client/post_view/', {}) - self.assertEqual(response.status_code, 200) - - # The CSRF-enabled client rejects it - response = csrf_client.post('/test_client/post_view/', {}) - self.assertEqual(response.status_code, 403) - - -class CustomTestClient(Client): - i_am_customized = "Yes" - -class CustomTestClientTest(TestCase): - client_class = CustomTestClient - - def test_custom_test_client(self): - """A test case can specify a custom class for self.client.""" - self.assertEqual(hasattr(self.client, "i_am_customized"), True) - - -class RequestFactoryTest(TestCase): - def test_request_factory(self): - factory = RequestFactory() - request = factory.get('/somewhere/') - response = get_view(request) - - self.assertEqual(response.status_code, 200) - self.assertContains(response, 'This is a test') diff --git a/tests/test_client/tests.py b/tests/test_client/tests.py index 6ad51ac9a0..0f3cba7e88 100644 --- a/tests/test_client/tests.py +++ b/tests/test_client/tests.py @@ -1,21 +1,508 @@ -# Validate that you can override the default test suite +# coding: utf-8 +""" +39. Testing using the Test Client -from django.utils import unittest +The test client is a class that can act like a simple +browser for testing purposes. + +It allows the user to compose GET and POST requests, and +obtain the response that the server gave to those requests. +The server Response objects are annotated with the details +of the contexts and templates that were rendered during the +process of serving the request. + +``Client`` objects are stateful - they will retain cookie (and +thus session) details for the lifetime of the ``Client`` instance. + +This is not intended as a replacement for Twill, Selenium, or +other browser automation frameworks - it is here to allow +testing against the contexts and templates produced by a view, +rather than the HTML rendered to the end-user. + +""" +from __future__ import absolute_import, unicode_literals + +from django.conf import settings +from django.core import mail +from django.test import Client, TestCase, RequestFactory +from django.test.utils import override_settings + +from .views import get_view + +@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',)) +class ClientTest(TestCase): + fixtures = ['testdata.json'] + + def test_get_view(self): + "GET a view" + # The data is ignored, but let's check it doesn't crash the system + # anyway. + data = {'var': '\xf2'} + response = self.client.get('/test_client/get_view/', data) + + # Check some response details + self.assertContains(response, 'This is a test') + self.assertEqual(response.context['var'], '\xf2') + self.assertEqual(response.templates[0].name, 'GET Template') + + def test_get_post_view(self): + "GET a view that normally expects POSTs" + response = self.client.get('/test_client/post_view/', {}) + + # Check some response details + self.assertEqual(response.status_code, 200) + self.assertEqual(response.templates[0].name, 'Empty GET Template') + self.assertTemplateUsed(response, 'Empty GET Template') + self.assertTemplateNotUsed(response, 'Empty POST Template') + + def test_empty_post(self): + "POST an empty dictionary to a view" + response = self.client.post('/test_client/post_view/', {}) + + # Check some response details + self.assertEqual(response.status_code, 200) + self.assertEqual(response.templates[0].name, 'Empty POST Template') + self.assertTemplateNotUsed(response, 'Empty GET Template') + self.assertTemplateUsed(response, 'Empty POST Template') + + def test_post(self): + "POST some data to a view" + post_data = { + 'value': 37 + } + response = self.client.post('/test_client/post_view/', post_data) + + # Check some response details + self.assertEqual(response.status_code, 200) + self.assertEqual(response.context['data'], '37') + self.assertEqual(response.templates[0].name, 'POST Template') + self.assertContains(response, 'Data received') + + def test_response_headers(self): + "Check the value of HTTP headers returned in a response" + response = self.client.get("/test_client/header_view/") + + self.assertEqual(response['X-DJANGO-TEST'], 'Slartibartfast') + + def test_raw_post(self): + "POST raw data (with a content type) to a view" + test_doc = """BlinkMalcolm Gladwell""" + response = self.client.post("/test_client/raw_post_view/", test_doc, + content_type="text/xml") + self.assertEqual(response.status_code, 200) + self.assertEqual(response.templates[0].name, "Book template") + self.assertEqual(response.content, b"Blink - Malcolm Gladwell") + + def test_redirect(self): + "GET a URL that redirects elsewhere" + response = self.client.get('/test_client/redirect_view/') + # Check that the response was a 302 (redirect) and that + # assertRedirect() understands to put an implicit http://testserver/ in + # front of non-absolute URLs. + self.assertRedirects(response, '/test_client/get_view/') + + host = 'django.testserver' + client_providing_host = Client(HTTP_HOST=host) + response = client_providing_host.get('/test_client/redirect_view/') + # Check that the response was a 302 (redirect) with absolute URI + self.assertRedirects(response, '/test_client/get_view/', host=host) + + def test_redirect_with_query(self): + "GET a URL that redirects with given GET parameters" + response = self.client.get('/test_client/redirect_view/', {'var': 'value'}) + + # Check if parameters are intact + self.assertRedirects(response, 'http://testserver/test_client/get_view/?var=value') + + def test_permanent_redirect(self): + "GET a URL that redirects permanently elsewhere" + response = self.client.get('/test_client/permanent_redirect_view/') + # Check that the response was a 301 (permanent redirect) + self.assertRedirects(response, 'http://testserver/test_client/get_view/', status_code=301) + + client_providing_host = Client(HTTP_HOST='django.testserver') + response = client_providing_host.get('/test_client/permanent_redirect_view/') + # Check that the response was a 301 (permanent redirect) with absolute URI + self.assertRedirects(response, 'http://django.testserver/test_client/get_view/', status_code=301) + + def test_temporary_redirect(self): + "GET a URL that does a non-permanent redirect" + response = self.client.get('/test_client/temporary_redirect_view/') + # Check that the response was a 302 (non-permanent redirect) + self.assertRedirects(response, 'http://testserver/test_client/get_view/', status_code=302) + + def test_redirect_to_strange_location(self): + "GET a URL that redirects to a non-200 page" + response = self.client.get('/test_client/double_redirect_view/') + + # Check that the response was a 302, and that + # the attempt to get the redirection location returned 301 when retrieved + self.assertRedirects(response, 'http://testserver/test_client/permanent_redirect_view/', target_status_code=301) + + def test_follow_redirect(self): + "A URL that redirects can be followed to termination." + response = self.client.get('/test_client/double_redirect_view/', follow=True) + self.assertRedirects(response, 'http://testserver/test_client/get_view/', status_code=302, target_status_code=200) + self.assertEqual(len(response.redirect_chain), 2) + + def test_redirect_http(self): + "GET a URL that redirects to an http URI" + response = self.client.get('/test_client/http_redirect_view/',follow=True) + self.assertFalse(response.test_was_secure_request) + + def test_redirect_https(self): + "GET a URL that redirects to an https URI" + response = self.client.get('/test_client/https_redirect_view/',follow=True) + self.assertTrue(response.test_was_secure_request) + + def test_notfound_response(self): + "GET a URL that responds as '404:Not Found'" + response = self.client.get('/test_client/bad_view/') + + # Check that the response was a 404, and that the content contains MAGIC + self.assertContains(response, 'MAGIC', status_code=404) + + def test_valid_form(self): + "POST valid data to a form" + post_data = { + 'text': 'Hello World', + 'email': 'foo@example.com', + 'value': 37, + 'single': 'b', + 'multi': ('b','c','e') + } + response = self.client.post('/test_client/form_view/', post_data) + self.assertEqual(response.status_code, 200) + self.assertTemplateUsed(response, "Valid POST Template") + + def test_valid_form_with_hints(self): + "GET a form, providing hints in the GET data" + hints = { + 'text': 'Hello World', + 'multi': ('b','c','e') + } + response = self.client.get('/test_client/form_view/', data=hints) + self.assertEqual(response.status_code, 200) + self.assertTemplateUsed(response, "Form GET Template") + # Check that the multi-value data has been rolled out ok + self.assertContains(response, 'Select a valid choice.', 0) + + def test_incomplete_data_form(self): + "POST incomplete data to a form" + post_data = { + 'text': 'Hello World', + 'value': 37 + } + response = self.client.post('/test_client/form_view/', post_data) + self.assertContains(response, 'This field is required.', 3) + self.assertEqual(response.status_code, 200) + self.assertTemplateUsed(response, "Invalid POST Template") + + self.assertFormError(response, 'form', 'email', 'This field is required.') + self.assertFormError(response, 'form', 'single', 'This field is required.') + self.assertFormError(response, 'form', 'multi', 'This field is required.') + + def test_form_error(self): + "POST erroneous data to a form" + post_data = { + 'text': 'Hello World', + 'email': 'not an email address', + 'value': 37, + 'single': 'b', + 'multi': ('b','c','e') + } + response = self.client.post('/test_client/form_view/', post_data) + self.assertEqual(response.status_code, 200) + self.assertTemplateUsed(response, "Invalid POST Template") + + self.assertFormError(response, 'form', 'email', 'Enter a valid email address.') + + def test_valid_form_with_template(self): + "POST valid data to a form using multiple templates" + post_data = { + 'text': 'Hello World', + 'email': 'foo@example.com', + 'value': 37, + 'single': 'b', + 'multi': ('b','c','e') + } + response = self.client.post('/test_client/form_view_with_template/', post_data) + self.assertContains(response, 'POST data OK') + self.assertTemplateUsed(response, "form_view.html") + self.assertTemplateUsed(response, 'base.html') + self.assertTemplateNotUsed(response, "Valid POST Template") + + def test_incomplete_data_form_with_template(self): + "POST incomplete data to a form using multiple templates" + post_data = { + 'text': 'Hello World', + 'value': 37 + } + response = self.client.post('/test_client/form_view_with_template/', post_data) + self.assertContains(response, 'POST data has errors') + self.assertTemplateUsed(response, 'form_view.html') + self.assertTemplateUsed(response, 'base.html') + self.assertTemplateNotUsed(response, "Invalid POST Template") + + self.assertFormError(response, 'form', 'email', 'This field is required.') + self.assertFormError(response, 'form', 'single', 'This field is required.') + self.assertFormError(response, 'form', 'multi', 'This field is required.') + + def test_form_error_with_template(self): + "POST erroneous data to a form using multiple templates" + post_data = { + 'text': 'Hello World', + 'email': 'not an email address', + 'value': 37, + 'single': 'b', + 'multi': ('b','c','e') + } + response = self.client.post('/test_client/form_view_with_template/', post_data) + self.assertContains(response, 'POST data has errors') + self.assertTemplateUsed(response, "form_view.html") + self.assertTemplateUsed(response, 'base.html') + self.assertTemplateNotUsed(response, "Invalid POST Template") + + self.assertFormError(response, 'form', 'email', 'Enter a valid email address.') + + def test_unknown_page(self): + "GET an invalid URL" + response = self.client.get('/test_client/unknown_view/') + + # Check that the response was a 404 + self.assertEqual(response.status_code, 404) + + def test_url_parameters(self): + "Make sure that URL ;-parameters are not stripped." + response = self.client.get('/test_client/unknown_view/;some-parameter') + + # Check that the path in the response includes it (ignore that it's a 404) + self.assertEqual(response.request['PATH_INFO'], '/test_client/unknown_view/;some-parameter') + + def test_view_with_login(self): + "Request a page that is protected with @login_required" + + # Get the page without logging in. Should result in 302. + response = self.client.get('/test_client/login_protected_view/') + self.assertRedirects(response, 'http://testserver/accounts/login/?next=/test_client/login_protected_view/') + + # Log in + login = self.client.login(username='testclient', password='password') + self.assertTrue(login, 'Could not log in') + + # Request a page that requires a login + response = self.client.get('/test_client/login_protected_view/') + self.assertEqual(response.status_code, 200) + self.assertEqual(response.context['user'].username, 'testclient') + + def test_view_with_method_login(self): + "Request a page that is protected with a @login_required method" + + # Get the page without logging in. Should result in 302. + response = self.client.get('/test_client/login_protected_method_view/') + self.assertRedirects(response, 'http://testserver/accounts/login/?next=/test_client/login_protected_method_view/') + + # Log in + login = self.client.login(username='testclient', password='password') + self.assertTrue(login, 'Could not log in') + + # Request a page that requires a login + response = self.client.get('/test_client/login_protected_method_view/') + self.assertEqual(response.status_code, 200) + self.assertEqual(response.context['user'].username, 'testclient') + + def test_view_with_login_and_custom_redirect(self): + "Request a page that is protected with @login_required(redirect_field_name='redirect_to')" + + # Get the page without logging in. Should result in 302. + response = self.client.get('/test_client/login_protected_view_custom_redirect/') + self.assertRedirects(response, 'http://testserver/accounts/login/?redirect_to=/test_client/login_protected_view_custom_redirect/') + + # Log in + login = self.client.login(username='testclient', password='password') + self.assertTrue(login, 'Could not log in') + + # Request a page that requires a login + response = self.client.get('/test_client/login_protected_view_custom_redirect/') + self.assertEqual(response.status_code, 200) + self.assertEqual(response.context['user'].username, 'testclient') + + def test_view_with_bad_login(self): + "Request a page that is protected with @login, but use bad credentials" + + login = self.client.login(username='otheruser', password='nopassword') + self.assertFalse(login) + + def test_view_with_inactive_login(self): + "Request a page that is protected with @login, but use an inactive login" + + login = self.client.login(username='inactive', password='password') + self.assertFalse(login) + + def test_logout(self): + "Request a logout after logging in" + # Log in + self.client.login(username='testclient', password='password') + + # Request a page that requires a login + response = self.client.get('/test_client/login_protected_view/') + self.assertEqual(response.status_code, 200) + self.assertEqual(response.context['user'].username, 'testclient') + + # Log out + self.client.logout() + + # Request a page that requires a login + response = self.client.get('/test_client/login_protected_view/') + self.assertRedirects(response, 'http://testserver/accounts/login/?next=/test_client/login_protected_view/') + + def test_view_with_permissions(self): + "Request a page that is protected with @permission_required" + + # Get the page without logging in. Should result in 302. + response = self.client.get('/test_client/permission_protected_view/') + self.assertRedirects(response, 'http://testserver/accounts/login/?next=/test_client/permission_protected_view/') + + # Log in + login = self.client.login(username='testclient', password='password') + self.assertTrue(login, 'Could not log in') + + # Log in with wrong permissions. Should result in 302. + response = self.client.get('/test_client/permission_protected_view/') + self.assertRedirects(response, 'http://testserver/accounts/login/?next=/test_client/permission_protected_view/') + + # TODO: Log in with right permissions and request the page again + + def test_view_with_permissions_exception(self): + "Request a page that is protected with @permission_required but raises a exception" + + # Get the page without logging in. Should result in 403. + response = self.client.get('/test_client/permission_protected_view_exception/') + self.assertEqual(response.status_code, 403) + + # Log in + login = self.client.login(username='testclient', password='password') + self.assertTrue(login, 'Could not log in') + + # Log in with wrong permissions. Should result in 403. + response = self.client.get('/test_client/permission_protected_view_exception/') + self.assertEqual(response.status_code, 403) + + def test_view_with_method_permissions(self): + "Request a page that is protected with a @permission_required method" + + # Get the page without logging in. Should result in 302. + response = self.client.get('/test_client/permission_protected_method_view/') + self.assertRedirects(response, 'http://testserver/accounts/login/?next=/test_client/permission_protected_method_view/') + + # Log in + login = self.client.login(username='testclient', password='password') + self.assertTrue(login, 'Could not log in') + + # Log in with wrong permissions. Should result in 302. + response = self.client.get('/test_client/permission_protected_method_view/') + self.assertRedirects(response, 'http://testserver/accounts/login/?next=/test_client/permission_protected_method_view/') + + # TODO: Log in with right permissions and request the page again + + def test_session_modifying_view(self): + "Request a page that modifies the session" + # Session value isn't set initially + try: + self.client.session['tobacconist'] + self.fail("Shouldn't have a session value") + except KeyError: + pass + + from django.contrib.sessions.models import Session + response = self.client.post('/test_client/session_view/') + + # Check that the session was modified + self.assertEqual(self.client.session['tobacconist'], 'hovercraft') + + def test_view_with_exception(self): + "Request a page that is known to throw an error" + self.assertRaises(KeyError, self.client.get, "/test_client/broken_view/") + + #Try the same assertion, a different way + try: + self.client.get('/test_client/broken_view/') + self.fail('Should raise an error') + except KeyError: + pass + + def test_mail_sending(self): + "Test that mail is redirected to a dummy outbox during test setup" + + response = self.client.get('/test_client/mail_sending_view/') + self.assertEqual(response.status_code, 200) + + self.assertEqual(len(mail.outbox), 1) + self.assertEqual(mail.outbox[0].subject, 'Test message') + self.assertEqual(mail.outbox[0].body, 'This is a test email') + self.assertEqual(mail.outbox[0].from_email, 'from@example.com') + self.assertEqual(mail.outbox[0].to[0], 'first@example.com') + self.assertEqual(mail.outbox[0].to[1], 'second@example.com') + + def test_mass_mail_sending(self): + "Test that mass mail is redirected to a dummy outbox during test setup" + + response = self.client.get('/test_client/mass_mail_sending_view/') + self.assertEqual(response.status_code, 200) + + self.assertEqual(len(mail.outbox), 2) + self.assertEqual(mail.outbox[0].subject, 'First Test message') + self.assertEqual(mail.outbox[0].body, 'This is the first test email') + self.assertEqual(mail.outbox[0].from_email, 'from@example.com') + self.assertEqual(mail.outbox[0].to[0], 'first@example.com') + self.assertEqual(mail.outbox[0].to[1], 'second@example.com') + + self.assertEqual(mail.outbox[1].subject, 'Second Test message') + self.assertEqual(mail.outbox[1].body, 'This is the second test email') + self.assertEqual(mail.outbox[1].from_email, 'from@example.com') + self.assertEqual(mail.outbox[1].to[0], 'second@example.com') + self.assertEqual(mail.outbox[1].to[1], 'third@example.com') + +class CSRFEnabledClientTests(TestCase): + def setUp(self): + # Enable the CSRF middleware for this test + self.old_MIDDLEWARE_CLASSES = settings.MIDDLEWARE_CLASSES + csrf_middleware_class = 'django.middleware.csrf.CsrfViewMiddleware' + if csrf_middleware_class not in settings.MIDDLEWARE_CLASSES: + settings.MIDDLEWARE_CLASSES += (csrf_middleware_class,) + + def tearDown(self): + settings.MIDDLEWARE_CLASSES = self.old_MIDDLEWARE_CLASSES + + def test_csrf_enabled_client(self): + "A client can be instantiated with CSRF checks enabled" + csrf_client = Client(enforce_csrf_checks=True) + + # The normal client allows the post + response = self.client.post('/test_client/post_view/', {}) + self.assertEqual(response.status_code, 200) + + # The CSRF-enabled client rejects it + response = csrf_client.post('/test_client/post_view/', {}) + self.assertEqual(response.status_code, 403) -def suite(): - """ - Define a suite that deliberately ignores a test defined in - this module. - """ +class CustomTestClient(Client): + i_am_customized = "Yes" - testSuite = unittest.TestSuite() - testSuite.addTest(SampleTests('testGoodStuff')) - return testSuite +class CustomTestClientTest(TestCase): + client_class = CustomTestClient -class SampleTests(unittest.TestCase): - def testGoodStuff(self): - pass + def test_custom_test_client(self): + """A test case can specify a custom class for self.client.""" + self.assertEqual(hasattr(self.client, "i_am_customized"), True) - def testBadStuff(self): - self.fail("This test shouldn't run") + +class RequestFactoryTest(TestCase): + def test_request_factory(self): + factory = RequestFactory() + request = factory.get('/somewhere/') + response = get_view(request) + + self.assertEqual(response.status_code, 200) + self.assertContains(response, 'This is a test') diff --git a/tests/test_client_override/__init__.py b/tests/test_client_override/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/test_client_override/models.py b/tests/test_client_override/models.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/test_client_override/tests.py b/tests/test_client_override/tests.py new file mode 100644 index 0000000000..ec97b776d9 --- /dev/null +++ b/tests/test_client_override/tests.py @@ -0,0 +1,21 @@ +from django.utils import unittest + + +def suite(): + """ + Validate that you can override the default test suite + Define a suite that deliberately ignores a test defined in + this module. + """ + + testSuite = unittest.TestSuite() + testSuite.addTest(SampleTests('testGoodStuff')) + return testSuite + + +class SampleTests(unittest.TestCase): + def testGoodStuff(self): + pass + + def testBadStuff(self): + self.fail("This test shouldn't run")