From 4abfa73c1861c53d43f0448726346866b04b9b72 Mon Sep 17 00:00:00 2001 From: Tim Graham Date: Wed, 31 Dec 2014 11:25:11 -0500 Subject: [1.7.x] Renamed tests for util -> utils moves; refs #17627. Backport of 8a9b0c15a6c0ef60dea3ba3042317520bc201206 from master --- tests/admin_util/__init__.py | 0 tests/admin_util/models.py | 64 ------ tests/admin_util/tests.py | 353 ---------------------------------- tests/admin_utils/__init__.py | 0 tests/admin_utils/models.py | 64 ++++++ tests/admin_utils/tests.py | 353 ++++++++++++++++++++++++++++++++++ tests/forms_tests/tests/test_util.py | 91 --------- tests/forms_tests/tests/test_utils.py | 91 +++++++++ 8 files changed, 508 insertions(+), 508 deletions(-) delete mode 100644 tests/admin_util/__init__.py delete mode 100644 tests/admin_util/models.py delete mode 100644 tests/admin_util/tests.py create mode 100644 tests/admin_utils/__init__.py create mode 100644 tests/admin_utils/models.py create mode 100644 tests/admin_utils/tests.py delete mode 100644 tests/forms_tests/tests/test_util.py create mode 100644 tests/forms_tests/tests/test_utils.py diff --git a/tests/admin_util/__init__.py b/tests/admin_util/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/admin_util/models.py b/tests/admin_util/models.py deleted file mode 100644 index 05fb7c4efb..0000000000 --- a/tests/admin_util/models.py +++ /dev/null @@ -1,64 +0,0 @@ -from django.db import models -from django.utils import six -from django.utils.encoding import python_2_unicode_compatible - - -class Article(models.Model): - """ - A simple Article model for testing - """ - site = models.ForeignKey('sites.Site', related_name="admin_articles") - title = models.CharField(max_length=100) - title2 = models.CharField(max_length=100, verbose_name="another name") - created = models.DateTimeField() - - def test_from_model(self): - return "nothing" - - def test_from_model_with_override(self): - return "nothing" - test_from_model_with_override.short_description = "not What you Expect" - - -@python_2_unicode_compatible -class Count(models.Model): - num = models.PositiveSmallIntegerField() - parent = models.ForeignKey('self', null=True) - - def __str__(self): - return six.text_type(self.num) - - -class Event(models.Model): - date = models.DateTimeField(auto_now_add=True) - - -class Location(models.Model): - event = models.OneToOneField(Event, verbose_name='awesome event') - - -class Guest(models.Model): - event = models.OneToOneField(Event) - name = models.CharField(max_length=255) - - class Meta: - verbose_name = "awesome guest" - - -class EventGuide(models.Model): - event = models.ForeignKey(Event, on_delete=models.DO_NOTHING) - - -class Vehicle(models.Model): - pass - - -class VehicleMixin(Vehicle): - vehicle = models.OneToOneField(Vehicle, parent_link=True, related_name='vehicle_%(app_label)s_%(class)s') - - class Meta: - abstract = True - - -class Car(VehicleMixin): - pass diff --git a/tests/admin_util/tests.py b/tests/admin_util/tests.py deleted file mode 100644 index 20980efffa..0000000000 --- a/tests/admin_util/tests.py +++ /dev/null @@ -1,353 +0,0 @@ -from __future__ import unicode_literals - -from datetime import datetime - -from django.conf import settings -from django.contrib import admin -from django.contrib.admin import helpers -from django.contrib.admin.utils import (display_for_field, flatten, - flatten_fieldsets, label_for_field, lookup_field, NestedObjects) -from django.contrib.admin.views.main import EMPTY_CHANGELIST_VALUE -from django.contrib.sites.models import Site -from django.db import models, DEFAULT_DB_ALIAS -from django import forms -from django.test import SimpleTestCase, TestCase -from django.utils.formats import localize -from django.utils.safestring import mark_safe -from django.utils import six - -from .models import Article, Count, Event, Location, EventGuide, Vehicle, Car - - -class NestedObjectsTests(TestCase): - """ - Tests for ``NestedObject`` utility collection. - """ - def setUp(self): - self.n = NestedObjects(using=DEFAULT_DB_ALIAS) - self.objs = [Count.objects.create(num=i) for i in range(5)] - - def _check(self, target): - self.assertEqual(self.n.nested(lambda obj: obj.num), target) - - def _connect(self, i, j): - self.objs[i].parent = self.objs[j] - self.objs[i].save() - - def _collect(self, *indices): - self.n.collect([self.objs[i] for i in indices]) - - def test_unrelated_roots(self): - self._connect(2, 1) - self._collect(0) - self._collect(1) - self._check([0, 1, [2]]) - - def test_siblings(self): - self._connect(1, 0) - self._connect(2, 0) - self._collect(0) - self._check([0, [1, 2]]) - - def test_non_added_parent(self): - self._connect(0, 1) - self._collect(0) - self._check([0]) - - def test_cyclic(self): - self._connect(0, 2) - self._connect(1, 0) - self._connect(2, 1) - self._collect(0) - self._check([0, [1, [2]]]) - - def test_queries(self): - self._connect(1, 0) - self._connect(2, 0) - # 1 query to fetch all children of 0 (1 and 2) - # 1 query to fetch all children of 1 and 2 (none) - # Should not require additional queries to populate the nested graph. - self.assertNumQueries(2, self._collect, 0) - - def test_on_delete_do_nothing(self): - """ - Check that the nested collector doesn't query for DO_NOTHING objects. - """ - n = NestedObjects(using=DEFAULT_DB_ALIAS) - objs = [Event.objects.create()] - EventGuide.objects.create(event=objs[0]) - with self.assertNumQueries(2): - # One for Location, one for Guest, and no query for EventGuide - n.collect(objs) - - def test_relation_on_abstract(self): - """ - #21846 -- Check that `NestedObjects.collect()` doesn't trip - (AttributeError) on the special notation for relations on abstract - models (related_name that contains %(app_label)s and/or %(class)s). - """ - n = NestedObjects(using=DEFAULT_DB_ALIAS) - Car.objects.create() - n.collect([Vehicle.objects.first()]) - - -class UtilTests(SimpleTestCase): - def test_values_from_lookup_field(self): - """ - Regression test for #12654: lookup_field - """ - SITE_NAME = 'example.com' - TITLE_TEXT = 'Some title' - CREATED_DATE = datetime.min - ADMIN_METHOD = 'admin method' - SIMPLE_FUNCTION = 'function' - INSTANCE_ATTRIBUTE = 'attr' - - class MockModelAdmin(object): - def get_admin_value(self, obj): - return ADMIN_METHOD - - simple_function = lambda obj: SIMPLE_FUNCTION - - article = Article( - site=Site(domain=SITE_NAME), - title=TITLE_TEXT, - created=CREATED_DATE, - ) - article.non_field = INSTANCE_ATTRIBUTE - - verifications = ( - ('site', SITE_NAME), - ('created', localize(CREATED_DATE)), - ('title', TITLE_TEXT), - ('get_admin_value', ADMIN_METHOD), - (simple_function, SIMPLE_FUNCTION), - ('test_from_model', article.test_from_model()), - ('non_field', INSTANCE_ATTRIBUTE) - ) - - mock_admin = MockModelAdmin() - for name, value in verifications: - field, attr, resolved_value = lookup_field(name, article, mock_admin) - - if field is not None: - resolved_value = display_for_field(resolved_value, field) - - self.assertEqual(value, resolved_value) - - def test_null_display_for_field(self): - """ - Regression test for #12550: display_for_field should handle None - value. - """ - display_value = display_for_field(None, models.CharField()) - self.assertEqual(display_value, EMPTY_CHANGELIST_VALUE) - - display_value = display_for_field(None, models.CharField( - choices=( - (None, "test_none"), - ) - )) - self.assertEqual(display_value, "test_none") - - display_value = display_for_field(None, models.DateField()) - self.assertEqual(display_value, EMPTY_CHANGELIST_VALUE) - - display_value = display_for_field(None, models.TimeField()) - self.assertEqual(display_value, EMPTY_CHANGELIST_VALUE) - - # Regression test for #13071: NullBooleanField has special - # handling. - display_value = display_for_field(None, models.NullBooleanField()) - expected = 'None' % settings.STATIC_URL - self.assertHTMLEqual(display_value, expected) - - display_value = display_for_field(None, models.DecimalField()) - self.assertEqual(display_value, EMPTY_CHANGELIST_VALUE) - - display_value = display_for_field(None, models.FloatField()) - self.assertEqual(display_value, EMPTY_CHANGELIST_VALUE) - - def test_label_for_field(self): - """ - Tests for label_for_field - """ - self.assertEqual( - label_for_field("title", Article), - "title" - ) - self.assertEqual( - label_for_field("title2", Article), - "another name" - ) - self.assertEqual( - label_for_field("title2", Article, return_attr=True), - ("another name", None) - ) - - self.assertEqual( - label_for_field("__unicode__", Article), - "article" - ) - self.assertEqual( - label_for_field("__str__", Article), - str("article") - ) - - self.assertRaises( - AttributeError, - lambda: label_for_field("unknown", Article) - ) - - def test_callable(obj): - return "nothing" - self.assertEqual( - label_for_field(test_callable, Article), - "Test callable" - ) - self.assertEqual( - label_for_field(test_callable, Article, return_attr=True), - ("Test callable", test_callable) - ) - - self.assertEqual( - label_for_field("test_from_model", Article), - "Test from model" - ) - self.assertEqual( - label_for_field("test_from_model", Article, return_attr=True), - ("Test from model", Article.test_from_model) - ) - self.assertEqual( - label_for_field("test_from_model_with_override", Article), - "not What you Expect" - ) - - self.assertEqual( - label_for_field(lambda x: "nothing", Article), - "--" - ) - - class MockModelAdmin(object): - def test_from_model(self, obj): - return "nothing" - test_from_model.short_description = "not Really the Model" - - self.assertEqual( - label_for_field("test_from_model", Article, model_admin=MockModelAdmin), - "not Really the Model" - ) - self.assertEqual( - label_for_field("test_from_model", Article, - model_admin=MockModelAdmin, - return_attr=True), - ("not Really the Model", MockModelAdmin.test_from_model) - ) - - def test_label_for_property(self): - # NOTE: cannot use @property decorator, because of - # AttributeError: 'property' object has no attribute 'short_description' - class MockModelAdmin(object): - def my_property(self): - return "this if from property" - my_property.short_description = 'property short description' - test_from_property = property(my_property) - - self.assertEqual( - label_for_field("test_from_property", Article, model_admin=MockModelAdmin), - 'property short description' - ) - - def test_related_name(self): - """ - Regression test for #13963 - """ - self.assertEqual( - label_for_field('location', Event, return_attr=True), - ('location', None), - ) - self.assertEqual( - label_for_field('event', Location, return_attr=True), - ('awesome event', None), - ) - self.assertEqual( - label_for_field('guest', Event, return_attr=True), - ('awesome guest', None), - ) - - def test_logentry_unicode(self): - """ - Regression test for #15661 - """ - log_entry = admin.models.LogEntry() - - log_entry.action_flag = admin.models.ADDITION - self.assertTrue( - six.text_type(log_entry).startswith('Added ') - ) - - log_entry.action_flag = admin.models.CHANGE - self.assertTrue( - six.text_type(log_entry).startswith('Changed ') - ) - - log_entry.action_flag = admin.models.DELETION - self.assertTrue( - six.text_type(log_entry).startswith('Deleted ') - ) - - # Make sure custom action_flags works - log_entry.action_flag = 4 - self.assertEqual(six.text_type(log_entry), 'LogEntry Object') - - def test_safestring_in_field_label(self): - # safestring should not be escaped - class MyForm(forms.Form): - text = forms.CharField(label=mark_safe('text')) - cb = forms.BooleanField(label=mark_safe('cb')) - - form = MyForm() - self.assertHTMLEqual(helpers.AdminField(form, 'text', is_first=False).label_tag(), - '') - self.assertHTMLEqual(helpers.AdminField(form, 'cb', is_first=False).label_tag(), - '') - - # normal strings needs to be escaped - class MyForm(forms.Form): - text = forms.CharField(label='&text') - cb = forms.BooleanField(label='&cb') - - form = MyForm() - self.assertHTMLEqual(helpers.AdminField(form, 'text', is_first=False).label_tag(), - '') - self.assertHTMLEqual(helpers.AdminField(form, 'cb', is_first=False).label_tag(), - '') - - def test_flatten(self): - flat_all = ['url', 'title', 'content', 'sites'] - inputs = ( - ((), []), - (('url', 'title', ('content', 'sites')), flat_all), - (('url', 'title', 'content', 'sites'), flat_all), - ((('url', 'title'), ('content', 'sites')), flat_all) - ) - for orig, expected in inputs: - self.assertEqual(flatten(orig), expected) - - def test_flatten_fieldsets(self): - """ - Regression test for #18051 - """ - fieldsets = ( - (None, { - 'fields': ('url', 'title', ('content', 'sites')) - }), - ) - self.assertEqual(flatten_fieldsets(fieldsets), ['url', 'title', 'content', 'sites']) - - fieldsets = ( - (None, { - 'fields': ('url', 'title', ['content', 'sites']) - }), - ) - self.assertEqual(flatten_fieldsets(fieldsets), ['url', 'title', 'content', 'sites']) diff --git a/tests/admin_utils/__init__.py b/tests/admin_utils/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/admin_utils/models.py b/tests/admin_utils/models.py new file mode 100644 index 0000000000..05fb7c4efb --- /dev/null +++ b/tests/admin_utils/models.py @@ -0,0 +1,64 @@ +from django.db import models +from django.utils import six +from django.utils.encoding import python_2_unicode_compatible + + +class Article(models.Model): + """ + A simple Article model for testing + """ + site = models.ForeignKey('sites.Site', related_name="admin_articles") + title = models.CharField(max_length=100) + title2 = models.CharField(max_length=100, verbose_name="another name") + created = models.DateTimeField() + + def test_from_model(self): + return "nothing" + + def test_from_model_with_override(self): + return "nothing" + test_from_model_with_override.short_description = "not What you Expect" + + +@python_2_unicode_compatible +class Count(models.Model): + num = models.PositiveSmallIntegerField() + parent = models.ForeignKey('self', null=True) + + def __str__(self): + return six.text_type(self.num) + + +class Event(models.Model): + date = models.DateTimeField(auto_now_add=True) + + +class Location(models.Model): + event = models.OneToOneField(Event, verbose_name='awesome event') + + +class Guest(models.Model): + event = models.OneToOneField(Event) + name = models.CharField(max_length=255) + + class Meta: + verbose_name = "awesome guest" + + +class EventGuide(models.Model): + event = models.ForeignKey(Event, on_delete=models.DO_NOTHING) + + +class Vehicle(models.Model): + pass + + +class VehicleMixin(Vehicle): + vehicle = models.OneToOneField(Vehicle, parent_link=True, related_name='vehicle_%(app_label)s_%(class)s') + + class Meta: + abstract = True + + +class Car(VehicleMixin): + pass diff --git a/tests/admin_utils/tests.py b/tests/admin_utils/tests.py new file mode 100644 index 0000000000..3318981a23 --- /dev/null +++ b/tests/admin_utils/tests.py @@ -0,0 +1,353 @@ +from __future__ import unicode_literals + +from datetime import datetime + +from django.conf import settings +from django.contrib import admin +from django.contrib.admin import helpers +from django.contrib.admin.utils import (display_for_field, flatten, + flatten_fieldsets, label_for_field, lookup_field, NestedObjects) +from django.contrib.admin.views.main import EMPTY_CHANGELIST_VALUE +from django.contrib.sites.models import Site +from django.db import models, DEFAULT_DB_ALIAS +from django import forms +from django.test import SimpleTestCase, TestCase +from django.utils.formats import localize +from django.utils.safestring import mark_safe +from django.utils import six + +from .models import Article, Count, Event, Location, EventGuide, Vehicle, Car + + +class NestedObjectsTests(TestCase): + """ + Tests for ``NestedObject`` utility collection. + """ + def setUp(self): + self.n = NestedObjects(using=DEFAULT_DB_ALIAS) + self.objs = [Count.objects.create(num=i) for i in range(5)] + + def _check(self, target): + self.assertEqual(self.n.nested(lambda obj: obj.num), target) + + def _connect(self, i, j): + self.objs[i].parent = self.objs[j] + self.objs[i].save() + + def _collect(self, *indices): + self.n.collect([self.objs[i] for i in indices]) + + def test_unrelated_roots(self): + self._connect(2, 1) + self._collect(0) + self._collect(1) + self._check([0, 1, [2]]) + + def test_siblings(self): + self._connect(1, 0) + self._connect(2, 0) + self._collect(0) + self._check([0, [1, 2]]) + + def test_non_added_parent(self): + self._connect(0, 1) + self._collect(0) + self._check([0]) + + def test_cyclic(self): + self._connect(0, 2) + self._connect(1, 0) + self._connect(2, 1) + self._collect(0) + self._check([0, [1, [2]]]) + + def test_queries(self): + self._connect(1, 0) + self._connect(2, 0) + # 1 query to fetch all children of 0 (1 and 2) + # 1 query to fetch all children of 1 and 2 (none) + # Should not require additional queries to populate the nested graph. + self.assertNumQueries(2, self._collect, 0) + + def test_on_delete_do_nothing(self): + """ + Check that the nested collector doesn't query for DO_NOTHING objects. + """ + n = NestedObjects(using=DEFAULT_DB_ALIAS) + objs = [Event.objects.create()] + EventGuide.objects.create(event=objs[0]) + with self.assertNumQueries(2): + # One for Location, one for Guest, and no query for EventGuide + n.collect(objs) + + def test_relation_on_abstract(self): + """ + #21846 -- Check that `NestedObjects.collect()` doesn't trip + (AttributeError) on the special notation for relations on abstract + models (related_name that contains %(app_label)s and/or %(class)s). + """ + n = NestedObjects(using=DEFAULT_DB_ALIAS) + Car.objects.create() + n.collect([Vehicle.objects.first()]) + + +class UtilsTests(SimpleTestCase): + def test_values_from_lookup_field(self): + """ + Regression test for #12654: lookup_field + """ + SITE_NAME = 'example.com' + TITLE_TEXT = 'Some title' + CREATED_DATE = datetime.min + ADMIN_METHOD = 'admin method' + SIMPLE_FUNCTION = 'function' + INSTANCE_ATTRIBUTE = 'attr' + + class MockModelAdmin(object): + def get_admin_value(self, obj): + return ADMIN_METHOD + + simple_function = lambda obj: SIMPLE_FUNCTION + + article = Article( + site=Site(domain=SITE_NAME), + title=TITLE_TEXT, + created=CREATED_DATE, + ) + article.non_field = INSTANCE_ATTRIBUTE + + verifications = ( + ('site', SITE_NAME), + ('created', localize(CREATED_DATE)), + ('title', TITLE_TEXT), + ('get_admin_value', ADMIN_METHOD), + (simple_function, SIMPLE_FUNCTION), + ('test_from_model', article.test_from_model()), + ('non_field', INSTANCE_ATTRIBUTE) + ) + + mock_admin = MockModelAdmin() + for name, value in verifications: + field, attr, resolved_value = lookup_field(name, article, mock_admin) + + if field is not None: + resolved_value = display_for_field(resolved_value, field) + + self.assertEqual(value, resolved_value) + + def test_null_display_for_field(self): + """ + Regression test for #12550: display_for_field should handle None + value. + """ + display_value = display_for_field(None, models.CharField()) + self.assertEqual(display_value, EMPTY_CHANGELIST_VALUE) + + display_value = display_for_field(None, models.CharField( + choices=( + (None, "test_none"), + ) + )) + self.assertEqual(display_value, "test_none") + + display_value = display_for_field(None, models.DateField()) + self.assertEqual(display_value, EMPTY_CHANGELIST_VALUE) + + display_value = display_for_field(None, models.TimeField()) + self.assertEqual(display_value, EMPTY_CHANGELIST_VALUE) + + # Regression test for #13071: NullBooleanField has special + # handling. + display_value = display_for_field(None, models.NullBooleanField()) + expected = 'None' % settings.STATIC_URL + self.assertHTMLEqual(display_value, expected) + + display_value = display_for_field(None, models.DecimalField()) + self.assertEqual(display_value, EMPTY_CHANGELIST_VALUE) + + display_value = display_for_field(None, models.FloatField()) + self.assertEqual(display_value, EMPTY_CHANGELIST_VALUE) + + def test_label_for_field(self): + """ + Tests for label_for_field + """ + self.assertEqual( + label_for_field("title", Article), + "title" + ) + self.assertEqual( + label_for_field("title2", Article), + "another name" + ) + self.assertEqual( + label_for_field("title2", Article, return_attr=True), + ("another name", None) + ) + + self.assertEqual( + label_for_field("__unicode__", Article), + "article" + ) + self.assertEqual( + label_for_field("__str__", Article), + str("article") + ) + + self.assertRaises( + AttributeError, + lambda: label_for_field("unknown", Article) + ) + + def test_callable(obj): + return "nothing" + self.assertEqual( + label_for_field(test_callable, Article), + "Test callable" + ) + self.assertEqual( + label_for_field(test_callable, Article, return_attr=True), + ("Test callable", test_callable) + ) + + self.assertEqual( + label_for_field("test_from_model", Article), + "Test from model" + ) + self.assertEqual( + label_for_field("test_from_model", Article, return_attr=True), + ("Test from model", Article.test_from_model) + ) + self.assertEqual( + label_for_field("test_from_model_with_override", Article), + "not What you Expect" + ) + + self.assertEqual( + label_for_field(lambda x: "nothing", Article), + "--" + ) + + class MockModelAdmin(object): + def test_from_model(self, obj): + return "nothing" + test_from_model.short_description = "not Really the Model" + + self.assertEqual( + label_for_field("test_from_model", Article, model_admin=MockModelAdmin), + "not Really the Model" + ) + self.assertEqual( + label_for_field("test_from_model", Article, + model_admin=MockModelAdmin, + return_attr=True), + ("not Really the Model", MockModelAdmin.test_from_model) + ) + + def test_label_for_property(self): + # NOTE: cannot use @property decorator, because of + # AttributeError: 'property' object has no attribute 'short_description' + class MockModelAdmin(object): + def my_property(self): + return "this if from property" + my_property.short_description = 'property short description' + test_from_property = property(my_property) + + self.assertEqual( + label_for_field("test_from_property", Article, model_admin=MockModelAdmin), + 'property short description' + ) + + def test_related_name(self): + """ + Regression test for #13963 + """ + self.assertEqual( + label_for_field('location', Event, return_attr=True), + ('location', None), + ) + self.assertEqual( + label_for_field('event', Location, return_attr=True), + ('awesome event', None), + ) + self.assertEqual( + label_for_field('guest', Event, return_attr=True), + ('awesome guest', None), + ) + + def test_logentry_unicode(self): + """ + Regression test for #15661 + """ + log_entry = admin.models.LogEntry() + + log_entry.action_flag = admin.models.ADDITION + self.assertTrue( + six.text_type(log_entry).startswith('Added ') + ) + + log_entry.action_flag = admin.models.CHANGE + self.assertTrue( + six.text_type(log_entry).startswith('Changed ') + ) + + log_entry.action_flag = admin.models.DELETION + self.assertTrue( + six.text_type(log_entry).startswith('Deleted ') + ) + + # Make sure custom action_flags works + log_entry.action_flag = 4 + self.assertEqual(six.text_type(log_entry), 'LogEntry Object') + + def test_safestring_in_field_label(self): + # safestring should not be escaped + class MyForm(forms.Form): + text = forms.CharField(label=mark_safe('text')) + cb = forms.BooleanField(label=mark_safe('cb')) + + form = MyForm() + self.assertHTMLEqual(helpers.AdminField(form, 'text', is_first=False).label_tag(), + '') + self.assertHTMLEqual(helpers.AdminField(form, 'cb', is_first=False).label_tag(), + '') + + # normal strings needs to be escaped + class MyForm(forms.Form): + text = forms.CharField(label='&text') + cb = forms.BooleanField(label='&cb') + + form = MyForm() + self.assertHTMLEqual(helpers.AdminField(form, 'text', is_first=False).label_tag(), + '') + self.assertHTMLEqual(helpers.AdminField(form, 'cb', is_first=False).label_tag(), + '') + + def test_flatten(self): + flat_all = ['url', 'title', 'content', 'sites'] + inputs = ( + ((), []), + (('url', 'title', ('content', 'sites')), flat_all), + (('url', 'title', 'content', 'sites'), flat_all), + ((('url', 'title'), ('content', 'sites')), flat_all) + ) + for orig, expected in inputs: + self.assertEqual(flatten(orig), expected) + + def test_flatten_fieldsets(self): + """ + Regression test for #18051 + """ + fieldsets = ( + (None, { + 'fields': ('url', 'title', ('content', 'sites')) + }), + ) + self.assertEqual(flatten_fieldsets(fieldsets), ['url', 'title', 'content', 'sites']) + + fieldsets = ( + (None, { + 'fields': ('url', 'title', ['content', 'sites']) + }), + ) + self.assertEqual(flatten_fieldsets(fieldsets), ['url', 'title', 'content', 'sites']) diff --git a/tests/forms_tests/tests/test_util.py b/tests/forms_tests/tests/test_util.py deleted file mode 100644 index c2dbc5ba8a..0000000000 --- a/tests/forms_tests/tests/test_util.py +++ /dev/null @@ -1,91 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -import copy - -from django.core.exceptions import ValidationError -from django.forms.utils import flatatt, ErrorDict, ErrorList -from django.test import TestCase -from django.utils.safestring import mark_safe -from django.utils import six -from django.utils.translation import ugettext_lazy -from django.utils.encoding import python_2_unicode_compatible - - -class FormsUtilTestCase(TestCase): - # Tests for forms/utils.py module. - - def test_flatatt(self): - ########### - # flatatt # - ########### - - self.assertEqual(flatatt({'id': "header"}), ' id="header"') - self.assertEqual(flatatt({'class': "news", 'title': "Read this"}), ' class="news" title="Read this"') - self.assertEqual(flatatt({}), '') - - def test_validation_error(self): - ################### - # ValidationError # - ################### - - # Can take a string. - self.assertHTMLEqual(str(ErrorList(ValidationError("There was an error.").messages)), - '') - - # Can take a unicode string. - self.assertHTMLEqual(six.text_type(ErrorList(ValidationError("Not \u03C0.").messages)), - '') - - # Can take a lazy string. - self.assertHTMLEqual(str(ErrorList(ValidationError(ugettext_lazy("Error.")).messages)), - '') - - # Can take a list. - self.assertHTMLEqual(str(ErrorList(ValidationError(["Error one.", "Error two."]).messages)), - '') - - # Can take a mixture in a list. - self.assertHTMLEqual(str(ErrorList(ValidationError(["First error.", "Not \u03C0.", ugettext_lazy("Error.")]).messages)), - '') - - @python_2_unicode_compatible - class VeryBadError: - def __str__(self): - return "A very bad error." - - # Can take a non-string. - self.assertHTMLEqual(str(ErrorList(ValidationError(VeryBadError()).messages)), - '') - - # Escapes non-safe input but not input marked safe. - example = 'Example of link: example' - self.assertHTMLEqual(str(ErrorList([example])), - '') - self.assertHTMLEqual(str(ErrorList([mark_safe(example)])), - '') - self.assertHTMLEqual(str(ErrorDict({'name': example})), - '') - self.assertHTMLEqual(str(ErrorDict({'name': mark_safe(example)})), - '') - - def test_error_dict_copy(self): - e = ErrorDict() - e['__all__'] = ErrorList([ - ValidationError( - message='message %(i)s', - params={'i': 1}, - ), - ValidationError( - message='message %(i)s', - params={'i': 2}, - ), - ]) - - e_copy = copy.copy(e) - self.assertEqual(e, e_copy) - self.assertEqual(e.as_data(), e_copy.as_data()) - - e_deepcopy = copy.deepcopy(e) - self.assertEqual(e, e_deepcopy) - self.assertEqual(e.as_data(), e_copy.as_data()) diff --git a/tests/forms_tests/tests/test_utils.py b/tests/forms_tests/tests/test_utils.py new file mode 100644 index 0000000000..f909bb9893 --- /dev/null +++ b/tests/forms_tests/tests/test_utils.py @@ -0,0 +1,91 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +import copy + +from django.core.exceptions import ValidationError +from django.forms.utils import flatatt, ErrorDict, ErrorList +from django.test import TestCase +from django.utils.safestring import mark_safe +from django.utils import six +from django.utils.translation import ugettext_lazy +from django.utils.encoding import python_2_unicode_compatible + + +class FormsUtilsTestCase(TestCase): + # Tests for forms/utils.py module. + + def test_flatatt(self): + ########### + # flatatt # + ########### + + self.assertEqual(flatatt({'id': "header"}), ' id="header"') + self.assertEqual(flatatt({'class': "news", 'title': "Read this"}), ' class="news" title="Read this"') + self.assertEqual(flatatt({}), '') + + def test_validation_error(self): + ################### + # ValidationError # + ################### + + # Can take a string. + self.assertHTMLEqual(str(ErrorList(ValidationError("There was an error.").messages)), + '') + + # Can take a unicode string. + self.assertHTMLEqual(six.text_type(ErrorList(ValidationError("Not \u03C0.").messages)), + '') + + # Can take a lazy string. + self.assertHTMLEqual(str(ErrorList(ValidationError(ugettext_lazy("Error.")).messages)), + '') + + # Can take a list. + self.assertHTMLEqual(str(ErrorList(ValidationError(["Error one.", "Error two."]).messages)), + '') + + # Can take a mixture in a list. + self.assertHTMLEqual(str(ErrorList(ValidationError(["First error.", "Not \u03C0.", ugettext_lazy("Error.")]).messages)), + '') + + @python_2_unicode_compatible + class VeryBadError: + def __str__(self): + return "A very bad error." + + # Can take a non-string. + self.assertHTMLEqual(str(ErrorList(ValidationError(VeryBadError()).messages)), + '') + + # Escapes non-safe input but not input marked safe. + example = 'Example of link: example' + self.assertHTMLEqual(str(ErrorList([example])), + '') + self.assertHTMLEqual(str(ErrorList([mark_safe(example)])), + '') + self.assertHTMLEqual(str(ErrorDict({'name': example})), + '') + self.assertHTMLEqual(str(ErrorDict({'name': mark_safe(example)})), + '') + + def test_error_dict_copy(self): + e = ErrorDict() + e['__all__'] = ErrorList([ + ValidationError( + message='message %(i)s', + params={'i': 1}, + ), + ValidationError( + message='message %(i)s', + params={'i': 2}, + ), + ]) + + e_copy = copy.copy(e) + self.assertEqual(e, e_copy) + self.assertEqual(e.as_data(), e_copy.as_data()) + + e_deepcopy = copy.deepcopy(e) + self.assertEqual(e, e_deepcopy) + self.assertEqual(e.as_data(), e_copy.as_data()) -- cgit v1.3