diff options
| author | Andrew Godwin <andrew@aeracode.org> | 2012-10-26 08:41:13 +0100 |
|---|---|---|
| committer | Andrew Godwin <andrew@aeracode.org> | 2012-10-26 08:41:13 +0100 |
| commit | 6a632e04578776e877adc5e2dc53f008c890a0d4 (patch) | |
| tree | aa47200fb63adf44609066a45601bd3b8768ec1c /tests | |
| parent | a589fdff81ab36c57ff0a1003e60ee0dd55f3a88 (diff) | |
| parent | fabe9c9e5f0a437b5389faaf469ce53091abd3cf (diff) | |
Merge branch 'master' into schema-alteration
Conflicts:
django/db/backends/__init__.py
django/db/models/fields/related.py
django/db/models/options.py
Diffstat (limited to 'tests')
182 files changed, 2206 insertions, 6418 deletions
diff --git a/tests/.coveragerc b/tests/.coveragerc new file mode 100644 index 0000000000..b979e94c58 --- /dev/null +++ b/tests/.coveragerc @@ -0,0 +1,5 @@ +[run] +omit = runtests,test_sqlite,regressiontests*,modeltests*,*/django/contrib/*/tests*,*/django/utils/unittest*,*/django/utils/simplejson*,*/django/utils/importlib.py,*/django/test/_doctest.py,*/django/core/servers/fastcgi.py,*/django/utils/autoreload.py,*/django/utils/dictconfig.py + +[html] +directory = coverage_html diff --git a/tests/modeltests/basic/tests.py b/tests/modeltests/basic/tests.py index 6ec9ca03af..ebd70d14d9 100644 --- a/tests/modeltests/basic/tests.py +++ b/tests/modeltests/basic/tests.py @@ -259,9 +259,8 @@ class ModelTest(TestCase): "datetime.datetime(2005, 7, 28, 0, 0)"]) # dates() requires valid arguments. - six.assertRaisesRegex(self, + self.assertRaises( TypeError, - "dates\(\) takes at least 3 arguments \(1 given\)", Article.objects.dates, ) diff --git a/tests/modeltests/delete/models.py b/tests/modeltests/delete/models.py index e0cec426ea..65d4e6f725 100644 --- a/tests/modeltests/delete/models.py +++ b/tests/modeltests/delete/models.py @@ -95,7 +95,7 @@ class MRNull(models.Model): class Avatar(models.Model): - pass + desc = models.TextField(null=True) class User(models.Model): @@ -108,3 +108,21 @@ class HiddenUser(models.Model): class HiddenUserProfile(models.Model): user = models.ForeignKey(HiddenUser) + +class M2MTo(models.Model): + pass + +class M2MFrom(models.Model): + m2m = models.ManyToManyField(M2MTo) + +class Parent(models.Model): + pass + +class Child(Parent): + pass + +class Base(models.Model): + pass + +class RelToBase(models.Model): + base = models.ForeignKey(Base, on_delete=models.DO_NOTHING) diff --git a/tests/modeltests/delete/tests.py b/tests/modeltests/delete/tests.py index 26f2fd52c1..20b815c33d 100644 --- a/tests/modeltests/delete/tests.py +++ b/tests/modeltests/delete/tests.py @@ -1,11 +1,12 @@ from __future__ import absolute_import -from django.db import models, IntegrityError +from django.db import models, IntegrityError, connection from django.test import TestCase, skipUnlessDBFeature, skipIfDBFeature from django.utils.six.moves import xrange from .models import (R, RChild, S, T, U, A, M, MR, MRNull, - create_a, get_default_r, User, Avatar, HiddenUser, HiddenUserProfile) + create_a, get_default_r, User, Avatar, HiddenUser, HiddenUserProfile, + M2MTo, M2MFrom, Parent, Child, Base) class OnDeleteTests(TestCase): @@ -74,6 +75,16 @@ class OnDeleteTests(TestCase): self.assertEqual(replacement_r, a.donothing) models.signals.pre_delete.disconnect(check_do_nothing) + def test_do_nothing_qscount(self): + """ + Test that a models.DO_NOTHING relation doesn't trigger a query. + """ + b = Base.objects.create() + with self.assertNumQueries(1): + # RelToBase should not be queried. + b.delete() + self.assertEqual(Base.objects.count(), 0) + def test_inheritance_cascade_up(self): child = RChild.objects.create() child.delete() @@ -229,16 +240,34 @@ class DeletionTests(TestCase): # 1 query to delete the avatar # The important thing is that when we can defer constraint checks there # is no need to do an UPDATE on User.avatar to null it out. + + # Attach a signal to make sure we will not do fast_deletes. + calls = [] + def noop(*args, **kwargs): + calls.append('') + models.signals.post_delete.connect(noop, sender=User) + self.assertNumQueries(3, a.delete) self.assertFalse(User.objects.exists()) self.assertFalse(Avatar.objects.exists()) + self.assertEqual(len(calls), 1) + models.signals.post_delete.disconnect(noop, sender=User) @skipIfDBFeature("can_defer_constraint_checks") def test_cannot_defer_constraint_checks(self): u = User.objects.create( avatar=Avatar.objects.create() ) + # Attach a signal to make sure we will not do fast_deletes. + calls = [] + def noop(*args, **kwargs): + calls.append('') + models.signals.post_delete.connect(noop, sender=User) + a = Avatar.objects.get(pk=u.avatar_id) + # The below doesn't make sense... Why do we need to null out + # user.avatar if we are going to delete the user immediately after it, + # and there are no more cascades. # 1 query to find the users for the avatar. # 1 query to delete the user # 1 query to null out user.avatar, because we can't defer the constraint @@ -246,6 +275,8 @@ class DeletionTests(TestCase): self.assertNumQueries(4, a.delete) self.assertFalse(User.objects.exists()) self.assertFalse(Avatar.objects.exists()) + self.assertEqual(len(calls), 1) + models.signals.post_delete.disconnect(noop, sender=User) def test_hidden_related(self): r = R.objects.create() @@ -254,3 +285,69 @@ class DeletionTests(TestCase): r.delete() self.assertEqual(HiddenUserProfile.objects.count(), 0) + +class FastDeleteTests(TestCase): + + def test_fast_delete_fk(self): + u = User.objects.create( + avatar=Avatar.objects.create() + ) + a = Avatar.objects.get(pk=u.avatar_id) + # 1 query to fast-delete the user + # 1 query to delete the avatar + self.assertNumQueries(2, a.delete) + self.assertFalse(User.objects.exists()) + self.assertFalse(Avatar.objects.exists()) + + def test_fast_delete_m2m(self): + t = M2MTo.objects.create() + f = M2MFrom.objects.create() + f.m2m.add(t) + # 1 to delete f, 1 to fast-delete m2m for f + self.assertNumQueries(2, f.delete) + + def test_fast_delete_revm2m(self): + t = M2MTo.objects.create() + f = M2MFrom.objects.create() + f.m2m.add(t) + # 1 to delete t, 1 to fast-delete t's m_set + self.assertNumQueries(2, f.delete) + + def test_fast_delete_qs(self): + u1 = User.objects.create() + u2 = User.objects.create() + self.assertNumQueries(1, User.objects.filter(pk=u1.pk).delete) + self.assertEqual(User.objects.count(), 1) + self.assertTrue(User.objects.filter(pk=u2.pk).exists()) + + def test_fast_delete_joined_qs(self): + a = Avatar.objects.create(desc='a') + User.objects.create(avatar=a) + u2 = User.objects.create() + expected_queries = 1 if connection.features.update_can_self_select else 2 + self.assertNumQueries(expected_queries, + User.objects.filter(avatar__desc='a').delete) + self.assertEqual(User.objects.count(), 1) + self.assertTrue(User.objects.filter(pk=u2.pk).exists()) + + def test_fast_delete_inheritance(self): + c = Child.objects.create() + p = Parent.objects.create() + # 1 for self, 1 for parent + # However, this doesn't work as child.parent access creates a query, + # and this means we will be generating extra queries (a lot for large + # querysets). This is not a fast-delete problem. + # self.assertNumQueries(2, c.delete) + c.delete() + self.assertFalse(Child.objects.exists()) + self.assertEqual(Parent.objects.count(), 1) + self.assertEqual(Parent.objects.filter(pk=p.pk).count(), 1) + # 1 for self delete, 1 for fast delete of empty "child" qs. + self.assertNumQueries(2, p.delete) + self.assertFalse(Parent.objects.exists()) + # 1 for self delete, 1 for fast delete of empty "child" qs. + c = Child.objects.create() + p = c.parent_ptr + self.assertNumQueries(2, p.delete) + self.assertFalse(Parent.objects.exists()) + self.assertFalse(Child.objects.exists()) diff --git a/tests/modeltests/invalid_models/invalid_models/models.py b/tests/modeltests/invalid_models/invalid_models/models.py index b2ba253c5d..ccb6396352 100644 --- a/tests/modeltests/invalid_models/invalid_models/models.py +++ b/tests/modeltests/invalid_models/invalid_models/models.py @@ -21,11 +21,12 @@ class FieldErrors(models.Model): decimalfield5 = models.DecimalField(max_digits=10, decimal_places=10) filefield = models.FileField() choices = models.CharField(max_length=10, choices='bad') - choices2 = models.CharField(max_length=10, choices=[(1,2,3),(1,2,3)]) + choices2 = models.CharField(max_length=10, choices=[(1, 2, 3), (1, 2, 3)]) index = models.CharField(max_length=10, db_index='bad') field_ = models.CharField(max_length=10) nullbool = models.BooleanField(null=True) + class Target(models.Model): tgt_safe = models.CharField(max_length=10) clash1 = models.CharField(max_length=10) @@ -33,12 +34,14 @@ class Target(models.Model): clash1_set = models.CharField(max_length=10) + class Clash1(models.Model): src_safe = models.CharField(max_length=10) foreign = models.ForeignKey(Target) m2m = models.ManyToManyField(Target) + class Clash2(models.Model): src_safe = models.CharField(max_length=10) @@ -48,6 +51,7 @@ class Clash2(models.Model): m2m_1 = models.ManyToManyField(Target, related_name='id') m2m_2 = models.ManyToManyField(Target, related_name='src_safe') + class Target2(models.Model): clash3 = models.CharField(max_length=10) foreign_tgt = models.ForeignKey(Target) @@ -56,6 +60,7 @@ class Target2(models.Model): m2m_tgt = models.ManyToManyField(Target) clashm2m_set = models.ManyToManyField(Target) + class Clash3(models.Model): src_safe = models.CharField(max_length=10) @@ -65,12 +70,15 @@ class Clash3(models.Model): m2m_1 = models.ManyToManyField(Target2, related_name='foreign_tgt') m2m_2 = models.ManyToManyField(Target2, related_name='m2m_tgt') + class ClashForeign(models.Model): foreign = models.ForeignKey(Target2) + class ClashM2M(models.Model): m2m = models.ManyToManyField(Target2) + class SelfClashForeign(models.Model): src_safe = models.CharField(max_length=10) selfclashforeign = models.CharField(max_length=10) @@ -79,6 +87,7 @@ class SelfClashForeign(models.Model): foreign_1 = models.ForeignKey("SelfClashForeign", related_name='id') foreign_2 = models.ForeignKey("SelfClashForeign", related_name='src_safe') + class ValidM2M(models.Model): src_safe = models.CharField(max_length=10) validm2m = models.CharField(max_length=10) @@ -94,6 +103,7 @@ class ValidM2M(models.Model): m2m_3 = models.ManyToManyField('self') m2m_4 = models.ManyToManyField('self') + class SelfClashM2M(models.Model): src_safe = models.CharField(max_length=10) selfclashm2m = models.CharField(max_length=10) @@ -108,120 +118,148 @@ class SelfClashM2M(models.Model): m2m_3 = models.ManyToManyField('self', symmetrical=False) m2m_4 = models.ManyToManyField('self', symmetrical=False) + class Model(models.Model): "But it's valid to call a model Model." - year = models.PositiveIntegerField() #1960 - make = models.CharField(max_length=10) #Aston Martin - name = models.CharField(max_length=10) #DB 4 GT + year = models.PositiveIntegerField() # 1960 + make = models.CharField(max_length=10) # Aston Martin + name = models.CharField(max_length=10) # DB 4 GT + class Car(models.Model): colour = models.CharField(max_length=5) model = models.ForeignKey(Model) + class MissingRelations(models.Model): rel1 = models.ForeignKey("Rel1") rel2 = models.ManyToManyField("Rel2") + class MissingManualM2MModel(models.Model): name = models.CharField(max_length=5) missing_m2m = models.ManyToManyField(Model, through="MissingM2MModel") + class Person(models.Model): name = models.CharField(max_length=5) + class Group(models.Model): name = models.CharField(max_length=5) primary = models.ManyToManyField(Person, through="Membership", related_name="primary") secondary = models.ManyToManyField(Person, through="Membership", related_name="secondary") tertiary = models.ManyToManyField(Person, through="RelationshipDoubleFK", related_name="tertiary") + class GroupTwo(models.Model): name = models.CharField(max_length=5) primary = models.ManyToManyField(Person, through="Membership") secondary = models.ManyToManyField(Group, through="MembershipMissingFK") + class Membership(models.Model): person = models.ForeignKey(Person) group = models.ForeignKey(Group) not_default_or_null = models.CharField(max_length=5) + class MembershipMissingFK(models.Model): person = models.ForeignKey(Person) + class PersonSelfRefM2M(models.Model): name = models.CharField(max_length=5) friends = models.ManyToManyField('self', through="Relationship") too_many_friends = models.ManyToManyField('self', through="RelationshipTripleFK") + class PersonSelfRefM2MExplicit(models.Model): name = models.CharField(max_length=5) friends = models.ManyToManyField('self', through="ExplicitRelationship", symmetrical=True) + class Relationship(models.Model): first = models.ForeignKey(PersonSelfRefM2M, related_name="rel_from_set") second = models.ForeignKey(PersonSelfRefM2M, related_name="rel_to_set") date_added = models.DateTimeField() + class ExplicitRelationship(models.Model): first = models.ForeignKey(PersonSelfRefM2MExplicit, related_name="rel_from_set") second = models.ForeignKey(PersonSelfRefM2MExplicit, related_name="rel_to_set") date_added = models.DateTimeField() + class RelationshipTripleFK(models.Model): first = models.ForeignKey(PersonSelfRefM2M, related_name="rel_from_set_2") second = models.ForeignKey(PersonSelfRefM2M, related_name="rel_to_set_2") third = models.ForeignKey(PersonSelfRefM2M, related_name="too_many_by_far") date_added = models.DateTimeField() + class RelationshipDoubleFK(models.Model): first = models.ForeignKey(Person, related_name="first_related_name") second = models.ForeignKey(Person, related_name="second_related_name") third = models.ForeignKey(Group, related_name="rel_to_set") date_added = models.DateTimeField() + class AbstractModel(models.Model): name = models.CharField(max_length=10) + class Meta: abstract = True + class AbstractRelationModel(models.Model): fk1 = models.ForeignKey('AbstractModel') fk2 = models.ManyToManyField('AbstractModel') + class UniqueM2M(models.Model): """ Model to test for unique ManyToManyFields, which are invalid. """ unique_people = models.ManyToManyField(Person, unique=True) + class NonUniqueFKTarget1(models.Model): """ Model to test for non-unique FK target in yet-to-be-defined model: expect an error """ tgt = models.ForeignKey('FKTarget', to_field='bad') + class UniqueFKTarget1(models.Model): """ Model to test for unique FK target in yet-to-be-defined model: expect no error """ tgt = models.ForeignKey('FKTarget', to_field='good') + class FKTarget(models.Model): bad = models.IntegerField() good = models.IntegerField(unique=True) + class NonUniqueFKTarget2(models.Model): """ Model to test for non-unique FK target in previously seen model: expect an error """ tgt = models.ForeignKey(FKTarget, to_field='bad') + class UniqueFKTarget2(models.Model): """ Model to test for unique FK target in previously seen model: expect no error """ tgt = models.ForeignKey(FKTarget, to_field='good') + class NonExistingOrderingWithSingleUnderscore(models.Model): class Meta: ordering = ("does_not_exist",) + class InvalidSetNull(models.Model): fk = models.ForeignKey('self', on_delete=models.SET_NULL) + class InvalidSetDefault(models.Model): fk = models.ForeignKey('self', on_delete=models.SET_DEFAULT) + class UnicodeForeignKeys(models.Model): """Foreign keys which can translate to ascii should be OK, but fail if they're not.""" @@ -232,9 +270,11 @@ class UnicodeForeignKeys(models.Model): # when adding the errors in core/management/validation.py #bad = models.ForeignKey('★') + class PrimaryKeyNull(models.Model): my_pk_field = models.IntegerField(primary_key=True, null=True) + class OrderByPKModel(models.Model): """ Model to test that ordering by pk passes validation. @@ -245,6 +285,77 @@ class OrderByPKModel(models.Model): class Meta: ordering = ('pk',) + +class SwappableModel(models.Model): + """A model that can be, but isn't swapped out. + + References to this model *shoudln't* raise any validation error. + """ + name = models.CharField(max_length=100) + + class Meta: + swappable = 'TEST_SWAPPABLE_MODEL' + + +class SwappedModel(models.Model): + """A model that is swapped out. + + References to this model *should* raise a validation error. + Requires TEST_SWAPPED_MODEL to be defined in the test environment; + this is guaranteed by the test runner using @override_settings. + + The foreign keys and m2m relations on this model *shouldn't* + install related accessors, so there shouldn't be clashes with + the equivalent names on the replacement. + """ + name = models.CharField(max_length=100) + + foreign = models.ForeignKey(Target, related_name='swappable_fk_set') + m2m = models.ManyToManyField(Target, related_name='swappable_m2m_set') + + class Meta: + swappable = 'TEST_SWAPPED_MODEL' + + +class ReplacementModel(models.Model): + """A replacement model for swapping purposes.""" + name = models.CharField(max_length=100) + + foreign = models.ForeignKey(Target, related_name='swappable_fk_set') + m2m = models.ManyToManyField(Target, related_name='swappable_m2m_set') + + +class BadSwappableValue(models.Model): + """A model that can be swapped out; during testing, the swappable + value is not of the format app.model + """ + name = models.CharField(max_length=100) + + class Meta: + swappable = 'TEST_SWAPPED_MODEL_BAD_VALUE' + + +class BadSwappableModel(models.Model): + """A model that can be swapped out; during testing, the swappable + value references an unknown model. + """ + name = models.CharField(max_length=100) + + class Meta: + swappable = 'TEST_SWAPPED_MODEL_BAD_MODEL' + + +class HardReferenceModel(models.Model): + fk_1 = models.ForeignKey(SwappableModel, related_name='fk_hardref1') + fk_2 = models.ForeignKey('invalid_models.SwappableModel', related_name='fk_hardref2') + fk_3 = models.ForeignKey(SwappedModel, related_name='fk_hardref3') + fk_4 = models.ForeignKey('invalid_models.SwappedModel', related_name='fk_hardref4') + m2m_1 = models.ManyToManyField(SwappableModel, related_name='m2m_hardref1') + m2m_2 = models.ManyToManyField('invalid_models.SwappableModel', related_name='m2m_hardref2') + m2m_3 = models.ManyToManyField(SwappedModel, related_name='m2m_hardref3') + m2m_4 = models.ManyToManyField('invalid_models.SwappedModel', related_name='m2m_hardref4') + + model_errors = """invalid_models.fielderrors: "charfield": CharFields require a "max_length" attribute that is a positive integer. invalid_models.fielderrors: "charfield2": CharFields require a "max_length" attribute that is a positive integer. invalid_models.fielderrors: "charfield3": CharFields require a "max_length" attribute that is a positive integer. @@ -353,6 +464,12 @@ invalid_models.nonuniquefktarget2: Field 'bad' under model 'FKTarget' must have invalid_models.nonexistingorderingwithsingleunderscore: "ordering" refers to "does_not_exist", a field that doesn't exist. invalid_models.invalidsetnull: 'fk' specifies on_delete=SET_NULL, but cannot be null. invalid_models.invalidsetdefault: 'fk' specifies on_delete=SET_DEFAULT, but has no default value. +invalid_models.hardreferencemodel: 'fk_3' defines a relation with the model 'invalid_models.SwappedModel', which has been swapped out. Update the relation to point at settings.TEST_SWAPPED_MODEL. +invalid_models.hardreferencemodel: 'fk_4' defines a relation with the model 'invalid_models.SwappedModel', which has been swapped out. Update the relation to point at settings.TEST_SWAPPED_MODEL. +invalid_models.hardreferencemodel: 'm2m_3' defines a relation with the model 'invalid_models.SwappedModel', which has been swapped out. Update the relation to point at settings.TEST_SWAPPED_MODEL. +invalid_models.hardreferencemodel: 'm2m_4' defines a relation with the model 'invalid_models.SwappedModel', which has been swapped out. Update the relation to point at settings.TEST_SWAPPED_MODEL. +invalid_models.badswappablevalue: TEST_SWAPPED_MODEL_BAD_VALUE is not of the form 'app_label.app_name'. +invalid_models.badswappablemodel: Model has been swapped out for 'not_an_app.Target' which has not been installed or is abstract. """ if not connection.features.interprets_empty_strings_as_nulls: diff --git a/tests/modeltests/invalid_models/tests.py b/tests/modeltests/invalid_models/tests.py index e1fc68743e..5f6224c45d 100644 --- a/tests/modeltests/invalid_models/tests.py +++ b/tests/modeltests/invalid_models/tests.py @@ -4,6 +4,7 @@ import sys from django.core.management.validation import get_validation_errors from django.db.models.loading import cache, load_app +from django.test.utils import override_settings from django.utils import unittest from django.utils.six import StringIO @@ -31,14 +32,22 @@ class InvalidModelTestCase(unittest.TestCase): cache._get_models_cache = {} sys.stdout = self.old_stdout + # Technically, this isn't an override -- TEST_SWAPPED_MODEL must be + # set to *something* in order for the test to work. However, it's + # easier to set this up as an override than to require every developer + # to specify a value in their test settings. + @override_settings( + TEST_SWAPPED_MODEL='invalid_models.ReplacementModel', + TEST_SWAPPED_MODEL_BAD_VALUE='not-a-model', + TEST_SWAPPED_MODEL_BAD_MODEL='not_an_app.Target', + ) def test_invalid_models(self): - try: module = load_app("modeltests.invalid_models.invalid_models") except Exception: self.fail('Unable to load invalid model module') - count = get_validation_errors(self.stdout, module) + get_validation_errors(self.stdout, module) self.stdout.seek(0) error_log = self.stdout.read() actual = error_log.split('\n') diff --git a/tests/modeltests/model_forms/tests.py b/tests/modeltests/model_forms/tests.py index 038ce32287..947d0cf3c3 100644 --- a/tests/modeltests/model_forms/tests.py +++ b/tests/modeltests/model_forms/tests.py @@ -8,6 +8,7 @@ from django import forms from django.core.files.uploadedfile import SimpleUploadedFile from django.core.validators import ValidationError from django.db import connection +from django.db.models.query import EmptyQuerySet from django.forms.models import model_to_dict from django.utils.unittest import skipUnless from django.test import TestCase @@ -1035,8 +1036,8 @@ class OldFormForXTests(TestCase): f.clean([c6.id]) f = forms.ModelMultipleChoiceField(Category.objects.all(), required=False) - self.assertEqual(f.clean([]), []) - self.assertEqual(f.clean(()), []) + self.assertIsInstance(f.clean([]), EmptyQuerySet) + self.assertIsInstance(f.clean(()), EmptyQuerySet) with self.assertRaises(ValidationError): f.clean(['10']) with self.assertRaises(ValidationError): diff --git a/tests/modeltests/proxy_models/tests.py b/tests/modeltests/proxy_models/tests.py index 7ec86e9b22..d1c95467ee 100644 --- a/tests/modeltests/proxy_models/tests.py +++ b/tests/modeltests/proxy_models/tests.py @@ -1,10 +1,13 @@ from __future__ import absolute_import, unicode_literals +import copy +from django.conf import settings from django.contrib.contenttypes.models import ContentType from django.core import management from django.core.exceptions import FieldError from django.db import models, DEFAULT_DB_ALIAS from django.db.models import signals +from django.db.models.loading import cache from django.test import TestCase @@ -13,6 +16,7 @@ from .models import (MyPerson, Person, StatusPerson, LowerStatusPerson, Country, State, StateProxy, TrackerUser, BaseUser, Bug, ProxyTrackerUser, Improvement, ProxyProxyBug, ProxyBug, ProxyImprovement) + class ProxyModelTests(TestCase): def test_same_manager_queries(self): """ @@ -91,7 +95,7 @@ class ProxyModelTests(TestCase): ) self.assertRaises(Person.MultipleObjectsReturned, MyPersonProxy.objects.get, - id__lt=max_id+1 + id__lt=max_id + 1 ) self.assertRaises(Person.DoesNotExist, StatusPerson.objects.get, @@ -104,7 +108,7 @@ class ProxyModelTests(TestCase): self.assertRaises(Person.MultipleObjectsReturned, StatusPerson.objects.get, - id__lt=max_id+1 + id__lt=max_id + 1 ) def test_abc(self): @@ -138,10 +142,40 @@ class ProxyModelTests(TestCase): def build_new_fields(): class NoNewFields(Person): newfield = models.BooleanField() + class Meta: proxy = True self.assertRaises(FieldError, build_new_fields) + def test_swappable(self): + try: + # This test adds dummy applications to the app cache. These + # need to be removed in order to prevent bad interactions + # with the flush operation in other tests. + old_app_models = copy.deepcopy(cache.app_models) + old_app_store = copy.deepcopy(cache.app_store) + + settings.TEST_SWAPPABLE_MODEL = 'proxy_models.AlternateModel' + + class SwappableModel(models.Model): + + class Meta: + swappable = 'TEST_SWAPPABLE_MODEL' + + class AlternateModel(models.Model): + pass + + # You can't proxy a swapped model + with self.assertRaises(TypeError): + class ProxyModel(SwappableModel): + + class Meta: + proxy = True + finally: + del settings.TEST_SWAPPABLE_MODEL + cache.app_models = old_app_models + cache.app_store = old_app_store + def test_myperson_manager(self): Person.objects.create(name="fred") Person.objects.create(name="wilma") diff --git a/tests/modeltests/test_client/models.py b/tests/modeltests/test_client/models.py index 1d9c999f21..0f3cba7e88 100644 --- a/tests/modeltests/test_client/models.py +++ b/tests/modeltests/test_client/models.py @@ -215,7 +215,7 @@ class ClientTest(TestCase): self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, "Invalid POST Template") - self.assertFormError(response, 'form', 'email', 'Enter a valid e-mail address.') + 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" @@ -263,7 +263,7 @@ class ClientTest(TestCase): self.assertTemplateUsed(response, 'base.html') self.assertTemplateNotUsed(response, "Invalid POST Template") - self.assertFormError(response, 'form', 'email', 'Enter a valid e-mail address.') + self.assertFormError(response, 'form', 'email', 'Enter a valid email address.') def test_unknown_page(self): "GET an invalid URL" diff --git a/tests/modeltests/timezones/tests.py b/tests/modeltests/timezones/tests.py index 4621f0a60c..2fdf6733a0 100644 --- a/tests/modeltests/timezones/tests.py +++ b/tests/modeltests/timezones/tests.py @@ -5,6 +5,7 @@ import os import sys import time import warnings +from xml.dom.minidom import parseString try: import pytz @@ -492,27 +493,40 @@ class SerializationTests(TestCase): # returns a naive datetime object in UTC (http://pyyaml.org/ticket/202). # Tests are adapted to take these quirks into account. + def assert_python_contains_datetime(self, objects, dt): + self.assertEqual(objects[0]['fields']['dt'], dt) + + def assert_json_contains_datetime(self, json, dt): + self.assertIn('"fields": {"dt": "%s"}' % dt, json) + + def assert_xml_contains_datetime(self, xml, dt): + field = parseString(xml).getElementsByTagName('field')[0] + self.assertXMLEqual(field.childNodes[0].wholeText, dt) + + def assert_yaml_contains_datetime(self, yaml, dt): + self.assertIn("- fields: {dt: !!timestamp '%s'}" % dt, yaml) + def test_naive_datetime(self): dt = datetime.datetime(2011, 9, 1, 13, 20, 30) data = serializers.serialize('python', [Event(dt=dt)]) - self.assertEqual(data[0]['fields']['dt'], dt) + self.assert_python_contains_datetime(data, dt) obj = next(serializers.deserialize('python', data)).object self.assertEqual(obj.dt, dt) data = serializers.serialize('json', [Event(dt=dt)]) - self.assertIn('"fields": {"dt": "2011-09-01T13:20:30"}', data) + self.assert_json_contains_datetime(data, "2011-09-01T13:20:30") obj = next(serializers.deserialize('json', data)).object self.assertEqual(obj.dt, dt) data = serializers.serialize('xml', [Event(dt=dt)]) - self.assertIn('<field type="DateTimeField" name="dt">2011-09-01T13:20:30</field>', data) + self.assert_xml_contains_datetime(data, "2011-09-01T13:20:30") obj = next(serializers.deserialize('xml', data)).object self.assertEqual(obj.dt, dt) if 'yaml' in serializers.get_serializer_formats(): data = serializers.serialize('yaml', [Event(dt=dt)]) - self.assertIn("- fields: {dt: !!timestamp '2011-09-01 13:20:30'}", data) + self.assert_yaml_contains_datetime(data, "2011-09-01 13:20:30") obj = next(serializers.deserialize('yaml', data)).object self.assertEqual(obj.dt, dt) @@ -520,23 +534,23 @@ class SerializationTests(TestCase): dt = datetime.datetime(2011, 9, 1, 13, 20, 30, 405060) data = serializers.serialize('python', [Event(dt=dt)]) - self.assertEqual(data[0]['fields']['dt'], dt) + self.assert_python_contains_datetime(data, dt) obj = next(serializers.deserialize('python', data)).object self.assertEqual(obj.dt, dt) data = serializers.serialize('json', [Event(dt=dt)]) - self.assertIn('"fields": {"dt": "2011-09-01T13:20:30.405"}', data) + self.assert_json_contains_datetime(data, "2011-09-01T13:20:30.405") obj = next(serializers.deserialize('json', data)).object self.assertEqual(obj.dt, dt.replace(microsecond=405000)) data = serializers.serialize('xml', [Event(dt=dt)]) - self.assertIn('<field type="DateTimeField" name="dt">2011-09-01T13:20:30.405060</field>', data) + self.assert_xml_contains_datetime(data, "2011-09-01T13:20:30.405060") obj = next(serializers.deserialize('xml', data)).object self.assertEqual(obj.dt, dt) if 'yaml' in serializers.get_serializer_formats(): data = serializers.serialize('yaml', [Event(dt=dt)]) - self.assertIn("- fields: {dt: !!timestamp '2011-09-01 13:20:30.405060'}", data) + self.assert_yaml_contains_datetime(data, "2011-09-01 13:20:30.405060") obj = next(serializers.deserialize('yaml', data)).object self.assertEqual(obj.dt, dt) @@ -544,23 +558,23 @@ class SerializationTests(TestCase): dt = datetime.datetime(2011, 9, 1, 17, 20, 30, 405060, tzinfo=ICT) data = serializers.serialize('python', [Event(dt=dt)]) - self.assertEqual(data[0]['fields']['dt'], dt) + self.assert_python_contains_datetime(data, dt) obj = next(serializers.deserialize('python', data)).object self.assertEqual(obj.dt, dt) data = serializers.serialize('json', [Event(dt=dt)]) - self.assertIn('"fields": {"dt": "2011-09-01T17:20:30.405+07:00"}', data) + self.assert_json_contains_datetime(data, "2011-09-01T17:20:30.405+07:00") obj = next(serializers.deserialize('json', data)).object self.assertEqual(obj.dt, dt.replace(microsecond=405000)) data = serializers.serialize('xml', [Event(dt=dt)]) - self.assertIn('<field type="DateTimeField" name="dt">2011-09-01T17:20:30.405060+07:00</field>', data) + self.assert_xml_contains_datetime(data, "2011-09-01T17:20:30.405060+07:00") obj = next(serializers.deserialize('xml', data)).object self.assertEqual(obj.dt, dt) if 'yaml' in serializers.get_serializer_formats(): data = serializers.serialize('yaml', [Event(dt=dt)]) - self.assertIn("- fields: {dt: !!timestamp '2011-09-01 17:20:30.405060+07:00'}", data) + self.assert_yaml_contains_datetime(data, "2011-09-01 17:20:30.405060+07:00") obj = next(serializers.deserialize('yaml', data)).object self.assertEqual(obj.dt.replace(tzinfo=UTC), dt) @@ -568,23 +582,23 @@ class SerializationTests(TestCase): dt = datetime.datetime(2011, 9, 1, 10, 20, 30, tzinfo=UTC) data = serializers.serialize('python', [Event(dt=dt)]) - self.assertEqual(data[0]['fields']['dt'], dt) + self.assert_python_contains_datetime(data, dt) obj = next(serializers.deserialize('python', data)).object self.assertEqual(obj.dt, dt) data = serializers.serialize('json', [Event(dt=dt)]) - self.assertIn('"fields": {"dt": "2011-09-01T10:20:30Z"}', data) + self.assert_json_contains_datetime(data, "2011-09-01T10:20:30Z") obj = next(serializers.deserialize('json', data)).object self.assertEqual(obj.dt, dt) data = serializers.serialize('xml', [Event(dt=dt)]) - self.assertIn('<field type="DateTimeField" name="dt">2011-09-01T10:20:30+00:00</field>', data) + self.assert_xml_contains_datetime(data, "2011-09-01T10:20:30+00:00") obj = next(serializers.deserialize('xml', data)).object self.assertEqual(obj.dt, dt) if 'yaml' in serializers.get_serializer_formats(): data = serializers.serialize('yaml', [Event(dt=dt)]) - self.assertIn("- fields: {dt: !!timestamp '2011-09-01 10:20:30+00:00'}", data) + self.assert_yaml_contains_datetime(data, "2011-09-01 10:20:30+00:00") obj = next(serializers.deserialize('yaml', data)).object self.assertEqual(obj.dt.replace(tzinfo=UTC), dt) @@ -592,23 +606,23 @@ class SerializationTests(TestCase): dt = datetime.datetime(2011, 9, 1, 13, 20, 30, tzinfo=EAT) data = serializers.serialize('python', [Event(dt=dt)]) - self.assertEqual(data[0]['fields']['dt'], dt) + self.assert_python_contains_datetime(data, dt) obj = next(serializers.deserialize('python', data)).object self.assertEqual(obj.dt, dt) data = serializers.serialize('json', [Event(dt=dt)]) - self.assertIn('"fields": {"dt": "2011-09-01T13:20:30+03:00"}', data) + self.assert_json_contains_datetime(data, "2011-09-01T13:20:30+03:00") obj = next(serializers.deserialize('json', data)).object self.assertEqual(obj.dt, dt) data = serializers.serialize('xml', [Event(dt=dt)]) - self.assertIn('<field type="DateTimeField" name="dt">2011-09-01T13:20:30+03:00</field>', data) + self.assert_xml_contains_datetime(data, "2011-09-01T13:20:30+03:00") obj = next(serializers.deserialize('xml', data)).object self.assertEqual(obj.dt, dt) if 'yaml' in serializers.get_serializer_formats(): data = serializers.serialize('yaml', [Event(dt=dt)]) - self.assertIn("- fields: {dt: !!timestamp '2011-09-01 13:20:30+03:00'}", data) + self.assert_yaml_contains_datetime(data, "2011-09-01 13:20:30+03:00") obj = next(serializers.deserialize('yaml', data)).object self.assertEqual(obj.dt.replace(tzinfo=UTC), dt) @@ -616,23 +630,23 @@ class SerializationTests(TestCase): dt = datetime.datetime(2011, 9, 1, 17, 20, 30, tzinfo=ICT) data = serializers.serialize('python', [Event(dt=dt)]) - self.assertEqual(data[0]['fields']['dt'], dt) + self.assert_python_contains_datetime(data, dt) obj = next(serializers.deserialize('python', data)).object self.assertEqual(obj.dt, dt) data = serializers.serialize('json', [Event(dt=dt)]) - self.assertIn('"fields": {"dt": "2011-09-01T17:20:30+07:00"}', data) + self.assert_json_contains_datetime(data, "2011-09-01T17:20:30+07:00") obj = next(serializers.deserialize('json', data)).object self.assertEqual(obj.dt, dt) data = serializers.serialize('xml', [Event(dt=dt)]) - self.assertIn('<field type="DateTimeField" name="dt">2011-09-01T17:20:30+07:00</field>', data) + self.assert_xml_contains_datetime(data, "2011-09-01T17:20:30+07:00") obj = next(serializers.deserialize('xml', data)).object self.assertEqual(obj.dt, dt) if 'yaml' in serializers.get_serializer_formats(): data = serializers.serialize('yaml', [Event(dt=dt)]) - self.assertIn("- fields: {dt: !!timestamp '2011-09-01 17:20:30+07:00'}", data) + self.assert_yaml_contains_datetime(data, "2011-09-01 17:20:30+07:00") obj = next(serializers.deserialize('yaml', data)).object self.assertEqual(obj.dt.replace(tzinfo=UTC), dt) diff --git a/tests/modeltests/validators/tests.py b/tests/modeltests/validators/tests.py index 018be6ae59..0174a606df 100644 --- a/tests/modeltests/validators/tests.py +++ b/tests/modeltests/validators/tests.py @@ -26,13 +26,23 @@ TEST_DATA = ( (validate_email, 'email@here.com', None), (validate_email, 'weirder-email@here.and.there.com', None), (validate_email, 'email@[127.0.0.1]', None), + (validate_email, 'example@valid-----hyphens.com', None), + (validate_email, 'example@valid-with-hyphens.com', None), + (validate_email, 'test@domain.with.idn.tld.उदाहरण.परीक्षा', None), (validate_email, None, ValidationError), (validate_email, '', ValidationError), (validate_email, 'abc', ValidationError), + (validate_email, 'abc@', ValidationError), + (validate_email, 'abc@bar', ValidationError), (validate_email, 'a @x.cz', ValidationError), + (validate_email, 'abc@.com', ValidationError), (validate_email, 'something@@somewhere.com', ValidationError), (validate_email, 'email@127.0.0.1', ValidationError), + (validate_email, 'example@invalid-.com', ValidationError), + (validate_email, 'example@-invalid.com', ValidationError), + (validate_email, 'example@inv-.alid-.com', ValidationError), + (validate_email, 'example@inv-.-alid.com', ValidationError), # Quoted-string format (CR not allowed) (validate_email, '"\\\011"@here.com', None), (validate_email, '"\\\012"@here.com', ValidationError), @@ -162,11 +172,23 @@ def create_simple_test_method(validator, expected, value, num): if expected is not None and issubclass(expected, Exception): test_mask = 'test_%s_raises_error_%d' def test_func(self): - self.assertRaises(expected, validator, value) + # assertRaises not used, so as to be able to produce an error message + # containing the tested value + try: + validator(value) + except expected: + pass + else: + self.fail("%s not raised when validating '%s'" % ( + expected.__name__, value)) else: test_mask = 'test_%s_%d' def test_func(self): - self.assertEqual(expected, validator(value)) + try: + self.assertEqual(expected, validator(value)) + except ValidationError as e: + self.fail("Validation of '%s' failed. Error message was: %s" % ( + value, str(e))) if isinstance(validator, types.FunctionType): val_name = validator.__name__ else: diff --git a/tests/regressiontests/admin_changelist/tests.py b/tests/regressiontests/admin_changelist/tests.py index be88c9a161..2b1c1a9bcf 100644 --- a/tests/regressiontests/admin_changelist/tests.py +++ b/tests/regressiontests/admin_changelist/tests.py @@ -6,6 +6,7 @@ from django.contrib import admin from django.contrib.admin.options import IncorrectLookupParameters from django.contrib.admin.views.main import ChangeList, SEARCH_VAR, ALL_VAR from django.contrib.auth.models import User +from django.core.urlresolvers import reverse from django.template import Context, Template from django.test import TestCase from django.test.client import RequestFactory @@ -65,7 +66,8 @@ class ChangeListTests(TestCase): template = Template('{% load admin_list %}{% spaceless %}{% result_list cl %}{% endspaceless %}') context = Context({'cl': cl}) table_output = template.render(context) - row_html = '<tbody><tr class="row1"><th><a href="%d/">name</a></th><td class="nowrap">(None)</td></tr></tbody>' % new_child.id + link = reverse('admin:admin_changelist_child_change', args=(new_child.id,)) + row_html = '<tbody><tr class="row1"><th><a href="%s">name</a></th><td class="nowrap">(None)</td></tr></tbody>' % link self.assertFalse(table_output.find(row_html) == -1, 'Failed to find expected row element: %s' % table_output) @@ -87,7 +89,8 @@ class ChangeListTests(TestCase): template = Template('{% load admin_list %}{% spaceless %}{% result_list cl %}{% endspaceless %}') context = Context({'cl': cl}) table_output = template.render(context) - row_html = '<tbody><tr class="row1"><th><a href="%d/">name</a></th><td class="nowrap">Parent object</td></tr></tbody>' % new_child.id + link = reverse('admin:admin_changelist_child_change', args=(new_child.id,)) + row_html = '<tbody><tr class="row1"><th><a href="%s">name</a></th><td class="nowrap">Parent object</td></tr></tbody>' % link self.assertFalse(table_output.find(row_html) == -1, 'Failed to find expected row element: %s' % table_output) @@ -425,7 +428,8 @@ class ChangeListTests(TestCase): request = self._mocked_authenticated_request('/child/', superuser) response = m.changelist_view(request) for i in range(1, 10): - self.assertContains(response, '<a href="%s/">%s</a>' % (i, i)) + link = reverse('admin:admin_changelist_child_change', args=(i,)) + self.assertContains(response, '<a href="%s">%s</a>' % (link, i)) list_display = m.get_list_display(request) list_display_links = m.get_list_display_links(request, list_display) diff --git a/tests/regressiontests/admin_custom_urls/fixtures/actions.json b/tests/regressiontests/admin_custom_urls/fixtures/actions.json index a63cf8135c..7c6341d71d 100644 --- a/tests/regressiontests/admin_custom_urls/fixtures/actions.json +++ b/tests/regressiontests/admin_custom_urls/fixtures/actions.json @@ -40,12 +40,5 @@ "fields": { "description": "An action with a name suspected of being a XSS attempt" } - }, - { - "pk": "The name of an action", - "model": "admin_custom_urls.action", - "fields": { - "description": "A generic action" - } } ] diff --git a/tests/regressiontests/admin_custom_urls/models.py b/tests/regressiontests/admin_custom_urls/models.py index a5b4983b09..b9b3285463 100644 --- a/tests/regressiontests/admin_custom_urls/models.py +++ b/tests/regressiontests/admin_custom_urls/models.py @@ -50,3 +50,40 @@ class ActionAdmin(admin.ModelAdmin): admin.site.register(Action, ActionAdmin) + + +class Person(models.Model): + nick = models.CharField(max_length=20) + + +class PersonAdmin(admin.ModelAdmin): + """A custom ModelAdmin that customizes the deprecated post_url_continue + argument to response_add()""" + def response_add(self, request, obj, post_url_continue='../%s/continue/', + continue_url=None, add_url=None, hasperm_url=None, + noperm_url=None): + return super(PersonAdmin, self).response_add(request, obj, + post_url_continue, + continue_url, add_url, + hasperm_url, noperm_url) + + +admin.site.register(Person, PersonAdmin) + + +class City(models.Model): + name = models.CharField(max_length=20) + + +class CityAdmin(admin.ModelAdmin): + """A custom ModelAdmin that redirects to the changelist when the user + presses the 'Save and add another' button when adding a model instance.""" + def response_add(self, request, obj, + add_another_url='admin:admin_custom_urls_city_changelist', + **kwargs): + return super(CityAdmin, self).response_add(request, obj, + add_another_url=add_another_url, + **kwargs) + + +admin.site.register(City, CityAdmin) diff --git a/tests/regressiontests/admin_custom_urls/tests.py b/tests/regressiontests/admin_custom_urls/tests.py index 64ff9f6692..87c72e2e71 100644 --- a/tests/regressiontests/admin_custom_urls/tests.py +++ b/tests/regressiontests/admin_custom_urls/tests.py @@ -1,11 +1,14 @@ from __future__ import absolute_import, unicode_literals +import warnings + +from django.contrib.admin.util import quote from django.core.urlresolvers import reverse from django.template.response import TemplateResponse from django.test import TestCase from django.test.utils import override_settings -from .models import Action +from .models import Action, Person, City @override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',)) @@ -67,7 +70,7 @@ class AdminCustomUrlsTest(TestCase): # Ditto, but use reverse() to build the URL url = reverse('admin:%s_action_change' % Action._meta.app_label, - args=('add',)) + args=(quote('add'),)) response = self.client.get(url) self.assertEqual(response.status_code, 200) self.assertContains(response, 'Change action') @@ -75,19 +78,50 @@ class AdminCustomUrlsTest(TestCase): # Should correctly get the change_view for the model instance with the # funny-looking PK (the one wth a 'path/to/html/document.html' value) url = reverse('admin:%s_action_change' % Action._meta.app_label, - args=("path/to/html/document.html",)) + args=(quote("path/to/html/document.html"),)) response = self.client.get(url) self.assertEqual(response.status_code, 200) self.assertContains(response, 'Change action') self.assertContains(response, 'value="path/to/html/document.html"') - def testChangeViewHistoryButton(self): - url = reverse('admin:%s_action_change' % Action._meta.app_label, - args=('The name of an action',)) - response = self.client.get(url) - self.assertEqual(response.status_code, 200) - expected_link = reverse('admin:%s_action_history' % - Action._meta.app_label, - args=('The name of an action',)) - self.assertContains(response, '<a href="%s" class="historylink"' % - expected_link) + +@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',)) +class CustomUrlsWorkflowTests(TestCase): + fixtures = ['users.json'] + + def setUp(self): + self.client.login(username='super', password='secret') + + def tearDown(self): + self.client.logout() + + def test_old_argument_deprecation(self): + """Test reporting of post_url_continue deprecation.""" + post_data = { + 'nick': 'johndoe', + } + cnt = Person.objects.count() + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + response = self.client.post(reverse('admin:admin_custom_urls_person_add'), post_data) + self.assertEqual(response.status_code, 302) + self.assertEqual(Person.objects.count(), cnt + 1) + # We should get a DeprecationWarning + self.assertEqual(len(w), 1) + self.assertTrue(isinstance(w[0].message, DeprecationWarning)) + + def test_custom_add_another_redirect(self): + """Test customizability of post-object-creation redirect URL.""" + post_data = { + 'name': 'Rome', + '_addanother': '1', + } + cnt = City.objects.count() + with warnings.catch_warnings(record=True) as w: + # POST to the view whose post-object-creation redir URL argument we + # are customizing (object creation) + response = self.client.post(reverse('admin:admin_custom_urls_city_add'), post_data) + self.assertEqual(City.objects.count(), cnt + 1) + # Check that it redirected to the URL we set + self.assertRedirects(response, reverse('admin:admin_custom_urls_city_changelist')) + self.assertEqual(len(w), 0) # We should get no DeprecationWarning diff --git a/tests/regressiontests/admin_inlines/models.py b/tests/regressiontests/admin_inlines/models.py index 5b703a7481..b004d5f85a 100644 --- a/tests/regressiontests/admin_inlines/models.py +++ b/tests/regressiontests/admin_inlines/models.py @@ -57,6 +57,9 @@ class Inner(models.Model): holder = models.ForeignKey(Holder) readonly = models.CharField("Inner readonly label", max_length=1) + def get_absolute_url(self): + return '/inner/' + class Holder2(models.Model): dummy = models.IntegerField() diff --git a/tests/regressiontests/admin_inlines/tests.py b/tests/regressiontests/admin_inlines/tests.py index 57f45ab0ff..5bb6077bff 100644 --- a/tests/regressiontests/admin_inlines/tests.py +++ b/tests/regressiontests/admin_inlines/tests.py @@ -148,6 +148,18 @@ class TestInline(TestCase): '<input id="id_-2-0-name" type="text" class="vTextField" ' 'name="-2-0-name" maxlength="100" />', html=True) + @override_settings(USE_L10N=True, USE_THOUSAND_SEPARATOR=True) + def test_localize_pk_shortcut(self): + """ + Ensure that the "View on Site" link is correct for locales that use + thousand separators + """ + holder = Holder.objects.create(pk=123456789, dummy=42) + inner = Inner.objects.create(pk=987654321, holder=holder, dummy=42, readonly='') + response = self.client.get('/admin/admin_inlines/holder/%i/' % holder.id) + inner_shortcut = 'r/%s/%s/'%(ContentType.objects.get_for_model(inner).pk, inner.pk) + self.assertContains(response, inner_shortcut) + def test_custom_pk_shortcut(self): """ Ensure that the "View on Site" link is correct for models with a diff --git a/tests/regressiontests/admin_scripts/tests.py b/tests/regressiontests/admin_scripts/tests.py index 6028eac846..3bb8bb0b50 100644 --- a/tests/regressiontests/admin_scripts/tests.py +++ b/tests/regressiontests/admin_scripts/tests.py @@ -982,13 +982,11 @@ class ManageMultipleSettings(AdminScriptTestCase): self.assertNoOutput(err) self.assertOutput(out, "EXECUTE:NoArgsCommand") + class ManageSettingsWithImportError(AdminScriptTestCase): """Tests for manage.py when using the default settings.py file with an import error. Ticket #14130. """ - def setUp(self): - self.write_settings_with_import_error('settings.py') - def tearDown(self): self.remove_settings('settings.py') @@ -1004,11 +1002,27 @@ class ManageSettingsWithImportError(AdminScriptTestCase): settings_file.write('# The next line will cause an import error:\nimport foo42bar\n') def test_builtin_command(self): - "import error: manage.py builtin commands shows useful diagnostic info when settings with import errors is provided" + """ + import error: manage.py builtin commands shows useful diagnostic info + when settings with import errors is provided + """ + self.write_settings_with_import_error('settings.py') args = ['sqlall', 'admin_scripts'] out, err = self.run_manage(args) self.assertNoOutput(out) - self.assertOutput(err, "No module named foo42bar") + self.assertOutput(err, "No module named") + self.assertOutput(err, "foo42bar") + + def test_builtin_command_with_attribute_error(self): + """ + manage.py builtin commands does not swallow attribute errors from bad settings (#18845) + """ + self.write_settings('settings.py', sdict={'BAD_VAR': 'INSTALLED_APPS.crash'}) + args = ['collectstatic', 'admin_scripts'] + out, err = self.run_manage(args) + self.assertNoOutput(out) + self.assertOutput(err, "AttributeError: 'list' object has no attribute 'crash'") + class ManageValidate(AdminScriptTestCase): def tearDown(self): @@ -1020,7 +1034,8 @@ class ManageValidate(AdminScriptTestCase): args = ['validate'] out, err = self.run_manage(args) self.assertNoOutput(out) - self.assertOutput(err, 'No module named admin_scriptz') + self.assertOutput(err, 'No module named') + self.assertOutput(err, 'admin_scriptz') def test_broken_app(self): "manage.py validate reports an ImportError if an app's models.py raises one on import" @@ -1590,3 +1605,15 @@ class StartProject(LiveServerTestCase, AdminScriptTestCase): with codecs.open(path, 'r', 'utf-8') as f: self.assertEqual(f.read(), 'Some non-ASCII text for testing ticket #18091:\nüäö €\n') + + +class DiffSettings(AdminScriptTestCase): + """Tests for diffsettings management command.""" + def test_basic(self): + "Runs without error and emits settings diff." + self.write_settings('settings_to_diff.py', sdict={'FOO': '"bar"'}) + args = ['diffsettings', '--settings=settings_to_diff'] + out, err = self.run_manage(args) + self.remove_settings('settings_to_diff.py') + self.assertNoOutput(err) + self.assertOutput(out, "FOO = 'bar' ###") diff --git a/tests/regressiontests/admin_util/models.py b/tests/regressiontests/admin_util/models.py index b3504a1fa4..32a6cd6291 100644 --- a/tests/regressiontests/admin_util/models.py +++ b/tests/regressiontests/admin_util/models.py @@ -39,3 +39,6 @@ class Guest(models.Model): class Meta: verbose_name = "awesome guest" + +class EventGuide(models.Model): + event = models.ForeignKey(Event, on_delete=models.DO_NOTHING) diff --git a/tests/regressiontests/admin_util/tests.py b/tests/regressiontests/admin_util/tests.py index d04740ce95..ef8a91d1db 100644 --- a/tests/regressiontests/admin_util/tests.py +++ b/tests/regressiontests/admin_util/tests.py @@ -17,7 +17,7 @@ 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 +from .models import Article, Count, Event, Location, EventGuide class NestedObjectsTests(TestCase): @@ -71,6 +71,17 @@ class NestedObjectsTests(TestCase): # 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) + class UtilTests(unittest.TestCase): def test_values_from_lookup_field(self): """ diff --git a/tests/regressiontests/admin_views/tests.py b/tests/regressiontests/admin_views/tests.py index 36fea59f2e..72dc6a3f97 100644 --- a/tests/regressiontests/admin_views/tests.py +++ b/tests/regressiontests/admin_views/tests.py @@ -52,6 +52,7 @@ from .models import (Article, BarAccount, CustomArticle, EmptyModel, FooAccount, ERROR_MESSAGE = "Please enter the correct username and password \ for a staff account. Note that both fields are case-sensitive." + @override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',)) class AdminViewBasicTest(TestCase): fixtures = ['admin-views-users.xml', 'admin-views-colors.xml', @@ -141,7 +142,7 @@ class AdminViewBasicTest(TestCase): "article_set-MAX_NUM_FORMS": "0", } response = self.client.post('/test_admin/%s/admin_views/section/add/' % self.urlbit, post_data) - self.assertEqual(response.status_code, 302) # redirect somewhere + self.assertEqual(response.status_code, 302) # redirect somewhere def testPopupAddPost(self): """ @@ -205,7 +206,7 @@ class AdminViewBasicTest(TestCase): A smoke test to ensure POST on edit_view works. """ response = self.client.post('/test_admin/%s/admin_views/section/1/' % self.urlbit, self.inline_post_data) - self.assertEqual(response.status_code, 302) # redirect somewhere + self.assertEqual(response.status_code, 302) # redirect somewhere def testEditSaveAs(self): """ @@ -221,7 +222,7 @@ class AdminViewBasicTest(TestCase): "article_set-5-section": "1", }) response = self.client.post('/test_admin/%s/admin_views/section/1/' % self.urlbit, post_data) - self.assertEqual(response.status_code, 302) # redirect somewhere + self.assertEqual(response.status_code, 302) # redirect somewhere def testChangeListSortingCallable(self): """ @@ -260,19 +261,21 @@ class AdminViewBasicTest(TestCase): p1 = Person.objects.create(name="Chris", gender=1, alive=True) p2 = Person.objects.create(name="Chris", gender=2, alive=True) p3 = Person.objects.create(name="Bob", gender=1, alive=True) - link = '<a href="%s/' + link1 = reverse('admin:admin_views_person_change', args=(p1.pk,)) + link2 = reverse('admin:admin_views_person_change', args=(p2.pk,)) + link3 = reverse('admin:admin_views_person_change', args=(p3.pk,)) # Sort by name, gender # This hard-codes the URL because it'll fail if it runs against the # 'admin2' custom admin (which doesn't have the Person model). response = self.client.get('/test_admin/admin/admin_views/person/', {'o': '1.2'}) - self.assertContentBefore(response, link % p3.id, link % p1.id) - self.assertContentBefore(response, link % p1.id, link % p2.id) + self.assertContentBefore(response, link3, link1) + self.assertContentBefore(response, link1, link2) # Sort by gender descending, name response = self.client.get('/test_admin/admin/admin_views/person/', {'o': '-2.1'}) - self.assertContentBefore(response, link % p2.id, link % p3.id) - self.assertContentBefore(response, link % p3.id, link % p1.id) + self.assertContentBefore(response, link2, link3) + self.assertContentBefore(response, link3, link1) def testChangeListSortingPreserveQuerySetOrdering(self): """ @@ -284,37 +287,41 @@ class AdminViewBasicTest(TestCase): p1 = Person.objects.create(name="Amy", gender=1, alive=True, age=80) p2 = Person.objects.create(name="Bob", gender=1, alive=True, age=70) p3 = Person.objects.create(name="Chris", gender=2, alive=False, age=60) - link = '<a href="%s/' + link1 = reverse('admin:admin_views_person_change', args=(p1.pk,)) + link2 = reverse('admin:admin_views_person_change', args=(p2.pk,)) + link3 = reverse('admin:admin_views_person_change', args=(p3.pk,)) # This hard-codes the URL because it'll fail if it runs against the # 'admin2' custom admin (which doesn't have the Person model). response = self.client.get('/test_admin/admin/admin_views/person/', {}) - self.assertContentBefore(response, link % p3.id, link % p2.id) - self.assertContentBefore(response, link % p2.id, link % p1.id) + self.assertContentBefore(response, link3, link2) + self.assertContentBefore(response, link2, link1) def testChangeListSortingModelMeta(self): # Test ordering on Model Meta is respected l1 = Language.objects.create(iso='ur', name='Urdu') l2 = Language.objects.create(iso='ar', name='Arabic') - link = '<a href="%s/' + link1 = reverse('admin:admin_views_language_change', args=(quote(l1.pk),)) + link2 = reverse('admin:admin_views_language_change', args=(quote(l2.pk),)) response = self.client.get('/test_admin/admin/admin_views/language/', {}) - self.assertContentBefore(response, link % l2.pk, link % l1.pk) + self.assertContentBefore(response, link2, link1) # Test we can override with query string - response = self.client.get('/test_admin/admin/admin_views/language/', {'o':'-1'}) - self.assertContentBefore(response, link % l1.pk, link % l2.pk) + response = self.client.get('/test_admin/admin/admin_views/language/', {'o': '-1'}) + self.assertContentBefore(response, link1, link2) def testChangeListSortingOverrideModelAdmin(self): # Test ordering on Model Admin is respected, and overrides Model Meta dt = datetime.datetime.now() p1 = Podcast.objects.create(name="A", release_date=dt) p2 = Podcast.objects.create(name="B", release_date=dt - datetime.timedelta(10)) + link1 = reverse('admin:admin_views_podcast_change', args=(p1.pk,)) + link2 = reverse('admin:admin_views_podcast_change', args=(p2.pk,)) - link = '<a href="%s/' response = self.client.get('/test_admin/admin/admin_views/podcast/', {}) - self.assertContentBefore(response, link % p1.pk, link % p2.pk) + self.assertContentBefore(response, link1, link2) def testMultipleSortSameField(self): # Check that we get the columns we expect if we have two columns @@ -322,14 +329,16 @@ class AdminViewBasicTest(TestCase): dt = datetime.datetime.now() p1 = Podcast.objects.create(name="A", release_date=dt) p2 = Podcast.objects.create(name="B", release_date=dt - datetime.timedelta(10)) + link1 = reverse('admin:admin_views_podcast_change', args=(quote(p1.pk),)) + link2 = reverse('admin:admin_views_podcast_change', args=(quote(p2.pk),)) - link = '<a href="%s/' response = self.client.get('/test_admin/admin/admin_views/podcast/', {}) - self.assertContentBefore(response, link % p1.pk, link % p2.pk) + self.assertContentBefore(response, link1, link2) p1 = ComplexSortedPerson.objects.create(name="Bob", age=10) p2 = ComplexSortedPerson.objects.create(name="Amy", age=20) - link = '<a href="%s/' + link1 = reverse('admin:admin_views_complexsortedperson_change', args=(p1.pk,)) + link2 = reverse('admin:admin_views_complexsortedperson_change', args=(p2.pk,)) response = self.client.get('/test_admin/admin/admin_views/complexsortedperson/', {}) # Should have 5 columns (including action checkbox col) @@ -342,7 +351,7 @@ class AdminViewBasicTest(TestCase): self.assertContentBefore(response, 'Name', 'Colored name') # Check sorting - should be by name - self.assertContentBefore(response, link % p2.id, link % p1.id) + self.assertContentBefore(response, link2, link1) def testSortIndicatorsAdminOrder(self): """ @@ -350,13 +359,13 @@ class AdminViewBasicTest(TestCase): kinds of 'ordering' fields: field names, method on the model admin and model itself, and other callables. See #17252. """ - models = [(AdminOrderedField, 'adminorderedfield' ), + models = [(AdminOrderedField, 'adminorderedfield'), (AdminOrderedModelMethod, 'adminorderedmodelmethod'), (AdminOrderedAdminMethod, 'adminorderedadminmethod'), - (AdminOrderedCallable, 'adminorderedcallable' )] + (AdminOrderedCallable, 'adminorderedcallable')] for model, url in models: - a1 = model.objects.create(stuff='The Last Item', order=3) - a2 = model.objects.create(stuff='The First Item', order=1) + a1 = model.objects.create(stuff='The Last Item', order=3) + a2 = model.objects.create(stuff='The First Item', order=1) a3 = model.objects.create(stuff='The Middle Item', order=2) response = self.client.get('/test_admin/admin/admin_views/%s/' % url, {}) self.assertEqual(response.status_code, 200) @@ -461,10 +470,12 @@ class AdminViewBasicTest(TestCase): for rows corresponding to instances of a model in which a named group has been used in the choices option of a field. """ + link1 = reverse('admin:admin_views_fabric_change', args=(1,), current_app=self.urlbit) + link2 = reverse('admin:admin_views_fabric_change', args=(2,), current_app=self.urlbit) response = self.client.get('/test_admin/%s/admin_views/fabric/' % self.urlbit) fail_msg = "Changelist table isn't showing the right human-readable values set by a model field 'choices' option named group." - self.assertContains(response, '<a href="1/">Horizontal</a>', msg_prefix=fail_msg, html=True) - self.assertContains(response, '<a href="2/">Vertical</a>', msg_prefix=fail_msg, html=True) + self.assertContains(response, '<a href="%s">Horizontal</a>' % link1, msg_prefix=fail_msg, html=True) + self.assertContains(response, '<a href="%s">Vertical</a>' % link2, msg_prefix=fail_msg, html=True) def testNamedGroupFieldChoicesFilter(self): """ @@ -661,7 +672,6 @@ class AdminJavaScriptTest(TestCase): '<script type="text/javascript">document.getElementById("id_start_date_0").focus();</script>' ) - def test_js_minified_only_if_debug_is_false(self): """ Ensure that the minified versions of the JS files are only used when @@ -699,7 +709,7 @@ class AdminJavaScriptTest(TestCase): @override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',)) class SaveAsTests(TestCase): urls = "regressiontests.admin_views.urls" - fixtures = ['admin-views-users.xml','admin-views-person.xml'] + fixtures = ['admin-views-users.xml', 'admin-views-person.xml'] def setUp(self): self.client.login(username='super', password='secret') @@ -709,7 +719,7 @@ class SaveAsTests(TestCase): def test_save_as_duplication(self): """Ensure save as actually creates a new person""" - post_data = {'_saveasnew':'', 'name':'John M', 'gender':1, 'age': 42} + post_data = {'_saveasnew': '', 'name': 'John M', 'gender': 1, 'age': 42} response = self.client.post('/test_admin/admin/admin_views/person/1/', post_data) self.assertEqual(len(Person.objects.filter(name='John M')), 1) self.assertEqual(len(Person.objects.filter(id=1)), 1) @@ -722,10 +732,11 @@ class SaveAsTests(TestCase): """ response = self.client.get('/test_admin/admin/admin_views/person/1/') self.assertTrue(response.context['save_as']) - post_data = {'_saveasnew':'', 'name':'John M', 'gender':3, 'alive':'checked'} + post_data = {'_saveasnew': '', 'name': 'John M', 'gender': 3, 'alive': 'checked'} response = self.client.post('/test_admin/admin/admin_views/person/1/', post_data) self.assertEqual(response.context['form_url'], '/test_admin/admin/admin_views/person/add/') + class CustomModelAdminTest(AdminViewBasicTest): urls = "regressiontests.admin_views.urls" urlbit = "admin2" @@ -781,11 +792,13 @@ class CustomModelAdminTest(AdminViewBasicTest): response = self.client.get('/test_admin/%s/my_view/' % self.urlbit) self.assertEqual(response.content, b"Django is a magical pony!") + def get_perm(Model, perm): """Return the permission object, for the Model""" ct = ContentType.objects.get_for_model(Model) return Permission.objects.get(content_type=ct, codename=perm) + @override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',)) class AdminViewPermissionsTest(TestCase): """Tests for Admin Views Permissions.""" @@ -884,17 +897,17 @@ class AdminViewPermissionsTest(TestCase): self.assertFalse(login.context) self.client.get('/test_admin/admin/logout/') - # Test if user enters e-mail address + # Test if user enters email address response = self.client.get('/test_admin/admin/') self.assertEqual(response.status_code, 200) login = self.client.post('/test_admin/admin/', self.super_email_login) - self.assertContains(login, "Your e-mail address is not your username") + self.assertContains(login, ERROR_MESSAGE) # only correct passwords get a username hint login = self.client.post('/test_admin/admin/', self.super_email_bad_login) self.assertContains(login, ERROR_MESSAGE) new_user = User(username='jondoe', password='secret', email='super@example.com') new_user.save() - # check to ensure if there are multiple e-mail addresses a user doesn't get a 500 + # check to ensure if there are multiple email addresses a user doesn't get a 500 login = self.client.post('/test_admin/admin/', self.super_email_login) self.assertContains(login, ERROR_MESSAGE) @@ -949,7 +962,7 @@ class AdminViewPermissionsTest(TestCase): def testAddView(self): """Test add view restricts access and actually adds items.""" - add_dict = {'title' : 'Døm ikke', + add_dict = {'title': 'Døm ikke', 'content': '<p>great article</p>', 'date_0': '2008-03-18', 'date_1': '10:54:39', 'section': 1} @@ -1004,7 +1017,7 @@ class AdminViewPermissionsTest(TestCase): def testChangeView(self): """Change view should restrict access and allow users to edit items.""" - change_dict = {'title' : 'Ikke fordømt', + change_dict = {'title': 'Ikke fordømt', 'content': '<p>edited article</p>', 'date_0': '2008-03-18', 'date_1': '10:54:39', 'section': 1} @@ -1336,6 +1349,7 @@ class AdminViewDeletedObjectsTest(TestCase): response = self.client.get('/test_admin/admin/admin_views/plot/%s/delete/' % quote(3)) self.assertContains(response, should_contain) + @override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',)) class AdminViewStringPrimaryKeyTest(TestCase): urls = "regressiontests.admin_views.urls" @@ -1371,9 +1385,12 @@ class AdminViewStringPrimaryKeyTest(TestCase): self.assertEqual(response.status_code, 200) def test_changelist_to_changeform_link(self): - "The link from the changelist referring to the changeform of the object should be quoted" - response = self.client.get('/test_admin/admin/admin_views/modelwithstringprimarykey/') - should_contain = """<th><a href="%s/">%s</a></th></tr>""" % (escape(quote(self.pk)), escape(self.pk)) + "Link to the changeform of the object in changelist should use reverse() and be quoted -- #18072" + prefix = '/test_admin/admin/admin_views/modelwithstringprimarykey/' + response = self.client.get(prefix) + # this URL now comes through reverse(), thus iri_to_uri encoding + pk_final_url = escape(iri_to_uri(quote(self.pk))) + should_contain = """<th><a href="%s%s/">%s</a></th>""" % (prefix, pk_final_url, escape(self.pk)) self.assertContains(response, should_contain) def test_recentactions_link(self): @@ -1387,7 +1404,7 @@ class AdminViewStringPrimaryKeyTest(TestCase): response = self.client.get('/test_admin/admin/') should_contain = """<a href="admin_views/modelwithstringprimarykey/%s/">%s</a>""" % (escape(quote(self.pk)), escape(self.pk)) self.assertContains(response, should_contain) - should_contain = "Model with string primary key" # capitalized in Recent Actions + should_contain = "Model with string primary key" # capitalized in Recent Actions self.assertContains(response, should_contain) logentry = LogEntry.objects.get(content_type__name__iexact=should_contain) # http://code.djangoproject.com/ticket/10275 @@ -1441,6 +1458,18 @@ class AdminViewStringPrimaryKeyTest(TestCase): should_contain = '/%s/" class="viewsitelink">' % model.pk self.assertContains(response, should_contain) + def test_change_view_history_link(self): + """Object history button link should work and contain the pk value quoted.""" + url = reverse('admin:%s_modelwithstringprimarykey_change' % + ModelWithStringPrimaryKey._meta.app_label, + args=(quote(self.pk),)) + response = self.client.get(url) + self.assertEqual(response.status_code, 200) + expected_link = reverse('admin:%s_modelwithstringprimarykey_history' % + ModelWithStringPrimaryKey._meta.app_label, + args=(quote(self.pk),)) + self.assertContains(response, '<a href="%s" class="historylink"' % expected_link) + @override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',)) class SecureViewTests(TestCase): @@ -1497,7 +1526,7 @@ class SecureViewTests(TestCase): def test_secure_view_shows_login_if_not_logged_in(self): "Ensure that we see the login form" - response = self.client.get('/test_admin/admin/secure-view/' ) + response = self.client.get('/test_admin/admin/secure-view/') self.assertTemplateUsed(response, 'admin/login.html') def test_secure_view_login_successfully_redirects_to_original_url(self): @@ -1527,17 +1556,17 @@ class SecureViewTests(TestCase): # make sure the view removes test cookie self.assertEqual(self.client.session.test_cookie_worked(), False) - # Test if user enters e-mail address + # Test if user enters email address response = self.client.get('/test_admin/admin/secure-view/') self.assertEqual(response.status_code, 200) login = self.client.post('/test_admin/admin/secure-view/', self.super_email_login) - self.assertContains(login, "Your e-mail address is not your username") + self.assertContains(login, ERROR_MESSAGE) # only correct passwords get a username hint login = self.client.post('/test_admin/admin/secure-view/', self.super_email_bad_login) self.assertContains(login, ERROR_MESSAGE) new_user = User(username='jondoe', password='secret', email='super@example.com') new_user.save() - # check to ensure if there are multiple e-mail addresses a user doesn't get a 500 + # check to ensure if there are multiple email addresses a user doesn't get a 500 login = self.client.post('/test_admin/admin/secure-view/', self.super_email_login) self.assertContains(login, ERROR_MESSAGE) @@ -1601,6 +1630,7 @@ class SecureViewTests(TestCase): self.assertEqual(response.status_code, 302) self.assertEqual(response['Location'], 'http://example.com/users/super/') + @override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',)) class AdminViewUnicodeTest(TestCase): urls = "regressiontests.admin_views.urls" @@ -1643,7 +1673,7 @@ class AdminViewUnicodeTest(TestCase): } response = self.client.post('/test_admin/admin/admin_views/book/1/', post_data) - self.assertEqual(response.status_code, 302) # redirect somewhere + self.assertEqual(response.status_code, 302) # redirect somewhere def testUnicodeDelete(self): """ @@ -2010,7 +2040,7 @@ class AdminViewListEditable(TestCase): story1 = Story.objects.create(title='The adventures of Guido', content='Once upon a time in Djangoland...') story2 = Story.objects.create(title='Crouching Tiger, Hidden Python', content='The Python was sneaking into...') response = self.client.get('/test_admin/admin/admin_views/story/') - self.assertContains(response, 'id="id_form-0-id"', 1) # Only one hidden field, in a separate place than the table. + self.assertContains(response, 'id="id_form-0-id"', 1) # Only one hidden field, in a separate place than the table. self.assertContains(response, 'id="id_form-1-id"', 1) self.assertContains(response, '<div class="hiddenfields">\n<input type="hidden" name="form-0-id" value="%d" id="id_form-0-id" /><input type="hidden" name="form-1-id" value="%d" id="id_form-1-id" />\n</div>' % (story2.id, story1.id), html=True) self.assertContains(response, '<td>%d</td>' % story1.id, 1) @@ -2023,12 +2053,14 @@ class AdminViewListEditable(TestCase): """ story1 = OtherStory.objects.create(title='The adventures of Guido', content='Once upon a time in Djangoland...') story2 = OtherStory.objects.create(title='Crouching Tiger, Hidden Python', content='The Python was sneaking into...') + link1 = reverse('admin:admin_views_otherstory_change', args=(story1.pk,)) + link2 = reverse('admin:admin_views_otherstory_change', args=(story2.pk,)) response = self.client.get('/test_admin/admin/admin_views/otherstory/') - self.assertContains(response, 'id="id_form-0-id"', 1) # Only one hidden field, in a separate place than the table. + self.assertContains(response, 'id="id_form-0-id"', 1) # Only one hidden field, in a separate place than the table. self.assertContains(response, 'id="id_form-1-id"', 1) self.assertContains(response, '<div class="hiddenfields">\n<input type="hidden" name="form-0-id" value="%d" id="id_form-0-id" /><input type="hidden" name="form-1-id" value="%d" id="id_form-1-id" />\n</div>' % (story2.id, story1.id), html=True) - self.assertContains(response, '<th><a href="%d/">%d</a></th>' % (story1.id, story1.id), 1) - self.assertContains(response, '<th><a href="%d/">%d</a></th>' % (story2.id, story2.id), 1) + self.assertContains(response, '<th><a href="%s">%d</a></th>' % (link1, story1.id), 1) + self.assertContains(response, '<th><a href="%s">%d</a></th>' % (link2, story2.id), 1) @override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',)) @@ -2082,7 +2114,7 @@ class AdminSearchTest(TestCase): @override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',)) class AdminInheritedInlinesTest(TestCase): urls = "regressiontests.admin_views.urls" - fixtures = ['admin-views-users.xml',] + fixtures = ['admin-views-users.xml'] def setUp(self): self.client.login(username='super', password='secret') @@ -2119,7 +2151,7 @@ class AdminInheritedInlinesTest(TestCase): } response = self.client.post('/test_admin/admin/admin_views/persona/add/', post_data) - self.assertEqual(response.status_code, 302) # redirect somewhere + self.assertEqual(response.status_code, 302) # redirect somewhere self.assertEqual(Persona.objects.count(), 1) self.assertEqual(FooAccount.objects.count(), 1) self.assertEqual(BarAccount.objects.count(), 1) @@ -2166,6 +2198,7 @@ class AdminInheritedInlinesTest(TestCase): self.assertEqual(BarAccount.objects.all()[0].username, "%s-1" % bar_user) self.assertEqual(Persona.objects.all()[0].accounts.count(), 2) + @override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',)) class AdminActionsTest(TestCase): urls = "regressiontests.admin_views.urls" @@ -2181,7 +2214,7 @@ class AdminActionsTest(TestCase): "Tests a custom action defined in a ModelAdmin method" action_data = { ACTION_CHECKBOX_NAME: [1], - 'action' : 'mail_admin', + 'action': 'mail_admin', 'index': 0, } response = self.client.post('/test_admin/admin/admin_views/subscriber/', action_data) @@ -2192,12 +2225,12 @@ class AdminActionsTest(TestCase): "Tests the default delete action defined as a ModelAdmin method" action_data = { ACTION_CHECKBOX_NAME: [1, 2], - 'action' : 'delete_selected', + 'action': 'delete_selected', 'index': 0, } delete_confirmation_data = { ACTION_CHECKBOX_NAME: [1, 2], - 'action' : 'delete_selected', + 'action': 'delete_selected', 'post': 'yes', } confirmation = self.client.post('/test_admin/admin/admin_views/subscriber/', action_data) @@ -2221,12 +2254,12 @@ class AdminActionsTest(TestCase): subscriber.save() action_data = { ACTION_CHECKBOX_NAME: [9999, 2], - 'action' : 'delete_selected', + 'action': 'delete_selected', 'index': 0, } response = self.client.post('/test_admin/admin/admin_views/subscriber/', action_data) self.assertTemplateUsed(response, 'admin/delete_selected_confirmation.html') - self.assertContains(response, 'value="9999"') # Instead of 9,999 + self.assertContains(response, 'value="9999"') # Instead of 9,999 self.assertContains(response, 'value="2"') settings.USE_THOUSAND_SEPARATOR = self.old_USE_THOUSAND_SEPARATOR settings.USE_L10N = self.old_USE_L10N @@ -2243,7 +2276,7 @@ class AdminActionsTest(TestCase): action_data = { ACTION_CHECKBOX_NAME: [q1.pk, q2.pk], - 'action' : 'delete_selected', + 'action': 'delete_selected', 'index': 0, } @@ -2257,7 +2290,7 @@ class AdminActionsTest(TestCase): "Tests a custom action defined in a function" action_data = { ACTION_CHECKBOX_NAME: [1], - 'action' : 'external_mail', + 'action': 'external_mail', 'index': 0, } response = self.client.post('/test_admin/admin/admin_views/externalsubscriber/', action_data) @@ -2268,7 +2301,7 @@ class AdminActionsTest(TestCase): "Tests a custom action defined in a function" action_data = { ACTION_CHECKBOX_NAME: [1], - 'action' : 'redirect_to', + 'action': 'redirect_to', 'index': 0, } response = self.client.post('/test_admin/admin/admin_views/externalsubscriber/', action_data) @@ -2282,7 +2315,7 @@ class AdminActionsTest(TestCase): """ action_data = { ACTION_CHECKBOX_NAME: [1], - 'action' : 'external_mail', + 'action': 'external_mail', 'index': 0, } url = '/test_admin/admin/admin_views/externalsubscriber/?o=1' @@ -2347,7 +2380,7 @@ class AdminActionsTest(TestCase): """ action_data = { ACTION_CHECKBOX_NAME: [], - 'action' : 'delete_selected', + 'action': 'delete_selected', 'index': 0, } response = self.client.post('/test_admin/admin/admin_views/subscriber/', action_data) @@ -2361,7 +2394,7 @@ class AdminActionsTest(TestCase): """ action_data = { ACTION_CHECKBOX_NAME: [1, 2], - 'action' : '', + 'action': '', 'index': 0, } response = self.client.post('/test_admin/admin/admin_views/subscriber/', action_data) @@ -2405,7 +2438,7 @@ class TestCustomChangeList(TestCase): # Insert some data post_data = {"name": "First Gadget"} response = self.client.post('/test_admin/%s/admin_views/gadget/add/' % self.urlbit, post_data) - self.assertEqual(response.status_code, 302) # redirect somewhere + self.assertEqual(response.status_code, 302) # redirect somewhere # Hit the page once to get messages out of the queue message list response = self.client.get('/test_admin/%s/admin_views/gadget/' % self.urlbit) # Ensure that that data is still not visible on the page @@ -2433,6 +2466,7 @@ class TestInlineNotEditable(TestCase): response = self.client.get('/test_admin/admin/admin_views/parent/add/') self.assertEqual(response.status_code, 200) + @override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',)) class AdminCustomQuerysetTest(TestCase): urls = "regressiontests.admin_views.urls" @@ -2489,6 +2523,7 @@ class AdminCustomQuerysetTest(TestCase): # Message should contain non-ugly model name. Instance representation is set by model's __unicode__() self.assertContains(response, '<li class="info">The cover letter "John Doe II" was changed successfully.</li>', html=True) + @override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',)) class AdminInlineFileUploadTest(TestCase): urls = "regressiontests.admin_views.urls" @@ -2629,7 +2664,7 @@ class AdminInlineTests(TestCase): result = self.client.login(username='super', password='secret') self.assertEqual(result, True) - self.collector = Collector(pk=1,name='John Fowles') + self.collector = Collector(pk=1, name='John Fowles') self.collector.save() def tearDown(self): @@ -2955,14 +2990,14 @@ class PrePopulatedTest(TestCase): self.assertNotContains(response, "field['dependency_ids'].push('#id_title');") self.assertNotContains(response, "id: '#id_prepopulatedsubpost_set-0-subslug',") - @override_settings(USE_THOUSAND_SEPARATOR = True, USE_L10N = True) + @override_settings(USE_THOUSAND_SEPARATOR=True, USE_L10N=True) def test_prepopulated_maxlength_localized(self): """ Regression test for #15938: if USE_THOUSAND_SEPARATOR is set, make sure that maxLength (in the JavaScript) is rendered without separators. """ response = self.client.get('/test_admin/admin/admin_views/prepopulatedpostlargeslug/add/') - self.assertContains(response, "maxLength: 1000") # instead of 1,000 + self.assertContains(response, "maxLength: 1000") # instead of 1,000 @override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',)) @@ -3008,8 +3043,8 @@ class SeleniumPrePopulatedFirefoxTests(AdminSeleniumWebDriverTestCase): self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-1-name').send_keys(' now you haVe anöther sŤāÇkeð inline with a very ... loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooog text... ') slug1 = self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-1-slug1').get_attribute('value') slug2 = self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-1-slug2').get_attribute('value') - self.assertEqual(slug1, 'now-you-have-another-stacked-inline-very-loooooooo') # 50 characters maximum for slug1 field - self.assertEqual(slug2, 'option-two-now-you-have-another-stacked-inline-very-looooooo') # 60 characters maximum for slug2 field + self.assertEqual(slug1, 'now-you-have-another-stacked-inline-very-loooooooo') # 50 characters maximum for slug1 field + self.assertEqual(slug2, 'option-two-now-you-have-another-stacked-inline-very-looooooo') # 60 characters maximum for slug2 field # Tabular inlines ---------------------------------------------------- # Initial inline @@ -3060,7 +3095,7 @@ class SeleniumPrePopulatedFirefoxTests(AdminSeleniumWebDriverTestCase): slug2='option-one-here-stacked-inline', ) RelatedPrepopulated.objects.get( - name=' now you haVe anöther sŤāÇkeð inline with a very ... loooooooooooooooooo', # 75 characters in name field + name=' now you haVe anöther sŤāÇkeð inline with a very ... loooooooooooooooooo', # 75 characters in name field pubdate='1999-01-25', status='option two', slug1='now-you-have-another-stacked-inline-very-loooooooo', @@ -3085,6 +3120,7 @@ class SeleniumPrePopulatedFirefoxTests(AdminSeleniumWebDriverTestCase): class SeleniumPrePopulatedChromeTests(SeleniumPrePopulatedFirefoxTests): webdriver_class = 'selenium.webdriver.chrome.webdriver.WebDriver' + class SeleniumPrePopulatedIETests(SeleniumPrePopulatedFirefoxTests): webdriver_class = 'selenium.webdriver.ie.webdriver.WebDriver' @@ -3145,7 +3181,7 @@ class ReadonlyTest(TestCase): p = Post.objects.get() self.assertEqual(p.posted, datetime.date.today()) - data["posted"] = "10-8-1990" # some date that's not today + data["posted"] = "10-8-1990" # some date that's not today response = self.client.post('/test_admin/admin/admin_views/post/add/', data) self.assertEqual(response.status_code, 302) self.assertEqual(Post.objects.count(), 2) @@ -3187,7 +3223,7 @@ class RawIdFieldsTest(TestCase): response = self.client.get('/test_admin/admin/admin_views/sketch/add/') # Find the link m = re.search(br'<a href="([^"]*)"[^>]* id="lookup_id_inquisition"', response.content) - self.assertTrue(m) # Got a match + self.assertTrue(m) # Got a match popup_url = m.groups()[0].decode().replace("&", "&") # Handle relative links @@ -3197,6 +3233,7 @@ class RawIdFieldsTest(TestCase): self.assertContains(response2, "Spain") self.assertNotContains(response2, "England") + @override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',)) class UserAdminTest(TestCase): """ @@ -3351,7 +3388,7 @@ class CSSTest(TestCase): self.assertContains(response, 'class="form-row field-awesomeness_level"') self.assertContains(response, 'class="form-row field-coolness"') self.assertContains(response, 'class="form-row field-value"') - self.assertContains(response, 'class="form-row"') # The lambda function + self.assertContains(response, 'class="form-row"') # The lambda function # The tabular inline self.assertContains(response, '<td class="field-url">') @@ -3363,6 +3400,7 @@ try: except ImportError: docutils = None + @unittest.skipUnless(docutils, "no docutils installed.") @override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',)) class AdminDocsTest(TestCase): @@ -3421,7 +3459,7 @@ class ValidXHTMLTests(TestCase): @override_settings( TEMPLATE_CONTEXT_PROCESSORS=filter( - lambda t:t!='django.core.context_processors.i18n', + lambda t: t != 'django.core.context_processors.i18n', global_settings.TEMPLATE_CONTEXT_PROCESSORS), USE_I18N=False, ) @@ -3558,6 +3596,7 @@ class DateHierarchyTests(TestCase): self.assert_non_localized_year(response, 2003) self.assert_non_localized_year(response, 2005) + @override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',)) class AdminCustomSaveRelatedTests(TestCase): """ diff --git a/tests/regressiontests/aggregation_regress/tests.py b/tests/regressiontests/aggregation_regress/tests.py index b9f3ab27eb..af0f421502 100644 --- a/tests/regressiontests/aggregation_regress/tests.py +++ b/tests/regressiontests/aggregation_regress/tests.py @@ -878,3 +878,14 @@ class AggregationTests(TestCase): connection.ops.convert_values(testData, testField), testData ) + + def test_annotate_joins(self): + """ + Test that the base table's join isn't promoted to LOUTER. This could + cause the query generation to fail if there is an exclude() for fk-field + in the query, too. Refs #19087. + """ + qs = Book.objects.annotate(n=Count('pk')) + self.assertIs(qs.query.alias_map['aggregation_regress_book'].join_type, None) + # Check that the query executes without problems. + self.assertEqual(len(qs.exclude(publisher=-1)), 6) diff --git a/tests/regressiontests/backends/tests.py b/tests/regressiontests/backends/tests.py index cfa298253c..d284cfaac8 100644 --- a/tests/regressiontests/backends/tests.py +++ b/tests/regressiontests/backends/tests.py @@ -666,13 +666,6 @@ class ThreadTests(TestCase): self.assertEqual(len(exceptions), 0) -class BackendLoadingTests(TestCase): - def test_old_style_backends_raise_useful_exception(self): - six.assertRaisesRegex(self, ImproperlyConfigured, - "Try using django.db.backends.sqlite3 instead", - load_backend, 'sqlite3') - - class MySQLPKZeroTests(TestCase): """ Zero as id for AutoField should raise exception in MySQL, because MySQL diff --git a/tests/regressiontests/bulk_create/tests.py b/tests/regressiontests/bulk_create/tests.py index 33108ea9b0..5d61242b9b 100644 --- a/tests/regressiontests/bulk_create/tests.py +++ b/tests/regressiontests/bulk_create/tests.py @@ -3,7 +3,7 @@ from __future__ import absolute_import from operator import attrgetter from django.db import connection -from django.test import TestCase, skipIfDBFeature +from django.test import TestCase, skipIfDBFeature, skipUnlessDBFeature from django.test.utils import override_settings from .models import Country, Restaurant, Pizzeria, State, TwoFields @@ -29,6 +29,7 @@ class BulkCreateTests(TestCase): self.assertEqual(created, []) self.assertEqual(Country.objects.count(), 4) + @skipUnlessDBFeature('has_bulk_insert') def test_efficiency(self): with self.assertNumQueries(1): Country.objects.bulk_create(self.data) @@ -50,6 +51,16 @@ class BulkCreateTests(TestCase): ], attrgetter("name")) def test_non_auto_increment_pk(self): + State.objects.bulk_create([ + State(two_letter_code=s) + for s in ["IL", "NY", "CA", "ME"] + ]) + self.assertQuerysetEqual(State.objects.order_by("two_letter_code"), [ + "CA", "IL", "ME", "NY", + ], attrgetter("two_letter_code")) + + @skipUnlessDBFeature('has_bulk_insert') + def test_non_auto_increment_pk_efficiency(self): with self.assertNumQueries(1): State.objects.bulk_create([ State(two_letter_code=s) @@ -77,13 +88,21 @@ class BulkCreateTests(TestCase): TwoFields.objects.bulk_create([ TwoFields(f1=i, f2=i+1) for i in range(0, 1001) ]) - self.assertTrue(len(connection.queries) < 10) self.assertEqual(TwoFields.objects.count(), 1001) self.assertEqual( TwoFields.objects.filter(f1__gte=450, f1__lte=550).count(), 101) self.assertEqual(TwoFields.objects.filter(f2__gte=901).count(), 101) + @skipUnlessDBFeature('has_bulk_insert') + def test_large_batch_efficiency(self): + with override_settings(DEBUG=True): + connection.queries = [] + TwoFields.objects.bulk_create([ + TwoFields(f1=i, f2=i+1) for i in range(0, 1001) + ]) + self.assertTrue(len(connection.queries) < 10) + def test_large_batch_mixed(self): """ Test inserting a large batch with objects having primary key set @@ -94,7 +113,6 @@ class BulkCreateTests(TestCase): TwoFields.objects.bulk_create([ TwoFields(id=i if i % 2 == 0 else None, f1=i, f2=i+1) for i in range(100000, 101000)]) - self.assertTrue(len(connection.queries) < 10) self.assertEqual(TwoFields.objects.count(), 1000) # We can't assume much about the ID's created, except that the above # created IDs must exist. @@ -102,7 +120,29 @@ class BulkCreateTests(TestCase): self.assertEqual(TwoFields.objects.filter(id__in=id_range).count(), 500) self.assertEqual(TwoFields.objects.exclude(id__in=id_range).count(), 500) + @skipUnlessDBFeature('has_bulk_insert') + def test_large_batch_mixed_efficiency(self): + """ + Test inserting a large batch with objects having primary key set + mixed together with objects without PK set. + """ + with override_settings(DEBUG=True): + connection.queries = [] + TwoFields.objects.bulk_create([ + TwoFields(id=i if i % 2 == 0 else None, f1=i, f2=i+1) + for i in range(100000, 101000)]) + self.assertTrue(len(connection.queries) < 10) + def test_explicit_batch_size(self): + objs = [TwoFields(f1=i, f2=i) for i in range(0, 4)] + TwoFields.objects.bulk_create(objs, 2) + self.assertEqual(TwoFields.objects.count(), len(objs)) + TwoFields.objects.all().delete() + TwoFields.objects.bulk_create(objs, len(objs)) + self.assertEqual(TwoFields.objects.count(), len(objs)) + + @skipUnlessDBFeature('has_bulk_insert') + def test_explicit_batch_size_efficiency(self): objs = [TwoFields(f1=i, f2=i) for i in range(0, 100)] with self.assertNumQueries(2): TwoFields.objects.bulk_create(objs, 50) diff --git a/tests/regressiontests/cache/tests.py b/tests/regressiontests/cache/tests.py index de27bc9476..a6eff8950b 100644 --- a/tests/regressiontests/cache/tests.py +++ b/tests/regressiontests/cache/tests.py @@ -19,7 +19,8 @@ from django.core.cache import get_cache from django.core.cache.backends.base import (CacheKeyWarning, InvalidCacheBackendError) from django.db import router -from django.http import HttpResponse, HttpRequest, QueryDict +from django.http import (HttpResponse, HttpRequest, StreamingHttpResponse, + QueryDict) from django.middleware.cache import (FetchFromCacheMiddleware, UpdateCacheMiddleware, CacheMiddleware) from django.template import Template @@ -1416,6 +1417,29 @@ class CacheI18nTest(TestCase): # reset the language translation.deactivate() + @override_settings( + CACHE_MIDDLEWARE_KEY_PREFIX="test", + CACHE_MIDDLEWARE_SECONDS=60, + USE_ETAGS=True, + ) + def test_middleware_with_streaming_response(self): + # cache with non empty request.GET + request = self._get_request_cache(query_string='foo=baz&other=true') + + # first access, cache must return None + get_cache_data = FetchFromCacheMiddleware().process_request(request) + self.assertEqual(get_cache_data, None) + + # pass streaming response through UpdateCacheMiddleware. + content = 'Check for cache with QUERY_STRING and streaming content' + response = StreamingHttpResponse(content) + UpdateCacheMiddleware().process_response(request, response) + + # second access, cache must still return None, because we can't cache + # streaming response. + get_cache_data = FetchFromCacheMiddleware().process_request(request) + self.assertEqual(get_cache_data, None) + @override_settings( CACHES={ diff --git a/tests/regressiontests/comment_tests/tests/feed_tests.py b/tests/regressiontests/comment_tests/tests/feed_tests.py index b15ec0c7b8..1ec316eab8 100644 --- a/tests/regressiontests/comment_tests/tests/feed_tests.py +++ b/tests/regressiontests/comment_tests/tests/feed_tests.py @@ -1,12 +1,32 @@ from __future__ import absolute_import +from django.conf import settings +from django.contrib.comments.models import Comment +from django.contrib.contenttypes.models import ContentType +from django.contrib.sites.models import Site + from . import CommentTestCase +from ..models import Article class CommentFeedTests(CommentTestCase): urls = 'regressiontests.comment_tests.urls' feed_url = '/rss/comments/' + def setUp(self): + site_2 = Site.objects.create(id=settings.SITE_ID+1, + domain="example2.com", name="example2.com") + # A comment for another site + c5 = Comment.objects.create( + content_type = ContentType.objects.get_for_model(Article), + object_pk = "1", + user_name = "Joe Somebody", + user_email = "jsomebody@example.com", + user_url = "http://example.com/~joe/", + comment = "A comment for the second site.", + site = site_2, + ) + def test_feed(self): response = self.client.get(self.feed_url) self.assertEqual(response.status_code, 200) @@ -15,3 +35,4 @@ class CommentFeedTests(CommentTestCase): self.assertContains(response, '<title>example.com comments</title>') self.assertContains(response, '<link>http://example.com/</link>') self.assertContains(response, '</rss>') + self.assertNotContains(response, "A comment for the second site.") diff --git a/tests/regressiontests/comment_tests/urls.py b/tests/regressiontests/comment_tests/urls.py index b2f676786f..0a7e8b5fdf 100644 --- a/tests/regressiontests/comment_tests/urls.py +++ b/tests/regressiontests/comment_tests/urls.py @@ -15,6 +15,7 @@ urlpatterns = patterns('', url(r'^flag/(\d+)/$', views.custom_flag_comment), url(r'^delete/(\d+)/$', views.custom_delete_comment), url(r'^approve/(\d+)/$', views.custom_approve_comment), + url(r'^cr/(\d+)/(.+)/$', 'django.contrib.contenttypes.views.shortcut', name='comments-url-redirect'), ) urlpatterns += patterns('', diff --git a/tests/regressiontests/conditional_processing/models.py b/tests/regressiontests/conditional_processing/models.py index d0838e153d..b47fdf6fb5 100644 --- a/tests/regressiontests/conditional_processing/models.py +++ b/tests/regressiontests/conditional_processing/models.py @@ -4,8 +4,6 @@ from __future__ import unicode_literals from datetime import datetime from django.test import TestCase -from django.utils import unittest -from django.utils.http import parse_etags, quote_etag, parse_http_date FULL_RESPONSE = 'Test conditional get response' @@ -129,30 +127,3 @@ class ConditionalGet(TestCase): self.client.defaults['HTTP_IF_NONE_MATCH'] = r'"\"' response = self.client.get('/condition/etag/') self.assertFullResponse(response, check_last_modified=False) - - -class ETagProcessing(unittest.TestCase): - def testParsing(self): - etags = parse_etags(r'"", "etag", "e\"t\"ag", "e\\tag", W/"weak"') - self.assertEqual(etags, ['', 'etag', 'e"t"ag', r'e\tag', 'weak']) - - def testQuoting(self): - quoted_etag = quote_etag(r'e\t"ag') - self.assertEqual(quoted_etag, r'"e\\t\"ag"') - - -class HttpDateProcessing(unittest.TestCase): - def testParsingRfc1123(self): - parsed = parse_http_date('Sun, 06 Nov 1994 08:49:37 GMT') - self.assertEqual(datetime.utcfromtimestamp(parsed), - datetime(1994, 11, 6, 8, 49, 37)) - - def testParsingRfc850(self): - parsed = parse_http_date('Sunday, 06-Nov-94 08:49:37 GMT') - self.assertEqual(datetime.utcfromtimestamp(parsed), - datetime(1994, 11, 6, 8, 49, 37)) - - def testParsingAsctime(self): - parsed = parse_http_date('Sun Nov 6 08:49:37 1994') - self.assertEqual(datetime.utcfromtimestamp(parsed), - datetime(1994, 11, 6, 8, 49, 37)) diff --git a/tests/regressiontests/delete_regress/models.py b/tests/regressiontests/delete_regress/models.py index 5db253f713..dbe383fb41 100644 --- a/tests/regressiontests/delete_regress/models.py +++ b/tests/regressiontests/delete_regress/models.py @@ -2,7 +2,6 @@ from django.contrib.contenttypes import generic from django.contrib.contenttypes.models import ContentType from django.db import models - class Award(models.Model): name = models.CharField(max_length=25) object_id = models.PositiveIntegerField() @@ -93,3 +92,10 @@ class FooPhoto(models.Model): class FooFileProxy(FooFile): class Meta: proxy = True + +class OrgUnit(models.Model): + name = models.CharField(max_length=64, unique=True) + +class Login(models.Model): + description = models.CharField(max_length=32) + orgunit = models.ForeignKey(OrgUnit) diff --git a/tests/regressiontests/delete_regress/tests.py b/tests/regressiontests/delete_regress/tests.py index 32feae2ded..f94bb2f20c 100644 --- a/tests/regressiontests/delete_regress/tests.py +++ b/tests/regressiontests/delete_regress/tests.py @@ -3,12 +3,13 @@ from __future__ import absolute_import import datetime from django.conf import settings -from django.db import backend, transaction, DEFAULT_DB_ALIAS +from django.db import backend, transaction, DEFAULT_DB_ALIAS, models from django.test import TestCase, TransactionTestCase, skipUnlessDBFeature from .models import (Book, Award, AwardNote, Person, Child, Toy, PlayedWith, PlayedWithNote, Email, Researcher, Food, Eaten, Policy, Version, Location, - Item, Image, File, Photo, FooFile, FooImage, FooPhoto, FooFileProxy) + Item, Image, File, Photo, FooFile, FooImage, FooPhoto, FooFileProxy, Login, + OrgUnit) # Can't run this test under SQLite, because you can't @@ -139,17 +140,24 @@ class DeleteCascadeTransactionTests(TransactionTestCase): eaten = Eaten.objects.create(food=apple, meal="lunch") apple.delete() + self.assertFalse(Food.objects.exists()) + self.assertFalse(Eaten.objects.exists()) + class LargeDeleteTests(TestCase): def test_large_deletes(self): "Regression for #13309 -- if the number of objects > chunk size, deletion still occurs" for x in range(300): track = Book.objects.create(pagecount=x+100) + # attach a signal to make sure we will not fast-delete + def noop(*args, **kwargs): + pass + models.signals.post_delete.connect(noop, sender=Book) Book.objects.all().delete() + models.signals.post_delete.disconnect(noop, sender=Book) self.assertEqual(Book.objects.count(), 0) - class ProxyDeleteTest(TestCase): """ Tests on_delete behavior for proxy models. @@ -258,3 +266,92 @@ class ProxyDeleteTest(TestCase): Image.objects.all().delete() self.assertEqual(len(FooFileProxy.objects.all()), 0) + + def test_19187_values(self): + with self.assertRaises(TypeError): + Image.objects.values().delete() + with self.assertRaises(TypeError): + Image.objects.values_list().delete() + +class Ticket19102Tests(TestCase): + """ + Test different queries which alter the SELECT clause of the query. We + also must be using a subquery for the deletion (that is, the original + query has a join in it). The deletion should be done as "fast-path" + deletion (that is, just one query for the .delete() call). + + Note that .values() is not tested here on purpose. .values().delete() + doesn't work for non fast-path deletes at all. + """ + def setUp(self): + self.o1 = OrgUnit.objects.create(name='o1') + self.o2 = OrgUnit.objects.create(name='o2') + self.l1 = Login.objects.create(description='l1', orgunit=self.o1) + self.l2 = Login.objects.create(description='l2', orgunit=self.o2) + + @skipUnlessDBFeature("update_can_self_select") + def test_ticket_19102_annotate(self): + with self.assertNumQueries(1): + Login.objects.order_by('description').filter( + orgunit__name__isnull=False + ).annotate( + n=models.Count('description') + ).filter( + n=1, pk=self.l1.pk + ).delete() + self.assertFalse(Login.objects.filter(pk=self.l1.pk).exists()) + self.assertTrue(Login.objects.filter(pk=self.l2.pk).exists()) + + @skipUnlessDBFeature("update_can_self_select") + def test_ticket_19102_extra(self): + with self.assertNumQueries(1): + Login.objects.order_by('description').filter( + orgunit__name__isnull=False + ).extra( + select={'extraf':'1'} + ).filter( + pk=self.l1.pk + ).delete() + self.assertFalse(Login.objects.filter(pk=self.l1.pk).exists()) + self.assertTrue(Login.objects.filter(pk=self.l2.pk).exists()) + + @skipUnlessDBFeature("update_can_self_select") + @skipUnlessDBFeature('can_distinct_on_fields') + def test_ticket_19102_distinct_on(self): + # Both Login objs should have same description so that only the one + # having smaller PK will be deleted. + Login.objects.update(description='description') + with self.assertNumQueries(1): + Login.objects.distinct('description').order_by('pk').filter( + orgunit__name__isnull=False + ).delete() + # Assumed that l1 which is created first has smaller PK. + self.assertFalse(Login.objects.filter(pk=self.l1.pk).exists()) + self.assertTrue(Login.objects.filter(pk=self.l2.pk).exists()) + + @skipUnlessDBFeature("update_can_self_select") + def test_ticket_19102_select_related(self): + with self.assertNumQueries(1): + Login.objects.filter( + pk=self.l1.pk + ).filter( + orgunit__name__isnull=False + ).order_by( + 'description' + ).select_related('orgunit').delete() + self.assertFalse(Login.objects.filter(pk=self.l1.pk).exists()) + self.assertTrue(Login.objects.filter(pk=self.l2.pk).exists()) + + @skipUnlessDBFeature("update_can_self_select") + def test_ticket_19102_defer(self): + with self.assertNumQueries(1): + Login.objects.filter( + pk=self.l1.pk + ).filter( + orgunit__name__isnull=False + ).order_by( + 'description' + ).only('id').delete() + self.assertFalse(Login.objects.filter(pk=self.l1.pk).exists()) + self.assertTrue(Login.objects.filter(pk=self.l2.pk).exists()) + diff --git a/tests/regressiontests/dispatch/tests/test_dispatcher.py b/tests/regressiontests/dispatch/tests/test_dispatcher.py index 5f7094d5fa..5f8f92acaf 100644 --- a/tests/regressiontests/dispatch/tests/test_dispatcher.py +++ b/tests/regressiontests/dispatch/tests/test_dispatcher.py @@ -126,6 +126,17 @@ class DispatcherTests(unittest.TestCase): a_signal.disconnect(receiver_3) self._testIsClean(a_signal) + def test_has_listeners(self): + self.assertFalse(a_signal.has_listeners()) + self.assertFalse(a_signal.has_listeners(sender=object())) + receiver_1 = Callable() + a_signal.connect(receiver_1) + self.assertTrue(a_signal.has_listeners()) + self.assertTrue(a_signal.has_listeners(sender=object())) + a_signal.disconnect(receiver_1) + self.assertFalse(a_signal.has_listeners()) + self.assertFalse(a_signal.has_listeners(sender=object())) + class ReceiverTestCase(unittest.TestCase): """ diff --git a/tests/regressiontests/expressions_regress/tests.py b/tests/regressiontests/expressions_regress/tests.py index 80ddfadbe7..508a497151 100644 --- a/tests/regressiontests/expressions_regress/tests.py +++ b/tests/regressiontests/expressions_regress/tests.py @@ -128,7 +128,7 @@ class ExpressionOperatorTests(TestCase): def test_lefthand_bitwise_and(self): # LH Bitwise ands on integers - Number.objects.filter(pk=self.n.pk).update(integer=F('integer') & 56) + Number.objects.filter(pk=self.n.pk).update(integer=F('integer').bitand(56)) self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 40) self.assertEqual(Number.objects.get(pk=self.n.pk).float, Approximate(15.500, places=3)) @@ -136,7 +136,7 @@ class ExpressionOperatorTests(TestCase): @skipUnlessDBFeature('supports_bitwise_or') def test_lefthand_bitwise_or(self): # LH Bitwise or on integers - Number.objects.filter(pk=self.n.pk).update(integer=F('integer') | 48) + Number.objects.filter(pk=self.n.pk).update(integer=F('integer').bitor(48)) self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 58) self.assertEqual(Number.objects.get(pk=self.n.pk).float, Approximate(15.500, places=3)) @@ -181,20 +181,6 @@ class ExpressionOperatorTests(TestCase): self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 27) self.assertEqual(Number.objects.get(pk=self.n.pk).float, Approximate(15.500, places=3)) - def test_right_hand_bitwise_and(self): - # RH Bitwise ands on integers - Number.objects.filter(pk=self.n.pk).update(integer=15 & F('integer')) - - self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 10) - self.assertEqual(Number.objects.get(pk=self.n.pk).float, Approximate(15.500, places=3)) - - @skipUnlessDBFeature('supports_bitwise_or') - def test_right_hand_bitwise_or(self): - # RH Bitwise or on integers - Number.objects.filter(pk=self.n.pk).update(integer=15 | F('integer')) - - self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 47) - self.assertEqual(Number.objects.get(pk=self.n.pk).float, Approximate(15.500, places=3)) class FTimeDeltaTests(TestCase): @@ -385,7 +371,7 @@ class FTimeDeltaTests(TestCase): def test_delta_invalid_op_and(self): raised = False try: - r = repr(Experiment.objects.filter(end__lt=F('start')&self.deltas[0])) + r = repr(Experiment.objects.filter(end__lt=F('start').bitand(self.deltas[0]))) except TypeError: raised = True self.assertTrue(raised, "TypeError not raised on attempt to binary and a datetime with a timedelta.") @@ -393,7 +379,7 @@ class FTimeDeltaTests(TestCase): def test_delta_invalid_op_or(self): raised = False try: - r = repr(Experiment.objects.filter(end__lt=F('start')|self.deltas[0])) + r = repr(Experiment.objects.filter(end__lt=F('start').bitor(self.deltas[0]))) except TypeError: raised = True self.assertTrue(raised, "TypeError not raised on attempt to binary or a datetime with a timedelta.") diff --git a/tests/regressiontests/file_storage/tests.py b/tests/regressiontests/file_storage/tests.py index 281041e651..595b65d9f1 100644 --- a/tests/regressiontests/file_storage/tests.py +++ b/tests/regressiontests/file_storage/tests.py @@ -4,6 +4,7 @@ from __future__ import absolute_import, unicode_literals import errno import os import shutil +import sys import tempfile import time from datetime import datetime, timedelta @@ -23,6 +24,7 @@ from django.core.files.uploadedfile import UploadedFile from django.test import SimpleTestCase from django.utils import six from django.utils import unittest +from django.test.utils import override_settings from ..servers.tests import LiveServerBase # Try to import PIL in either of the two ways it can end up installed. @@ -76,7 +78,7 @@ class GetStorageClassTests(SimpleTestCase): six.assertRaisesRegex(self, ImproperlyConfigured, ('Error importing storage module django.core.files.non_existing_' - 'storage: "No module named .*non_existing_storage"'), + 'storage: "No module named .*non_existing_storage'), get_storage_class, 'django.core.files.non_existing_storage.NonExistingStorage' ) @@ -433,22 +435,29 @@ class FileSaveRaceConditionTest(unittest.TestCase): self.storage.delete('conflict') self.storage.delete('conflict_1') +@unittest.skipIf(sys.platform.startswith('win'), "Windows only partially supports umasks and chmod.") class FileStoragePermissions(unittest.TestCase): def setUp(self): - self.old_perms = settings.FILE_UPLOAD_PERMISSIONS - settings.FILE_UPLOAD_PERMISSIONS = 0o666 + self.umask = 0o027 + self.old_umask = os.umask(self.umask) self.storage_dir = tempfile.mkdtemp() self.storage = FileSystemStorage(self.storage_dir) def tearDown(self): - settings.FILE_UPLOAD_PERMISSIONS = self.old_perms shutil.rmtree(self.storage_dir) + os.umask(self.old_umask) + @override_settings(FILE_UPLOAD_PERMISSIONS=0o654) def test_file_upload_permissions(self): name = self.storage.save("the_file", ContentFile("data")) actual_mode = os.stat(self.storage.path(name))[0] & 0o777 - self.assertEqual(actual_mode, 0o666) + self.assertEqual(actual_mode, 0o654) + @override_settings(FILE_UPLOAD_PERMISSIONS=None) + def test_file_upload_default_permissions(self): + fname = self.storage.save("some_file", ContentFile("data")) + mode = os.stat(self.storage.path(fname))[0] & 0o777 + self.assertEqual(mode, 0o666 & ~self.umask) class FileStoragePathParsing(unittest.TestCase): def setUp(self): diff --git a/tests/regressiontests/file_uploads/tests.py b/tests/regressiontests/file_uploads/tests.py index 2a1ec7db21..918f77d73c 100644 --- a/tests/regressiontests/file_uploads/tests.py +++ b/tests/regressiontests/file_uploads/tests.py @@ -62,22 +62,20 @@ class FileUploadTests(TestCase): def test_base64_upload(self): test_string = "This data will be transmitted base64-encoded." - payload = "\r\n".join([ + payload = client.FakePayload("\r\n".join([ '--' + client.BOUNDARY, 'Content-Disposition: form-data; name="file"; filename="test.txt"', 'Content-Type: application/octet-stream', 'Content-Transfer-Encoding: base64', - '', - base64.b64encode(force_bytes(test_string)).decode('ascii'), - '--' + client.BOUNDARY + '--', - '', - ]).encode('utf-8') + '',])) + payload.write(b"\r\n" + base64.b64encode(force_bytes(test_string)) + b"\r\n") + payload.write('--' + client.BOUNDARY + '--\r\n') r = { 'CONTENT_LENGTH': len(payload), 'CONTENT_TYPE': client.MULTIPART_CONTENT, 'PATH_INFO': "/file_uploads/echo_content/", 'REQUEST_METHOD': 'POST', - 'wsgi.input': client.FakePayload(payload), + 'wsgi.input': payload, } response = self.client.request(**r) received = json.loads(response.content.decode('utf-8')) @@ -126,27 +124,23 @@ class FileUploadTests(TestCase): "../..\\hax0rd.txt" # Relative path, mixed. ] - payload = [] + payload = client.FakePayload() for i, name in enumerate(scary_file_names): - payload.extend([ + payload.write('\r\n'.join([ '--' + client.BOUNDARY, 'Content-Disposition: form-data; name="file%s"; filename="%s"' % (i, name), 'Content-Type: application/octet-stream', '', - 'You got pwnd.' - ]) - payload.extend([ - '--' + client.BOUNDARY + '--', - '', - ]) + 'You got pwnd.\r\n' + ])) + payload.write('\r\n--' + client.BOUNDARY + '--\r\n') - payload = "\r\n".join(payload).encode('utf-8') r = { 'CONTENT_LENGTH': len(payload), 'CONTENT_TYPE': client.MULTIPART_CONTENT, 'PATH_INFO': "/file_uploads/echo/", 'REQUEST_METHOD': 'POST', - 'wsgi.input': client.FakePayload(payload), + 'wsgi.input': payload, } response = self.client.request(**r) @@ -159,7 +153,7 @@ class FileUploadTests(TestCase): def test_filename_overflow(self): """File names over 256 characters (dangerous on some platforms) get fixed up.""" name = "%s.txt" % ("f"*500) - payload = "\r\n".join([ + payload = client.FakePayload("\r\n".join([ '--' + client.BOUNDARY, 'Content-Disposition: form-data; name="file"; filename="%s"' % name, 'Content-Type: application/octet-stream', @@ -167,13 +161,13 @@ class FileUploadTests(TestCase): 'Oops.' '--' + client.BOUNDARY + '--', '', - ]).encode('utf-8') + ])) r = { 'CONTENT_LENGTH': len(payload), 'CONTENT_TYPE': client.MULTIPART_CONTENT, 'PATH_INFO': "/file_uploads/echo/", 'REQUEST_METHOD': 'POST', - 'wsgi.input': client.FakePayload(payload), + 'wsgi.input': payload, } got = json.loads(self.client.request(**r).content.decode('utf-8')) self.assertTrue(len(got['file']) < 256, "Got a long file name (%s characters)." % len(got['file'])) @@ -184,7 +178,7 @@ class FileUploadTests(TestCase): attempt to read beyond the end of the stream, and simply will handle the part that can be parsed gracefully. """ - payload = "\r\n".join([ + payload_str = "\r\n".join([ '--' + client.BOUNDARY, 'Content-Disposition: form-data; name="file"; filename="foo.txt"', 'Content-Type: application/octet-stream', @@ -192,14 +186,14 @@ class FileUploadTests(TestCase): 'file contents' '--' + client.BOUNDARY + '--', '', - ]).encode('utf-8') - payload = payload[:-10] + ]) + payload = client.FakePayload(payload_str[:-10]) r = { 'CONTENT_LENGTH': len(payload), 'CONTENT_TYPE': client.MULTIPART_CONTENT, 'PATH_INFO': '/file_uploads/echo/', 'REQUEST_METHOD': 'POST', - 'wsgi.input': client.FakePayload(payload), + 'wsgi.input': payload, } got = json.loads(self.client.request(**r).content.decode('utf-8')) self.assertEqual(got, {}) diff --git a/tests/regressiontests/fixtures_regress/fixtures/sequence_extra.json b/tests/regressiontests/fixtures_regress/fixtures/sequence_extra.json new file mode 100644 index 0000000000..03c0f36696 --- /dev/null +++ b/tests/regressiontests/fixtures_regress/fixtures/sequence_extra.json @@ -0,0 +1,13 @@ +[ + { + "pk": "1", + "model": "fixtures_regress.animal", + "fields": { + "name": "Lion", + "extra_name": "Super Lion", + "latin_name": "Panthera leo", + "count": 3, + "weight": 1.2 + } + } +] diff --git a/tests/regressiontests/fixtures_regress/tests.py b/tests/regressiontests/fixtures_regress/tests.py index d675372c7a..55363bc5b7 100644 --- a/tests/regressiontests/fixtures_regress/tests.py +++ b/tests/regressiontests/fixtures_regress/tests.py @@ -5,6 +5,7 @@ from __future__ import absolute_import, unicode_literals import os import re +from django.core.serializers.base import DeserializationError from django.core import management from django.core.management.base import CommandError from django.core.management.commands.dumpdata import sort_dependencies @@ -22,6 +23,7 @@ from .models import (Animal, Stuff, Absolute, Parent, Child, Article, Widget, class TestFixtures(TestCase): + def animal_pre_save_check(self, signal, sender, instance, **kwargs): self.pre_save_checks.append( ( @@ -54,6 +56,34 @@ class TestFixtures(TestCase): animal.save() self.assertGreater(animal.id, 1) + def test_loaddata_not_found_fields_not_ignore(self): + """ + Test for ticket #9279 -- Error is raised for entries in + the serialised data for fields that have been removed + from the database when not ignored. + """ + with self.assertRaises(DeserializationError): + management.call_command( + 'loaddata', + 'sequence_extra', + verbosity=0 + ) + + def test_loaddata_not_found_fields_ignore(self): + """ + Test for ticket #9279 -- Ignores entries in + the serialised data for fields that have been removed + from the database. + """ + management.call_command( + 'loaddata', + 'sequence_extra', + ignore=True, + verbosity=0, + commit=False + ) + self.assertEqual(Animal.specimens.all()[0].name, 'Lion') + @skipIfDBFeature('interprets_empty_strings_as_nulls') def test_pretty_print_xml(self): """ @@ -129,7 +159,7 @@ class TestFixtures(TestCase): Test that failing serializer import raises the proper error """ with six.assertRaisesRegex(self, ImportError, - "No module named unexistent.path"): + r"No module named.*unexistent"): management.call_command( 'loaddata', 'bad_fixture1.unkn', diff --git a/tests/regressiontests/forms/models.py b/tests/regressiontests/forms/models.py index 2f3ee9fa31..6e9c269356 100644 --- a/tests/regressiontests/forms/models.py +++ b/tests/regressiontests/forms/models.py @@ -63,6 +63,12 @@ class ChoiceFieldModel(models.Model): multi_choice_int = models.ManyToManyField(ChoiceOptionModel, blank=False, related_name='multi_choice_int', default=lambda: [1]) +class OptionalMultiChoiceModel(models.Model): + multi_choice = models.ManyToManyField(ChoiceOptionModel, blank=False, related_name='not_relevant', + default=lambda: ChoiceOptionModel.objects.filter(name='default')) + multi_choice_optional = models.ManyToManyField(ChoiceOptionModel, blank=True, null=True, + related_name='not_relevant2') + class FileModel(models.Model): file = models.FileField(storage=temp_storage, upload_to='tests') diff --git a/tests/regressiontests/forms/tests/extra.py b/tests/regressiontests/forms/tests/extra.py index 2ab5d40942..07acb29741 100644 --- a/tests/regressiontests/forms/tests/extra.py +++ b/tests/regressiontests/forms/tests/extra.py @@ -3,11 +3,11 @@ from __future__ import absolute_import, unicode_literals import datetime -from django.conf import settings from django.forms import * from django.forms.extras import SelectDateWidget from django.forms.util import ErrorList from django.test import TestCase +from django.test.utils import override_settings from django.utils import six from django.utils import translation from django.utils.encoding import force_text, smart_text, python_2_unicode_compatible @@ -613,7 +613,7 @@ class FormsExtraTestCase(TestCase, AssertFormErrorsMixin): data = dict(email='invalid') f = CommentForm(data, auto_id=False, error_class=DivErrorList) self.assertHTMLEqual(f.as_p(), """<p>Name: <input type="text" name="name" maxlength="50" /></p> -<div class="errorlist"><div class="error">Enter a valid e-mail address.</div></div> +<div class="errorlist"><div class="error">Enter a valid email address.</div></div> <p>Email: <input type="text" name="email" value="invalid" /></p> <div class="errorlist"><div class="error">This field is required.</div></div> <p>Comment: <input type="text" name="comment" /></p>""") @@ -642,17 +642,14 @@ class FormsExtraTestCase(TestCase, AssertFormErrorsMixin): self.assertFalse(b.has_changed()) - +@override_settings(USE_L10N=True) class FormsExtraL10NTestCase(TestCase): def setUp(self): super(FormsExtraL10NTestCase, self).setUp() - self.old_use_l10n = getattr(settings, 'USE_L10N', False) - settings.USE_L10N = True translation.activate('nl') def tearDown(self): translation.deactivate() - settings.USE_L10N = self.old_use_l10n super(FormsExtraL10NTestCase, self).tearDown() def test_l10n(self): diff --git a/tests/regressiontests/forms/tests/fields.py b/tests/regressiontests/forms/tests/fields.py index 197ce1abd9..1027afceb1 100644 --- a/tests/regressiontests/forms/tests/fields.py +++ b/tests/regressiontests/forms/tests/fields.py @@ -356,6 +356,11 @@ class FieldsTests(SimpleTestCase): self.assertEqual(datetime.date(2006, 10, 25), f.clean(' 25 October 2006 ')) self.assertRaisesMessage(ValidationError, "'Enter a valid date.'", f.clean, ' ') + def test_datefield_5(self): + # Test null bytes (#18982) + f = DateField() + self.assertRaisesMessage(ValidationError, "'Enter a valid date.'", f.clean, 'a\x00b') + # TimeField ################################################################### def test_timefield_1(self): @@ -496,46 +501,33 @@ class FieldsTests(SimpleTestCase): self.assertRaisesMessage(ValidationError, "'Enter a valid value.'", f.clean, 'abcd') # EmailField ################################################################## + # See also modeltests/validators tests for validate_email specific tests def test_emailfield_1(self): f = EmailField() self.assertRaisesMessage(ValidationError, "'This field is required.'", f.clean, '') self.assertRaisesMessage(ValidationError, "'This field is required.'", f.clean, None) self.assertEqual('person@example.com', f.clean('person@example.com')) - self.assertRaisesMessage(ValidationError, "'Enter a valid e-mail address.'", f.clean, 'foo') - self.assertRaisesMessage(ValidationError, "'Enter a valid e-mail address.'", f.clean, 'foo@') - self.assertRaisesMessage(ValidationError, "'Enter a valid e-mail address.'", f.clean, 'foo@bar') - self.assertRaisesMessage(ValidationError, "'Enter a valid e-mail address.'", f.clean, 'example@invalid-.com') - self.assertRaisesMessage(ValidationError, "'Enter a valid e-mail address.'", f.clean, 'example@-invalid.com') - self.assertRaisesMessage(ValidationError, "'Enter a valid e-mail address.'", f.clean, 'example@inv-.alid-.com') - self.assertRaisesMessage(ValidationError, "'Enter a valid e-mail address.'", f.clean, 'example@inv-.-alid.com') - self.assertEqual('example@valid-----hyphens.com', f.clean('example@valid-----hyphens.com')) - self.assertEqual('example@valid-with-hyphens.com', f.clean('example@valid-with-hyphens.com')) - self.assertRaisesMessage(ValidationError, "'Enter a valid e-mail address.'", f.clean, 'example@.com') - self.assertEqual('local@domain.with.idn.xyz\xe4\xf6\xfc\xdfabc.part.com', f.clean('local@domain.with.idn.xyzäöüßabc.part.com')) + self.assertRaisesMessage(ValidationError, "'Enter a valid email address.'", f.clean, 'foo') + self.assertEqual('local@domain.with.idn.xyz\xe4\xf6\xfc\xdfabc.part.com', + f.clean('local@domain.with.idn.xyzäöüßabc.part.com')) def test_email_regexp_for_performance(self): f = EmailField() # Check for runaway regex security problem. This will take for-freeking-ever # if the security fix isn't in place. - self.assertRaisesMessage( - ValidationError, - "'Enter a valid e-mail address.'", - f.clean, - 'viewx3dtextx26qx3d@yahoo.comx26latlngx3d15854521645943074058' - ) + addr = 'viewx3dtextx26qx3d@yahoo.comx26latlngx3d15854521645943074058' + self.assertEqual(addr, f.clean(addr)) - def test_emailfield_2(self): + def test_emailfield_not_required(self): f = EmailField(required=False) self.assertEqual('', f.clean('')) self.assertEqual('', f.clean(None)) self.assertEqual('person@example.com', f.clean('person@example.com')) self.assertEqual('example@example.com', f.clean(' example@example.com \t \t ')) - self.assertRaisesMessage(ValidationError, "'Enter a valid e-mail address.'", f.clean, 'foo') - self.assertRaisesMessage(ValidationError, "'Enter a valid e-mail address.'", f.clean, 'foo@') - self.assertRaisesMessage(ValidationError, "'Enter a valid e-mail address.'", f.clean, 'foo@bar') + self.assertRaisesMessage(ValidationError, "'Enter a valid email address.'", f.clean, 'foo') - def test_emailfield_3(self): + def test_emailfield_min_max_length(self): f = EmailField(min_length=10, max_length=15) self.assertRaisesMessage(ValidationError, "'Ensure this value has at least 10 characters (it has 9).'", f.clean, 'a@foo.com') self.assertEqual('alf@foo.com', f.clean('alf@foo.com')) @@ -921,7 +913,7 @@ class FieldsTests(SimpleTestCase): f = ComboField(fields=[CharField(max_length=20), EmailField()]) self.assertEqual('test@example.com', f.clean('test@example.com')) self.assertRaisesMessage(ValidationError, "'Ensure this value has at most 20 characters (it has 28).'", f.clean, 'longemailaddress@example.com') - self.assertRaisesMessage(ValidationError, "'Enter a valid e-mail address.'", f.clean, 'not an e-mail') + self.assertRaisesMessage(ValidationError, "'Enter a valid email address.'", f.clean, 'not an email') self.assertRaisesMessage(ValidationError, "'This field is required.'", f.clean, '') self.assertRaisesMessage(ValidationError, "'This field is required.'", f.clean, None) @@ -929,7 +921,7 @@ class FieldsTests(SimpleTestCase): f = ComboField(fields=[CharField(max_length=20), EmailField()], required=False) self.assertEqual('test@example.com', f.clean('test@example.com')) self.assertRaisesMessage(ValidationError, "'Ensure this value has at most 20 characters (it has 28).'", f.clean, 'longemailaddress@example.com') - self.assertRaisesMessage(ValidationError, "'Enter a valid e-mail address.'", f.clean, 'not an e-mail') + self.assertRaisesMessage(ValidationError, "'Enter a valid email address.'", f.clean, 'not an email') self.assertEqual('', f.clean('')) self.assertEqual('', f.clean(None)) diff --git a/tests/regressiontests/forms/tests/formsets.py b/tests/regressiontests/forms/tests/formsets.py index 3decd1f085..b3ceee551b 100644 --- a/tests/regressiontests/forms/tests/formsets.py +++ b/tests/regressiontests/forms/tests/formsets.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals from django.forms import Form, CharField, IntegerField, ValidationError, DateField from django.forms.formsets import formset_factory, BaseFormSet +from django.forms.util import ErrorList from django.test import TestCase @@ -847,6 +848,15 @@ class FormsFormsetTestCase(TestCase): self.assertTrue(formset) + def test_formset_error_class(self): + # Regression tests for #16479 -- formsets form use ErrorList instead of supplied error_class + class CustomErrorList(ErrorList): + pass + + formset = FavoriteDrinksFormSet(error_class=CustomErrorList) + self.assertEqual(formset.forms[0].error_class, CustomErrorList) + + data = { 'choices-TOTAL_FORMS': '1', # the number of forms rendered 'choices-INITIAL_FORMS': '0', # the number of forms with initial data diff --git a/tests/regressiontests/forms/tests/input_formats.py b/tests/regressiontests/forms/tests/input_formats.py index e362620ddb..d591804b9d 100644 --- a/tests/regressiontests/forms/tests/input_formats.py +++ b/tests/regressiontests/forms/tests/input_formats.py @@ -1,25 +1,17 @@ from datetime import time, date, datetime from django import forms -from django.conf import settings +from django.test.utils import override_settings from django.utils.translation import activate, deactivate from django.utils.unittest import TestCase +@override_settings(TIME_INPUT_FORMATS=["%I:%M:%S %p", "%I:%M %p"], USE_L10N=True) class LocalizedTimeTests(TestCase): def setUp(self): - self.old_TIME_INPUT_FORMATS = settings.TIME_INPUT_FORMATS - self.old_USE_L10N = settings.USE_L10N - - settings.TIME_INPUT_FORMATS = ["%I:%M:%S %p", "%I:%M %p"] - settings.USE_L10N = True - activate('de') def tearDown(self): - settings.TIME_INPUT_FORMATS = self.old_TIME_INPUT_FORMATS - settings.USE_L10N = self.old_USE_L10N - deactivate() def test_timeField(self): @@ -113,14 +105,8 @@ class LocalizedTimeTests(TestCase): self.assertEqual(text, "13:30:00") +@override_settings(TIME_INPUT_FORMATS=["%I:%M:%S %p", "%I:%M %p"]) class CustomTimeInputFormatsTests(TestCase): - def setUp(self): - self.old_TIME_INPUT_FORMATS = settings.TIME_INPUT_FORMATS - settings.TIME_INPUT_FORMATS = ["%I:%M:%S %p", "%I:%M %p"] - - def tearDown(self): - settings.TIME_INPUT_FORMATS = self.old_TIME_INPUT_FORMATS - def test_timeField(self): "TimeFields can parse dates in the default format" f = forms.TimeField() @@ -302,20 +288,12 @@ class SimpleTimeFormatTests(TestCase): self.assertEqual(text, "13:30:00") +@override_settings(DATE_INPUT_FORMATS=["%d/%m/%Y", "%d-%m-%Y"], USE_L10N=True) class LocalizedDateTests(TestCase): def setUp(self): - self.old_DATE_INPUT_FORMATS = settings.DATE_INPUT_FORMATS - self.old_USE_L10N = settings.USE_L10N - - settings.DATE_INPUT_FORMATS = ["%d/%m/%Y", "%d-%m-%Y"] - settings.USE_L10N = True - activate('de') def tearDown(self): - settings.DATE_INPUT_FORMATS = self.old_DATE_INPUT_FORMATS - settings.USE_L10N = self.old_USE_L10N - deactivate() def test_dateField(self): @@ -410,14 +388,9 @@ class LocalizedDateTests(TestCase): text = f.widget._format_value(result) self.assertEqual(text, "21.12.2010") -class CustomDateInputFormatsTests(TestCase): - def setUp(self): - self.old_DATE_INPUT_FORMATS = settings.DATE_INPUT_FORMATS - settings.DATE_INPUT_FORMATS = ["%d.%m.%Y", "%d-%m-%Y"] - - def tearDown(self): - settings.DATE_INPUT_FORMATS = self.old_DATE_INPUT_FORMATS +@override_settings(DATE_INPUT_FORMATS=["%d.%m.%Y", "%d-%m-%Y"]) +class CustomDateInputFormatsTests(TestCase): def test_dateField(self): "DateFields can parse dates in the default format" f = forms.DateField() @@ -597,20 +570,13 @@ class SimpleDateFormatTests(TestCase): text = f.widget._format_value(result) self.assertEqual(text, "2010-12-21") + +@override_settings(DATETIME_INPUT_FORMATS=["%I:%M:%S %p %d/%m/%Y", "%I:%M %p %d-%m-%Y"], USE_L10N=True) class LocalizedDateTimeTests(TestCase): def setUp(self): - self.old_DATETIME_INPUT_FORMATS = settings.DATETIME_INPUT_FORMATS - self.old_USE_L10N = settings.USE_L10N - - settings.DATETIME_INPUT_FORMATS = ["%I:%M:%S %p %d/%m/%Y", "%I:%M %p %d-%m-%Y"] - settings.USE_L10N = True - activate('de') def tearDown(self): - settings.DATETIME_INPUT_FORMATS = self.old_DATETIME_INPUT_FORMATS - settings.USE_L10N = self.old_USE_L10N - deactivate() def test_dateTimeField(self): @@ -706,14 +672,8 @@ class LocalizedDateTimeTests(TestCase): self.assertEqual(text, "21.12.2010 13:30:00") +@override_settings(DATETIME_INPUT_FORMATS=["%I:%M:%S %p %d/%m/%Y", "%I:%M %p %d-%m-%Y"]) class CustomDateTimeInputFormatsTests(TestCase): - def setUp(self): - self.old_DATETIME_INPUT_FORMATS = settings.DATETIME_INPUT_FORMATS - settings.DATETIME_INPUT_FORMATS = ["%I:%M:%S %p %d/%m/%Y", "%I:%M %p %d-%m-%Y"] - - def tearDown(self): - settings.DATETIME_INPUT_FORMATS = self.old_DATETIME_INPUT_FORMATS - def test_dateTimeField(self): "DateTimeFields can parse dates in the default format" f = forms.DateTimeField() diff --git a/tests/regressiontests/forms/tests/models.py b/tests/regressiontests/forms/tests/models.py index c351509cee..be75643b28 100644 --- a/tests/regressiontests/forms/tests/models.py +++ b/tests/regressiontests/forms/tests/models.py @@ -11,7 +11,7 @@ from django.test import TestCase from django.utils import six from ..models import (ChoiceOptionModel, ChoiceFieldModel, FileModel, Group, - BoundaryModel, Defaults) + BoundaryModel, Defaults, OptionalMultiChoiceModel) class ChoiceFieldForm(ModelForm): @@ -19,6 +19,11 @@ class ChoiceFieldForm(ModelForm): model = ChoiceFieldModel +class OptionalMultiChoiceModelForm(ModelForm): + class Meta: + model = OptionalMultiChoiceModel + + class FileForm(Form): file1 = FileField() @@ -34,6 +39,21 @@ class TestTicket12510(TestCase): 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)." @@ -103,7 +123,6 @@ class ModelFormCallableModelDefault(TestCase): <input type="hidden" name="initial-multi_choice_int" value="3" id="initial-id_multi_choice_int_1" /> <span class="helptext"> Hold down "Control", or "Command" on a Mac, to select more than one.</span></p>""") - class FormsModelTestCase(TestCase): def test_unicode_filename(self): # FileModel with unicode filename and data ######################### diff --git a/tests/regressiontests/forms/tests/widgets.py b/tests/regressiontests/forms/tests/widgets.py index 104144b288..4bdd3f76ea 100644 --- a/tests/regressiontests/forms/tests/widgets.py +++ b/tests/regressiontests/forms/tests/widgets.py @@ -4,7 +4,6 @@ from __future__ import unicode_literals import copy import datetime -from django.conf import settings from django.core.files.uploadedfile import SimpleUploadedFile from django.forms import * from django.forms.widgets import RadioFieldRenderer @@ -13,6 +12,7 @@ from django.utils.safestring import mark_safe from django.utils import six from django.utils.translation import activate, deactivate from django.test import TestCase +from django.test.utils import override_settings from django.utils.encoding import python_2_unicode_compatible @@ -989,16 +989,14 @@ class NullBooleanSelectLazyForm(Form): """Form to test for lazy evaluation. Refs #17190""" bool = BooleanField(widget=NullBooleanSelect()) +@override_settings(USE_L10N=True) class FormsI18NWidgetsTestCase(TestCase): def setUp(self): super(FormsI18NWidgetsTestCase, self).setUp() - self.old_use_l10n = getattr(settings, 'USE_L10N', False) - settings.USE_L10N = True activate('de-at') def tearDown(self): deactivate() - settings.USE_L10N = self.old_use_l10n super(FormsI18NWidgetsTestCase, self).tearDown() def test_splitdatetime(self): diff --git a/tests/regressiontests/generic_views/dates.py b/tests/regressiontests/generic_views/dates.py index c2fa71b376..0c565daf9f 100644 --- a/tests/regressiontests/generic_views/dates.py +++ b/tests/regressiontests/generic_views/dates.py @@ -23,29 +23,30 @@ requires_tz_support = skipUnless(TZ_SUPPORT, "time zone, but your operating system isn't able to do that.") +def _make_books(n, base_date): + for i in range(n): + b = Book.objects.create( + name='Book %d' % i, + slug='book-%d' % i, + pages=100+i, + pubdate=base_date - datetime.timedelta(days=i)) + class ArchiveIndexViewTests(TestCase): fixtures = ['generic-views-test-data.json'] urls = 'regressiontests.generic_views.urls' - def _make_books(self, n, base_date): - for i in range(n): - b = Book.objects.create( - name='Book %d' % i, - slug='book-%d' % i, - pages=100+i, - pubdate=base_date - datetime.timedelta(days=1)) def test_archive_view(self): res = self.client.get('/dates/books/') self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['date_list'], Book.objects.dates('pubdate', 'year')[::-1]) + self.assertEqual(list(res.context['date_list']), list(Book.objects.dates('pubdate', 'year', 'DESC'))) self.assertEqual(list(res.context['latest']), list(Book.objects.all())) self.assertTemplateUsed(res, 'generic_views/book_archive.html') def test_archive_view_context_object_name(self): res = self.client.get('/dates/books/context_object_name/') self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['date_list'], Book.objects.dates('pubdate', 'year')[::-1]) + self.assertEqual(list(res.context['date_list']), list(Book.objects.dates('pubdate', 'year', 'DESC'))) self.assertEqual(list(res.context['thingies']), list(Book.objects.all())) self.assertFalse('latest' in res.context) self.assertTemplateUsed(res, 'generic_views/book_archive.html') @@ -65,14 +66,14 @@ class ArchiveIndexViewTests(TestCase): def test_archive_view_template(self): res = self.client.get('/dates/books/template_name/') self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['date_list'], Book.objects.dates('pubdate', 'year')[::-1]) + self.assertEqual(list(res.context['date_list']), list(Book.objects.dates('pubdate', 'year', 'DESC'))) self.assertEqual(list(res.context['latest']), list(Book.objects.all())) self.assertTemplateUsed(res, 'generic_views/list.html') def test_archive_view_template_suffix(self): res = self.client.get('/dates/books/template_name_suffix/') self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['date_list'], Book.objects.dates('pubdate', 'year')[::-1]) + self.assertEqual(list(res.context['date_list']), list(Book.objects.dates('pubdate', 'year', 'DESC'))) self.assertEqual(list(res.context['latest']), list(Book.objects.all())) self.assertTemplateUsed(res, 'generic_views/book_detail.html') @@ -82,13 +83,13 @@ class ArchiveIndexViewTests(TestCase): def test_archive_view_by_month(self): res = self.client.get('/dates/books/by_month/') self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['date_list'], Book.objects.dates('pubdate', 'month')[::-1]) + self.assertEqual(list(res.context['date_list']), list(Book.objects.dates('pubdate', 'month', 'DESC'))) def test_paginated_archive_view(self): - self._make_books(20, base_date=datetime.date.today()) + _make_books(20, base_date=datetime.date.today()) res = self.client.get('/dates/books/paginated/') self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['date_list'], Book.objects.dates('pubdate', 'year')[::-1]) + self.assertEqual(list(res.context['date_list']), list(Book.objects.dates('pubdate', 'year', 'DESC'))) self.assertEqual(list(res.context['latest']), list(Book.objects.all()[0:10])) self.assertTemplateUsed(res, 'generic_views/book_archive.html') @@ -99,7 +100,7 @@ class ArchiveIndexViewTests(TestCase): def test_paginated_archive_view_does_not_load_entire_table(self): # Regression test for #18087 - self._make_books(20, base_date=datetime.date.today()) + _make_books(20, base_date=datetime.date.today()) # 1 query for years list + 1 query for books with self.assertNumQueries(2): self.client.get('/dates/books/') @@ -124,6 +125,13 @@ class ArchiveIndexViewTests(TestCase): res = self.client.get('/dates/booksignings/') self.assertEqual(res.status_code, 200) + def test_date_list_order(self): + """date_list should be sorted descending in index""" + _make_books(5, base_date=datetime.date(2011, 12, 25)) + res = self.client.get('/dates/books/') + self.assertEqual(res.status_code, 200) + self.assertEqual(list(res.context['date_list']), list(reversed(sorted(res.context['date_list'])))) + class YearArchiveViewTests(TestCase): fixtures = ['generic-views-test-data.json'] @@ -202,6 +210,12 @@ class YearArchiveViewTests(TestCase): res = self.client.get('/dates/booksignings/2008/') self.assertEqual(res.status_code, 200) + def test_date_list_order(self): + """date_list should be sorted ascending in year view""" + _make_books(10, base_date=datetime.date(2011, 12, 25)) + res = self.client.get('/dates/books/2011/') + self.assertEqual(list(res.context['date_list']), list(sorted(res.context['date_list']))) + class MonthArchiveViewTests(TestCase): fixtures = ['generic-views-test-data.json'] @@ -322,6 +336,12 @@ class MonthArchiveViewTests(TestCase): res = self.client.get('/dates/booksignings/2008/apr/') self.assertEqual(res.status_code, 200) + def test_date_list_order(self): + """date_list should be sorted ascending in month view""" + _make_books(10, base_date=datetime.date(2011, 12, 25)) + res = self.client.get('/dates/books/2011/dec/') + self.assertEqual(list(res.context['date_list']), list(sorted(res.context['date_list']))) + class WeekArchiveViewTests(TestCase): fixtures = ['generic-views-test-data.json'] diff --git a/tests/regressiontests/handlers/tests.py b/tests/regressiontests/handlers/tests.py index 34863b6493..8676a448d9 100644 --- a/tests/regressiontests/handlers/tests.py +++ b/tests/regressiontests/handlers/tests.py @@ -1,27 +1,23 @@ -from django.conf import settings from django.core.handlers.wsgi import WSGIHandler from django.test import RequestFactory +from django.test.utils import override_settings from django.utils import unittest - class HandlerTests(unittest.TestCase): + # Mangle settings so the handler will fail + @override_settings(MIDDLEWARE_CLASSES=42) def test_lock_safety(self): """ Tests for bug #11193 (errors inside middleware shouldn't leave the initLock locked). """ - # Mangle settings so the handler will fail - old_middleware_classes = settings.MIDDLEWARE_CLASSES - settings.MIDDLEWARE_CLASSES = 42 # Try running the handler, it will fail in load_middleware handler = WSGIHandler() self.assertEqual(handler.initLock.locked(), False) with self.assertRaises(Exception): handler(None, None) self.assertEqual(handler.initLock.locked(), False) - # Reset settings - settings.MIDDLEWARE_CLASSES = old_middleware_classes def test_bad_path_info(self): """Tests for bug #15672 ('request' referenced before assignment)""" diff --git a/tests/regressiontests/localflavor/ar/__init__.py b/tests/regressiontests/http_utils/__init__.py index e69de29bb2..e69de29bb2 100644 --- a/tests/regressiontests/localflavor/ar/__init__.py +++ b/tests/regressiontests/http_utils/__init__.py diff --git a/tests/regressiontests/localflavor/at/__init__.py b/tests/regressiontests/http_utils/models.py index e69de29bb2..e69de29bb2 100644 --- a/tests/regressiontests/localflavor/at/__init__.py +++ b/tests/regressiontests/http_utils/models.py diff --git a/tests/regressiontests/http_utils/tests.py b/tests/regressiontests/http_utils/tests.py new file mode 100644 index 0000000000..7dfd24d721 --- /dev/null +++ b/tests/regressiontests/http_utils/tests.py @@ -0,0 +1,45 @@ +from __future__ import unicode_literals + +from django.http import HttpRequest, HttpResponse, StreamingHttpResponse +from django.http.utils import conditional_content_removal +from django.test import TestCase + + +class HttpUtilTests(TestCase): + + def test_conditional_content_removal(self): + """ + Tests that content is removed from regular and streaming responses with + a status_code of 100-199, 204, 304 or a method of "HEAD". + """ + req = HttpRequest() + + # Do nothing for 200 responses. + res = HttpResponse('abc') + conditional_content_removal(req, res) + self.assertEqual(res.content, b'abc') + + res = StreamingHttpResponse(['abc']) + conditional_content_removal(req, res) + self.assertEqual(b''.join(res), b'abc') + + # Strip content for some status codes. + for status_code in (100, 150, 199, 204, 304): + res = HttpResponse('abc', status=status_code) + conditional_content_removal(req, res) + self.assertEqual(res.content, b'') + + res = StreamingHttpResponse(['abc'], status=status_code) + conditional_content_removal(req, res) + self.assertEqual(b''.join(res), b'') + + # Strip content for HEAD requests. + req.method = 'HEAD' + + res = HttpResponse('abc') + conditional_content_removal(req, res) + self.assertEqual(res.content, b'') + + res = StreamingHttpResponse(['abc']) + conditional_content_removal(req, res) + self.assertEqual(b''.join(res), b'') diff --git a/tests/regressiontests/httpwrappers/abc.txt b/tests/regressiontests/httpwrappers/abc.txt new file mode 100644 index 0000000000..6bac42b3ad --- /dev/null +++ b/tests/regressiontests/httpwrappers/abc.txt @@ -0,0 +1 @@ +random content diff --git a/tests/regressiontests/httpwrappers/tests.py b/tests/regressiontests/httpwrappers/tests.py index 4c6aed1b97..553b6ecff4 100644 --- a/tests/regressiontests/httpwrappers/tests.py +++ b/tests/regressiontests/httpwrappers/tests.py @@ -2,12 +2,14 @@ from __future__ import unicode_literals import copy +import os import pickle +import warnings from django.core.exceptions import SuspiciousOperation from django.http import (QueryDict, HttpResponse, HttpResponseRedirect, HttpResponsePermanentRedirect, HttpResponseNotAllowed, - HttpResponseNotModified, + HttpResponseNotModified, StreamingHttpResponse, SimpleCookie, BadHeaderError, parse_cookie) from django.test import TestCase @@ -127,10 +129,14 @@ class QueryDictTests(unittest.TestCase): self.assertTrue(q.has_key('foo')) self.assertTrue('foo' in q) - self.assertEqual(list(six.iteritems(q)), [('foo', 'another'), ('name', 'john')]) - self.assertEqual(list(six.iterlists(q)), [('foo', ['bar', 'baz', 'another']), ('name', ['john'])]) - self.assertEqual(list(six.iterkeys(q)), ['foo', 'name']) - self.assertEqual(list(six.itervalues(q)), ['another', 'john']) + self.assertEqual(sorted(list(six.iteritems(q))), + [('foo', 'another'), ('name', 'john')]) + self.assertEqual(sorted(list(six.iterlists(q))), + [('foo', ['bar', 'baz', 'another']), ('name', ['john'])]) + self.assertEqual(sorted(list(six.iterkeys(q))), + ['foo', 'name']) + self.assertEqual(sorted(list(six.itervalues(q))), + ['another', 'john']) self.assertEqual(len(q), 2) q.update({'foo': 'hello'}) @@ -312,23 +318,61 @@ class HttpResponseTests(unittest.TestCase): r.content = [1, 2, 3] self.assertEqual(r.content, b'123') - #test retrieval explicitly using iter and odd inputs + #test retrieval explicitly using iter (deprecated) and odd inputs r = HttpResponse() r.content = ['1', '2', 3, '\u079e'] - my_iter = r.__iter__() - result = list(my_iter) + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always", PendingDeprecationWarning) + my_iter = iter(r) + self.assertEqual(w[0].category, PendingDeprecationWarning) + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always", PendingDeprecationWarning) + result = list(my_iter) + self.assertEqual(w[0].category, PendingDeprecationWarning) #'\xde\x9e' == unichr(1950).encode('utf-8') self.assertEqual(result, [b'1', b'2', b'3', b'\xde\x9e']) self.assertEqual(r.content, b'123\xde\x9e') #with Content-Encoding header - r = HttpResponse([1,1,2,4,8]) + r = HttpResponse() r['Content-Encoding'] = 'winning' - self.assertEqual(r.content, b'11248') - r.content = ['\u079e',] - self.assertRaises(UnicodeEncodeError, + r.content = [b'abc', b'def'] + self.assertEqual(r.content, b'abcdef') + r.content = ['\u079e'] + self.assertRaises(TypeError if six.PY3 else UnicodeEncodeError, getattr, r, 'content') + # .content can safely be accessed multiple times. + r = HttpResponse(iter(['hello', 'world'])) + self.assertEqual(r.content, r.content) + self.assertEqual(r.content, b'helloworld') + # accessing the iterator works (once) after accessing .content + self.assertEqual(b''.join(r), b'helloworld') + self.assertEqual(b''.join(r), b'') + # accessing .content still works + self.assertEqual(r.content, b'helloworld') + + # XXX accessing .content doesn't work if the response was iterated first + # XXX change this when the deprecation completes in HttpResponse + r = HttpResponse(iter(['hello', 'world'])) + with warnings.catch_warnings(): + warnings.simplefilter("ignore", PendingDeprecationWarning) + self.assertEqual(b''.join(r), b'helloworld') + self.assertEqual(r.content, b'') # not the expected result! + + # additional content can be written to the response. + r = HttpResponse(iter(['hello', 'world'])) + self.assertEqual(r.content, b'helloworld') + r.write('!') + self.assertEqual(r.content, b'helloworld!') + + def test_iterator_isnt_rewound(self): + # Regression test for #13222 + r = HttpResponse('abc') + i = iter(r) + self.assertEqual(list(i), [b'abc']) + self.assertEqual(list(i), []) + def test_file_interface(self): r = HttpResponse() r.write(b"hello") @@ -337,7 +381,9 @@ class HttpResponseTests(unittest.TestCase): self.assertEqual(r.tell(), 17) r = HttpResponse(['abc']) - self.assertRaises(Exception, r.write, 'def') + r.write('def') + self.assertEqual(r.tell(), 6) + self.assertEqual(r.content, b'abcdef') def test_unsafe_redirect(self): bad_urls = [ @@ -351,7 +397,6 @@ class HttpResponseTests(unittest.TestCase): self.assertRaises(SuspiciousOperation, HttpResponsePermanentRedirect, url) - class HttpResponseSubclassesTests(TestCase): def test_redirect(self): response = HttpResponseRedirect('/redirected/') @@ -379,6 +424,115 @@ class HttpResponseSubclassesTests(TestCase): content_type='text/html') self.assertContains(response, 'Only the GET method is allowed', status_code=405) +class StreamingHttpResponseTests(TestCase): + def test_streaming_response(self): + r = StreamingHttpResponse(iter(['hello', 'world'])) + + # iterating over the response itself yields bytestring chunks. + chunks = list(r) + self.assertEqual(chunks, [b'hello', b'world']) + for chunk in chunks: + self.assertIsInstance(chunk, six.binary_type) + + # and the response can only be iterated once. + self.assertEqual(list(r), []) + + # even when a sequence that can be iterated many times, like a list, + # is given as content. + r = StreamingHttpResponse(['abc', 'def']) + self.assertEqual(list(r), [b'abc', b'def']) + self.assertEqual(list(r), []) + + # streaming responses don't have a `content` attribute. + self.assertFalse(hasattr(r, 'content')) + + # and you can't accidentally assign to a `content` attribute. + with self.assertRaises(AttributeError): + r.content = 'xyz' + + # but they do have a `streaming_content` attribute. + self.assertTrue(hasattr(r, 'streaming_content')) + + # that exists so we can check if a response is streaming, and wrap or + # replace the content iterator. + r.streaming_content = iter(['abc', 'def']) + r.streaming_content = (chunk.upper() for chunk in r.streaming_content) + self.assertEqual(list(r), [b'ABC', b'DEF']) + + # coercing a streaming response to bytes doesn't return a complete HTTP + # message like a regular response does. it only gives us the headers. + r = StreamingHttpResponse(iter(['hello', 'world'])) + self.assertEqual( + six.binary_type(r), b'Content-Type: text/html; charset=utf-8') + + # and this won't consume its content. + self.assertEqual(list(r), [b'hello', b'world']) + + # additional content cannot be written to the response. + r = StreamingHttpResponse(iter(['hello', 'world'])) + with self.assertRaises(Exception): + r.write('!') + + # and we can't tell the current position. + with self.assertRaises(Exception): + r.tell() + +class FileCloseTests(TestCase): + def test_response(self): + filename = os.path.join(os.path.dirname(__file__), 'abc.txt') + + # file isn't closed until we close the response. + file1 = open(filename) + r = HttpResponse(file1) + self.assertFalse(file1.closed) + r.close() + self.assertTrue(file1.closed) + + # don't automatically close file when we finish iterating the response. + file1 = open(filename) + r = HttpResponse(file1) + self.assertFalse(file1.closed) + with warnings.catch_warnings(): + warnings.simplefilter("ignore", PendingDeprecationWarning) + list(r) + self.assertFalse(file1.closed) + r.close() + self.assertTrue(file1.closed) + + # when multiple file are assigned as content, make sure they are all + # closed with the response. + file1 = open(filename) + file2 = open(filename) + r = HttpResponse(file1) + r.content = file2 + self.assertFalse(file1.closed) + self.assertFalse(file2.closed) + r.close() + self.assertTrue(file1.closed) + self.assertTrue(file2.closed) + + def test_streaming_response(self): + filename = os.path.join(os.path.dirname(__file__), 'abc.txt') + + # file isn't closed until we close the response. + file1 = open(filename) + r = StreamingHttpResponse(file1) + self.assertFalse(file1.closed) + r.close() + self.assertTrue(file1.closed) + + # when multiple file are assigned as content, make sure they are all + # closed with the response. + file1 = open(filename) + file2 = open(filename) + r = StreamingHttpResponse(file1) + r.streaming_content = file2 + self.assertFalse(file1.closed) + self.assertFalse(file2.closed) + r.close() + self.assertTrue(file1.closed) + self.assertTrue(file2.closed) + class CookieTests(unittest.TestCase): def test_encode(self): """ @@ -419,7 +573,7 @@ class CookieTests(unittest.TestCase): """ Test that a repeated non-standard name doesn't affect all cookies. Ticket #15852 """ - self.assertTrue('good_cookie' in parse_cookie('a,=b; a,=c; good_cookie=yes').keys()) + self.assertTrue('good_cookie' in parse_cookie('a:=b; a:=c; good_cookie=yes').keys()) def test_httponly_after_load(self): """ diff --git a/tests/regressiontests/i18n/commands/extraction.py b/tests/regressiontests/i18n/commands/extraction.py index 29d9e277ff..ca2c3cc026 100644 --- a/tests/regressiontests/i18n/commands/extraction.py +++ b/tests/regressiontests/i18n/commands/extraction.py @@ -156,6 +156,21 @@ class BasicExtractorTests(ExtractorTests): self.assertTrue('msgctxt "Special blocktrans context #4"' in po_contents) self.assertTrue("Translatable literal #8d" in po_contents) + def test_context_in_single_quotes(self): + os.chdir(self.test_dir) + management.call_command('makemessages', locale=LOCALE, verbosity=0) + self.assertTrue(os.path.exists(self.PO_FILE)) + with open(self.PO_FILE, 'r') as fp: + po_contents = fp.read() + # {% trans %} + self.assertTrue('msgctxt "Context wrapped in double quotes"' in po_contents) + self.assertTrue('msgctxt "Context wrapped in single quotes"' in po_contents) + + # {% blocktrans %} + self.assertTrue('msgctxt "Special blocktrans context wrapped in double quotes"' in po_contents) + self.assertTrue('msgctxt "Special blocktrans context wrapped in single quotes"' in po_contents) + + class JavascriptExtractorTests(ExtractorTests): PO_FILE='locale/%s/LC_MESSAGES/djangojs.po' % LOCALE diff --git a/tests/regressiontests/i18n/commands/templates/test.html b/tests/regressiontests/i18n/commands/templates/test.html index 5789346984..e7d7f3ca53 100644 --- a/tests/regressiontests/i18n/commands/templates/test.html +++ b/tests/regressiontests/i18n/commands/templates/test.html @@ -77,3 +77,8 @@ continued here.{% endcomment %} {% trans "Shouldn't double escape this sequence %% either" context "ctx1" %} {% trans "Looks like a str fmt spec %s but shouldn't be interpreted as such" %} {% trans "Looks like a str fmt spec % o but shouldn't be interpreted as such" %} + +{% trans "Translatable literal with context wrapped in single quotes" context 'Context wrapped in single quotes' as var %} +{% trans "Translatable literal with context wrapped in double quotes" context "Context wrapped in double quotes" as var %} +{% blocktrans context 'Special blocktrans context wrapped in single quotes' %}Translatable literal with context wrapped in single quotes{% endblocktrans %} +{% blocktrans context "Special blocktrans context wrapped in double quotes" %}Translatable literal with context wrapped in double quotes{% endblocktrans %}
\ No newline at end of file diff --git a/tests/regressiontests/i18n/tests.py b/tests/regressiontests/i18n/tests.py index bce3d617d2..4054f85ef0 100644 --- a/tests/regressiontests/i18n/tests.py +++ b/tests/regressiontests/i18n/tests.py @@ -23,7 +23,7 @@ from django.utils import six from django.utils.six import PY3 from django.utils.translation import (ugettext, ugettext_lazy, activate, deactivate, gettext_lazy, pgettext, npgettext, to_locale, - get_language_info, get_language, get_language_from_request) + get_language_info, get_language, get_language_from_request, trans_real) from .commands.tests import can_run_extraction_tests, can_run_compilation_tests @@ -45,6 +45,9 @@ from .patterns.tests import (URLRedirectWithoutTrailingSlashTests, here = os.path.dirname(os.path.abspath(__file__)) +extended_locale_paths = settings.LOCALE_PATHS + ( + os.path.join(here, 'other', 'locale'), +) class TranslationTests(TestCase): @@ -86,139 +89,129 @@ class TranslationTests(TestCase): s2 = pickle.loads(pickle.dumps(s1)) self.assertEqual(six.text_type(s2), "test") + @override_settings(LOCALE_PATHS=extended_locale_paths) def test_pgettext(self): - # Reset translation catalog to include other/locale/de - extended_locale_paths = settings.LOCALE_PATHS + ( - os.path.join(here, 'other', 'locale'), - ) - with self.settings(LOCALE_PATHS=extended_locale_paths): - from django.utils.translation import trans_real - trans_real._active = local() - trans_real._translations = {} - with translation.override('de'): - self.assertEqual(pgettext("unexisting", "May"), "May") - self.assertEqual(pgettext("month name", "May"), "Mai") - self.assertEqual(pgettext("verb", "May"), "Kann") - self.assertEqual(npgettext("search", "%d result", "%d results", 4) % 4, "4 Resultate") + trans_real._active = local() + trans_real._translations = {} + with translation.override('de'): + self.assertEqual(pgettext("unexisting", "May"), "May") + self.assertEqual(pgettext("month name", "May"), "Mai") + self.assertEqual(pgettext("verb", "May"), "Kann") + self.assertEqual(npgettext("search", "%d result", "%d results", 4) % 4, "4 Resultate") + @override_settings(LOCALE_PATHS=extended_locale_paths) def test_template_tags_pgettext(self): """ Ensure that message contexts are taken into account the {% trans %} and {% blocktrans %} template tags. Refs #14806. """ - # Reset translation catalog to include other/locale/de - extended_locale_paths = settings.LOCALE_PATHS + ( - os.path.join(here, 'other', 'locale'), - ) - with self.settings(LOCALE_PATHS=extended_locale_paths): - from django.utils.translation import trans_real - trans_real._active = local() - trans_real._translations = {} - with translation.override('de'): + trans_real._active = local() + trans_real._translations = {} + with translation.override('de'): - # {% trans %} ----------------------------------- + # {% trans %} ----------------------------------- - # Inexisting context... - t = Template('{% load i18n %}{% trans "May" context "unexisting" %}') - rendered = t.render(Context()) - self.assertEqual(rendered, 'May') + # Inexisting context... + t = Template('{% load i18n %}{% trans "May" context "unexisting" %}') + rendered = t.render(Context()) + self.assertEqual(rendered, 'May') - # Existing context... - # Using a literal - t = Template('{% load i18n %}{% trans "May" context "month name" %}') - rendered = t.render(Context()) - self.assertEqual(rendered, 'Mai') - t = Template('{% load i18n %}{% trans "May" context "verb" %}') - rendered = t.render(Context()) - self.assertEqual(rendered, 'Kann') + # Existing context... + # Using a literal + t = Template('{% load i18n %}{% trans "May" context "month name" %}') + rendered = t.render(Context()) + self.assertEqual(rendered, 'Mai') + t = Template('{% load i18n %}{% trans "May" context "verb" %}') + rendered = t.render(Context()) + self.assertEqual(rendered, 'Kann') - # Using a variable - t = Template('{% load i18n %}{% trans "May" context message_context %}') - rendered = t.render(Context({'message_context': 'month name'})) - self.assertEqual(rendered, 'Mai') - t = Template('{% load i18n %}{% trans "May" context message_context %}') - rendered = t.render(Context({'message_context': 'verb'})) - self.assertEqual(rendered, 'Kann') + # Using a variable + t = Template('{% load i18n %}{% trans "May" context message_context %}') + rendered = t.render(Context({'message_context': 'month name'})) + self.assertEqual(rendered, 'Mai') + t = Template('{% load i18n %}{% trans "May" context message_context %}') + rendered = t.render(Context({'message_context': 'verb'})) + self.assertEqual(rendered, 'Kann') - # Using a filter - t = Template('{% load i18n %}{% trans "May" context message_context|lower %}') - rendered = t.render(Context({'message_context': 'MONTH NAME'})) - self.assertEqual(rendered, 'Mai') - t = Template('{% load i18n %}{% trans "May" context message_context|lower %}') - rendered = t.render(Context({'message_context': 'VERB'})) - self.assertEqual(rendered, 'Kann') + # Using a filter + t = Template('{% load i18n %}{% trans "May" context message_context|lower %}') + rendered = t.render(Context({'message_context': 'MONTH NAME'})) + self.assertEqual(rendered, 'Mai') + t = Template('{% load i18n %}{% trans "May" context message_context|lower %}') + rendered = t.render(Context({'message_context': 'VERB'})) + self.assertEqual(rendered, 'Kann') - # Using 'as' - t = Template('{% load i18n %}{% trans "May" context "month name" as var %}Value: {{ var }}') - rendered = t.render(Context()) - self.assertEqual(rendered, 'Value: Mai') - t = Template('{% load i18n %}{% trans "May" as var context "verb" %}Value: {{ var }}') - rendered = t.render(Context()) - self.assertEqual(rendered, 'Value: Kann') + # Using 'as' + t = Template('{% load i18n %}{% trans "May" context "month name" as var %}Value: {{ var }}') + rendered = t.render(Context()) + self.assertEqual(rendered, 'Value: Mai') + t = Template('{% load i18n %}{% trans "May" as var context "verb" %}Value: {{ var }}') + rendered = t.render(Context()) + self.assertEqual(rendered, 'Value: Kann') - # Mis-uses - self.assertRaises(TemplateSyntaxError, Template, '{% load i18n %}{% trans "May" context as var %}{{ var }}') - self.assertRaises(TemplateSyntaxError, Template, '{% load i18n %}{% trans "May" as var context %}{{ var }}') + # Mis-uses + self.assertRaises(TemplateSyntaxError, Template, '{% load i18n %}{% trans "May" context as var %}{{ var }}') + self.assertRaises(TemplateSyntaxError, Template, '{% load i18n %}{% trans "May" as var context %}{{ var }}') - # {% blocktrans %} ------------------------------ + # {% blocktrans %} ------------------------------ - # Inexisting context... - t = Template('{% load i18n %}{% blocktrans context "unexisting" %}May{% endblocktrans %}') - rendered = t.render(Context()) - self.assertEqual(rendered, 'May') + # Inexisting context... + t = Template('{% load i18n %}{% blocktrans context "unexisting" %}May{% endblocktrans %}') + rendered = t.render(Context()) + self.assertEqual(rendered, 'May') - # Existing context... - # Using a literal - t = Template('{% load i18n %}{% blocktrans context "month name" %}May{% endblocktrans %}') - rendered = t.render(Context()) - self.assertEqual(rendered, 'Mai') - t = Template('{% load i18n %}{% blocktrans context "verb" %}May{% endblocktrans %}') - rendered = t.render(Context()) - self.assertEqual(rendered, 'Kann') + # Existing context... + # Using a literal + t = Template('{% load i18n %}{% blocktrans context "month name" %}May{% endblocktrans %}') + rendered = t.render(Context()) + self.assertEqual(rendered, 'Mai') + t = Template('{% load i18n %}{% blocktrans context "verb" %}May{% endblocktrans %}') + rendered = t.render(Context()) + self.assertEqual(rendered, 'Kann') - # Using a variable - t = Template('{% load i18n %}{% blocktrans context message_context %}May{% endblocktrans %}') - rendered = t.render(Context({'message_context': 'month name'})) - self.assertEqual(rendered, 'Mai') - t = Template('{% load i18n %}{% blocktrans context message_context %}May{% endblocktrans %}') - rendered = t.render(Context({'message_context': 'verb'})) - self.assertEqual(rendered, 'Kann') + # Using a variable + t = Template('{% load i18n %}{% blocktrans context message_context %}May{% endblocktrans %}') + rendered = t.render(Context({'message_context': 'month name'})) + self.assertEqual(rendered, 'Mai') + t = Template('{% load i18n %}{% blocktrans context message_context %}May{% endblocktrans %}') + rendered = t.render(Context({'message_context': 'verb'})) + self.assertEqual(rendered, 'Kann') - # Using a filter - t = Template('{% load i18n %}{% blocktrans context message_context|lower %}May{% endblocktrans %}') - rendered = t.render(Context({'message_context': 'MONTH NAME'})) - self.assertEqual(rendered, 'Mai') - t = Template('{% load i18n %}{% blocktrans context message_context|lower %}May{% endblocktrans %}') - rendered = t.render(Context({'message_context': 'VERB'})) - self.assertEqual(rendered, 'Kann') + # Using a filter + t = Template('{% load i18n %}{% blocktrans context message_context|lower %}May{% endblocktrans %}') + rendered = t.render(Context({'message_context': 'MONTH NAME'})) + self.assertEqual(rendered, 'Mai') + t = Template('{% load i18n %}{% blocktrans context message_context|lower %}May{% endblocktrans %}') + rendered = t.render(Context({'message_context': 'VERB'})) + self.assertEqual(rendered, 'Kann') - # Using 'count' - t = Template('{% load i18n %}{% blocktrans count number=1 context "super search" %}{{ number }} super result{% plural %}{{ number }} super results{% endblocktrans %}') - rendered = t.render(Context()) - self.assertEqual(rendered, '1 Super-Ergebnis') - t = Template('{% load i18n %}{% blocktrans count number=2 context "super search" %}{{ number }} super result{% plural %}{{ number }} super results{% endblocktrans %}') - rendered = t.render(Context()) - self.assertEqual(rendered, '2 Super-Ergebnisse') - t = Template('{% load i18n %}{% blocktrans context "other super search" count number=1 %}{{ number }} super result{% plural %}{{ number }} super results{% endblocktrans %}') - rendered = t.render(Context()) - self.assertEqual(rendered, '1 anderen Super-Ergebnis') - t = Template('{% load i18n %}{% blocktrans context "other super search" count number=2 %}{{ number }} super result{% plural %}{{ number }} super results{% endblocktrans %}') - rendered = t.render(Context()) - self.assertEqual(rendered, '2 andere Super-Ergebnisse') + # Using 'count' + t = Template('{% load i18n %}{% blocktrans count number=1 context "super search" %}{{ number }} super result{% plural %}{{ number }} super results{% endblocktrans %}') + rendered = t.render(Context()) + self.assertEqual(rendered, '1 Super-Ergebnis') + t = Template('{% load i18n %}{% blocktrans count number=2 context "super search" %}{{ number }} super result{% plural %}{{ number }} super results{% endblocktrans %}') + rendered = t.render(Context()) + self.assertEqual(rendered, '2 Super-Ergebnisse') + t = Template('{% load i18n %}{% blocktrans context "other super search" count number=1 %}{{ number }} super result{% plural %}{{ number }} super results{% endblocktrans %}') + rendered = t.render(Context()) + self.assertEqual(rendered, '1 anderen Super-Ergebnis') + t = Template('{% load i18n %}{% blocktrans context "other super search" count number=2 %}{{ number }} super result{% plural %}{{ number }} super results{% endblocktrans %}') + rendered = t.render(Context()) + self.assertEqual(rendered, '2 andere Super-Ergebnisse') - # Using 'with' - t = Template('{% load i18n %}{% blocktrans with num_comments=5 context "comment count" %}There are {{ num_comments }} comments{% endblocktrans %}') - rendered = t.render(Context()) - self.assertEqual(rendered, 'Es gibt 5 Kommentare') - t = Template('{% load i18n %}{% blocktrans with num_comments=5 context "other comment count" %}There are {{ num_comments }} comments{% endblocktrans %}') - rendered = t.render(Context()) - self.assertEqual(rendered, 'Andere: Es gibt 5 Kommentare') + # Using 'with' + t = Template('{% load i18n %}{% blocktrans with num_comments=5 context "comment count" %}There are {{ num_comments }} comments{% endblocktrans %}') + rendered = t.render(Context()) + self.assertEqual(rendered, 'Es gibt 5 Kommentare') + t = Template('{% load i18n %}{% blocktrans with num_comments=5 context "other comment count" %}There are {{ num_comments }} comments{% endblocktrans %}') + rendered = t.render(Context()) + self.assertEqual(rendered, 'Andere: Es gibt 5 Kommentare') - # Mis-uses - self.assertRaises(TemplateSyntaxError, Template, '{% load i18n %}{% blocktrans context with month="May" %}{{ month }}{% endblocktrans %}') - self.assertRaises(TemplateSyntaxError, Template, '{% load i18n %}{% blocktrans context %}{% endblocktrans %}') - self.assertRaises(TemplateSyntaxError, Template, '{% load i18n %}{% blocktrans count number=2 context %}{{ number }} super result{% plural %}{{ number }} super results{% endblocktrans %}') + # Mis-uses + self.assertRaises(TemplateSyntaxError, Template, '{% load i18n %}{% blocktrans context with month="May" %}{{ month }}{% endblocktrans %}') + self.assertRaises(TemplateSyntaxError, Template, '{% load i18n %}{% blocktrans context %}{% endblocktrans %}') + self.assertRaises(TemplateSyntaxError, Template, '{% load i18n %}{% blocktrans count number=2 context %}{{ number }} super result{% plural %}{{ number }} super results{% endblocktrans %}') def test_string_concat(self): @@ -247,8 +240,7 @@ class TranslationTests(TestCase): Translations on files with mac or dos end of lines will be converted to unix eof in .po catalogs, and they have to match when retrieved """ - from django.utils.translation.trans_real import translation as Trans - ca_translation = Trans('ca') + ca_translation = trans_real.translation('ca') ca_translation._catalog['Mac\nEOF\n'] = 'Catalan Mac\nEOF\n' ca_translation._catalog['Win\nEOF\n'] = 'Catalan Win\nEOF\n' with translation.override('ca', deactivate=True): @@ -267,9 +259,8 @@ class TranslationTests(TestCase): """ Test the to_language function """ - from django.utils.translation.trans_real import to_language - self.assertEqual(to_language('en_US'), 'en-us') - self.assertEqual(to_language('sr_Lat'), 'sr-lat') + self.assertEqual(trans_real.to_language('en_US'), 'en-us') + self.assertEqual(trans_real.to_language('sr_Lat'), 'sr-lat') @override_settings(LOCALE_PATHS=(os.path.join(here, 'other', 'locale'),)) def test_bad_placeholder_1(self): @@ -278,7 +269,6 @@ class TranslationTests(TestCase): (%(person)s is translated as %(personne)s in fr.po) Refs #16516. """ - from django.template import Template, Context with translation.override('fr'): t = Template('{% load i18n %}{% blocktrans %}My name is {{ person }}.{% endblocktrans %}') rendered = t.render(Context({'person': 'James'})) @@ -291,7 +281,6 @@ class TranslationTests(TestCase): (%(person) misses a 's' in fr.po, causing the string formatting to fail) Refs #18393. """ - from django.template import Template, Context with translation.override('fr'): t = Template('{% load i18n %}{% blocktrans %}My other name is {{ person }}.{% endblocktrans %}') rendered = t.render(Context({'person': 'James'})) @@ -710,11 +699,11 @@ class MiscTests(TestCase): values according to the spec (and that we extract all the pieces in the right order). """ - from django.utils.translation.trans_real import parse_accept_lang_header - p = parse_accept_lang_header + p = trans_real.parse_accept_lang_header # Good headers. self.assertEqual([('de', 1.0)], p('de')) self.assertEqual([('en-AU', 1.0)], p('en-AU')) + self.assertEqual([('es-419', 1.0)], p('es-419')) self.assertEqual([('*', 1.0)], p('*;q=1.00')) self.assertEqual([('en-AU', 0.123)], p('en-AU;q=0.123')) self.assertEqual([('en-au', 0.5)], p('en-au;q=0.5')) @@ -739,6 +728,7 @@ class MiscTests(TestCase): self.assertEqual([], p('da, en-gb;q=0.8, en;q=0.7,#')) self.assertEqual([], p('de;q=2.0')) self.assertEqual([], p('de;q=0.a')) + self.assertEqual([], p('12-345')) self.assertEqual([], p('')) def test_parse_literal_http_header(self): @@ -809,7 +799,7 @@ class MiscTests(TestCase): self.assertEqual(g(r), 'zh-cn') def test_get_language_from_path_real(self): - from django.utils.translation.trans_real import get_language_from_path as g + g = trans_real.get_language_from_path self.assertEqual(g('/pl/'), 'pl') self.assertEqual(g('/pl'), 'pl') self.assertEqual(g('/xyz/'), None) @@ -820,23 +810,33 @@ class MiscTests(TestCase): self.assertEqual(g('/pl'), None) self.assertEqual(g('/xyz/'), None) + @override_settings(LOCALE_PATHS=extended_locale_paths) def test_percent_in_translatable_block(self): - extended_locale_paths = settings.LOCALE_PATHS + ( - os.path.join(here, 'other', 'locale'), - ) - with self.settings(LOCALE_PATHS=extended_locale_paths): - t_sing = Template("{% load i18n %}{% blocktrans %}The result was {{ percent }}%{% endblocktrans %}") - t_plur = Template("{% load i18n %}{% blocktrans count num as number %}{{ percent }}% represents {{ num }} object{% plural %}{{ percent }}% represents {{ num }} objects{% endblocktrans %}") - with translation.override('de'): - self.assertEqual(t_sing.render(Context({'percent': 42})), 'Das Ergebnis war 42%') - self.assertEqual(t_plur.render(Context({'percent': 42, 'num': 1})), '42% stellt 1 Objekt dar') - self.assertEqual(t_plur.render(Context({'percent': 42, 'num': 4})), '42% stellt 4 Objekte dar') + t_sing = Template("{% load i18n %}{% blocktrans %}The result was {{ percent }}%{% endblocktrans %}") + t_plur = Template("{% load i18n %}{% blocktrans count num as number %}{{ percent }}% represents {{ num }} object{% plural %}{{ percent }}% represents {{ num }} objects{% endblocktrans %}") + with translation.override('de'): + self.assertEqual(t_sing.render(Context({'percent': 42})), 'Das Ergebnis war 42%') + self.assertEqual(t_plur.render(Context({'percent': 42, 'num': 1})), '42% stellt 1 Objekt dar') + self.assertEqual(t_plur.render(Context({'percent': 42, 'num': 4})), '42% stellt 4 Objekte dar') + + @override_settings(LOCALE_PATHS=extended_locale_paths) + def test_percent_formatting_in_blocktrans(self): + """ + Test that using Python's %-formatting is properly escaped in blocktrans, + singular or plural + """ + t_sing = Template("{% load i18n %}{% blocktrans %}There are %(num_comments)s comments{% endblocktrans %}") + t_plur = Template("{% load i18n %}{% blocktrans count num as number %}%(percent)s% represents {{ num }} object{% plural %}%(percent)s% represents {{ num }} objects{% endblocktrans %}") + with translation.override('de'): + # Strings won't get translated as they don't match after escaping % + self.assertEqual(t_sing.render(Context({'num_comments': 42})), 'There are %(num_comments)s comments') + self.assertEqual(t_plur.render(Context({'percent': 42, 'num': 1})), '%(percent)s% represents 1 object') + self.assertEqual(t_plur.render(Context({'percent': 42, 'num': 4})), '%(percent)s% represents 4 objects') class ResolutionOrderI18NTests(TestCase): def setUp(self): - from django.utils.translation import trans_real # Okay, this is brutal, but we have no other choice to fully reset # the translation framework trans_real._active = local() @@ -865,17 +865,9 @@ class AppResolutionOrderI18NTests(ResolutionOrderI18NTests): def test_app_translation(self): self.assertUgettext('Date/time', 'APP') +@override_settings(LOCALE_PATHS=extended_locale_paths) class LocalePathsResolutionOrderI18NTests(ResolutionOrderI18NTests): - def setUp(self): - self.old_locale_paths = settings.LOCALE_PATHS - settings.LOCALE_PATHS += (os.path.join(here, 'other', 'locale'),) - super(LocalePathsResolutionOrderI18NTests, self).setUp() - - def tearDown(self): - settings.LOCALE_PATHS = self.old_locale_paths - super(LocalePathsResolutionOrderI18NTests, self).tearDown() - def test_locale_paths_translation(self): self.assertUgettext('Time', 'LOCALE_PATHS') diff --git a/tests/regressiontests/localflavor/ar/tests.py b/tests/regressiontests/localflavor/ar/tests.py deleted file mode 100644 index 0bc228eae9..0000000000 --- a/tests/regressiontests/localflavor/ar/tests.py +++ /dev/null @@ -1,103 +0,0 @@ -from __future__ import unicode_literals - -from django.contrib.localflavor.ar.forms import (ARProvinceSelect, - ARPostalCodeField, ARDNIField, ARCUITField) - -from django.test import SimpleTestCase - - -class ARLocalFlavorTests(SimpleTestCase): - def test_ARProvinceSelect(self): - f = ARProvinceSelect() - out = '''<select name="provincias"> -<option value="B">Buenos Aires</option> -<option value="K">Catamarca</option> -<option value="H">Chaco</option> -<option value="U">Chubut</option> -<option value="C">Ciudad Aut\xf3noma de Buenos Aires</option> -<option value="X">C\xf3rdoba</option> -<option value="W">Corrientes</option> -<option value="E">Entre R\xedos</option> -<option value="P">Formosa</option> -<option value="Y">Jujuy</option> -<option value="L">La Pampa</option> -<option value="F">La Rioja</option> -<option value="M">Mendoza</option> -<option value="N">Misiones</option> -<option value="Q">Neuqu\xe9n</option> -<option value="R">R\xedo Negro</option> -<option value="A" selected="selected">Salta</option> -<option value="J">San Juan</option> -<option value="D">San Luis</option> -<option value="Z">Santa Cruz</option> -<option value="S">Santa Fe</option> -<option value="G">Santiago del Estero</option> -<option value="V">Tierra del Fuego, Ant\xe1rtida e Islas del Atl\xe1ntico Sur</option> -<option value="T">Tucum\xe1n</option> -</select>''' - self.assertHTMLEqual(f.render('provincias', 'A'), out) - - def test_ARPostalCodeField(self): - error_format = ['Enter a postal code in the format NNNN or ANNNNAAA.'] - error_atmost = ['Ensure this value has at most 8 characters (it has 9).'] - error_atleast = ['Ensure this value has at least 4 characters (it has 3).'] - valid = { - '5000': '5000', - 'C1064AAB': 'C1064AAB', - 'c1064AAB': 'C1064AAB', - 'C1064aab': 'C1064AAB', - '4400': '4400', - 'C1064AAB': 'C1064AAB', - } - invalid = { - 'C1064AABB': error_atmost + error_format, - 'C1064AA': error_format, - 'C1064AB': error_format, - '106AAB': error_format, - '500': error_atleast + error_format, - '5PPP': error_format, - } - self.assertFieldOutput(ARPostalCodeField, valid, invalid) - - def test_ARDNIField(self): - error_length = ['This field requires 7 or 8 digits.'] - error_digitsonly = ['This field requires only numbers.'] - valid = { - '20123456': '20123456', - '20.123.456': '20123456', - '20123456': '20123456', - '20.123.456': '20123456', - '20.123456': '20123456', - '9123456': '9123456', - '9.123.456': '9123456', - } - invalid = { - '101234566': error_length, - 'W0123456': error_digitsonly, - '10,123,456': error_digitsonly, - } - self.assertFieldOutput(ARDNIField, valid, invalid) - - def test_ARCUITField(self): - error_format = ['Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.'] - error_invalid = ['Invalid CUIT.'] - error_legal_type = ['Invalid legal type. Type must be 27, 20, 23 or 30.'] - valid = { - '20-10123456-9': '20-10123456-9', - '20-10123456-9': '20-10123456-9', - '27-10345678-4': '27-10345678-4', - '20101234569': '20-10123456-9', - '27103456784': '27-10345678-4', - '30011111110': '30-01111111-0', - } - invalid = { - '2-10123456-9': error_format, - '210123456-9': error_format, - '20-10123456': error_format, - '20-10123456-': error_format, - '20-10123456-5': error_invalid, - '27-10345678-1': error_invalid, - '27-10345678-1': error_invalid, - '11211111110': error_legal_type, - } - self.assertFieldOutput(ARCUITField, valid, invalid) diff --git a/tests/regressiontests/localflavor/at/tests.py b/tests/regressiontests/localflavor/at/tests.py deleted file mode 100644 index 9123ba4e88..0000000000 --- a/tests/regressiontests/localflavor/at/tests.py +++ /dev/null @@ -1,49 +0,0 @@ -from __future__ import unicode_literals - -from django.contrib.localflavor.at.forms import (ATZipCodeField, ATStateSelect, - ATSocialSecurityNumberField) - -from django.test import SimpleTestCase - - -class ATLocalFlavorTests(SimpleTestCase): - def test_ATStateSelect(self): - f = ATStateSelect() - out = '''<select name="bundesland"> -<option value="BL">Burgenland</option> -<option value="KA">Carinthia</option> -<option value="NO">Lower Austria</option> -<option value="OO">Upper Austria</option> -<option value="SA">Salzburg</option> -<option value="ST">Styria</option> -<option value="TI">Tyrol</option> -<option value="VO">Vorarlberg</option> -<option value="WI" selected="selected">Vienna</option> -</select>''' - self.assertHTMLEqual(f.render('bundesland', 'WI'), out) - - def test_ATZipCodeField(self): - error_format = ['Enter a zip code in the format XXXX.'] - valid = { - '1150': '1150', - '4020': '4020', - '8020': '8020', - } - invalid = { - '0000' : error_format, - '0123' : error_format, - '111222': error_format, - 'eeffee': error_format, - } - self.assertFieldOutput(ATZipCodeField, valid, invalid) - - def test_ATSocialSecurityNumberField(self): - error_format = ['Enter a valid Austrian Social Security Number in XXXX XXXXXX format.'] - valid = { - '1237 010180': '1237 010180', - } - invalid = { - '1237 010181': error_format, - '12370 010180': error_format, - } - self.assertFieldOutput(ATSocialSecurityNumberField, valid, invalid) diff --git a/tests/regressiontests/localflavor/au/__init__.py b/tests/regressiontests/localflavor/au/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/au/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/au/forms.py b/tests/regressiontests/localflavor/au/forms.py deleted file mode 100644 index aec00694fe..0000000000 --- a/tests/regressiontests/localflavor/au/forms.py +++ /dev/null @@ -1,11 +0,0 @@ -from __future__ import absolute_import - -from django.forms import ModelForm - -from .models import AustralianPlace - - -class AustralianPlaceForm(ModelForm): - """ Form for storing an Australian place. """ - class Meta: - model = AustralianPlace diff --git a/tests/regressiontests/localflavor/au/models.py b/tests/regressiontests/localflavor/au/models.py deleted file mode 100644 index 39061c5bb3..0000000000 --- a/tests/regressiontests/localflavor/au/models.py +++ /dev/null @@ -1,14 +0,0 @@ -from django.contrib.localflavor.au.models import AUStateField, AUPostCodeField -from django.db import models - -class AustralianPlace(models.Model): - state = AUStateField(blank=True) - state_required = AUStateField() - state_default = AUStateField(default="NSW", blank=True) - postcode = AUPostCodeField(blank=True) - postcode_required = AUPostCodeField() - postcode_default = AUPostCodeField(default="2500", blank=True) - name = models.CharField(max_length=20) - - class Meta: - app_label = 'localflavor' diff --git a/tests/regressiontests/localflavor/au/tests.py b/tests/regressiontests/localflavor/au/tests.py deleted file mode 100644 index 69472f0935..0000000000 --- a/tests/regressiontests/localflavor/au/tests.py +++ /dev/null @@ -1,108 +0,0 @@ -from __future__ import absolute_import, unicode_literals - -import re - -from django.test import SimpleTestCase -from django.contrib.localflavor.au.forms import (AUPostCodeField, - AUPhoneNumberField, AUStateSelect) - -from .forms import AustralianPlaceForm - - -SELECTED_OPTION_PATTERN = r'<option value="%s" selected="selected">' -BLANK_OPTION_PATTERN = r'<option value="">' -INPUT_VALUE_PATTERN = r'<input[^>]*value="%s"[^>]*>' - - -class AULocalflavorTests(SimpleTestCase): - - def setUp(self): - self.form = AustralianPlaceForm( - {'state':'WA', - 'state_required':'QLD', - 'name':'dummy', - 'postcode':'1234', - 'postcode_required':'4321', - }) - - def test_get_display_methods(self): - """ Ensure get_*_display() methods are added to model instances. """ - place = self.form.save() - self.assertEqual(place.get_state_display(), 'Western Australia') - self.assertEqual(place.get_state_required_display(), 'Queensland') - - def test_default_values(self): - """ Ensure that default values are selected in forms. """ - form = AustralianPlaceForm() - self.assertTrue(re.search(SELECTED_OPTION_PATTERN % 'NSW', - str(form['state_default']))) - self.assertTrue(re.search(INPUT_VALUE_PATTERN % '2500', - str(form['postcode_default']))) - - def test_required(self): - """ Test that required AUStateFields throw appropriate errors. """ - form = AustralianPlaceForm({'state':'NSW', 'name':'Wollongong'}) - self.assertFalse(form.is_valid()) - self.assertEqual( - form.errors['state_required'], ['This field is required.']) - self.assertEqual( - form.errors['postcode_required'], ['This field is required.']) - - def test_field_blank_option(self): - """ Test that the empty option is there. """ - self.assertTrue(re.search(BLANK_OPTION_PATTERN, - str(self.form['state']))) - - def test_selected_values(self): - """ Ensure selected states match the initial values provided. """ - self.assertTrue(re.search(SELECTED_OPTION_PATTERN % 'WA', - str(self.form['state']))) - self.assertTrue(re.search(SELECTED_OPTION_PATTERN % 'QLD', - str(self.form['state_required']))) - self.assertTrue(re.search(INPUT_VALUE_PATTERN % '1234', - str(self.form['postcode']))) - self.assertTrue(re.search(INPUT_VALUE_PATTERN % '4321', - str(self.form['postcode_required']))) - - def test_AUStateSelect(self): - f = AUStateSelect() - out = '''<select name="state"> -<option value="ACT">Australian Capital Territory</option> -<option value="NSW" selected="selected">New South Wales</option> -<option value="NT">Northern Territory</option> -<option value="QLD">Queensland</option> -<option value="SA">South Australia</option> -<option value="TAS">Tasmania</option> -<option value="VIC">Victoria</option> -<option value="WA">Western Australia</option> -</select>''' - self.assertHTMLEqual(f.render('state', 'NSW'), out) - - def test_AUPostCodeField(self): - error_format = ['Enter a 4 digit postcode.'] - valid = { - '1234': '1234', - '2000': '2000', - } - invalid = { - 'abcd': error_format, - '20001': ['Ensure this value has at most 4 characters (it has 5).'] + error_format, - } - self.assertFieldOutput(AUPostCodeField, valid, invalid) - - def test_AUPhoneNumberField(self): - error_format = ['Phone numbers must contain 10 digits.'] - valid = { - '1234567890': '1234567890', - '0213456789': '0213456789', - '02 13 45 67 89': '0213456789', - '(02) 1345 6789': '0213456789', - '(02) 1345-6789': '0213456789', - '(02)1345-6789': '0213456789', - '0408 123 456': '0408123456', - } - invalid = { - '123': error_format, - '1800DJANGO': error_format, - } - self.assertFieldOutput(AUPhoneNumberField, valid, invalid) diff --git a/tests/regressiontests/localflavor/be/__init__.py b/tests/regressiontests/localflavor/be/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/be/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/be/tests.py b/tests/regressiontests/localflavor/be/tests.py deleted file mode 100644 index 69f77eb35f..0000000000 --- a/tests/regressiontests/localflavor/be/tests.py +++ /dev/null @@ -1,81 +0,0 @@ -from __future__ import unicode_literals - -from django.contrib.localflavor.be.forms import (BEPostalCodeField, - BEPhoneNumberField, BERegionSelect, BEProvinceSelect) - -from django.test import SimpleTestCase - - -class BELocalFlavorTests(SimpleTestCase): - def test_BEPostalCodeField(self): - error_format = ['Enter a valid postal code in the range and format 1XXX - 9XXX.'] - valid = { - '1451': '1451', - '2540': '2540', - } - invalid = { - '0287': error_format, - '14309': error_format, - '873': error_format, - '35 74': error_format, - '859A': error_format, - } - self.assertFieldOutput(BEPostalCodeField, valid, invalid) - - def test_BEPhoneNumberField(self): - error_format = [ - ('Enter a valid phone number in one of the formats 0x xxx xx xx, ' - '0xx xx xx xx, 04xx xx xx xx, 0x/xxx.xx.xx, 0xx/xx.xx.xx, ' - '04xx/xx.xx.xx, 0x.xxx.xx.xx, 0xx.xx.xx.xx, 04xx.xx.xx.xx, ' - '0xxxxxxxx or 04xxxxxxxx.') - ] - valid = { - '01 234 56 78': '01 234 56 78', - '01/234.56.78': '01/234.56.78', - '01.234.56.78': '01.234.56.78', - '012 34 56 78': '012 34 56 78', - '012/34.56.78': '012/34.56.78', - '012.34.56.78': '012.34.56.78', - '0412 34 56 78': '0412 34 56 78', - '0412/34.56.78': '0412/34.56.78', - '0412.34.56.78': '0412.34.56.78', - '012345678': '012345678', - '0412345678': '0412345678', - } - invalid = { - '01234567': error_format, - '12/345.67.89': error_format, - '012/345.678.90': error_format, - '012/34.56.789': error_format, - '0123/45.67.89': error_format, - '012/345 678 90': error_format, - '012/34 56 789': error_format, - '012.34 56 789': error_format, - } - self.assertFieldOutput(BEPhoneNumberField, valid, invalid) - - def test_BERegionSelect(self): - f = BERegionSelect() - out = '''<select name="regions"> -<option value="BRU">Brussels Capital Region</option> -<option value="VLG" selected="selected">Flemish Region</option> -<option value="WAL">Wallonia</option> -</select>''' - self.assertHTMLEqual(f.render('regions', 'VLG'), out) - - def test_BEProvinceSelect(self): - f = BEProvinceSelect() - out = '''<select name="provinces"> -<option value="VAN">Antwerp</option> -<option value="BRU">Brussels</option> -<option value="VOV">East Flanders</option> -<option value="VBR">Flemish Brabant</option> -<option value="WHT">Hainaut</option> -<option value="WLG" selected="selected">Liege</option> -<option value="VLI">Limburg</option> -<option value="WLX">Luxembourg</option> -<option value="WNA">Namur</option> -<option value="WBR">Walloon Brabant</option> -<option value="VWV">West Flanders</option> -</select>''' - self.assertHTMLEqual(f.render('provinces', 'WLG'), out) diff --git a/tests/regressiontests/localflavor/br/__init__.py b/tests/regressiontests/localflavor/br/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/br/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/br/tests.py b/tests/regressiontests/localflavor/br/tests.py deleted file mode 100644 index abee2d7336..0000000000 --- a/tests/regressiontests/localflavor/br/tests.py +++ /dev/null @@ -1,146 +0,0 @@ -from __future__ import unicode_literals - -from django.contrib.localflavor.br.forms import (BRZipCodeField, - BRCNPJField, BRCPFField, BRPhoneNumberField, BRStateSelect, - BRStateChoiceField) - -from django.test import SimpleTestCase - - -class BRLocalFlavorTests(SimpleTestCase): - def test_BRZipCodeField(self): - error_format = ['Enter a zip code in the format XXXXX-XXX.'] - valid = { - '12345-123': '12345-123', - } - invalid = { - '12345_123': error_format, - '1234-123': error_format, - 'abcde-abc': error_format, - '12345-': error_format, - '-123': error_format, - } - self.assertFieldOutput(BRZipCodeField, valid, invalid) - - def test_BRCNPJField(self): - error_format = ['Invalid CNPJ number.'] - error_numbersonly = ['This field requires only numbers.'] - valid = { - '64.132.916/0001-88': '64.132.916/0001-88', - '64-132-916/0001-88': '64-132-916/0001-88', - '64132916/0001-88': '64132916/0001-88', - } - invalid = { - '12-345-678/9012-10': error_format, - '12.345.678/9012-10': error_format, - '12345678/9012-10': error_format, - '64.132.916/0001-XX': error_numbersonly, - } - self.assertFieldOutput(BRCNPJField, valid, invalid) - - def test_BRCPFField(self): - error_format = ['Invalid CPF number.'] - error_numbersonly = ['This field requires only numbers.'] - error_atmost_chars = ['Ensure this value has at most 14 characters (it has 15).'] - error_atleast_chars = ['Ensure this value has at least 11 characters (it has 10).'] - error_atmost = ['This field requires at most 11 digits or 14 characters.'] - valid = { - '663.256.017-26': '663.256.017-26', - '66325601726': '66325601726', - '375.788.573-20': '375.788.573-20', - '84828509895': '84828509895', - } - invalid = { - '489.294.654-54': error_format, - '295.669.575-98': error_format, - '539.315.127-22': error_format, - '375.788.573-XX': error_numbersonly, - '375.788.573-000': error_atmost_chars, - '123.456.78': error_atleast_chars, - '123456789555': error_atmost, - } - self.assertFieldOutput(BRCPFField, valid, invalid) - - def test_BRPhoneNumberField(self): - # TODO: this doesn't test for any invalid inputs. - valid = { - '41-3562-3464': '41-3562-3464', - '4135623464': '41-3562-3464', - '41 3562-3464': '41-3562-3464', - '41 3562 3464': '41-3562-3464', - '(41) 3562 3464': '41-3562-3464', - '41.3562.3464': '41-3562-3464', - '41.3562-3464': '41-3562-3464', - ' (41) 3562.3464': '41-3562-3464', - } - invalid = {} - self.assertFieldOutput(BRPhoneNumberField, valid, invalid) - - def test_BRStateSelect(self): - f = BRStateSelect() - out = '''<select name="states"> -<option value="AC">Acre</option> -<option value="AL">Alagoas</option> -<option value="AP">Amap\xe1</option> -<option value="AM">Amazonas</option> -<option value="BA">Bahia</option> -<option value="CE">Cear\xe1</option> -<option value="DF">Distrito Federal</option> -<option value="ES">Esp\xedrito Santo</option> -<option value="GO">Goi\xe1s</option> -<option value="MA">Maranh\xe3o</option> -<option value="MT">Mato Grosso</option> -<option value="MS">Mato Grosso do Sul</option> -<option value="MG">Minas Gerais</option> -<option value="PA">Par\xe1</option> -<option value="PB">Para\xedba</option> -<option value="PR" selected="selected">Paran\xe1</option> -<option value="PE">Pernambuco</option> -<option value="PI">Piau\xed</option> -<option value="RJ">Rio de Janeiro</option> -<option value="RN">Rio Grande do Norte</option> -<option value="RS">Rio Grande do Sul</option> -<option value="RO">Rond\xf4nia</option> -<option value="RR">Roraima</option> -<option value="SC">Santa Catarina</option> -<option value="SP">S\xe3o Paulo</option> -<option value="SE">Sergipe</option> -<option value="TO">Tocantins</option> -</select>''' - self.assertHTMLEqual(f.render('states', 'PR'), out) - - def test_BRStateChoiceField(self): - error_invalid = ['Select a valid brazilian state. That state is not one of the available states.'] - valid = { - 'AC': 'AC', - 'AL': 'AL', - 'AP': 'AP', - 'AM': 'AM', - 'BA': 'BA', - 'CE': 'CE', - 'DF': 'DF', - 'ES': 'ES', - 'GO': 'GO', - 'MA': 'MA', - 'MT': 'MT', - 'MS': 'MS', - 'MG': 'MG', - 'PA': 'PA', - 'PB': 'PB', - 'PR': 'PR', - 'PE': 'PE', - 'PI': 'PI', - 'RJ': 'RJ', - 'RN': 'RN', - 'RS': 'RS', - 'RO': 'RO', - 'RR': 'RR', - 'SC': 'SC', - 'SP': 'SP', - 'SE': 'SE', - 'TO': 'TO', - } - invalid = { - 'pr': error_invalid, - } - self.assertFieldOutput(BRStateChoiceField, valid, invalid) diff --git a/tests/regressiontests/localflavor/ca/__init__.py b/tests/regressiontests/localflavor/ca/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/ca/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/ca/tests.py b/tests/regressiontests/localflavor/ca/tests.py deleted file mode 100644 index 8f0eb9c702..0000000000 --- a/tests/regressiontests/localflavor/ca/tests.py +++ /dev/null @@ -1,115 +0,0 @@ -from __future__ import unicode_literals - -import warnings - -from django.contrib.localflavor.ca.forms import (CAPostalCodeField, - CAPhoneNumberField, CAProvinceField, CAProvinceSelect, - CASocialInsuranceNumberField) - -from django.test import SimpleTestCase - - -class CALocalFlavorTests(SimpleTestCase): - def setUp(self): - self.save_warnings_state() - warnings.filterwarnings( - "ignore", - category=RuntimeWarning, - module='django.contrib.localflavor.ca.ca_provinces' - ) - - def tearDown(self): - self.restore_warnings_state() - - def test_CAProvinceSelect(self): - f = CAProvinceSelect() - out = '''<select name="province"> -<option value="AB" selected="selected">Alberta</option> -<option value="BC">British Columbia</option> -<option value="MB">Manitoba</option> -<option value="NB">New Brunswick</option> -<option value="NL">Newfoundland and Labrador</option> -<option value="NT">Northwest Territories</option> -<option value="NS">Nova Scotia</option> -<option value="NU">Nunavut</option> -<option value="ON">Ontario</option> -<option value="PE">Prince Edward Island</option> -<option value="QC">Quebec</option> -<option value="SK">Saskatchewan</option> -<option value="YT">Yukon</option> -</select>''' - self.assertHTMLEqual(f.render('province', 'AB'), out) - - def test_CAPostalCodeField(self): - error_format = ['Enter a postal code in the format XXX XXX.'] - valid = { - 'T2S 2H7': 'T2S 2H7', - 'T2S 2W7': 'T2S 2W7', - 'T2S 2Z7': 'T2S 2Z7', - 'T2Z 2H7': 'T2Z 2H7', - 'T2S2H7' : 'T2S 2H7', - 't2s 2h7': 'T2S 2H7', - 't2s2h7' : 'T2S 2H7', - 't2s 2H7': 'T2S 2H7', - ' t2s 2H7 ': 'T2S 2H7', - } - invalid = { - 'T2S 2H' : error_format, - '2T6 H8I': error_format, - 'T2S2H' : error_format, - 't2s h8i': error_format, - 90210 : error_format, - 'W2S 2H3': error_format, - 'Z2S 2H3': error_format, - 'F2S 2H3': error_format, - 'A2S 2D3': error_format, - 'A2I 2R3': error_format, - 'A2Q 2R3': error_format, - 'U2B 2R3': error_format, - 'O2B 2R3': error_format, - } - self.assertFieldOutput(CAPostalCodeField, valid, invalid) - - def test_CAPhoneNumberField(self): - error_format = ['Phone numbers must be in XXX-XXX-XXXX format.'] - valid = { - '403-555-1212': '403-555-1212', - '4035551212': '403-555-1212', - '403 555-1212': '403-555-1212', - '(403) 555-1212': '403-555-1212', - '403 555 1212': '403-555-1212', - '403.555.1212': '403-555-1212', - '403.555-1212': '403-555-1212', - ' (403) 555.1212 ': '403-555-1212', - } - invalid = { - '555-1212': error_format, - '403-55-1212': error_format, - } - self.assertFieldOutput(CAPhoneNumberField, valid, invalid) - - def test_CAProvinceField(self): - error_format = ['Enter a Canadian province or territory.'] - valid = { - 'ab': 'AB', - 'BC': 'BC', - 'nova scotia': 'NS', - ' manitoba ': 'MB', - 'pq': 'QC', - } - invalid = { - 'T2S 2H7': error_format, - } - self.assertFieldOutput(CAProvinceField, valid, invalid) - - def test_CASocialInsuranceField(self): - error_format = ['Enter a valid Canadian Social Insurance number in XXX-XXX-XXX format.'] - valid = { - '046-454-286': '046-454-286', - } - invalid = { - '046-454-287': error_format, - '046 454 286': error_format, - '046-44-286': error_format, - } - self.assertFieldOutput(CASocialInsuranceNumberField, valid, invalid) diff --git a/tests/regressiontests/localflavor/ch/__init__.py b/tests/regressiontests/localflavor/ch/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/ch/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/ch/tests.py b/tests/regressiontests/localflavor/ch/tests.py deleted file mode 100644 index f3491855a2..0000000000 --- a/tests/regressiontests/localflavor/ch/tests.py +++ /dev/null @@ -1,76 +0,0 @@ -from __future__ import unicode_literals - -from django.contrib.localflavor.ch.forms import (CHZipCodeField, - CHPhoneNumberField, CHIdentityCardNumberField, CHStateSelect) - -from django.test import SimpleTestCase - - -class CHLocalFlavorTests(SimpleTestCase): - def test_CHStateSelect(self): - f = CHStateSelect() - out = '''<select name="state"> -<option value="AG" selected="selected">Aargau</option> -<option value="AI">Appenzell Innerrhoden</option> -<option value="AR">Appenzell Ausserrhoden</option> -<option value="BS">Basel-Stadt</option> -<option value="BL">Basel-Land</option> -<option value="BE">Berne</option> -<option value="FR">Fribourg</option> -<option value="GE">Geneva</option> -<option value="GL">Glarus</option> -<option value="GR">Graubuenden</option> -<option value="JU">Jura</option> -<option value="LU">Lucerne</option> -<option value="NE">Neuchatel</option> -<option value="NW">Nidwalden</option> -<option value="OW">Obwalden</option> -<option value="SH">Schaffhausen</option> -<option value="SZ">Schwyz</option> -<option value="SO">Solothurn</option> -<option value="SG">St. Gallen</option> -<option value="TG">Thurgau</option> -<option value="TI">Ticino</option> -<option value="UR">Uri</option> -<option value="VS">Valais</option> -<option value="VD">Vaud</option> -<option value="ZG">Zug</option> -<option value="ZH">Zurich</option> -</select>''' - self.assertHTMLEqual(f.render('state', 'AG'), out) - - def test_CHZipCodeField(self): - error_format = ['Enter a zip code in the format XXXX.'] - valid = { - '1234': '1234', - '0000': '0000', - } - invalid = { - '800x': error_format, - '80 00': error_format, - } - self.assertFieldOutput(CHZipCodeField, valid, invalid) - - def test_CHPhoneNumberField(self): - error_format = ['Phone numbers must be in 0XX XXX XX XX format.'] - valid = { - '012 345 67 89': '012 345 67 89', - '0123456789': '012 345 67 89', - } - invalid = { - '01234567890': error_format, - '1234567890': error_format, - } - self.assertFieldOutput(CHPhoneNumberField, valid, invalid) - - def test_CHIdentityCardNumberField(self): - error_format = ['Enter a valid Swiss identity or passport card number in X1234567<0 or 1234567890 format.'] - valid = { - 'C1234567<0': 'C1234567<0', - '2123456700': '2123456700', - } - invalid = { - 'C1234567<1': error_format, - '2123456701': error_format, - } - self.assertFieldOutput(CHIdentityCardNumberField, valid, invalid) diff --git a/tests/regressiontests/localflavor/cl/__init__.py b/tests/regressiontests/localflavor/cl/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/cl/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/cl/tests.py b/tests/regressiontests/localflavor/cl/tests.py deleted file mode 100644 index 47cae6bd48..0000000000 --- a/tests/regressiontests/localflavor/cl/tests.py +++ /dev/null @@ -1,58 +0,0 @@ -from __future__ import unicode_literals - -from django.contrib.localflavor.cl.forms import CLRutField, CLRegionSelect - -from django.test import SimpleTestCase - - -class CLLocalFlavorTests(SimpleTestCase): - def test_CLRegionSelect(self): - f = CLRegionSelect() - out = '''<select name="foo"> -<option value="RM">Regi\xf3n Metropolitana de Santiago</option> -<option value="I">Regi\xf3n de Tarapac\xe1</option> -<option value="II">Regi\xf3n de Antofagasta</option> -<option value="III">Regi\xf3n de Atacama</option> -<option value="IV">Regi\xf3n de Coquimbo</option> -<option value="V">Regi\xf3n de Valpara\xedso</option> -<option value="VI">Regi\xf3n del Libertador Bernardo O'Higgins</option> -<option value="VII">Regi\xf3n del Maule</option> -<option value="VIII">Regi\xf3n del B\xedo B\xedo</option> -<option value="IX">Regi\xf3n de la Araucan\xeda</option> -<option value="X">Regi\xf3n de los Lagos</option> -<option value="XI">Regi\xf3n de Ays\xe9n del General Carlos Ib\xe1\xf1ez del Campo</option> -<option value="XII">Regi\xf3n de Magallanes y la Ant\xe1rtica Chilena</option> -<option value="XIV">Regi\xf3n de Los R\xedos</option> -<option value="XV">Regi\xf3n de Arica-Parinacota</option> -</select>''' - self.assertHTMLEqual(f.render('foo', 'bar'), out) - - def test_CLRutField(self): - error_invalid = ['The Chilean RUT is not valid.'] - error_format = ['Enter a valid Chilean RUT. The format is XX.XXX.XXX-X.'] - valid = { - '11-6': '11-6', - '116': '11-6', - '767484100': '76.748.410-0', - '78.412.790-7': '78.412.790-7', - '8.334.6043': '8.334.604-3', - '76793310-K': '76.793.310-K', - '76793310-k': '76.793.310-K', - } - invalid = { - '11.111.111-0': error_invalid, - '111': error_invalid, - } - self.assertFieldOutput(CLRutField, valid, invalid) - - # deal with special "Strict Mode". - invalid = { - '11-6': error_format, - '767484100': error_format, - '8.334.6043': error_format, - '76793310-K': error_format, - '11.111.111-0': error_invalid - } - self.assertFieldOutput(CLRutField, - {}, invalid, field_kwargs={"strict": True} - ) diff --git a/tests/regressiontests/localflavor/cn/__init__.py b/tests/regressiontests/localflavor/cn/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/cn/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/cn/tests.py b/tests/regressiontests/localflavor/cn/tests.py deleted file mode 100644 index 24bcc6e392..0000000000 --- a/tests/regressiontests/localflavor/cn/tests.py +++ /dev/null @@ -1,113 +0,0 @@ -# Tests for contrib/localflavor/ CN Form Fields -from __future__ import unicode_literals - -from django.contrib.localflavor.cn.forms import (CNProvinceSelect, - CNPostCodeField, CNIDCardField, CNPhoneNumberField, CNCellNumberField) -from django.test import SimpleTestCase - -class CNLocalFlavorTests(SimpleTestCase): - def test_CNProvinceSelect(self): - f = CNProvinceSelect() - correct_output = '''<select name="provinces"> -<option value="anhui">\u5b89\u5fbd</option> -<option value="beijing">\u5317\u4eac</option> -<option value="chongqing">\u91cd\u5e86</option> -<option value="fujian">\u798f\u5efa</option> -<option value="gansu">\u7518\u8083</option> -<option value="guangdong">\u5e7f\u4e1c</option> -<option value="guangxi">\u5e7f\u897f\u58ee\u65cf\u81ea\u6cbb\u533a</option> -<option value="guizhou">\u8d35\u5dde</option> -<option value="hainan">\u6d77\u5357</option> -<option value="hebei">\u6cb3\u5317</option> -<option value="heilongjiang">\u9ed1\u9f99\u6c5f</option> -<option value="henan">\u6cb3\u5357</option> -<option value="hongkong">\u9999\u6e2f</option> -<option value="hubei" selected="selected">\u6e56\u5317</option> -<option value="hunan">\u6e56\u5357</option> -<option value="jiangsu">\u6c5f\u82cf</option> -<option value="jiangxi">\u6c5f\u897f</option> -<option value="jilin">\u5409\u6797</option> -<option value="liaoning">\u8fbd\u5b81</option> -<option value="macao">\u6fb3\u95e8</option> -<option value="neimongol">\u5185\u8499\u53e4\u81ea\u6cbb\u533a</option> -<option value="ningxia">\u5b81\u590f\u56de\u65cf\u81ea\u6cbb\u533a</option> -<option value="qinghai">\u9752\u6d77</option> -<option value="shaanxi">\u9655\u897f</option> -<option value="shandong">\u5c71\u4e1c</option> -<option value="shanghai">\u4e0a\u6d77</option> -<option value="shanxi">\u5c71\u897f</option> -<option value="sichuan">\u56db\u5ddd</option> -<option value="taiwan">\u53f0\u6e7e</option> -<option value="tianjin">\u5929\u6d25</option> -<option value="xinjiang">\u65b0\u7586\u7ef4\u543e\u5c14\u81ea\u6cbb\u533a</option> -<option value="xizang">\u897f\u85cf\u81ea\u6cbb\u533a</option> -<option value="yunnan">\u4e91\u5357</option> -<option value="zhejiang">\u6d59\u6c5f</option> -</select>''' - self.assertHTMLEqual(f.render('provinces', 'hubei'), correct_output) - - def test_CNPostCodeField(self): - error_format = ['Enter a post code in the format XXXXXX.'] - valid = { - '091209': '091209' - } - invalid = { - '09120': error_format, - '09120916': error_format - } - self.assertFieldOutput(CNPostCodeField, valid, invalid) - - def test_CNIDCardField(self): - valid = { - # A valid 1st generation ID Card Number. - '110101491001001': '110101491001001', - # A valid 2nd generation ID Card number. - '11010119491001001X': '11010119491001001X', - # Another valid 2nd gen ID Number with a case change - '11010119491001001x': '11010119491001001X' - } - - wrong_format = ['ID Card Number consists of 15 or 18 digits.'] - wrong_location = ['Invalid ID Card Number: Wrong location code'] - wrong_bday = ['Invalid ID Card Number: Wrong birthdate'] - wrong_checksum = ['Invalid ID Card Number: Wrong checksum'] - - invalid = { - 'abcdefghijklmnop': wrong_format, - '1010101010101010': wrong_format, - '010101491001001' : wrong_location, # 1st gen, 01 is invalid - '110101491041001' : wrong_bday, # 1st gen. There wasn't day 41 - '92010119491001001X': wrong_location, # 2nd gen, 92 is invalid - '91010119491301001X': wrong_bday, # 2nd gen, 19491301 is invalid date - '910101194910010014': wrong_checksum #2nd gen - } - self.assertFieldOutput(CNIDCardField, valid, invalid) - - def test_CNPhoneNumberField(self): - error_format = ['Enter a valid phone number.'] - valid = { - '010-12345678': '010-12345678', - '010-1234567': '010-1234567', - '0101-12345678': '0101-12345678', - '0101-1234567': '0101-1234567', - '010-12345678-020':'010-12345678-020' - } - invalid = { - '01x-12345678': error_format, - '12345678': error_format, - '01123-12345678': error_format, - '010-123456789': error_format, - '010-12345678-': error_format - } - self.assertFieldOutput(CNPhoneNumberField, valid, invalid) - - def test_CNCellNumberField(self): - error_format = ['Enter a valid cell number.'] - valid = { - '13012345678': '13012345678', - } - invalid = { - '130123456789': error_format, - '14012345678': error_format - } - self.assertFieldOutput(CNCellNumberField, valid, invalid) diff --git a/tests/regressiontests/localflavor/co/__init__.py b/tests/regressiontests/localflavor/co/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/co/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/co/tests.py b/tests/regressiontests/localflavor/co/tests.py deleted file mode 100644 index 68b20c4308..0000000000 --- a/tests/regressiontests/localflavor/co/tests.py +++ /dev/null @@ -1,45 +0,0 @@ -from __future__ import unicode_literals - -from django.contrib.localflavor.co.forms import CODepartmentSelect - -from django.test import SimpleTestCase - -class COLocalFlavorTests(SimpleTestCase): - def test_CODepartmentSelect(self): - d = CODepartmentSelect() - out = """<select name="department"> -<option value="AMA">Amazonas</option> -<option value="ANT">Antioquia</option> -<option value="ARA">Arauca</option> -<option value="ATL">Atl\xe1ntico</option> -<option value="DC">Bogot\xe1</option> -<option value="BOL">Bol\xedvar</option> -<option value="BOY">Boyac\xe1</option> -<option value="CAL">Caldas</option> -<option value="CAQ">Caquet\xe1</option> -<option value="CAS">Casanare</option> -<option value="CAU">Cauca</option> -<option value="CES">Cesar</option> -<option value="CHO">Choc\xf3</option> -<option value="COR" selected="selected">C\xf3rdoba</option> -<option value="CUN">Cundinamarca</option> -<option value="GUA">Guain\xeda</option> -<option value="GUV">Guaviare</option> -<option value="HUI">Huila</option> -<option value="LAG">La Guajira</option> -<option value="MAG">Magdalena</option> -<option value="MET">Meta</option> -<option value="NAR">Nari\xf1o</option> -<option value="NSA">Norte de Santander</option> -<option value="PUT">Putumayo</option> -<option value="QUI">Quind\xedo</option> -<option value="RIS">Risaralda</option> -<option value="SAP">San Andr\xe9s and Providencia</option> -<option value="SAN">Santander</option> -<option value="SUC">Sucre</option> -<option value="TOL">Tolima</option> -<option value="VAC">Valle del Cauca</option> -<option value="VAU">Vaup\xe9s</option> -<option value="VID">Vichada</option> -</select>""" - self.assertHTMLEqual(d.render('department', 'COR'), out) diff --git a/tests/regressiontests/localflavor/cz/__init__.py b/tests/regressiontests/localflavor/cz/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/cz/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/cz/tests.py b/tests/regressiontests/localflavor/cz/tests.py deleted file mode 100644 index e4cc05e0c6..0000000000 --- a/tests/regressiontests/localflavor/cz/tests.py +++ /dev/null @@ -1,80 +0,0 @@ -from __future__ import unicode_literals - -from django.contrib.localflavor.cz.forms import (CZPostalCodeField, - CZRegionSelect, CZBirthNumberField, CZICNumberField) - -from django.core.exceptions import ValidationError -from django.test import SimpleTestCase - - -class CZLocalFlavorTests(SimpleTestCase): - def test_CZRegionSelect(self): - f = CZRegionSelect() - out = '''<select name="regions"> -<option value="PR">Prague</option> -<option value="CE">Central Bohemian Region</option> -<option value="SO">South Bohemian Region</option> -<option value="PI">Pilsen Region</option> -<option value="CA">Carlsbad Region</option> -<option value="US">Usti Region</option> -<option value="LB">Liberec Region</option> -<option value="HK">Hradec Region</option> -<option value="PA">Pardubice Region</option> -<option value="VY">Vysocina Region</option> -<option value="SM">South Moravian Region</option> -<option value="OL">Olomouc Region</option> -<option value="ZL">Zlin Region</option> -<option value="MS">Moravian-Silesian Region</option> -</select>''' - self.assertHTMLEqual(f.render('regions', 'TT'), out) - - def test_CZPostalCodeField(self): - error_format = ['Enter a postal code in the format XXXXX or XXX XX.'] - valid = { - '91909': '91909', - '917 01': '91701', - '12345': '12345', - } - invalid = { - '84545x': error_format, - '123456': error_format, - '1234': error_format, - '123 4': error_format, - } - self.assertFieldOutput(CZPostalCodeField, valid, invalid) - - def test_CZBirthNumberField(self): - error_format = ['Enter a birth number in the format XXXXXX/XXXX or XXXXXXXXXX.'] - error_invalid = ['Enter a valid birth number.'] - valid = { - '880523/1237': '880523/1237', - '8805231237': '8805231237', - '880523/000': '880523/000', - '880523000': '880523000', - '882101/0011': '882101/0011', - } - invalid = { - '123456/12': error_format, - '123456/12345': error_format, - '12345612': error_format, - '12345612345': error_format, - '880523/1239': error_invalid, - '8805231239': error_invalid, - '990101/0011': error_invalid, - } - self.assertFieldOutput(CZBirthNumberField, valid, invalid) - - def test_CZICNumberField(self): - error_invalid = ['Enter a valid IC number.'] - valid ={ - '12345679': '12345679', - '12345601': '12345601', - '12345661': '12345661', - '12345610': '12345610', - } - invalid = { - '1234567': error_invalid, - '12345660': error_invalid, - '12345600': error_invalid, - } - self.assertFieldOutput(CZICNumberField, valid, invalid) diff --git a/tests/regressiontests/localflavor/de/__init__.py b/tests/regressiontests/localflavor/de/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/de/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/de/tests.py b/tests/regressiontests/localflavor/de/tests.py deleted file mode 100644 index bdf0bcf44f..0000000000 --- a/tests/regressiontests/localflavor/de/tests.py +++ /dev/null @@ -1,51 +0,0 @@ -from __future__ import unicode_literals - -from django.contrib.localflavor.de.forms import (DEZipCodeField, DEStateSelect, - DEIdentityCardNumberField) - -from django.test import SimpleTestCase - - -class DELocalFlavorTests(SimpleTestCase): - def test_DEStateSelect(self): - f = DEStateSelect() - out = '''<select name="states"> -<option value="BW">Baden-Wuerttemberg</option> -<option value="BY">Bavaria</option> -<option value="BE">Berlin</option> -<option value="BB">Brandenburg</option> -<option value="HB">Bremen</option> -<option value="HH">Hamburg</option> -<option value="HE">Hessen</option> -<option value="MV">Mecklenburg-Western Pomerania</option> -<option value="NI">Lower Saxony</option> -<option value="NW">North Rhine-Westphalia</option> -<option value="RP">Rhineland-Palatinate</option> -<option value="SL">Saarland</option> -<option value="SN">Saxony</option> -<option value="ST">Saxony-Anhalt</option> -<option value="SH">Schleswig-Holstein</option> -<option value="TH" selected="selected">Thuringia</option> -</select>''' - self.assertHTMLEqual(f.render('states', 'TH'), out) - - def test_DEZipCodeField(self): - error_format = ['Enter a zip code in the format XXXXX.'] - valid = { - '99423': '99423', - } - invalid = { - ' 99423': error_format, - } - self.assertFieldOutput(DEZipCodeField, valid, invalid) - - def test_DEIdentityCardNumberField(self): - error_format = ['Enter a valid German identity card number in XXXXXXXXXXX-XXXXXXX-XXXXXXX-X format.'] - valid = { - '7549313035D-6004103-0903042-0': '7549313035D-6004103-0903042-0', - '9786324830D 6104243 0910271 2': '9786324830D-6104243-0910271-2', - } - invalid = { - '0434657485D-6407276-0508137-9': error_format, - } - self.assertFieldOutput(DEIdentityCardNumberField, valid, invalid) diff --git a/tests/regressiontests/localflavor/ec/__init__.py b/tests/regressiontests/localflavor/ec/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/ec/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/ec/tests.py b/tests/regressiontests/localflavor/ec/tests.py deleted file mode 100644 index c72d77e558..0000000000 --- a/tests/regressiontests/localflavor/ec/tests.py +++ /dev/null @@ -1,36 +0,0 @@ -from __future__ import unicode_literals - -from django.contrib.localflavor.ec.forms import ECProvinceSelect - -from django.test import SimpleTestCase - -class ECLocalFlavorTests(SimpleTestCase): - def test_ECProvinceSelect(self): - p = ECProvinceSelect() - out = """<select name="province"> -<option value="A">Azuay</option> -<option value="B">Bol\xedvar</option> -<option value="F">Ca\xf1ar</option> -<option value="C">Carchi</option> -<option value="H">Chimborazo</option> -<option value="X">Cotopaxi</option> -<option value="O">El Oro</option> -<option value="E">Esmeraldas</option> -<option value="W">Gal\xe1pagos</option> -<option value="G">Guayas</option> -<option value="I">Imbabura</option> -<option value="L">Loja</option> -<option value="R">Los R\xedos</option> -<option value="M">Manab\xed</option> -<option value="S">Morona Santiago</option> -<option value="N">Napo</option> -<option value="D">Orellana</option> -<option value="Y">Pastaza</option> -<option value="P">Pichincha</option> -<option value="SE">Santa Elena</option> -<option value="SD">Santo Domingo de los Ts\xe1chilas</option> -<option value="U" selected="selected">Sucumb\xedos</option> -<option value="T">Tungurahua</option> -<option value="Z">Zamora Chinchipe</option> -</select>""" - self.assertHTMLEqual(p.render('province', 'U'), out) diff --git a/tests/regressiontests/localflavor/es/__init__.py b/tests/regressiontests/localflavor/es/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/es/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/es/tests.py b/tests/regressiontests/localflavor/es/tests.py deleted file mode 100644 index 3fc072cffc..0000000000 --- a/tests/regressiontests/localflavor/es/tests.py +++ /dev/null @@ -1,173 +0,0 @@ -from __future__ import unicode_literals - -from django.contrib.localflavor.es.forms import (ESPostalCodeField, ESPhoneNumberField, - ESIdentityCardNumberField, ESCCCField, ESRegionSelect, ESProvinceSelect) - -from django.test import SimpleTestCase - - -class ESLocalFlavorTests(SimpleTestCase): - def test_ESRegionSelect(self): - f = ESRegionSelect() - out = '''<select name="regions"> -<option value="AN">Andalusia</option> -<option value="AR">Aragon</option> -<option value="O">Principality of Asturias</option> -<option value="IB">Balearic Islands</option> -<option value="PV">Basque Country</option> -<option value="CN">Canary Islands</option> -<option value="S">Cantabria</option> -<option value="CM">Castile-La Mancha</option> -<option value="CL">Castile and Leon</option> -<option value="CT" selected="selected">Catalonia</option> -<option value="EX">Extremadura</option> -<option value="GA">Galicia</option> -<option value="LO">La Rioja</option> -<option value="M">Madrid</option> -<option value="MU">Region of Murcia</option> -<option value="NA">Foral Community of Navarre</option> -<option value="VC">Valencian Community</option> -</select>''' - self.assertHTMLEqual(f.render('regions', 'CT'), out) - - def test_ESProvinceSelect(self): - f = ESProvinceSelect() - out = '''<select name="provinces"> -<option value="01">Araba</option> -<option value="02">Albacete</option> -<option value="03">Alacant</option> -<option value="04">Almeria</option> -<option value="05">Avila</option> -<option value="06">Badajoz</option> -<option value="07">Illes Balears</option> -<option value="08" selected="selected">Barcelona</option> -<option value="09">Burgos</option> -<option value="10">Caceres</option> -<option value="11">Cadiz</option> -<option value="12">Castello</option> -<option value="13">Ciudad Real</option> -<option value="14">Cordoba</option> -<option value="15">A Coruna</option> -<option value="16">Cuenca</option> -<option value="17">Girona</option> -<option value="18">Granada</option> -<option value="19">Guadalajara</option> -<option value="20">Guipuzkoa</option> -<option value="21">Huelva</option> -<option value="22">Huesca</option> -<option value="23">Jaen</option> -<option value="24">Leon</option> -<option value="25">Lleida</option> -<option value="26">La Rioja</option> -<option value="27">Lugo</option> -<option value="28">Madrid</option> -<option value="29">Malaga</option> -<option value="30">Murcia</option> -<option value="31">Navarre</option> -<option value="32">Ourense</option> -<option value="33">Asturias</option> -<option value="34">Palencia</option> -<option value="35">Las Palmas</option> -<option value="36">Pontevedra</option> -<option value="37">Salamanca</option> -<option value="38">Santa Cruz de Tenerife</option> -<option value="39">Cantabria</option> -<option value="40">Segovia</option> -<option value="41">Seville</option> -<option value="42">Soria</option> -<option value="43">Tarragona</option> -<option value="44">Teruel</option> -<option value="45">Toledo</option> -<option value="46">Valencia</option> -<option value="47">Valladolid</option> -<option value="48">Bizkaia</option> -<option value="49">Zamora</option> -<option value="50">Zaragoza</option> -<option value="51">Ceuta</option> -<option value="52">Melilla</option> -</select>''' - self.assertHTMLEqual(f.render('provinces', '08'), out) - - def test_ESPostalCodeField(self): - error_invalid = ['Enter a valid postal code in the range and format 01XXX - 52XXX.'] - valid = { - '08028': '08028', - '28080': '28080', - } - invalid = { - '53001': error_invalid, - '0801': error_invalid, - '080001': error_invalid, - '00999': error_invalid, - '08 01': error_invalid, - '08A01': error_invalid, - } - self.assertFieldOutput(ESPostalCodeField, valid, invalid) - - def test_ESPhoneNumberField(self): - error_invalid = ['Enter a valid phone number in one of the formats 6XXXXXXXX, 8XXXXXXXX or 9XXXXXXXX.'] - valid = { - '650010101': '650010101', - '931234567': '931234567', - '800123123': '800123123', - '789789789': '789789789', - } - invalid = { - '555555555': error_invalid, - '489489489': error_invalid, - '99123123': error_invalid, - '9999123123': error_invalid, - } - self.assertFieldOutput(ESPhoneNumberField, valid, invalid) - - def test_ESIdentityCardNumberField(self): - error_invalid = ['Please enter a valid NIF, NIE, or CIF.'] - error_checksum_nif = ['Invalid checksum for NIF.'] - error_checksum_nie = ['Invalid checksum for NIE.'] - error_checksum_cif = ['Invalid checksum for CIF.'] - valid = { - '78699688J': '78699688J', - '78699688-J': '78699688J', - '78699688 J': '78699688J', - '78699688 j': '78699688J', - 'X0901797J': 'X0901797J', - 'X-6124387-Q': 'X6124387Q', - 'X 0012953 G': 'X0012953G', - 'x-3287690-r': 'X3287690R', - 't-03287690r': 'T03287690R', - 'P2907500I': 'P2907500I', - 'B38790911': 'B38790911', - 'B31234560': 'B31234560', - 'B-3879091A': 'B3879091A', - 'B 38790911': 'B38790911', - 'P-3900800-H': 'P3900800H', - 'P 39008008': 'P39008008', - 'C-28795565': 'C28795565', - 'C 2879556E': 'C2879556E', - } - invalid = { - '78699688T': error_checksum_nif, - 'X-03287690': error_invalid, - 'X-03287690-T': error_checksum_nie, - 'B 38790917': error_checksum_cif, - 'C28795567': error_checksum_cif, - 'I38790911': error_invalid, - '78699688-2': error_invalid, - } - self.assertFieldOutput(ESIdentityCardNumberField, valid, invalid) - - def test_ESCCCField(self): - error_invalid = ['Please enter a valid bank account number in format XXXX-XXXX-XX-XXXXXXXXXX.'] - error_checksum = ['Invalid checksum for bank account number.'] - valid = { - '20770338793100254321': '20770338793100254321', - '2077 0338 79 3100254321': '2077 0338 79 3100254321', - '2077-0338-79-3100254321': '2077-0338-79-3100254321', - } - invalid = { - '2077.0338.79.3100254321': error_invalid, - '2077-0338-78-3100254321': error_checksum, - '2077-0338-89-3100254321': error_checksum, - '2077-03-3879-3100254321': error_invalid, - } - self.assertFieldOutput(ESCCCField, valid, invalid) diff --git a/tests/regressiontests/localflavor/fi/__init__.py b/tests/regressiontests/localflavor/fi/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/fi/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/fi/tests.py b/tests/regressiontests/localflavor/fi/tests.py deleted file mode 100644 index bfd2e2a010..0000000000 --- a/tests/regressiontests/localflavor/fi/tests.py +++ /dev/null @@ -1,383 +0,0 @@ -from __future__ import unicode_literals - -from django.contrib.localflavor.fi.forms import (FIZipCodeField, - FISocialSecurityNumber, FIMunicipalitySelect) - -from django.test import SimpleTestCase - - -class FILocalFlavorTests(SimpleTestCase): - def test_FIMunicipalitySelect(self): - f = FIMunicipalitySelect() - out = '''<select name="municipalities"> -<option value="akaa">Akaa</option> -<option value="alajarvi">Alaj\xe4rvi</option> -<option value="alavieska">Alavieska</option> -<option value="alavus">Alavus</option> -<option value="artjarvi">Artj\xe4rvi</option> -<option value="asikkala">Asikkala</option> -<option value="askola">Askola</option> -<option value="aura">Aura</option> -<option value="brando">Br\xe4nd\xf6</option> -<option value="eckero">Ecker\xf6</option> -<option value="enonkoski">Enonkoski</option> -<option value="enontekio">Enonteki\xf6</option> -<option value="espoo">Espoo</option> -<option value="eura">Eura</option> -<option value="eurajoki">Eurajoki</option> -<option value="evijarvi">Evij\xe4rvi</option> -<option value="finstrom">Finstr\xf6m</option> -<option value="forssa">Forssa</option> -<option value="foglo">F\xf6gl\xf6</option> -<option value="geta">Geta</option> -<option value="haapajarvi">Haapaj\xe4rvi</option> -<option value="haapavesi">Haapavesi</option> -<option value="hailuoto">Hailuoto</option> -<option value="halsua">Halsua</option> -<option value="hamina">Hamina</option> -<option value="hammarland">Hammarland</option> -<option value="hankasalmi">Hankasalmi</option> -<option value="hanko">Hanko</option> -<option value="harjavalta">Harjavalta</option> -<option value="hartola">Hartola</option> -<option value="hattula">Hattula</option> -<option value="haukipudas">Haukipudas</option> -<option value="hausjarvi">Hausj\xe4rvi</option> -<option value="heinola">Heinola</option> -<option value="heinavesi">Hein\xe4vesi</option> -<option value="helsinki">Helsinki</option> -<option value="hirvensalmi">Hirvensalmi</option> -<option value="hollola">Hollola</option> -<option value="honkajoki">Honkajoki</option> -<option value="huittinen">Huittinen</option> -<option value="humppila">Humppila</option> -<option value="hyrynsalmi">Hyrynsalmi</option> -<option value="hyvinkaa">Hyvink\xe4\xe4</option> -<option value="hameenkoski">H\xe4meenkoski</option> -<option value="hameenkyro">H\xe4meenkyr\xf6</option> -<option value="hameenlinna">H\xe4meenlinna</option> -<option value="ii">Ii</option> -<option value="iisalmi">Iisalmi</option> -<option value="iitti">Iitti</option> -<option value="ikaalinen">Ikaalinen</option> -<option value="ilmajoki">Ilmajoki</option> -<option value="ilomantsi">Ilomantsi</option> -<option value="imatra">Imatra</option> -<option value="inari">Inari</option> -<option value="inkoo">Inkoo</option> -<option value="isojoki">Isojoki</option> -<option value="isokyro">Isokyr\xf6</option> -<option value="jalasjarvi">Jalasj\xe4rvi</option> -<option value="janakkala">Janakkala</option> -<option value="joensuu">Joensuu</option> -<option value="jokioinen">Jokioinen</option> -<option value="jomala">Jomala</option> -<option value="joroinen">Joroinen</option> -<option value="joutsa">Joutsa</option> -<option value="juankoski">Juankoski</option> -<option value="juuka">Juuka</option> -<option value="juupajoki">Juupajoki</option> -<option value="juva">Juva</option> -<option value="jyvaskyla">Jyv\xe4skyl\xe4</option> -<option value="jamijarvi">J\xe4mij\xe4rvi</option> -<option value="jamsa">J\xe4ms\xe4</option> -<option value="jarvenpaa">J\xe4rvenp\xe4\xe4</option> -<option value="kaarina">Kaarina</option> -<option value="kaavi">Kaavi</option> -<option value="kajaani">Kajaani</option> -<option value="kalajoki">Kalajoki</option> -<option value="kangasala">Kangasala</option> -<option value="kangasniemi">Kangasniemi</option> -<option value="kankaanpaa">Kankaanp\xe4\xe4</option> -<option value="kannonkoski">Kannonkoski</option> -<option value="kannus">Kannus</option> -<option value="karijoki">Karijoki</option> -<option value="karjalohja">Karjalohja</option> -<option value="karkkila">Karkkila</option> -<option value="karstula">Karstula</option> -<option value="karttula">Karttula</option> -<option value="karvia">Karvia</option> -<option value="kaskinen">Kaskinen</option> -<option value="kauhajoki">Kauhajoki</option> -<option value="kauhava">Kauhava</option> -<option value="kauniainen">Kauniainen</option> -<option value="kaustinen">Kaustinen</option> -<option value="keitele">Keitele</option> -<option value="kemi">Kemi</option> -<option value="kemijarvi">Kemij\xe4rvi</option> -<option value="keminmaa">Keminmaa</option> -<option value="kemionsaari">Kemi\xf6nsaari</option> -<option value="kempele">Kempele</option> -<option value="kerava">Kerava</option> -<option value="kerimaki">Kerim\xe4ki</option> -<option value="kesalahti">Kes\xe4lahti</option> -<option value="keuruu">Keuruu</option> -<option value="kihnio">Kihni\xf6</option> -<option value="kiikoinen">Kiikoinen</option> -<option value="kiiminki">Kiiminki</option> -<option value="kinnula">Kinnula</option> -<option value="kirkkonummi">Kirkkonummi</option> -<option value="kitee">Kitee</option> -<option value="kittila">Kittil\xe4</option> -<option value="kiuruvesi">Kiuruvesi</option> -<option value="kivijarvi">Kivij\xe4rvi</option> -<option value="kokemaki">Kokem\xe4ki</option> -<option value="kokkola">Kokkola</option> -<option value="kolari">Kolari</option> -<option value="konnevesi">Konnevesi</option> -<option value="kontiolahti">Kontiolahti</option> -<option value="korsnas">Korsn\xe4s</option> -<option value="koskitl">Koski Tl</option> -<option value="kotka">Kotka</option> -<option value="kouvola">Kouvola</option> -<option value="kristiinankaupunki">Kristiinankaupunki</option> -<option value="kruunupyy">Kruunupyy</option> -<option value="kuhmalahti">Kuhmalahti</option> -<option value="kuhmo">Kuhmo</option> -<option value="kuhmoinen">Kuhmoinen</option> -<option value="kumlinge">Kumlinge</option> -<option value="kuopio">Kuopio</option> -<option value="kuortane">Kuortane</option> -<option value="kurikka">Kurikka</option> -<option value="kustavi">Kustavi</option> -<option value="kuusamo">Kuusamo</option> -<option value="kylmakoski">Kylm\xe4koski</option> -<option value="kyyjarvi">Kyyj\xe4rvi</option> -<option value="karkola">K\xe4rk\xf6l\xe4</option> -<option value="karsamaki">K\xe4rs\xe4m\xe4ki</option> -<option value="kokar">K\xf6kar</option> -<option value="koylio">K\xf6yli\xf6</option> -<option value="lahti">Lahti</option> -<option value="laihia">Laihia</option> -<option value="laitila">Laitila</option> -<option value="lapinjarvi">Lapinj\xe4rvi</option> -<option value="lapinlahti">Lapinlahti</option> -<option value="lappajarvi">Lappaj\xe4rvi</option> -<option value="lappeenranta">Lappeenranta</option> -<option value="lapua">Lapua</option> -<option value="laukaa">Laukaa</option> -<option value="lavia">Lavia</option> -<option value="lemi">Lemi</option> -<option value="lemland">Lemland</option> -<option value="lempaala">Lemp\xe4\xe4l\xe4</option> -<option value="leppavirta">Lepp\xe4virta</option> -<option value="lestijarvi">Lestij\xe4rvi</option> -<option value="lieksa">Lieksa</option> -<option value="lieto">Lieto</option> -<option value="liminka">Liminka</option> -<option value="liperi">Liperi</option> -<option value="lohja">Lohja</option> -<option value="loimaa">Loimaa</option> -<option value="loppi">Loppi</option> -<option value="loviisa">Loviisa</option> -<option value="luhanka">Luhanka</option> -<option value="lumijoki">Lumijoki</option> -<option value="lumparland">Lumparland</option> -<option value="luoto">Luoto</option> -<option value="luumaki">Luum\xe4ki</option> -<option value="luvia">Luvia</option> -<option value="lansi-turunmaa">L\xe4nsi-Turunmaa</option> -<option value="maalahti">Maalahti</option> -<option value="maaninka">Maaninka</option> -<option value="maarianhamina">Maarianhamina</option> -<option value="marttila">Marttila</option> -<option value="masku">Masku</option> -<option value="merijarvi">Merij\xe4rvi</option> -<option value="merikarvia">Merikarvia</option> -<option value="miehikkala">Miehikk\xe4l\xe4</option> -<option value="mikkeli">Mikkeli</option> -<option value="muhos">Muhos</option> -<option value="multia">Multia</option> -<option value="muonio">Muonio</option> -<option value="mustasaari">Mustasaari</option> -<option value="muurame">Muurame</option> -<option value="mynamaki">Myn\xe4m\xe4ki</option> -<option value="myrskyla">Myrskyl\xe4</option> -<option value="mantsala">M\xe4nts\xe4l\xe4</option> -<option value="mantta-vilppula">M\xe4ntt\xe4-Vilppula</option> -<option value="mantyharju">M\xe4ntyharju</option> -<option value="naantali">Naantali</option> -<option value="nakkila">Nakkila</option> -<option value="nastola">Nastola</option> -<option value="nilsia">Nilsi\xe4</option> -<option value="nivala">Nivala</option> -<option value="nokia">Nokia</option> -<option value="nousiainen">Nousiainen</option> -<option value="nummi-pusula">Nummi-Pusula</option> -<option value="nurmes">Nurmes</option> -<option value="nurmijarvi">Nurmij\xe4rvi</option> -<option value="narpio">N\xe4rpi\xf6</option> -<option value="oravainen">Oravainen</option> -<option value="orimattila">Orimattila</option> -<option value="oripaa">Orip\xe4\xe4</option> -<option value="orivesi">Orivesi</option> -<option value="oulainen">Oulainen</option> -<option value="oulu">Oulu</option> -<option value="oulunsalo">Oulunsalo</option> -<option value="outokumpu">Outokumpu</option> -<option value="padasjoki">Padasjoki</option> -<option value="paimio">Paimio</option> -<option value="paltamo">Paltamo</option> -<option value="parikkala">Parikkala</option> -<option value="parkano">Parkano</option> -<option value="pedersore">Peders\xf6re</option> -<option value="pelkosenniemi">Pelkosenniemi</option> -<option value="pello">Pello</option> -<option value="perho">Perho</option> -<option value="pertunmaa">Pertunmaa</option> -<option value="petajavesi">Pet\xe4j\xe4vesi</option> -<option value="pieksamaki">Pieks\xe4m\xe4ki</option> -<option value="pielavesi">Pielavesi</option> -<option value="pietarsaari">Pietarsaari</option> -<option value="pihtipudas">Pihtipudas</option> -<option value="pirkkala">Pirkkala</option> -<option value="polvijarvi">Polvij\xe4rvi</option> -<option value="pomarkku">Pomarkku</option> -<option value="pori">Pori</option> -<option value="pornainen">Pornainen</option> -<option value="porvoo">Porvoo</option> -<option value="posio">Posio</option> -<option value="pudasjarvi">Pudasj\xe4rvi</option> -<option value="pukkila">Pukkila</option> -<option value="punkaharju">Punkaharju</option> -<option value="punkalaidun">Punkalaidun</option> -<option value="puolanka">Puolanka</option> -<option value="puumala">Puumala</option> -<option value="pyhtaa">Pyht\xe4\xe4</option> -<option value="pyhajoki">Pyh\xe4joki</option> -<option value="pyhajarvi">Pyh\xe4j\xe4rvi</option> -<option value="pyhanta">Pyh\xe4nt\xe4</option> -<option value="pyharanta">Pyh\xe4ranta</option> -<option value="palkane">P\xe4lk\xe4ne</option> -<option value="poytya">P\xf6yty\xe4</option> -<option value="raahe">Raahe</option> -<option value="raasepori">Raasepori</option> -<option value="raisio">Raisio</option> -<option value="rantasalmi">Rantasalmi</option> -<option value="ranua">Ranua</option> -<option value="rauma">Rauma</option> -<option value="rautalampi">Rautalampi</option> -<option value="rautavaara">Rautavaara</option> -<option value="rautjarvi">Rautj\xe4rvi</option> -<option value="reisjarvi">Reisj\xe4rvi</option> -<option value="riihimaki">Riihim\xe4ki</option> -<option value="ristiina">Ristiina</option> -<option value="ristijarvi">Ristij\xe4rvi</option> -<option value="rovaniemi">Rovaniemi</option> -<option value="ruokolahti">Ruokolahti</option> -<option value="ruovesi">Ruovesi</option> -<option value="rusko">Rusko</option> -<option value="raakkyla">R\xe4\xe4kkyl\xe4</option> -<option value="saarijarvi">Saarij\xe4rvi</option> -<option value="salla">Salla</option> -<option value="salo">Salo</option> -<option value="saltvik">Saltvik</option> -<option value="sastamala">Sastamala</option> -<option value="sauvo">Sauvo</option> -<option value="savitaipale">Savitaipale</option> -<option value="savonlinna">Savonlinna</option> -<option value="savukoski">Savukoski</option> -<option value="seinajoki">Sein\xe4joki</option> -<option value="sievi">Sievi</option> -<option value="siikainen">Siikainen</option> -<option value="siikajoki">Siikajoki</option> -<option value="siikalatva">Siikalatva</option> -<option value="siilinjarvi">Siilinj\xe4rvi</option> -<option value="simo">Simo</option> -<option value="sipoo">Sipoo</option> -<option value="siuntio">Siuntio</option> -<option value="sodankyla">Sodankyl\xe4</option> -<option value="soini">Soini</option> -<option value="somero">Somero</option> -<option value="sonkajarvi">Sonkaj\xe4rvi</option> -<option value="sotkamo">Sotkamo</option> -<option value="sottunga">Sottunga</option> -<option value="sulkava">Sulkava</option> -<option value="sund">Sund</option> -<option value="suomenniemi">Suomenniemi</option> -<option value="suomussalmi">Suomussalmi</option> -<option value="suonenjoki">Suonenjoki</option> -<option value="sysma">Sysm\xe4</option> -<option value="sakyla">S\xe4kyl\xe4</option> -<option value="taipalsaari">Taipalsaari</option> -<option value="taivalkoski">Taivalkoski</option> -<option value="taivassalo">Taivassalo</option> -<option value="tammela">Tammela</option> -<option value="tampere">Tampere</option> -<option value="tarvasjoki">Tarvasjoki</option> -<option value="tervo">Tervo</option> -<option value="tervola">Tervola</option> -<option value="teuva">Teuva</option> -<option value="tohmajarvi">Tohmaj\xe4rvi</option> -<option value="toholampi">Toholampi</option> -<option value="toivakka">Toivakka</option> -<option value="tornio">Tornio</option> -<option value="turku" selected="selected">Turku</option> -<option value="tuusniemi">Tuusniemi</option> -<option value="tuusula">Tuusula</option> -<option value="tyrnava">Tyrn\xe4v\xe4</option> -<option value="toysa">T\xf6ys\xe4</option> -<option value="ulvila">Ulvila</option> -<option value="urjala">Urjala</option> -<option value="utajarvi">Utaj\xe4rvi</option> -<option value="utsjoki">Utsjoki</option> -<option value="uurainen">Uurainen</option> -<option value="uusikaarlepyy">Uusikaarlepyy</option> -<option value="uusikaupunki">Uusikaupunki</option> -<option value="vaala">Vaala</option> -<option value="vaasa">Vaasa</option> -<option value="valkeakoski">Valkeakoski</option> -<option value="valtimo">Valtimo</option> -<option value="vantaa">Vantaa</option> -<option value="varkaus">Varkaus</option> -<option value="varpaisjarvi">Varpaisj\xe4rvi</option> -<option value="vehmaa">Vehmaa</option> -<option value="vesanto">Vesanto</option> -<option value="vesilahti">Vesilahti</option> -<option value="veteli">Veteli</option> -<option value="vierema">Vierem\xe4</option> -<option value="vihanti">Vihanti</option> -<option value="vihti">Vihti</option> -<option value="viitasaari">Viitasaari</option> -<option value="vimpeli">Vimpeli</option> -<option value="virolahti">Virolahti</option> -<option value="virrat">Virrat</option> -<option value="vardo">V\xe5rd\xf6</option> -<option value="vahakyro">V\xe4h\xe4kyr\xf6</option> -<option value="voyri-maksamaa">V\xf6yri-Maksamaa</option> -<option value="yli-ii">Yli-Ii</option> -<option value="ylitornio">Ylitornio</option> -<option value="ylivieska">Ylivieska</option> -<option value="ylojarvi">Yl\xf6j\xe4rvi</option> -<option value="ypaja">Yp\xe4j\xe4</option> -<option value="ahtari">\xc4ht\xe4ri</option> -<option value="aanekoski">\xc4\xe4nekoski</option> -</select>''' - self.assertHTMLEqual(f.render('municipalities', 'turku'), out) - - def test_FIZipCodeField(self): - error_format = ['Enter a zip code in the format XXXXX.'] - valid = { - '20540': '20540', - '20101': '20101', - } - invalid = { - '20s40': error_format, - '205401': error_format - } - self.assertFieldOutput(FIZipCodeField, valid, invalid) - - def test_FISocialSecurityNumber(self): - error_invalid = ['Enter a valid Finnish social security number.'] - valid = { - '010101-0101': '010101-0101', - '010101+0101': '010101+0101', - '010101A0101': '010101A0101', - } - invalid = { - '101010-0102': error_invalid, - '10a010-0101': error_invalid, - '101010-0\xe401': error_invalid, - '101010b0101': error_invalid, - } - self.assertFieldOutput(FISocialSecurityNumber, valid, invalid) diff --git a/tests/regressiontests/localflavor/fr/__init__.py b/tests/regressiontests/localflavor/fr/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/fr/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/fr/tests.py b/tests/regressiontests/localflavor/fr/tests.py deleted file mode 100644 index 8e99ef462b..0000000000 --- a/tests/regressiontests/localflavor/fr/tests.py +++ /dev/null @@ -1,152 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.contrib.localflavor.fr.forms import (FRZipCodeField, - FRPhoneNumberField, FRDepartmentSelect) - -from django.test import SimpleTestCase - - -class FRLocalFlavorTests(SimpleTestCase): - def test_FRZipCodeField(self): - error_format = ['Enter a zip code in the format XXXXX.'] - valid = { - '75001': '75001', - '93200': '93200', - } - invalid = { - '2A200': error_format, - '980001': ['Ensure this value has at most 5 characters (it has 6).' - ] + error_format, - } - self.assertFieldOutput(FRZipCodeField, valid, invalid) - - def test_FRPhoneNumberField(self): - error_format = ['Phone numbers must be in 0X XX XX XX XX format.'] - valid = { - '01 55 44 58 64': '01 55 44 58 64', - '0155445864': '01 55 44 58 64', - '01 5544 5864': '01 55 44 58 64', - '01 55.44.58.64': '01 55 44 58 64', - '01.55.44.58.64': '01 55 44 58 64', - } - invalid = { - '01,55,44,58,64': error_format, - '555 015 544': error_format, - } - self.assertFieldOutput(FRPhoneNumberField, valid, invalid) - - def test_FRDepartmentSelect(self): - f = FRDepartmentSelect() - out = '''<select name="dep"> -<option value="01">01 - Ain</option> -<option value="02">02 - Aisne</option> -<option value="03">03 - Allier</option> -<option value="04">04 - Alpes-de-Haute-Provence</option> -<option value="05">05 - Hautes-Alpes</option> -<option value="06">06 - Alpes-Maritimes</option> -<option value="07">07 - Ardèche</option> -<option value="08">08 - Ardennes</option> -<option value="09">09 - Ariège</option> -<option value="10">10 - Aube</option> -<option value="11">11 - Aude</option> -<option value="12">12 - Aveyron</option> -<option value="13">13 - Bouches-du-Rhône</option> -<option value="14">14 - Calvados</option> -<option value="15">15 - Cantal</option> -<option value="16">16 - Charente</option> -<option value="17">17 - Charente-Maritime</option> -<option value="18">18 - Cher</option> -<option value="19">19 - Corrèze</option> -<option value="2A">2A - Corse-du-Sud</option> -<option value="2B">2B - Haute-Corse</option> -<option value="21">21 - Côte-d'Or</option> -<option value="22">22 - Côtes-d'Armor</option> -<option value="23">23 - Creuse</option> -<option value="24">24 - Dordogne</option> -<option value="25">25 - Doubs</option> -<option value="26">26 - Drôme</option> -<option value="27">27 - Eure</option> -<option value="28">28 - Eure-et-Loir</option> -<option value="29">29 - Finistère</option> -<option value="30">30 - Gard</option> -<option value="31">31 - Haute-Garonne</option> -<option value="32">32 - Gers</option> -<option value="33">33 - Gironde</option> -<option value="34">34 - Hérault</option> -<option value="35">35 - Ille-et-Vilaine</option> -<option value="36">36 - Indre</option> -<option value="37">37 - Indre-et-Loire</option> -<option value="38">38 - Isère</option> -<option value="39">39 - Jura</option> -<option value="40">40 - Landes</option> -<option value="41">41 - Loir-et-Cher</option> -<option value="42">42 - Loire</option> -<option value="43">43 - Haute-Loire</option> -<option value="44">44 - Loire-Atlantique</option> -<option value="45">45 - Loiret</option> -<option value="46">46 - Lot</option> -<option value="47">47 - Lot-et-Garonne</option> -<option value="48">48 - Lozère</option> -<option value="49">49 - Maine-et-Loire</option> -<option value="50">50 - Manche</option> -<option value="51">51 - Marne</option> -<option value="52">52 - Haute-Marne</option> -<option value="53">53 - Mayenne</option> -<option value="54">54 - Meurthe-et-Moselle</option> -<option value="55">55 - Meuse</option> -<option value="56">56 - Morbihan</option> -<option value="57">57 - Moselle</option> -<option value="58">58 - Nièvre</option> -<option value="59">59 - Nord</option> -<option value="60">60 - Oise</option> -<option value="61">61 - Orne</option> -<option value="62">62 - Pas-de-Calais</option> -<option value="63">63 - Puy-de-Dôme</option> -<option value="64">64 - Pyrénées-Atlantiques</option> -<option value="65">65 - Hautes-Pyrénées</option> -<option value="66">66 - Pyrénées-Orientales</option> -<option value="67">67 - Bas-Rhin</option> -<option value="68">68 - Haut-Rhin</option> -<option value="69">69 - Rhône</option> -<option value="70">70 - Haute-Saône</option> -<option value="71">71 - Saône-et-Loire</option> -<option value="72">72 - Sarthe</option> -<option value="73">73 - Savoie</option> -<option value="74">74 - Haute-Savoie</option> -<option value="75" selected="selected">75 - Paris</option> -<option value="76">76 - Seine-Maritime</option> -<option value="77">77 - Seine-et-Marne</option> -<option value="78">78 - Yvelines</option> -<option value="79">79 - Deux-Sèvres</option> -<option value="80">80 - Somme</option> -<option value="81">81 - Tarn</option> -<option value="82">82 - Tarn-et-Garonne</option> -<option value="83">83 - Var</option> -<option value="84">84 - Vaucluse</option> -<option value="85">85 - Vendée</option> -<option value="86">86 - Vienne</option> -<option value="87">87 - Haute-Vienne</option> -<option value="88">88 - Vosges</option> -<option value="89">89 - Yonne</option> -<option value="90">90 - Territoire de Belfort</option> -<option value="91">91 - Essonne</option> -<option value="92">92 - Hauts-de-Seine</option> -<option value="93">93 - Seine-Saint-Denis</option> -<option value="94">94 - Val-de-Marne</option> -<option value="95">95 - Val-d'Oise</option> -<option value="971">971 - Guadeloupe</option> -<option value="972">972 - Martinique</option> -<option value="973">973 - Guyane</option> -<option value="974">974 - La Réunion</option> -<option value="975">975 - Saint-Pierre-et-Miquelon</option> -<option value="976">976 - Mayotte</option> -<option value="977">977 - Saint-Barthélemy</option> -<option value="978">978 - Saint-Martin</option> -<option value="984">984 - Terres australes et antarctiques françaises</option> -<option value="986">986 - Wallis et Futuna</option> -<option value="987">987 - Polynésie française</option> -<option value="988">988 - Nouvelle-Calédonie</option> -<option value="989">989 - Île de Clipperton</option> -</select>''' - self.assertHTMLEqual(f.render('dep', '75'), out) diff --git a/tests/regressiontests/localflavor/gb/__init__.py b/tests/regressiontests/localflavor/gb/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/gb/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/gb/tests.py b/tests/regressiontests/localflavor/gb/tests.py deleted file mode 100644 index 5a267105d5..0000000000 --- a/tests/regressiontests/localflavor/gb/tests.py +++ /dev/null @@ -1,32 +0,0 @@ -from __future__ import unicode_literals - -from django.contrib.localflavor.gb.forms import GBPostcodeField - -from django.test import SimpleTestCase - - -class GBLocalFlavorTests(SimpleTestCase): - def test_GBPostcodeField(self): - error_invalid = ['Enter a valid postcode.'] - valid = { - 'BT32 4PX': 'BT32 4PX', - 'GIR 0AA': 'GIR 0AA', - 'BT324PX': 'BT32 4PX', - ' so11aa ': 'SO1 1AA', - ' so1 1aa ': 'SO1 1AA', - 'G2 3wt': 'G2 3WT', - 'EC1A 1BB': 'EC1A 1BB', - 'Ec1a1BB': 'EC1A 1BB', - } - invalid = { - '1NV 4L1D': error_invalid, - '1NV4L1D': error_invalid, - ' b0gUS': error_invalid, - } - self.assertFieldOutput(GBPostcodeField, valid, invalid) - valid = {} - invalid = { - '1NV 4L1D': ['Enter a bloody postcode!'], - } - kwargs = {'error_messages': {'invalid': 'Enter a bloody postcode!'}} - self.assertFieldOutput(GBPostcodeField, valid, invalid, field_kwargs=kwargs) diff --git a/tests/regressiontests/localflavor/hk/__init__.py b/tests/regressiontests/localflavor/hk/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/hk/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/hk/forms.py b/tests/regressiontests/localflavor/hk/forms.py deleted file mode 100644 index a6233d4245..0000000000 --- a/tests/regressiontests/localflavor/hk/forms.py +++ /dev/null @@ -1,11 +0,0 @@ -from __future__ import absolute_import - -from django.forms import ModelForm - -from .models import HKPlace - - -class HKPlaceForm(ModelForm): - - class Meta: - model = HKPlace diff --git a/tests/regressiontests/localflavor/hk/tests.py b/tests/regressiontests/localflavor/hk/tests.py deleted file mode 100644 index ed5e623ee2..0000000000 --- a/tests/regressiontests/localflavor/hk/tests.py +++ /dev/null @@ -1,35 +0,0 @@ -from __future__ import absolute_import - -from django.contrib.localflavor.hk.forms import HKPhoneNumberField -from django.test import SimpleTestCase - - -class HKLocalFlavorTests(SimpleTestCase): - """Tests for Hong Kong Local Flavors""" - - def test_HKPhoneNumberField(self): - error_msgs = HKPhoneNumberField.default_error_messages - valid = { - '2111-1111': '2111-1111', - '3111 1111': '3111-1111', - '51111111': '5111-1111', - '852-6111-1111': '6111-1111', - '(+852) 8111-1111': '8111-1111', - '(+852) 9111-1111': '9111-1111', - '85291111111': '9111-1111', - } - invalid = { - '9991-1111': [error_msgs['disguise'], ], - '9921-1111': [error_msgs['disguise'], ], - '1121-1111': [error_msgs['disguise'], ], - '99987654': [error_msgs['disguise'], ], - '99287654': [error_msgs['disguise'], ], - '11287654': [error_msgs['disguise'], ], - '1': [error_msgs['invalid'], ], - '2111--1111': [error_msgs['invalid'], ], - '11111111': [error_msgs['prefix'], ], - '00000000': [error_msgs['prefix'], ], - '44444444': [error_msgs['prefix'], ], - '77777777': [error_msgs['prefix'], ], - } - self.assertFieldOutput(HKPhoneNumberField, valid, invalid) diff --git a/tests/regressiontests/localflavor/hr/__init__.py b/tests/regressiontests/localflavor/hr/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/hr/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/hr/tests.py b/tests/regressiontests/localflavor/hr/tests.py deleted file mode 100644 index c1b097c03f..0000000000 --- a/tests/regressiontests/localflavor/hr/tests.py +++ /dev/null @@ -1,192 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.contrib.localflavor.hr.forms import (HRCountySelect, - HRPhoneNumberPrefixSelect, HRLicensePlatePrefixSelect, HRPhoneNumberField, - HRLicensePlateField, HRPostalCodeField, HROIBField, HRJMBGField, - HRJMBAGField) - -from django.test import SimpleTestCase - -class HRLocalFlavorTests(SimpleTestCase): - def test_HRCountySelect(self): - f = HRCountySelect() - out = '''<select name="county"> -<option value="GZG" selected="selected">Grad Zagreb</option> -<option value="BBŽ">Bjelovarsko-bilogorska županija</option> -<option value="BPŽ">Brodsko-posavska županija</option> -<option value="DNŽ">Dubrovačko-neretvanska županija</option> -<option value="IŽ">Istarska županija</option> -<option value="KŽ">Karlovačka županija</option> -<option value="KKŽ">Koprivničko-križevačka županija</option> -<option value="KZŽ">Krapinsko-zagorska županija</option> -<option value="LSŽ">Ličko-senjska županija</option> -<option value="MŽ">Međimurska županija</option> -<option value="OBŽ">Osječko-baranjska županija</option> -<option value="PSŽ">Požeško-slavonska županija</option> -<option value="PGŽ">Primorsko-goranska županija</option> -<option value="SMŽ">Sisačko-moslavačka županija</option> -<option value="SDŽ">Splitsko-dalmatinska županija</option> -<option value="ŠKŽ">Šibensko-kninska županija</option> -<option value="VŽ">Varaždinska županija</option> -<option value="VPŽ">Virovitičko-podravska županija</option> -<option value="VSŽ">Vukovarsko-srijemska županija</option> -<option value="ZDŽ">Zadarska županija</option> -<option value="ZGŽ">Zagrebačka županija</option> -</select>''' - self.assertHTMLEqual(f.render('county', 'GZG'), out) - - def test_HRPhoneNumberPrefixSelect(self): - f = HRPhoneNumberPrefixSelect() - out = '''<select name="phone"> -<option value="1" selected="selected">01</option> -<option value="20">020</option> -<option value="21">021</option> -<option value="22">022</option> -<option value="23">023</option> -<option value="31">031</option> -<option value="32">032</option> -<option value="33">033</option> -<option value="34">034</option> -<option value="35">035</option> -<option value="40">040</option> -<option value="42">042</option> -<option value="43">043</option> -<option value="44">044</option> -<option value="47">047</option> -<option value="48">048</option> -<option value="49">049</option> -<option value="51">051</option> -<option value="52">052</option> -<option value="53">053</option> -<option value="91">091</option> -<option value="92">092</option> -<option value="95">095</option> -<option value="97">097</option> -<option value="98">098</option> -<option value="99">099</option> -</select>''' - self.assertHTMLEqual(f.render('phone', '1'), out) - - def test_HRLicensePlatePrefixSelect(self): - f = HRLicensePlatePrefixSelect() - out = '''<select name="license"> -<option value="BJ" selected="selected">BJ</option> -<option value="BM">BM</option> -<option value="ČK">ČK</option> -<option value="DA">DA</option> -<option value="DE">DE</option> -<option value="DJ">DJ</option> -<option value="DU">DU</option> -<option value="GS">GS</option> -<option value="IM">IM</option> -<option value="KA">KA</option> -<option value="KC">KC</option> -<option value="KR">KR</option> -<option value="KT">KT</option> -<option value="KŽ">KŽ</option> -<option value="MA">MA</option> -<option value="NA">NA</option> -<option value="NG">NG</option> -<option value="OG">OG</option> -<option value="OS">OS</option> -<option value="PU">PU</option> -<option value="PŽ">PŽ</option> -<option value="RI">RI</option> -<option value="SB">SB</option> -<option value="SK">SK</option> -<option value="SL">SL</option> -<option value="ST">ST</option> -<option value="ŠI">ŠI</option> -<option value="VK">VK</option> -<option value="VT">VT</option> -<option value="VU">VU</option> -<option value="VŽ">VŽ</option> -<option value="ZD">ZD</option> -<option value="ZG">ZG</option> -<option value="ŽU">ŽU</option> -</select>''' - self.assertHTMLEqual(f.render('license', 'BJ'), out) - - def test_HRPhoneNumberField(self): - error_invalid = ['Enter a valid phone number'] - error_area = ['Enter a valid area or mobile network code'] - error_number = ['The phone nubmer is too long'] - valid = { - '+38511234567': '+38511234567', - '0038511234567': '+38511234567', - '011234567': '+38511234567', - '+38521123456': '+38521123456', - '0038521123456': '+38521123456', - '021123456': '+38521123456', - } - invalid = { - '123456789': error_invalid, - '0811234567': error_area, - '0111234567': error_number, - } - self.assertFieldOutput(HRPhoneNumberField, valid, invalid) - - def test_HRLicensePlateField(self): - error_invalid = ['Enter a valid vehicle license plate number'] - error_area = ['Enter a valid location code'] - error_number = ['Number part cannot be zero'] - valid = { - 'ZG 1234-AA': 'ZG 1234-AA', - 'ZG 123-A': 'ZG 123-A', - } - invalid = { - 'PV12345': error_invalid, - 'PV1234AA': error_area, - 'ZG0000CC': error_number, - } - self.assertFieldOutput(HRLicensePlateField, valid, invalid) - - def test_HRPostalCodeField(self): - error_invalid = ['Enter a valid 5 digit postal code'] - valid = { - '10000': '10000', - '35410': '35410', - } - invalid = { - 'ABCD': error_invalid, - '99999': error_invalid, - } - self.assertFieldOutput(HRPostalCodeField, valid, invalid) - - def test_HROIBField(self): - error_invalid = ['Enter a valid 11 digit OIB'] - valid = { - '12345678901': '12345678901', - } - invalid = { - '1234567890': ['Ensure this value has at least 11 characters (it has 10).'] + error_invalid, - 'ABCDEFGHIJK': error_invalid, - } - self.assertFieldOutput(HROIBField, valid, invalid) - - def test_HRJMBGField(self): - error_invalid = ['Enter a valid 13 digit JMBG'] - error_date = ['Error in date segment'] - valid = { - '1211984302155': '1211984302155', - '2701984307107': '2701984307107', - } - invalid = { - '1211984302156': error_invalid, - 'ABCDEFG': error_invalid, - '9999999123456': error_date, - } - self.assertFieldOutput(HRJMBGField, valid, invalid) - - def test_HRJMBAGField(self): - error_invalid = ['Enter a valid 19 digit JMBAG starting with 601983'] - error_copy = ['Card issue number cannot be zero'] - valid = { - '601983 11 0130185856 4': '6019831101301858564', - } - invalid = { - '601983 11 0130185856 5': error_invalid, - '601983 01 0130185856 4': error_copy, - } - self.assertFieldOutput(HRJMBAGField, valid, invalid) diff --git a/tests/regressiontests/localflavor/id/__init__.py b/tests/regressiontests/localflavor/id/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/id/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/id/tests.py b/tests/regressiontests/localflavor/id/tests.py deleted file mode 100644 index dd712d02a3..0000000000 --- a/tests/regressiontests/localflavor/id/tests.py +++ /dev/null @@ -1,195 +0,0 @@ -from __future__ import unicode_literals - -import warnings - -from django.contrib.localflavor.id.forms import (IDPhoneNumberField, - IDPostCodeField, IDNationalIdentityNumberField, IDLicensePlateField, - IDProvinceSelect, IDLicensePlatePrefixSelect) - -from django.test import SimpleTestCase - - -class IDLocalFlavorTests(SimpleTestCase): - def setUp(self): - self.save_warnings_state() - warnings.filterwarnings( - "ignore", - category=RuntimeWarning, - module='django.contrib.localflavor.id.id_choices' - ) - - def tearDown(self): - self.restore_warnings_state() - - def test_IDProvinceSelect(self): - f = IDProvinceSelect() - out = '''<select name="provinces"> -<option value="ACE">Aceh</option> -<option value="BLI">Bali</option> -<option value="BTN">Banten</option> -<option value="BKL">Bengkulu</option> -<option value="DIY">Yogyakarta</option> -<option value="JKT">Jakarta</option> -<option value="GOR">Gorontalo</option> -<option value="JMB">Jambi</option> -<option value="JBR">Jawa Barat</option> -<option value="JTG">Jawa Tengah</option> -<option value="JTM">Jawa Timur</option> -<option value="KBR">Kalimantan Barat</option> -<option value="KSL">Kalimantan Selatan</option> -<option value="KTG">Kalimantan Tengah</option> -<option value="KTM">Kalimantan Timur</option> -<option value="BBL">Kepulauan Bangka-Belitung</option> -<option value="KRI">Kepulauan Riau</option> -<option value="LPG" selected="selected">Lampung</option> -<option value="MLK">Maluku</option> -<option value="MUT">Maluku Utara</option> -<option value="NTB">Nusa Tenggara Barat</option> -<option value="NTT">Nusa Tenggara Timur</option> -<option value="PPA">Papua</option> -<option value="PPB">Papua Barat</option> -<option value="RIU">Riau</option> -<option value="SLB">Sulawesi Barat</option> -<option value="SLS">Sulawesi Selatan</option> -<option value="SLT">Sulawesi Tengah</option> -<option value="SLR">Sulawesi Tenggara</option> -<option value="SLU">Sulawesi Utara</option> -<option value="SMB">Sumatera Barat</option> -<option value="SMS">Sumatera Selatan</option> -<option value="SMU">Sumatera Utara</option> -</select>''' - self.assertHTMLEqual(f.render('provinces', 'LPG'), out) - - def test_IDLicensePlatePrefixSelect(self): - f = IDLicensePlatePrefixSelect() - out = '''<select name="codes"> -<option value="A">Banten</option> -<option value="AA">Magelang</option> -<option value="AB">Yogyakarta</option> -<option value="AD">Surakarta - Solo</option> -<option value="AE">Madiun</option> -<option value="AG">Kediri</option> -<option value="B">Jakarta</option> -<option value="BA">Sumatera Barat</option> -<option value="BB">Tapanuli</option> -<option value="BD">Bengkulu</option> -<option value="BE" selected="selected">Lampung</option> -<option value="BG">Sumatera Selatan</option> -<option value="BH">Jambi</option> -<option value="BK">Sumatera Utara</option> -<option value="BL">Nanggroe Aceh Darussalam</option> -<option value="BM">Riau</option> -<option value="BN">Kepulauan Bangka Belitung</option> -<option value="BP">Kepulauan Riau</option> -<option value="CC">Corps Consulate</option> -<option value="CD">Corps Diplomatic</option> -<option value="D">Bandung</option> -<option value="DA">Kalimantan Selatan</option> -<option value="DB">Sulawesi Utara Daratan</option> -<option value="DC">Sulawesi Barat</option> -<option value="DD">Sulawesi Selatan</option> -<option value="DE">Maluku</option> -<option value="DG">Maluku Utara</option> -<option value="DH">NTT - Timor</option> -<option value="DK">Bali</option> -<option value="DL">Sulawesi Utara Kepulauan</option> -<option value="DM">Gorontalo</option> -<option value="DN">Sulawesi Tengah</option> -<option value="DR">NTB - Lombok</option> -<option value="DS">Papua dan Papua Barat</option> -<option value="DT">Sulawesi Tenggara</option> -<option value="E">Cirebon</option> -<option value="EA">NTB - Sumbawa</option> -<option value="EB">NTT - Flores</option> -<option value="ED">NTT - Sumba</option> -<option value="F">Bogor</option> -<option value="G">Pekalongan</option> -<option value="H">Semarang</option> -<option value="K">Pati</option> -<option value="KB">Kalimantan Barat</option> -<option value="KH">Kalimantan Tengah</option> -<option value="KT">Kalimantan Timur</option> -<option value="L">Surabaya</option> -<option value="M">Madura</option> -<option value="N">Malang</option> -<option value="P">Jember</option> -<option value="R">Banyumas</option> -<option value="RI">Federal Government</option> -<option value="S">Bojonegoro</option> -<option value="T">Purwakarta</option> -<option value="W">Sidoarjo</option> -<option value="Z">Garut</option> -</select>''' - self.assertHTMLEqual(f.render('codes', 'BE'), out) - - def test_IDPhoneNumberField(self): - error_invalid = ['Enter a valid phone number'] - valid = { - '0812-3456789': '0812-3456789', - '081234567890': '081234567890', - '021 345 6789': '021 345 6789', - '0213456789': '0213456789', - '+62-21-3456789': '+62-21-3456789', - '(021) 345 6789': '(021) 345 6789', - } - invalid = { - '0123456789': error_invalid, - '+62-021-3456789': error_invalid, - '+62-0812-3456789': error_invalid, - '0812345678901': error_invalid, - 'foo': error_invalid, - } - self.assertFieldOutput(IDPhoneNumberField, valid, invalid) - - def test_IDPostCodeField(self): - error_invalid = ['Enter a valid post code'] - valid = { - '12340': '12340', - '25412': '25412', - ' 12340 ': '12340', - } - invalid = { - '12 3 4 0': error_invalid, - '12345': error_invalid, - '10100': error_invalid, - '123456': error_invalid, - 'foo': error_invalid, - } - self.assertFieldOutput(IDPostCodeField, valid, invalid) - - def test_IDNationalIdentityNumberField(self): - error_invalid = ['Enter a valid NIK/KTP number'] - valid = { - ' 12.3456.010178 3456 ': '12.3456.010178.3456', - '1234560101783456': '12.3456.010178.3456', - '12.3456.010101.3456': '12.3456.010101.3456', - } - invalid = { - '12.3456.310278.3456': error_invalid, - '00.0000.010101.0000': error_invalid, - '1234567890123456': error_invalid, - 'foo': error_invalid, - } - self.assertFieldOutput(IDNationalIdentityNumberField, valid, invalid) - - def test_IDLicensePlateField(self): - error_invalid = ['Enter a valid vehicle license plate number'] - valid = { - ' b 1234 ab ': 'B 1234 AB', - 'B 1234 ABC': 'B 1234 ABC', - 'A 12': 'A 12', - 'DK 12345 12': 'DK 12345 12', - 'RI 10': 'RI 10', - 'CD 12 12': 'CD 12 12', - } - invalid = { - 'CD 10 12': error_invalid, - 'CD 1234 12': error_invalid, - 'RI 10 AB': error_invalid, - 'B 12345 01': error_invalid, - 'N 1234 12': error_invalid, - 'A 12 XYZ': error_invalid, - 'Q 1234 AB': error_invalid, - 'foo': error_invalid, - } - self.assertFieldOutput(IDLicensePlateField, valid, invalid) diff --git a/tests/regressiontests/localflavor/ie/__init__.py b/tests/regressiontests/localflavor/ie/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/ie/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/ie/tests.py b/tests/regressiontests/localflavor/ie/tests.py deleted file mode 100644 index 717fa9d1c7..0000000000 --- a/tests/regressiontests/localflavor/ie/tests.py +++ /dev/null @@ -1,45 +0,0 @@ -from __future__ import unicode_literals - -from django.contrib.localflavor.ie.forms import IECountySelect - -from django.test import SimpleTestCase - - -class IELocalFlavorTests(SimpleTestCase): - def test_IECountySelect(self): - f = IECountySelect() - out = '''<select name="counties"> -<option value="antrim">Antrim</option> -<option value="armagh">Armagh</option> -<option value="carlow">Carlow</option> -<option value="cavan">Cavan</option> -<option value="clare">Clare</option> -<option value="cork">Cork</option> -<option value="derry">Derry</option> -<option value="donegal">Donegal</option> -<option value="down">Down</option> -<option value="dublin" selected="selected">Dublin</option> -<option value="fermanagh">Fermanagh</option> -<option value="galway">Galway</option> -<option value="kerry">Kerry</option> -<option value="kildare">Kildare</option> -<option value="kilkenny">Kilkenny</option> -<option value="laois">Laois</option> -<option value="leitrim">Leitrim</option> -<option value="limerick">Limerick</option> -<option value="longford">Longford</option> -<option value="louth">Louth</option> -<option value="mayo">Mayo</option> -<option value="meath">Meath</option> -<option value="monaghan">Monaghan</option> -<option value="offaly">Offaly</option> -<option value="roscommon">Roscommon</option> -<option value="sligo">Sligo</option> -<option value="tipperary">Tipperary</option> -<option value="tyrone">Tyrone</option> -<option value="waterford">Waterford</option> -<option value="westmeath">Westmeath</option> -<option value="wexford">Wexford</option> -<option value="wicklow">Wicklow</option> -</select>''' - self.assertHTMLEqual(f.render('counties', 'dublin'), out) diff --git a/tests/regressiontests/localflavor/il/__init__.py b/tests/regressiontests/localflavor/il/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/il/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/il/tests.py b/tests/regressiontests/localflavor/il/tests.py deleted file mode 100644 index 1b87cf2c19..0000000000 --- a/tests/regressiontests/localflavor/il/tests.py +++ /dev/null @@ -1,41 +0,0 @@ -from __future__ import unicode_literals - -from django.contrib.localflavor.il.forms import (ILPostalCodeField, - ILIDNumberField) - -from django.test import SimpleTestCase - - -class ILLocalFlavorTests(SimpleTestCase): - def test_ILPostalCodeField(self): - error_format = ['Enter a postal code in the format XXXXX'] - valid = { - '69973': '69973', - '699 73': '69973', - '12345': '12345', - } - invalid = { - '84545x': error_format, - '123456': error_format, - '1234': error_format, - '123 4': error_format, - } - self.assertFieldOutput(ILPostalCodeField, valid, invalid) - - def test_ILIDNumberField(self): - error_invalid = ['Enter a valid ID number.'] - valid = { - '3933742-3': '39337423', - '39337423': '39337423', - '039337423': '039337423', - '03933742-3': '039337423', - '0091': '0091', - } - invalid = { - '123456789': error_invalid, - '12345678-9': error_invalid, - '012346578': error_invalid, - '012346578-': error_invalid, - '0001': error_invalid, - } - self.assertFieldOutput(ILIDNumberField, valid, invalid) diff --git a/tests/regressiontests/localflavor/in_/__init__.py b/tests/regressiontests/localflavor/in_/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/in_/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/in_/tests.py b/tests/regressiontests/localflavor/in_/tests.py deleted file mode 100644 index 57d50f0ebf..0000000000 --- a/tests/regressiontests/localflavor/in_/tests.py +++ /dev/null @@ -1,178 +0,0 @@ -from __future__ import unicode_literals - -from django.contrib.localflavor.in_.forms import (INZipCodeField, - INStateField, INStateSelect, INPhoneNumberField) - -from django.test import SimpleTestCase - - - -class INLocalFlavorTests(SimpleTestCase): - def test_INPhoneNumberField(self): - error_format = ['Phone numbers must be in 02X-8X or 03X-7X or 04X-6X format.'] - valid = { - '0423-2443667': '0423-2443667', - '0423 2443667': '0423 2443667', - '04236-244366': '04236-244366', - '040-24436678': '040-24436678', - } - invalid = { - '04-2443667': error_format, - '423-2443667': error_format, - '0423-9442667': error_format, - '0423-0443667': error_format, - '0423-244366': error_format, - '04232442667': error_format, - '0423DJANGO': error_format, - } - self.assertFieldOutput(INPhoneNumberField, valid, invalid) - - def test_INPStateSelect(self): - f = INStateSelect() - out = '''<select name="state"> -<option value="KA">Karnataka</option> -<option value="AP" selected="selected">Andhra Pradesh</option> -<option value="KL">Kerala</option> -<option value="TN">Tamil Nadu</option> -<option value="MH">Maharashtra</option> -<option value="UP">Uttar Pradesh</option> -<option value="GA">Goa</option> -<option value="GJ">Gujarat</option> -<option value="RJ">Rajasthan</option> -<option value="HP">Himachal Pradesh</option> -<option value="JK">Jammu and Kashmir</option> -<option value="AR">Arunachal Pradesh</option> -<option value="AS">Assam</option> -<option value="BR">Bihar</option> -<option value="CG">Chattisgarh</option> -<option value="HR">Haryana</option> -<option value="JH">Jharkhand</option> -<option value="MP">Madhya Pradesh</option> -<option value="MN">Manipur</option> -<option value="ML">Meghalaya</option> -<option value="MZ">Mizoram</option> -<option value="NL">Nagaland</option> -<option value="OR">Orissa</option> -<option value="PB">Punjab</option> -<option value="SK">Sikkim</option> -<option value="TR">Tripura</option> -<option value="UA">Uttarakhand</option> -<option value="WB">West Bengal</option> -<option value="AN">Andaman and Nicobar</option> -<option value="CH">Chandigarh</option> -<option value="DN">Dadra and Nagar Haveli</option> -<option value="DD">Daman and Diu</option> -<option value="DL">Delhi</option> -<option value="LD">Lakshadweep</option> -<option value="PY">Pondicherry</option> -</select>''' - self.assertHTMLEqual(f.render('state', 'AP'), out) - - def test_INZipCodeField(self): - error_format = ['Enter a zip code in the format XXXXXX or XXX XXX.'] - valid = { - '360311': '360311', - '360 311': '360311', - } - invalid = { - '36 0311': error_format, - '3603111': error_format, - '360 31': error_format, - '36031': error_format, - 'O2B 2R3': error_format - } - self.assertFieldOutput(INZipCodeField, valid, invalid) - - def test_INStateField(self): - error_format = ['Enter an Indian state or territory.'] - valid = { - 'an': 'AN', - 'AN': 'AN', - 'andaman and nicobar': 'AN', - 'andra pradesh': 'AP', - 'andrapradesh': 'AP', - 'andhrapradesh': 'AP', - 'ap': 'AP', - 'andhra pradesh': 'AP', - 'ar': 'AR', - 'arunachal pradesh': 'AR', - 'assam': 'AS', - 'as': 'AS', - 'bihar': 'BR', - 'br': 'BR', - 'cg': 'CG', - 'chattisgarh': 'CG', - 'ch': 'CH', - 'chandigarh': 'CH', - 'daman and diu': 'DD', - 'dd': 'DD', - 'dl': 'DL', - 'delhi': 'DL', - 'dn': 'DN', - 'dadra and nagar haveli': 'DN', - 'ga': 'GA', - 'goa': 'GA', - 'gj': 'GJ', - 'gujarat': 'GJ', - 'himachal pradesh': 'HP', - 'hp': 'HP', - 'hr': 'HR', - 'haryana': 'HR', - 'jharkhand': 'JH', - 'jh': 'JH', - 'jammu and kashmir': 'JK', - 'jk': 'JK', - 'karnataka': 'KA', - 'karnatka': 'KA', - 'ka': 'KA', - 'kerala': 'KL', - 'kl': 'KL', - 'ld': 'LD', - 'lakshadweep': 'LD', - 'maharastra': 'MH', - 'mh': 'MH', - 'maharashtra': 'MH', - 'meghalaya': 'ML', - 'ml': 'ML', - 'mn': 'MN', - 'manipur': 'MN', - 'madhya pradesh': 'MP', - 'mp': 'MP', - 'mizoram': 'MZ', - 'mizo': 'MZ', - 'mz': 'MZ', - 'nl': 'NL', - 'nagaland': 'NL', - 'orissa': 'OR', - 'odisa': 'OR', - 'orisa': 'OR', - 'or': 'OR', - 'pb': 'PB', - 'punjab': 'PB', - 'py': 'PY', - 'pondicherry': 'PY', - 'rajasthan': 'RJ', - 'rajastan': 'RJ', - 'rj': 'RJ', - 'sikkim': 'SK', - 'sk': 'SK', - 'tamil nadu': 'TN', - 'tn': 'TN', - 'tamilnadu': 'TN', - 'tamilnad': 'TN', - 'tr': 'TR', - 'tripura': 'TR', - 'ua': 'UA', - 'uttarakhand': 'UA', - 'up': 'UP', - 'uttar pradesh': 'UP', - 'westbengal': 'WB', - 'bengal': 'WB', - 'wb': 'WB', - 'west bengal': 'WB' - } - invalid = { - 'florida': error_format, - 'FL': error_format, - } - self.assertFieldOutput(INStateField, valid, invalid) diff --git a/tests/regressiontests/localflavor/is_/__init__.py b/tests/regressiontests/localflavor/is_/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/is_/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/is_/tests.py b/tests/regressiontests/localflavor/is_/tests.py deleted file mode 100644 index 3ed15e937b..0000000000 --- a/tests/regressiontests/localflavor/is_/tests.py +++ /dev/null @@ -1,200 +0,0 @@ -from __future__ import unicode_literals - -from django.contrib.localflavor.is_.forms import (ISIdNumberField, - ISPhoneNumberField, ISPostalCodeSelect) - -from django.test import SimpleTestCase - - -class ISLocalFlavorTests(SimpleTestCase): - def test_ISPostalCodeSelect(self): - f = ISPostalCodeSelect() - out = '''<select name="foo"> -<option value="101">101 Reykjav\xedk</option> -<option value="103">103 Reykjav\xedk</option> -<option value="104">104 Reykjav\xedk</option> -<option value="105">105 Reykjav\xedk</option> -<option value="107">107 Reykjav\xedk</option> -<option value="108">108 Reykjav\xedk</option> -<option value="109">109 Reykjav\xedk</option> -<option value="110">110 Reykjav\xedk</option> -<option value="111">111 Reykjav\xedk</option> -<option value="112">112 Reykjav\xedk</option> -<option value="113">113 Reykjav\xedk</option> -<option value="116">116 Kjalarnes</option> -<option value="121">121 Reykjav\xedk</option> -<option value="123">123 Reykjav\xedk</option> -<option value="124">124 Reykjav\xedk</option> -<option value="125">125 Reykjav\xedk</option> -<option value="127">127 Reykjav\xedk</option> -<option value="128">128 Reykjav\xedk</option> -<option value="129">129 Reykjav\xedk</option> -<option value="130">130 Reykjav\xedk</option> -<option value="132">132 Reykjav\xedk</option> -<option value="150">150 Reykjav\xedk</option> -<option value="155">155 Reykjav\xedk</option> -<option value="170">170 Seltjarnarnes</option> -<option value="172">172 Seltjarnarnes</option> -<option value="190">190 Vogar</option> -<option value="200">200 K\xf3pavogur</option> -<option value="201">201 K\xf3pavogur</option> -<option value="202">202 K\xf3pavogur</option> -<option value="203">203 K\xf3pavogur</option> -<option value="210">210 Gar\xf0ab\xe6r</option> -<option value="212">212 Gar\xf0ab\xe6r</option> -<option value="220">220 Hafnarfj\xf6r\xf0ur</option> -<option value="221">221 Hafnarfj\xf6r\xf0ur</option> -<option value="222">222 Hafnarfj\xf6r\xf0ur</option> -<option value="225">225 \xc1lftanes</option> -<option value="230">230 Reykjanesb\xe6r</option> -<option value="232">232 Reykjanesb\xe6r</option> -<option value="233">233 Reykjanesb\xe6r</option> -<option value="235">235 Keflav\xedkurflugv\xf6llur</option> -<option value="240">240 Grindav\xedk</option> -<option value="245">245 Sandger\xf0i</option> -<option value="250">250 Gar\xf0ur</option> -<option value="260">260 Reykjanesb\xe6r</option> -<option value="270">270 Mosfellsb\xe6r</option> -<option value="300">300 Akranes</option> -<option value="301">301 Akranes</option> -<option value="302">302 Akranes</option> -<option value="310">310 Borgarnes</option> -<option value="311">311 Borgarnes</option> -<option value="320">320 Reykholt \xed Borgarfir\xf0i</option> -<option value="340">340 Stykkish\xf3lmur</option> -<option value="345">345 Flatey \xe1 Brei\xf0afir\xf0i</option> -<option value="350">350 Grundarfj\xf6r\xf0ur</option> -<option value="355">355 \xd3lafsv\xedk</option> -<option value="356">356 Sn\xe6fellsb\xe6r</option> -<option value="360">360 Hellissandur</option> -<option value="370">370 B\xfa\xf0ardalur</option> -<option value="371">371 B\xfa\xf0ardalur</option> -<option value="380">380 Reykh\xf3lahreppur</option> -<option value="400">400 \xcdsafj\xf6r\xf0ur</option> -<option value="401">401 \xcdsafj\xf6r\xf0ur</option> -<option value="410">410 Hn\xedfsdalur</option> -<option value="415">415 Bolungarv\xedk</option> -<option value="420">420 S\xfa\xf0av\xedk</option> -<option value="425">425 Flateyri</option> -<option value="430">430 Su\xf0ureyri</option> -<option value="450">450 Patreksfj\xf6r\xf0ur</option> -<option value="451">451 Patreksfj\xf6r\xf0ur</option> -<option value="460">460 T\xe1lknafj\xf6r\xf0ur</option> -<option value="465">465 B\xedldudalur</option> -<option value="470">470 \xdeingeyri</option> -<option value="471">471 \xdeingeyri</option> -<option value="500">500 Sta\xf0ur</option> -<option value="510">510 H\xf3lmav\xedk</option> -<option value="512">512 H\xf3lmav\xedk</option> -<option value="520">520 Drangsnes</option> -<option value="522">522 Kj\xf6rvogur</option> -<option value="523">523 B\xe6r</option> -<option value="524">524 Nor\xf0urfj\xf6r\xf0ur</option> -<option value="530">530 Hvammstangi</option> -<option value="531">531 Hvammstangi</option> -<option value="540">540 Bl\xf6ndu\xf3s</option> -<option value="541">541 Bl\xf6ndu\xf3s</option> -<option value="545">545 Skagastr\xf6nd</option> -<option value="550">550 Sau\xf0\xe1rkr\xf3kur</option> -<option value="551">551 Sau\xf0\xe1rkr\xf3kur</option> -<option value="560">560 Varmahl\xed\xf0</option> -<option value="565">565 Hofs\xf3s</option> -<option value="566">566 Hofs\xf3s</option> -<option value="570">570 Flj\xf3t</option> -<option value="580">580 Siglufj\xf6r\xf0ur</option> -<option value="600">600 Akureyri</option> -<option value="601">601 Akureyri</option> -<option value="602">602 Akureyri</option> -<option value="603">603 Akureyri</option> -<option value="610">610 Greniv\xedk</option> -<option value="611">611 Gr\xedmsey</option> -<option value="620">620 Dalv\xedk</option> -<option value="621">621 Dalv\xedk</option> -<option value="625">625 \xd3lafsfj\xf6r\xf0ur</option> -<option value="630">630 Hr\xedsey</option> -<option value="640">640 H\xfasav\xedk</option> -<option value="641">641 H\xfasav\xedk</option> -<option value="645">645 Fossh\xf3ll</option> -<option value="650">650 Laugar</option> -<option value="660">660 M\xfdvatn</option> -<option value="670">670 K\xf3pasker</option> -<option value="671">671 K\xf3pasker</option> -<option value="675">675 Raufarh\xf6fn</option> -<option value="680">680 \xde\xf3rsh\xf6fn</option> -<option value="681">681 \xde\xf3rsh\xf6fn</option> -<option value="685">685 Bakkafj\xf6r\xf0ur</option> -<option value="690">690 Vopnafj\xf6r\xf0ur</option> -<option value="700">700 Egilssta\xf0ir</option> -<option value="701">701 Egilssta\xf0ir</option> -<option value="710">710 Sey\xf0isfj\xf6r\xf0ur</option> -<option value="715">715 Mj\xf3ifj\xf6r\xf0ur</option> -<option value="720">720 Borgarfj\xf6r\xf0ur eystri</option> -<option value="730">730 Rey\xf0arfj\xf6r\xf0ur</option> -<option value="735">735 Eskifj\xf6r\xf0ur</option> -<option value="740">740 Neskaupsta\xf0ur</option> -<option value="750">750 F\xe1skr\xfa\xf0sfj\xf6r\xf0ur</option> -<option value="755">755 St\xf6\xf0varfj\xf6r\xf0ur</option> -<option value="760">760 Brei\xf0dalsv\xedk</option> -<option value="765">765 Dj\xfapivogur</option> -<option value="780">780 H\xf6fn \xed Hornafir\xf0i</option> -<option value="781">781 H\xf6fn \xed Hornafir\xf0i</option> -<option value="785">785 \xd6r\xe6fi</option> -<option value="800">800 Selfoss</option> -<option value="801">801 Selfoss</option> -<option value="802">802 Selfoss</option> -<option value="810">810 Hverager\xf0i</option> -<option value="815">815 \xdeorl\xe1ksh\xf6fn</option> -<option value="820">820 Eyrarbakki</option> -<option value="825">825 Stokkseyri</option> -<option value="840">840 Laugarvatn</option> -<option value="845">845 Fl\xfa\xf0ir</option> -<option value="850">850 Hella</option> -<option value="851">851 Hella</option> -<option value="860">860 Hvolsv\xf6llur</option> -<option value="861">861 Hvolsv\xf6llur</option> -<option value="870">870 V\xedk</option> -<option value="871">871 V\xedk</option> -<option value="880">880 Kirkjub\xe6jarklaustur</option> -<option value="900">900 Vestmannaeyjar</option> -<option value="902">902 Vestmannaeyjar</option> -</select>''' - self.assertHTMLEqual(f.render('foo', 'bar'), out) - - def test_ISIdNumberField(self): - error_atleast = ['Ensure this value has at least 10 characters (it has 9).'] - error_invalid = ['Enter a valid Icelandic identification number. The format is XXXXXX-XXXX.'] - error_atmost = ['Ensure this value has at most 11 characters (it has 12).'] - error_notvalid = ['The Icelandic identification number is not valid.'] - valid = { - '2308803449': '230880-3449', - '230880-3449': '230880-3449', - '230880 3449': '230880-3449', - '2308803440': '230880-3440', - } - invalid = { - '230880343': error_atleast + error_invalid, - '230880343234': error_atmost + error_invalid, - 'abcdefghijk': error_invalid, - '2308803439': error_notvalid, - - } - self.assertFieldOutput(ISIdNumberField, valid, invalid) - - def test_ISPhoneNumberField(self): - error_invalid = ['Enter a valid value.'] - error_atleast = ['Ensure this value has at least 7 characters (it has 6).'] - error_atmost = ['Ensure this value has at most 8 characters (it has 9).'] - valid = { - '1234567': '1234567', - '123 4567': '1234567', - '123-4567': '1234567', - } - invalid = { - '123-456': error_invalid, - '123456': error_atleast + error_invalid, - '123456555': error_atmost + error_invalid, - 'abcdefg': error_invalid, - ' 1234567 ': error_atmost + error_invalid, - ' 12367 ': error_invalid - } - self.assertFieldOutput(ISPhoneNumberField, valid, invalid) diff --git a/tests/regressiontests/localflavor/it/__init__.py b/tests/regressiontests/localflavor/it/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/it/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/it/tests.py b/tests/regressiontests/localflavor/it/tests.py deleted file mode 100644 index 680444400f..0000000000 --- a/tests/regressiontests/localflavor/it/tests.py +++ /dev/null @@ -1,71 +0,0 @@ -from __future__ import unicode_literals - -from django.contrib.localflavor.it.forms import (ITZipCodeField, ITRegionSelect, - ITSocialSecurityNumberField, ITVatNumberField) - -from django.test import SimpleTestCase - - -class ITLocalFlavorTests(SimpleTestCase): - def test_ITRegionSelect(self): - f = ITRegionSelect() - out = '''<select name="regions"> -<option value="ABR">Abruzzo</option> -<option value="BAS">Basilicata</option> -<option value="CAL">Calabria</option> -<option value="CAM">Campania</option> -<option value="EMR">Emilia-Romagna</option> -<option value="FVG">Friuli-Venezia Giulia</option> -<option value="LAZ">Lazio</option> -<option value="LIG">Liguria</option> -<option value="LOM">Lombardia</option> -<option value="MAR">Marche</option> -<option value="MOL">Molise</option> -<option value="PMN" selected="selected">Piemonte</option> -<option value="PUG">Puglia</option> -<option value="SAR">Sardegna</option> -<option value="SIC">Sicilia</option> -<option value="TOS">Toscana</option> -<option value="TAA">Trentino-Alto Adige</option> -<option value="UMB">Umbria</option> -<option value="VAO">Valle d\u2019Aosta</option> -<option value="VEN">Veneto</option> -</select>''' - self.assertHTMLEqual(f.render('regions', 'PMN'), out) - - def test_ITZipCodeField(self): - error_invalid = ['Enter a valid zip code.'] - valid = { - '00100': '00100', - } - invalid = { - ' 00100': error_invalid, - } - self.assertFieldOutput(ITZipCodeField, valid, invalid) - - def test_ITSocialSecurityNumberField(self): - error_invalid = ['Enter a valid Social Security number.'] - valid = { - 'LVSGDU99T71H501L': 'LVSGDU99T71H501L', - 'LBRRME11A01L736W': 'LBRRME11A01L736W', - 'lbrrme11a01l736w': 'LBRRME11A01L736W', - 'LBR RME 11A01 L736W': 'LBRRME11A01L736W', - } - invalid = { - 'LBRRME11A01L736A': error_invalid, - '%BRRME11A01L736W': error_invalid, - } - self.assertFieldOutput(ITSocialSecurityNumberField, valid, invalid) - - def test_ITVatNumberField(self): - error_invalid = ['Enter a valid VAT number.'] - valid = { - '07973780013': '07973780013', - '7973780013': '07973780013', - 7973780013: '07973780013', - } - invalid = { - '07973780014': error_invalid, - 'A7973780013': error_invalid, - } - self.assertFieldOutput(ITVatNumberField, valid, invalid) diff --git a/tests/regressiontests/localflavor/jp/__init__.py b/tests/regressiontests/localflavor/jp/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/jp/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/jp/tests.py b/tests/regressiontests/localflavor/jp/tests.py deleted file mode 100644 index d31c679bcb..0000000000 --- a/tests/regressiontests/localflavor/jp/tests.py +++ /dev/null @@ -1,75 +0,0 @@ -from __future__ import unicode_literals - -from django.contrib.localflavor.jp.forms import (JPPostalCodeField, - JPPrefectureSelect) - -from django.test import SimpleTestCase - - -class JPLocalFlavorTests(SimpleTestCase): - def test_JPPrefectureSelect(self): - f = JPPrefectureSelect() - out = '''<select name="prefecture"> -<option value="hokkaido">Hokkaido</option> -<option value="aomori">Aomori</option> -<option value="iwate">Iwate</option> -<option value="miyagi">Miyagi</option> -<option value="akita">Akita</option> -<option value="yamagata">Yamagata</option> -<option value="fukushima">Fukushima</option> -<option value="ibaraki">Ibaraki</option> -<option value="tochigi">Tochigi</option> -<option value="gunma">Gunma</option> -<option value="saitama">Saitama</option> -<option value="chiba">Chiba</option> -<option value="tokyo">Tokyo</option> -<option value="kanagawa" selected="selected">Kanagawa</option> -<option value="yamanashi">Yamanashi</option> -<option value="nagano">Nagano</option> -<option value="niigata">Niigata</option> -<option value="toyama">Toyama</option> -<option value="ishikawa">Ishikawa</option> -<option value="fukui">Fukui</option> -<option value="gifu">Gifu</option> -<option value="shizuoka">Shizuoka</option> -<option value="aichi">Aichi</option> -<option value="mie">Mie</option> -<option value="shiga">Shiga</option> -<option value="kyoto">Kyoto</option> -<option value="osaka">Osaka</option> -<option value="hyogo">Hyogo</option> -<option value="nara">Nara</option> -<option value="wakayama">Wakayama</option> -<option value="tottori">Tottori</option> -<option value="shimane">Shimane</option> -<option value="okayama">Okayama</option> -<option value="hiroshima">Hiroshima</option> -<option value="yamaguchi">Yamaguchi</option> -<option value="tokushima">Tokushima</option> -<option value="kagawa">Kagawa</option> -<option value="ehime">Ehime</option> -<option value="kochi">Kochi</option> -<option value="fukuoka">Fukuoka</option> -<option value="saga">Saga</option> -<option value="nagasaki">Nagasaki</option> -<option value="kumamoto">Kumamoto</option> -<option value="oita">Oita</option> -<option value="miyazaki">Miyazaki</option> -<option value="kagoshima">Kagoshima</option> -<option value="okinawa">Okinawa</option> -</select>''' - self.assertHTMLEqual(f.render('prefecture', 'kanagawa'), out) - - def test_JPPostalCodeField(self): - error_format = ['Enter a postal code in the format XXXXXXX or XXX-XXXX.'] - valid = { - '251-0032': '2510032', - '2510032': '2510032', - } - invalid = { - '2510-032': error_format, - '251a0032': error_format, - 'a51-0032': error_format, - '25100321': error_format, - } - self.assertFieldOutput(JPPostalCodeField, valid, invalid) diff --git a/tests/regressiontests/localflavor/kw/__init__.py b/tests/regressiontests/localflavor/kw/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/kw/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/kw/tests.py b/tests/regressiontests/localflavor/kw/tests.py deleted file mode 100644 index 0cf645b918..0000000000 --- a/tests/regressiontests/localflavor/kw/tests.py +++ /dev/null @@ -1,17 +0,0 @@ -from __future__ import unicode_literals - -from django.contrib.localflavor.kw.forms import KWCivilIDNumberField - -from django.test import SimpleTestCase - - -class KWLocalFlavorTests(SimpleTestCase): - def test_KWCivilIDNumberField(self): - error_invalid = ['Enter a valid Kuwaiti Civil ID number'] - valid = { - '282040701483': '282040701483', - } - invalid = { - '289332013455': error_invalid, - } - self.assertFieldOutput(KWCivilIDNumberField, valid, invalid) diff --git a/tests/regressiontests/localflavor/mk/__init__.py b/tests/regressiontests/localflavor/mk/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/mk/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/mk/forms.py b/tests/regressiontests/localflavor/mk/forms.py deleted file mode 100644 index d41bee77de..0000000000 --- a/tests/regressiontests/localflavor/mk/forms.py +++ /dev/null @@ -1,11 +0,0 @@ -from __future__ import absolute_import - -from django.forms import ModelForm - -from .models import MKPerson - - -class MKPersonForm(ModelForm): - - class Meta: - model = MKPerson diff --git a/tests/regressiontests/localflavor/mk/models.py b/tests/regressiontests/localflavor/mk/models.py deleted file mode 100644 index 29a8f587de..0000000000 --- a/tests/regressiontests/localflavor/mk/models.py +++ /dev/null @@ -1,15 +0,0 @@ -from django.contrib.localflavor.mk.models import ( - MKIdentityCardNumberField, MKMunicipalityField, UMCNField) -from django.db import models - - -class MKPerson(models.Model): - first_name = models.CharField(max_length = 20) - last_name = models.CharField(max_length = 20) - umcn = UMCNField() - id_number = MKIdentityCardNumberField() - municipality = MKMunicipalityField(blank = True) - municipality_req = MKMunicipalityField(blank = False) - - class Meta: - app_label = 'localflavor' diff --git a/tests/regressiontests/localflavor/mk/tests.py b/tests/regressiontests/localflavor/mk/tests.py deleted file mode 100644 index 4e075c5881..0000000000 --- a/tests/regressiontests/localflavor/mk/tests.py +++ /dev/null @@ -1,308 +0,0 @@ -# -*- encoding: utf-8 -*- -from __future__ import absolute_import, unicode_literals - -from django.contrib.localflavor.mk.forms import ( - MKIdentityCardNumberField, MKMunicipalitySelect, UMCNField) -from django.test import SimpleTestCase - -from .forms import MKPersonForm - - -class MKLocalFlavorTests(SimpleTestCase): - - def setUp(self): - self.form = MKPersonForm({ - 'first_name':'Someone', - 'last_name':'Something', - 'umcn': '2402983450006', - 'municipality':'OD', - 'municipality_req':'VE', - 'id_number':'A1234567', - }) - - def test_get_display_methods(self): - """ - Test that the get_*_display() methods are added to the model instances. - """ - person = self.form.save() - self.assertEqual(person.get_municipality_display(), 'Ohrid') - self.assertEqual(person.get_municipality_req_display(), 'Veles') - - def test_municipality_required(self): - """ - Test that required MKMunicipalityFields throw appropriate errors. - """ - - form = MKPersonForm({ - 'first_name':'Someone', - 'last_name':'Something', - 'umcn': '2402983450006', - 'municipality':'OD', - 'id_number':'A1234567', - }) - self.assertFalse(form.is_valid()) - self.assertEqual( - form.errors['municipality_req'], ['This field is required.']) - - def test_umcn_invalid(self): - """ - Test that UMCNFields throw appropriate errors for invalid UMCNs. - """ - form = MKPersonForm({ - 'first_name':'Someone', - 'last_name':'Something', - 'umcn': '2402983450007', - 'municipality':'OD', - 'municipality_req':'VE', - 'id_number':'A1234567', - }) - self.assertFalse(form.is_valid()) - self.assertEqual(form.errors['umcn'], ['The UMCN is not valid.']) - - form = MKPersonForm({ - 'first_name':'Someone', - 'last_name':'Something', - 'umcn': '3002983450007', - 'municipality':'OD', - 'municipality_req':'VE', - 'id_number':'A1234567', - }) - self.assertEqual(form.errors['umcn'], - ['The first 7 digits of the UMCN must represent a valid past date.']) - - def test_idnumber_invalid(self): - """ - Test that MKIdentityCardNumberFields throw - appropriate errors for invalid values - """ - - form = MKPersonForm({ - 'first_name':'Someone', - 'last_name':'Something', - 'umcn': '2402983450007', - 'municipality':'OD', - 'municipality_req':'VE', - 'id_number':'A123456a', - }) - self.assertFalse(form.is_valid()) - self.assertEqual(form.errors['id_number'], - ['Identity card numbers must contain either 4 to 7 ' - 'digits or an uppercase letter and 7 digits.']) - - def test_field_blank_option(self): - """ - Test that the empty option is there. - """ - municipality_select_html = """\ -<select name="municipality" id="id_municipality"> -<option value="">---------</option> -<option value="AD">Aerodrom</option> -<option value="AR">Aračinovo</option> -<option value="BR">Berovo</option> -<option value="TL">Bitola</option> -<option value="BG">Bogdanci</option> -<option value="VJ">Bogovinje</option> -<option value="BS">Bosilovo</option> -<option value="BN">Brvenica</option> -<option value="BU">Butel</option> -<option value="VA">Valandovo</option> -<option value="VL">Vasilevo</option> -<option value="VV">Vevčani</option> -<option value="VE">Veles</option> -<option value="NI">Vinica</option> -<option value="VC">Vraneštica</option> -<option value="VH">Vrapčište</option> -<option value="GB">Gazi Baba</option> -<option value="GV">Gevgelija</option> -<option value="GT">Gostivar</option> -<option value="GR">Gradsko</option> -<option value="DB">Debar</option> -<option value="DA">Debarca</option> -<option value="DL">Delčevo</option> -<option value="DK">Demir Kapija</option> -<option value="DM">Demir Hisar</option> -<option value="DE">Dolneni</option> -<option value="DR">Drugovo</option> -<option value="GP">Gjorče Petrov</option> -<option value="ZE">Želino</option> -<option value="ZA">Zajas</option> -<option value="ZK">Zelenikovo</option> -<option value="ZR">Zrnovci</option> -<option value="IL">Ilinden</option> -<option value="JG">Jegunovce</option> -<option value="AV">Kavadarci</option> -<option value="KB">Karbinci</option> -<option value="KX">Karpoš</option> -<option value="VD">Kisela Voda</option> -<option value="KH">Kičevo</option> -<option value="KN">Konče</option> -<option value="OC">Koćani</option> -<option value="KY">Kratovo</option> -<option value="KZ">Kriva Palanka</option> -<option value="KG">Krivogaštani</option> -<option value="KS">Kruševo</option> -<option value="UM">Kumanovo</option> -<option value="LI">Lipkovo</option> -<option value="LO">Lozovo</option> -<option value="MR">Mavrovo i Rostuša</option> -<option value="MK">Makedonska Kamenica</option> -<option value="MD">Makedonski Brod</option> -<option value="MG">Mogila</option> -<option value="NG">Negotino</option> -<option value="NV">Novaci</option> -<option value="NS">Novo Selo</option> -<option value="OS">Oslomej</option> -<option value="OD" selected="selected">Ohrid</option> -<option value="PE">Petrovec</option> -<option value="PH">Pehčevo</option> -<option value="PN">Plasnica</option> -<option value="PP">Prilep</option> -<option value="PT">Probištip</option> -<option value="RV">Radoviš</option> -<option value="RN">Rankovce</option> -<option value="RE">Resen</option> -<option value="RO">Rosoman</option> -<option value="AJ">Saraj</option> -<option value="SL">Sveti Nikole</option> -<option value="SS">Sopište</option> -<option value="SD">Star Dojran</option> -<option value="NA">Staro Nagoričane</option> -<option value="UG">Struga</option> -<option value="RU">Strumica</option> -<option value="SU">Studeničani</option> -<option value="TR">Tearce</option> -<option value="ET">Tetovo</option> -<option value="CE">Centar</option> -<option value="CZ">Centar-Župa</option> -<option value="CI">Čair</option> -<option value="CA">Čaška</option> -<option value="CH">Češinovo-Obleševo</option> -<option value="CS">Čučer-Sandevo</option> -<option value="ST">Štip</option> -<option value="SO">Šuto Orizari</option> -</select>""" - self.assertHTMLEqual(str(self.form['municipality']), municipality_select_html) - - def test_MKIdentityCardNumberField(self): - error_invalid = ['Identity card numbers must contain either 4 to 7 ' - 'digits or an uppercase letter and 7 digits.'] - valid = { - 'L0018077':'L0018077', - 'A0078315' : 'A0078315', - } - invalid = { - '123': error_invalid, - 'abcdf': error_invalid, - '234390a': error_invalid, - } - self.assertFieldOutput(MKIdentityCardNumberField, valid, invalid) - - def test_MKMunicipalitySelect(self): - f = MKMunicipalitySelect() - out='''<select name="municipality"> -<option value="AD">Aerodrom</option> -<option value="AR">Ara\u010dinovo</option> -<option value="BR">Berovo</option> -<option value="TL">Bitola</option> -<option value="BG">Bogdanci</option> -<option value="VJ">Bogovinje</option> -<option value="BS">Bosilovo</option> -<option value="BN">Brvenica</option> -<option value="BU">Butel</option> -<option value="VA">Valandovo</option> -<option value="VL">Vasilevo</option> -<option value="VV">Vev\u010dani</option> -<option value="VE">Veles</option> -<option value="NI">Vinica</option> -<option value="VC">Vrane\u0161tica</option> -<option value="VH">Vrap\u010di\u0161te</option> -<option value="GB">Gazi Baba</option> -<option value="GV">Gevgelija</option> -<option value="GT">Gostivar</option> -<option value="GR">Gradsko</option> -<option value="DB">Debar</option> -<option value="DA">Debarca</option> -<option value="DL" selected="selected">Del\u010devo</option> -<option value="DK">Demir Kapija</option> -<option value="DM">Demir Hisar</option> -<option value="DE">Dolneni</option> -<option value="DR">Drugovo</option> -<option value="GP">Gjor\u010de Petrov</option> -<option value="ZE">\u017delino</option> -<option value="ZA">Zajas</option> -<option value="ZK">Zelenikovo</option> -<option value="ZR">Zrnovci</option> -<option value="IL">Ilinden</option> -<option value="JG">Jegunovce</option> -<option value="AV">Kavadarci</option> -<option value="KB">Karbinci</option> -<option value="KX">Karpo\u0161</option> -<option value="VD">Kisela Voda</option> -<option value="KH">Ki\u010devo</option> -<option value="KN">Kon\u010de</option> -<option value="OC">Ko\u0107ani</option> -<option value="KY">Kratovo</option> -<option value="KZ">Kriva Palanka</option> -<option value="KG">Krivoga\u0161tani</option> -<option value="KS">Kru\u0161evo</option> -<option value="UM">Kumanovo</option> -<option value="LI">Lipkovo</option> -<option value="LO">Lozovo</option> -<option value="MR">Mavrovo i Rostu\u0161a</option> -<option value="MK">Makedonska Kamenica</option> -<option value="MD">Makedonski Brod</option> -<option value="MG">Mogila</option> -<option value="NG">Negotino</option> -<option value="NV">Novaci</option> -<option value="NS">Novo Selo</option> -<option value="OS">Oslomej</option> -<option value="OD">Ohrid</option> -<option value="PE">Petrovec</option> -<option value="PH">Peh\u010devo</option> -<option value="PN">Plasnica</option> -<option value="PP">Prilep</option> -<option value="PT">Probi\u0161tip</option> -<option value="RV">Radovi\u0161</option> -<option value="RN">Rankovce</option> -<option value="RE">Resen</option> -<option value="RO">Rosoman</option> -<option value="AJ">Saraj</option> -<option value="SL">Sveti Nikole</option> -<option value="SS">Sopi\u0161te</option> -<option value="SD">Star Dojran</option> -<option value="NA">Staro Nagori\u010dane</option> -<option value="UG">Struga</option> -<option value="RU">Strumica</option> -<option value="SU">Studeni\u010dani</option> -<option value="TR">Tearce</option> -<option value="ET">Tetovo</option> -<option value="CE">Centar</option> -<option value="CZ">Centar-\u017dupa</option> -<option value="CI">\u010cair</option> -<option value="CA">\u010ca\u0161ka</option> -<option value="CH">\u010ce\u0161inovo-Oble\u0161evo</option> -<option value="CS">\u010cu\u010der-Sandevo</option> -<option value="ST">\u0160tip</option> -<option value="SO">\u0160uto Orizari</option> -</select>''' - self.assertHTMLEqual(f.render('municipality', 'DL' ), out) - - def test_UMCNField(self): - error_invalid = ['This field should contain exactly 13 digits.'] - error_checksum = ['The UMCN is not valid.'] - error_date = ['The first 7 digits of the UMCN ' - 'must represent a valid past date.'] - valid = { - '2402983450006': '2402983450006', - '2803984430038': '2803984430038', - '1909982045004': '1909982045004', - } - invalid = { - '240298345': error_invalid, - 'abcdefghj': error_invalid, - '2402082450006': error_date, - '3002982450006': error_date, - '2402983450007': error_checksum, - '2402982450006': error_checksum, - } - self.assertFieldOutput(UMCNField, valid, invalid) diff --git a/tests/regressiontests/localflavor/mx/__init__.py b/tests/regressiontests/localflavor/mx/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/mx/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/mx/forms.py b/tests/regressiontests/localflavor/mx/forms.py deleted file mode 100644 index dac05319c8..0000000000 --- a/tests/regressiontests/localflavor/mx/forms.py +++ /dev/null @@ -1,11 +0,0 @@ -from __future__ import absolute_import - -from django.forms import ModelForm - -from .models import MXPersonProfile - - -class MXPersonProfileForm(ModelForm): - - class Meta: - model = MXPersonProfile diff --git a/tests/regressiontests/localflavor/mx/models.py b/tests/regressiontests/localflavor/mx/models.py deleted file mode 100644 index 4905836d3d..0000000000 --- a/tests/regressiontests/localflavor/mx/models.py +++ /dev/null @@ -1,13 +0,0 @@ -from django.contrib.localflavor.mx.models import ( - MXStateField, MXRFCField, MXCURPField, MXZipCodeField) -from django.db import models - - -class MXPersonProfile(models.Model): - state = MXStateField() - rfc = MXRFCField() - curp = MXCURPField() - zip_code = MXZipCodeField() - - class Meta: - app_label = 'localflavor' diff --git a/tests/regressiontests/localflavor/mx/mx.py b/tests/regressiontests/localflavor/mx/mx.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/mx/mx.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/mx/tests.py b/tests/regressiontests/localflavor/mx/tests.py deleted file mode 100644 index 5eeceec276..0000000000 --- a/tests/regressiontests/localflavor/mx/tests.py +++ /dev/null @@ -1,198 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import, unicode_literals - -from django.contrib.localflavor.mx.forms import (MXZipCodeField, MXRFCField, - MXStateSelect, MXCURPField) -from django.test import SimpleTestCase - -from .forms import MXPersonProfileForm - - -class MXLocalFlavorTests(SimpleTestCase): - - def setUp(self): - self.form = MXPersonProfileForm({ - 'state': 'MIC', - 'rfc': 'toma880125kv3', - 'curp': 'toma880125hmnrrn02', - 'zip_code': '58120', - }) - - def test_get_display_methods(self): - """Test that the get_*_display() methods are added to the model instances.""" - place = self.form.save() - self.assertEqual(place.get_state_display(), 'Michoacán') - - def test_errors(self): - """Test that required MXFields throw appropriate errors.""" - form = MXPersonProfileForm({ - 'state': 'Invalid state', - 'rfc': 'invalid rfc', - 'curp': 'invalid curp', - 'zip_code': 'xxx', - }) - self.assertFalse(form.is_valid()) - self.assertEqual(form.errors['state'], ['Select a valid choice. Invalid state is not one of the available choices.']) - self.assertEqual(form.errors['rfc'], ['Enter a valid RFC.']) - self.assertEqual(form.errors['curp'], ['Ensure this value has at least 18 characters (it has 12).', 'Enter a valid CURP.']) - self.assertEqual(form.errors['zip_code'], ['Enter a valid zip code in the format XXXXX.']) - - def test_field_blank_option(self): - """Test that the empty option is there.""" - state_select_html = """\ -<select name="state" id="id_state"> -<option value="">---------</option> -<option value="AGU">Aguascalientes</option> -<option value="BCN">Baja California</option> -<option value="BCS">Baja California Sur</option> -<option value="CAM">Campeche</option> -<option value="CHH">Chihuahua</option> -<option value="CHP">Chiapas</option> -<option value="COA">Coahuila</option> -<option value="COL">Colima</option> -<option value="DIF">Distrito Federal</option> -<option value="DUR">Durango</option> -<option value="GRO">Guerrero</option> -<option value="GUA">Guanajuato</option> -<option value="HID">Hidalgo</option> -<option value="JAL">Jalisco</option> -<option value="MEX">Estado de México</option> -<option value="MIC" selected="selected">Michoacán</option> -<option value="MOR">Morelos</option> -<option value="NAY">Nayarit</option> -<option value="NLE">Nuevo León</option> -<option value="OAX">Oaxaca</option> -<option value="PUE">Puebla</option> -<option value="QUE">Querétaro</option> -<option value="ROO">Quintana Roo</option> -<option value="SIN">Sinaloa</option> -<option value="SLP">San Luis Potosí</option> -<option value="SON">Sonora</option> -<option value="TAB">Tabasco</option> -<option value="TAM">Tamaulipas</option> -<option value="TLA">Tlaxcala</option> -<option value="VER">Veracruz</option> -<option value="YUC">Yucatán</option> -<option value="ZAC">Zacatecas</option> -</select>""" - self.assertHTMLEqual(str(self.form['state']), state_select_html) - - def test_MXStateSelect(self): - f = MXStateSelect() - out = '''<select name="state"> -<option value="AGU">Aguascalientes</option> -<option value="BCN">Baja California</option> -<option value="BCS">Baja California Sur</option> -<option value="CAM">Campeche</option> -<option value="CHH">Chihuahua</option> -<option value="CHP">Chiapas</option> -<option value="COA">Coahuila</option> -<option value="COL">Colima</option> -<option value="DIF">Distrito Federal</option> -<option value="DUR">Durango</option> -<option value="GRO">Guerrero</option> -<option value="GUA">Guanajuato</option> -<option value="HID">Hidalgo</option> -<option value="JAL">Jalisco</option> -<option value="MEX">Estado de México</option> -<option value="MIC" selected="selected">Michoacán</option> -<option value="MOR">Morelos</option> -<option value="NAY">Nayarit</option> -<option value="NLE">Nuevo León</option> -<option value="OAX">Oaxaca</option> -<option value="PUE">Puebla</option> -<option value="QUE">Querétaro</option> -<option value="ROO">Quintana Roo</option> -<option value="SIN">Sinaloa</option> -<option value="SLP">San Luis Potosí</option> -<option value="SON">Sonora</option> -<option value="TAB">Tabasco</option> -<option value="TAM">Tamaulipas</option> -<option value="TLA">Tlaxcala</option> -<option value="VER">Veracruz</option> -<option value="YUC">Yucatán</option> -<option value="ZAC">Zacatecas</option> -</select>''' - self.assertHTMLEqual(f.render('state', 'MIC'), out) - - def test_MXZipCodeField(self): - error_format = ['Enter a valid zip code in the format XXXXX.'] - valid = { - '58120': '58120', - '58502': '58502', - '59310': '59310', - '99999': '99999', - } - invalid = { - '17000': error_format, - '18000': error_format, - '19000': error_format, - '00000': error_format, - } - self.assertFieldOutput(MXZipCodeField, valid, invalid) - - def test_MXRFCField(self): - error_format = ['Enter a valid RFC.'] - error_checksum = ['Invalid checksum for RFC.'] - valid = { - 'MoFN641205eX5': 'MOFN641205EX5', - 'ICa060120873': 'ICA060120873', - 'eUcG751104rT0': 'EUCG751104RT0', - 'GME08100195A': 'GME08100195A', - 'AA&060524KX5': 'AA&060524KX5', - 'CAÑ0708045P7': 'CAÑ0708045P7', - 'aaa000101aa9': 'AAA000101AA9', - } - invalid = { - 'MED0000000XA': error_format, - '0000000000XA': error_format, - 'AAA000000AA6': error_format, - # Dates - 'XXX880002XXX': error_format, - 'XXX880200XXX': error_format, - 'XXX880132XXX': error_format, - 'XXX880230XXX': error_format, - 'XXX880431XXX': error_format, - # Incorrect checksum - 'MOGR650524E73': error_checksum, - 'HVA7810058F1': error_checksum, - 'MoFN641205eX2': error_checksum, - 'ICa060120871': error_checksum, - 'eUcG751104rT7': error_checksum, - 'GME081001955': error_checksum, - 'AA&060524KX9': error_checksum, - 'CAÑ0708045P2': error_checksum, - } - self.assertFieldOutput(MXRFCField, valid, invalid) - - def test_MXCURPField(self): - error_format = ['Enter a valid CURP.'] - error_checksum = ['Invalid checksum for CURP.'] - valid = { - 'AaMG890608HDFLJL00': 'AAMG890608HDFLJL00', - 'BAAd890419HMNRRV07': 'BAAD890419HMNRRV07', - 'VIAA900930MMNClL08': 'VIAA900930MMNCLL08', - 'HEGR891009HMNRRD09': 'HEGR891009HMNRRD09', - 'MARR890512HMNRMN09': 'MARR890512HMNRMN09', - 'MESJ890928HMNZNS00': 'MESJ890928HMNZNS00', - 'BAAA890317HDFRLL03': 'BAAA890317HDFRLL03', - 'TOMA880125HMNRRNO2': 'TOMA880125HMNRRNO2', - 'OOMG890727HMNRSR06': 'OOMG890727HMNRSR06', - 'AAAA000101HDFCCC09': 'AAAA000101HDFCCC09', - } - invalid = { - 'AAAA000000HDFCCC09': error_format, - 'AAAA000000HDFAAA03': error_format, - 'AAAA000000HXXCCC08': error_format, - 'AAAA000000XMNCCC02': error_format, - 'HEGR891009HMNRRD0A': error_format, - 'MARR890512HMNRMN0A': error_format, - 'AaMG890608HDFLJL01': error_checksum, - 'BAAd890419HMNRRV08': error_checksum, - 'VIAA900930MMNClL09': error_checksum, - 'MESJ890928HMNZNS01': error_checksum, - 'BAAA890317HDFRLL04': error_checksum, - 'TOMA880125HMNRRNO3': error_checksum, - 'OOMG890727HMNRSR07': error_checksum, - } - self.assertFieldOutput(MXCURPField, valid, invalid) diff --git a/tests/regressiontests/localflavor/nl/__init__.py b/tests/regressiontests/localflavor/nl/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/nl/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/nl/tests.py b/tests/regressiontests/localflavor/nl/tests.py deleted file mode 100644 index ef8bd3cf35..0000000000 --- a/tests/regressiontests/localflavor/nl/tests.py +++ /dev/null @@ -1,64 +0,0 @@ -from __future__ import unicode_literals - -from django.contrib.localflavor.nl.forms import (NLPhoneNumberField, - NLZipCodeField, NLSoFiNumberField, NLProvinceSelect) - -from django.test import SimpleTestCase - - -class NLLocalFlavorTests(SimpleTestCase): - def test_NLProvinceSelect(self): - f = NLProvinceSelect() - out = '''<select name="provinces"> -<option value="DR">Drenthe</option> -<option value="FL">Flevoland</option> -<option value="FR">Friesland</option> -<option value="GL">Gelderland</option> -<option value="GR">Groningen</option> -<option value="LB">Limburg</option> -<option value="NB">Noord-Brabant</option> -<option value="NH">Noord-Holland</option> -<option value="OV" selected="selected">Overijssel</option> -<option value="UT">Utrecht</option> -<option value="ZE">Zeeland</option> -<option value="ZH">Zuid-Holland</option> -</select>''' - self.assertHTMLEqual(f.render('provinces', 'OV'), out) - - def test_NLPhoneNumberField(self): - error_invalid = ['Enter a valid phone number'] - valid = { - '012-3456789': '012-3456789', - '0123456789': '0123456789', - '+31-12-3456789': '+31-12-3456789', - '(0123) 456789': '(0123) 456789', - } - invalid = { - 'foo': error_invalid, - } - self.assertFieldOutput(NLPhoneNumberField, valid, invalid) - - def test_NLZipCodeField(self): - error_invalid = ['Enter a valid postal code'] - valid = { - '1234ab': '1234 AB', - '1234 ab': '1234 AB', - '1234 AB': '1234 AB', - } - invalid = { - '0123AB': error_invalid, - 'foo': error_invalid, - } - self.assertFieldOutput(NLZipCodeField, valid, invalid) - - def test_NLSoFiNumberField(self): - error_invalid = ['Enter a valid SoFi number'] - valid = { - '123456782': '123456782', - } - invalid = { - '000000000': error_invalid, - '123456789': error_invalid, - 'foo': error_invalid, - } - self.assertFieldOutput(NLSoFiNumberField, valid, invalid) diff --git a/tests/regressiontests/localflavor/pl/__init__.py b/tests/regressiontests/localflavor/pl/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/pl/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/pl/tests.py b/tests/regressiontests/localflavor/pl/tests.py deleted file mode 100644 index 82c5d615c1..0000000000 --- a/tests/regressiontests/localflavor/pl/tests.py +++ /dev/null @@ -1,480 +0,0 @@ -from __future__ import unicode_literals - -from django.contrib.localflavor.pl.forms import (PLProvinceSelect, - PLCountySelect, PLPostalCodeField, PLNIPField, PLPESELField, PLNationalIDCardNumberField, PLREGONField) - -from django.test import SimpleTestCase - - -class PLLocalFlavorTests(SimpleTestCase): - def test_PLProvinceSelect(self): - f = PLProvinceSelect() - out = '''<select name="voivodeships"> -<option value="lower_silesia">Lower Silesia</option> -<option value="kuyavia-pomerania">Kuyavia-Pomerania</option> -<option value="lublin">Lublin</option> -<option value="lubusz">Lubusz</option> -<option value="lodz">Lodz</option> -<option value="lesser_poland">Lesser Poland</option> -<option value="masovia">Masovia</option> -<option value="opole">Opole</option> -<option value="subcarpatia">Subcarpatia</option> -<option value="podlasie">Podlasie</option> -<option value="pomerania" selected="selected">Pomerania</option> -<option value="silesia">Silesia</option> -<option value="swietokrzyskie">Swietokrzyskie</option> -<option value="warmia-masuria">Warmia-Masuria</option> -<option value="greater_poland">Greater Poland</option> -<option value="west_pomerania">West Pomerania</option> -</select>''' - self.assertHTMLEqual(f.render('voivodeships', 'pomerania'), out) - - def test_PLCountrySelect(self): - f = PLCountySelect() - out = '''<select name="administrativeunit"> -<option value="wroclaw">Wroc\u0142aw</option> -<option value="jeleniagora">Jelenia G\xf3ra</option> -<option value="legnica">Legnica</option> -<option value="boleslawiecki">boles\u0142awiecki</option> -<option value="dzierzoniowski">dzier\u017coniowski</option> -<option value="glogowski">g\u0142ogowski</option> -<option value="gorowski">g\xf3rowski</option> -<option value="jaworski">jaworski</option> -<option value="jeleniogorski">jeleniog\xf3rski</option> -<option value="kamiennogorski">kamiennog\xf3rski</option> -<option value="klodzki">k\u0142odzki</option> -<option value="legnicki">legnicki</option> -<option value="lubanski">luba\u0144ski</option> -<option value="lubinski">lubi\u0144ski</option> -<option value="lwowecki">lw\xf3wecki</option> -<option value="milicki">milicki</option> -<option value="olesnicki">ole\u015bnicki</option> -<option value="olawski">o\u0142awski</option> -<option value="polkowicki">polkowicki</option> -<option value="strzelinski">strzeli\u0144ski</option> -<option value="sredzki">\u015bredzki</option> -<option value="swidnicki">\u015bwidnicki</option> -<option value="trzebnicki">trzebnicki</option> -<option value="walbrzyski">wa\u0142brzyski</option> -<option value="wolowski">wo\u0142owski</option> -<option value="wroclawski">wroc\u0142awski</option> -<option value="zabkowicki">z\u0105bkowicki</option> -<option value="zgorzelecki">zgorzelecki</option> -<option value="zlotoryjski">z\u0142otoryjski</option> -<option value="bydgoszcz">Bydgoszcz</option> -<option value="torun">Toru\u0144</option> -<option value="wloclawek">W\u0142oc\u0142awek</option> -<option value="grudziadz">Grudzi\u0105dz</option> -<option value="aleksandrowski">aleksandrowski</option> -<option value="brodnicki">brodnicki</option> -<option value="bydgoski">bydgoski</option> -<option value="chelminski">che\u0142mi\u0144ski</option> -<option value="golubsko-dobrzynski">golubsko-dobrzy\u0144ski</option> -<option value="grudziadzki">grudzi\u0105dzki</option> -<option value="inowroclawski">inowroc\u0142awski</option> -<option value="lipnowski">lipnowski</option> -<option value="mogilenski">mogile\u0144ski</option> -<option value="nakielski">nakielski</option> -<option value="radziejowski">radziejowski</option> -<option value="rypinski">rypi\u0144ski</option> -<option value="sepolenski">s\u0119pole\u0144ski</option> -<option value="swiecki">\u015bwiecki</option> -<option value="torunski">toru\u0144ski</option> -<option value="tucholski">tucholski</option> -<option value="wabrzeski">w\u0105brzeski</option> -<option value="wloclawski">wroc\u0142awski</option> -<option value="zninski">\u017ani\u0144ski</option> -<option value="lublin">Lublin</option> -<option value="biala-podlaska">Bia\u0142a Podlaska</option> -<option value="chelm">Che\u0142m</option> -<option value="zamosc">Zamo\u015b\u0107</option> -<option value="bialski">bialski</option> -<option value="bilgorajski">bi\u0142gorajski</option> -<option value="chelmski">che\u0142mski</option> -<option value="hrubieszowski">hrubieszowski</option> -<option value="janowski">janowski</option> -<option value="krasnostawski">krasnostawski</option> -<option value="krasnicki">kra\u015bnicki</option> -<option value="lubartowski">lubartowski</option> -<option value="lubelski">lubelski</option> -<option value="leczynski">\u0142\u0119czy\u0144ski</option> -<option value="lukowski">\u0142ukowski</option> -<option value="opolski">opolski</option> -<option value="parczewski">parczewski</option> -<option value="pulawski">pu\u0142awski</option> -<option value="radzynski">radzy\u0144ski</option> -<option value="rycki">rycki</option> -<option value="swidnicki">\u015bwidnicki</option> -<option value="tomaszowski">tomaszowski</option> -<option value="wlodawski">w\u0142odawski</option> -<option value="zamojski">zamojski</option> -<option value="gorzow-wielkopolski">Gorz\xf3w Wielkopolski</option> -<option value="zielona-gora">Zielona G\xf3ra</option> -<option value="gorzowski">gorzowski</option> -<option value="krosnienski">kro\u015bnie\u0144ski</option> -<option value="miedzyrzecki">mi\u0119dzyrzecki</option> -<option value="nowosolski">nowosolski</option> -<option value="slubicki">s\u0142ubicki</option> -<option value="strzelecko-drezdenecki">strzelecko-drezdenecki</option> -<option value="sulecinski">sule\u0144ci\u0144ski</option> -<option value="swiebodzinski">\u015bwiebodzi\u0144ski</option> -<option value="wschowski">wschowski</option> -<option value="zielonogorski">zielonog\xf3rski</option> -<option value="zaganski">\u017caga\u0144ski</option> -<option value="zarski">\u017carski</option> -<option value="lodz">\u0141\xf3d\u017a</option> -<option value="piotrkow-trybunalski">Piotrk\xf3w Trybunalski</option> -<option value="skierniewice">Skierniewice</option> -<option value="belchatowski">be\u0142chatowski</option> -<option value="brzezinski">brzezi\u0144ski</option> -<option value="kutnowski">kutnowski</option> -<option value="laski">\u0142aski</option> -<option value="leczycki">\u0142\u0119czycki</option> -<option value="lowicki">\u0142owicki</option> -<option value="lodzki wschodni">\u0142\xf3dzki wschodni</option> -<option value="opoczynski">opoczy\u0144ski</option> -<option value="pabianicki">pabianicki</option> -<option value="pajeczanski">paj\u0119cza\u0144ski</option> -<option value="piotrkowski">piotrkowski</option> -<option value="poddebicki">podd\u0119bicki</option> -<option value="radomszczanski">radomszcza\u0144ski</option> -<option value="rawski">rawski</option> -<option value="sieradzki">sieradzki</option> -<option value="skierniewicki">skierniewicki</option> -<option value="tomaszowski">tomaszowski</option> -<option value="wielunski">wielu\u0144ski</option> -<option value="wieruszowski">wieruszowski</option> -<option value="zdunskowolski">zdu\u0144skowolski</option> -<option value="zgierski">zgierski</option> -<option value="krakow">Krak\xf3w</option> -<option value="tarnow">Tarn\xf3w</option> -<option value="nowy-sacz">Nowy S\u0105cz</option> -<option value="bochenski">boche\u0144ski</option> -<option value="brzeski">brzeski</option> -<option value="chrzanowski">chrzanowski</option> -<option value="dabrowski">d\u0105browski</option> -<option value="gorlicki">gorlicki</option> -<option value="krakowski">krakowski</option> -<option value="limanowski">limanowski</option> -<option value="miechowski">miechowski</option> -<option value="myslenicki">my\u015blenicki</option> -<option value="nowosadecki">nowos\u0105decki</option> -<option value="nowotarski">nowotarski</option> -<option value="olkuski">olkuski</option> -<option value="oswiecimski">o\u015bwi\u0119cimski</option> -<option value="proszowicki">proszowicki</option> -<option value="suski">suski</option> -<option value="tarnowski">tarnowski</option> -<option value="tatrzanski">tatrza\u0144ski</option> -<option value="wadowicki">wadowicki</option> -<option value="wielicki">wielicki</option> -<option value="warszawa">Warszawa</option> -<option value="ostroleka">Ostro\u0142\u0119ka</option> -<option value="plock">P\u0142ock</option> -<option value="radom">Radom</option> -<option value="siedlce">Siedlce</option> -<option value="bialobrzeski">bia\u0142obrzeski</option> -<option value="ciechanowski">ciechanowski</option> -<option value="garwolinski">garwoli\u0144ski</option> -<option value="gostyninski">gostyni\u0144ski</option> -<option value="grodziski">grodziski</option> -<option value="grojecki">gr\xf3jecki</option> -<option value="kozienicki">kozenicki</option> -<option value="legionowski">legionowski</option> -<option value="lipski">lipski</option> -<option value="losicki">\u0142osicki</option> -<option value="makowski">makowski</option> -<option value="minski">mi\u0144ski</option> -<option value="mlawski">m\u0142awski</option> -<option value="nowodworski">nowodworski</option> -<option value="ostrolecki">ostro\u0142\u0119cki</option> -<option value="ostrowski">ostrowski</option> -<option value="otwocki">otwocki</option> -<option value="piaseczynski">piaseczy\u0144ski</option> -<option value="plocki">p\u0142ocki</option> -<option value="plonski">p\u0142o\u0144ski</option> -<option value="pruszkowski">pruszkowski</option> -<option value="przasnyski">przasnyski</option> -<option value="przysuski">przysuski</option> -<option value="pultuski">pu\u0142tuski</option> -<option value="radomski">radomski</option> -<option value="siedlecki">siedlecki</option> -<option value="sierpecki">sierpecki</option> -<option value="sochaczewski">sochaczewski</option> -<option value="sokolowski">soko\u0142owski</option> -<option value="szydlowiecki">szyd\u0142owiecki</option> -<option value="warszawski-zachodni">warszawski zachodni</option> -<option value="wegrowski">w\u0119growski</option> -<option value="wolominski">wo\u0142omi\u0144ski</option> -<option value="wyszkowski">wyszkowski</option> -<option value="zwolenski">zwole\u0144ski</option> -<option value="zurominski">\u017curomi\u0144ski</option> -<option value="zyrardowski">\u017cyrardowski</option> -<option value="opole">Opole</option> -<option value="brzeski">brzeski</option> -<option value="glubczycki">g\u0142ubczyski</option> -<option value="kedzierzynsko-kozielski">k\u0119dzierzy\u0144ski-kozielski</option> -<option value="kluczborski">kluczborski</option> -<option value="krapkowicki">krapkowicki</option> -<option value="namyslowski">namys\u0142owski</option> -<option value="nyski">nyski</option> -<option value="oleski">oleski</option> -<option value="opolski">opolski</option> -<option value="prudnicki">prudnicki</option> -<option value="strzelecki">strzelecki</option> -<option value="rzeszow">Rzesz\xf3w</option> -<option value="krosno">Krosno</option> -<option value="przemysl">Przemy\u015bl</option> -<option value="tarnobrzeg">Tarnobrzeg</option> -<option value="bieszczadzki">bieszczadzki</option> -<option value="brzozowski">brzozowski</option> -<option value="debicki">d\u0119bicki</option> -<option value="jaroslawski">jaros\u0142awski</option> -<option value="jasielski">jasielski</option> -<option value="kolbuszowski">kolbuszowski</option> -<option value="krosnienski">kro\u015bnie\u0144ski</option> -<option value="leski">leski</option> -<option value="lezajski">le\u017cajski</option> -<option value="lubaczowski">lubaczowski</option> -<option value="lancucki">\u0142a\u0144cucki</option> -<option value="mielecki">mielecki</option> -<option value="nizanski">ni\u017ca\u0144ski</option> -<option value="przemyski">przemyski</option> -<option value="przeworski">przeworski</option> -<option value="ropczycko-sedziszowski">ropczycko-s\u0119dziszowski</option> -<option value="rzeszowski">rzeszowski</option> -<option value="sanocki">sanocki</option> -<option value="stalowowolski">stalowowolski</option> -<option value="strzyzowski">strzy\u017cowski</option> -<option value="tarnobrzeski">tarnobrzeski</option> -<option value="bialystok">Bia\u0142ystok</option> -<option value="lomza">\u0141om\u017ca</option> -<option value="suwalki">Suwa\u0142ki</option> -<option value="augustowski">augustowski</option> -<option value="bialostocki">bia\u0142ostocki</option> -<option value="bielski">bielski</option> -<option value="grajewski">grajewski</option> -<option value="hajnowski">hajnowski</option> -<option value="kolnenski">kolne\u0144ski</option> -<option value="\u0142omzynski">\u0142om\u017cy\u0144ski</option> -<option value="moniecki">moniecki</option> -<option value="sejnenski">sejne\u0144ski</option> -<option value="siemiatycki">siematycki</option> -<option value="sokolski">sok\xf3lski</option> -<option value="suwalski">suwalski</option> -<option value="wysokomazowiecki">wysokomazowiecki</option> -<option value="zambrowski">zambrowski</option> -<option value="gdansk">Gda\u0144sk</option> -<option value="gdynia">Gdynia</option> -<option value="slupsk">S\u0142upsk</option> -<option value="sopot">Sopot</option> -<option value="bytowski">bytowski</option> -<option value="chojnicki">chojnicki</option> -<option value="czluchowski">cz\u0142uchowski</option> -<option value="kartuski">kartuski</option> -<option value="koscierski">ko\u015bcierski</option> -<option value="kwidzynski">kwidzy\u0144ski</option> -<option value="leborski">l\u0119borski</option> -<option value="malborski">malborski</option> -<option value="nowodworski">nowodworski</option> -<option value="gdanski">gda\u0144ski</option> -<option value="pucki">pucki</option> -<option value="slupski">s\u0142upski</option> -<option value="starogardzki">starogardzki</option> -<option value="sztumski">sztumski</option> -<option value="tczewski">tczewski</option> -<option value="wejherowski">wejcherowski</option> -<option value="katowice" selected="selected">Katowice</option> -<option value="bielsko-biala">Bielsko-Bia\u0142a</option> -<option value="bytom">Bytom</option> -<option value="chorzow">Chorz\xf3w</option> -<option value="czestochowa">Cz\u0119stochowa</option> -<option value="dabrowa-gornicza">D\u0105browa G\xf3rnicza</option> -<option value="gliwice">Gliwice</option> -<option value="jastrzebie-zdroj">Jastrz\u0119bie Zdr\xf3j</option> -<option value="jaworzno">Jaworzno</option> -<option value="myslowice">Mys\u0142owice</option> -<option value="piekary-slaskie">Piekary \u015al\u0105skie</option> -<option value="ruda-slaska">Ruda \u015al\u0105ska</option> -<option value="rybnik">Rybnik</option> -<option value="siemianowice-slaskie">Siemianowice \u015al\u0105skie</option> -<option value="sosnowiec">Sosnowiec</option> -<option value="swietochlowice">\u015awi\u0119toch\u0142owice</option> -<option value="tychy">Tychy</option> -<option value="zabrze">Zabrze</option> -<option value="zory">\u017bory</option> -<option value="bedzinski">b\u0119dzi\u0144ski</option> -<option value="bielski">bielski</option> -<option value="bierunsko-ledzinski">bieru\u0144sko-l\u0119dzi\u0144ski</option> -<option value="cieszynski">cieszy\u0144ski</option> -<option value="czestochowski">cz\u0119stochowski</option> -<option value="gliwicki">gliwicki</option> -<option value="klobucki">k\u0142obucki</option> -<option value="lubliniecki">lubliniecki</option> -<option value="mikolowski">miko\u0142owski</option> -<option value="myszkowski">myszkowski</option> -<option value="pszczynski">pszczy\u0144ski</option> -<option value="raciborski">raciborski</option> -<option value="rybnicki">rybnicki</option> -<option value="tarnogorski">tarnog\xf3rski</option> -<option value="wodzislawski">wodzis\u0142awski</option> -<option value="zawiercianski">zawiercia\u0144ski</option> -<option value="zywiecki">\u017cywiecki</option> -<option value="kielce">Kielce</option> -<option value="buski">buski</option> -<option value="jedrzejowski">j\u0119drzejowski</option> -<option value="kazimierski">kazimierski</option> -<option value="kielecki">kielecki</option> -<option value="konecki">konecki</option> -<option value="opatowski">opatowski</option> -<option value="ostrowiecki">ostrowiecki</option> -<option value="pinczowski">pi\u0144czowski</option> -<option value="sandomierski">sandomierski</option> -<option value="skarzyski">skar\u017cyski</option> -<option value="starachowicki">starachowicki</option> -<option value="staszowski">staszowski</option> -<option value="wloszczowski">w\u0142oszczowski</option> -<option value="olsztyn">Olsztyn</option> -<option value="elblag">Elbl\u0105g</option> -<option value="bartoszycki">bartoszycki</option> -<option value="braniewski">braniewski</option> -<option value="dzialdowski">dzia\u0142dowski</option> -<option value="elblaski">elbl\u0105ski</option> -<option value="elcki">e\u0142cki</option> -<option value="gizycki">gi\u017cycki</option> -<option value="goldapski">go\u0142dapski</option> -<option value="ilawski">i\u0142awski</option> -<option value="ketrzynski">k\u0119trzy\u0144ski</option> -<option value="lidzbarski">lidzbarski</option> -<option value="mragowski">mr\u0105gowski</option> -<option value="nidzicki">nidzicki</option> -<option value="nowomiejski">nowomiejski</option> -<option value="olecki">olecki</option> -<option value="olsztynski">olszty\u0144ski</option> -<option value="ostrodzki">ostr\xf3dzki</option> -<option value="piski">piski</option> -<option value="szczycienski">szczycie\u0144ski</option> -<option value="wegorzewski">w\u0119gorzewski</option> -<option value="poznan">Pozna\u0144</option> -<option value="kalisz">Kalisz</option> -<option value="konin">Konin</option> -<option value="leszno">Leszno</option> -<option value="chodzieski">chodziejski</option> -<option value="czarnkowsko-trzcianecki">czarnkowsko-trzcianecki</option> -<option value="gnieznienski">gnie\u017anie\u0144ski</option> -<option value="gostynski">gosty\u0144ski</option> -<option value="grodziski">grodziski</option> -<option value="jarocinski">jaroci\u0144ski</option> -<option value="kaliski">kaliski</option> -<option value="kepinski">k\u0119pi\u0144ski</option> -<option value="kolski">kolski</option> -<option value="koninski">koni\u0144ski</option> -<option value="koscianski">ko\u015bcia\u0144ski</option> -<option value="krotoszynski">krotoszy\u0144ski</option> -<option value="leszczynski">leszczy\u0144ski</option> -<option value="miedzychodzki">mi\u0119dzychodzki</option> -<option value="nowotomyski">nowotomyski</option> -<option value="obornicki">obornicki</option> -<option value="ostrowski">ostrowski</option> -<option value="ostrzeszowski">ostrzeszowski</option> -<option value="pilski">pilski</option> -<option value="pleszewski">pleszewski</option> -<option value="poznanski">pozna\u0144ski</option> -<option value="rawicki">rawicki</option> -<option value="slupecki">s\u0142upecki</option> -<option value="szamotulski">szamotulski</option> -<option value="sredzki">\u015bredzki</option> -<option value="sremski">\u015bremski</option> -<option value="turecki">turecki</option> -<option value="wagrowiecki">w\u0105growiecki</option> -<option value="wolsztynski">wolszty\u0144ski</option> -<option value="wrzesinski">wrzesi\u0144ski</option> -<option value="zlotowski">z\u0142otowski</option> -<option value="bialogardzki">bia\u0142ogardzki</option> -<option value="choszczenski">choszcze\u0144ski</option> -<option value="drawski">drawski</option> -<option value="goleniowski">goleniowski</option> -<option value="gryficki">gryficki</option> -<option value="gryfinski">gryfi\u0144ski</option> -<option value="kamienski">kamie\u0144ski</option> -<option value="kolobrzeski">ko\u0142obrzeski</option> -<option value="koszalinski">koszali\u0144ski</option> -<option value="lobeski">\u0142obeski</option> -<option value="mysliborski">my\u015bliborski</option> -<option value="policki">policki</option> -<option value="pyrzycki">pyrzycki</option> -<option value="slawienski">s\u0142awie\u0144ski</option> -<option value="stargardzki">stargardzki</option> -<option value="szczecinecki">szczecinecki</option> -<option value="swidwinski">\u015bwidwi\u0144ski</option> -<option value="walecki">wa\u0142ecki</option> -</select>''' - self.assertHTMLEqual(f.render('administrativeunit', 'katowice'), out) - - def test_PLPostalCodeField(self): - error_format = ['Enter a postal code in the format XX-XXX.'] - valid = { - '41-403': '41-403', - } - invalid = { - '43--434': error_format, - } - self.assertFieldOutput(PLPostalCodeField, valid, invalid) - - def test_PLNIPField(self): - error_format = ['Enter a tax number field (NIP) in the format XXX-XXX-XX-XX, XXX-XX-XX-XXX or XXXXXXXXXX.'] - error_checksum = ['Wrong checksum for the Tax Number (NIP).'] - valid = { - '646-241-41-24': '6462414124', - '646-24-14-124': '6462414124', - '6462414124': '6462414124', - } - invalid = { - '43-343-234-323': error_format, - '64-62-414-124': error_format, - '646-241-41-23': error_checksum, - } - self.assertFieldOutput(PLNIPField, valid, invalid) - - def test_PLPESELField(self): - error_checksum = ['Wrong checksum for the National Identification Number.'] - error_format = ['National Identification Number consists of 11 digits.'] - valid = { - '80071610614': '80071610614', - } - invalid = { - '80071610610': error_checksum, - '80': error_format, - '800716106AA': error_format, - } - self.assertFieldOutput(PLPESELField, valid, invalid) - - def test_PLNationalIDCardNumberField(self): - error_checksum = ['Wrong checksum for the National ID Card Number.'] - error_format = ['National ID Card Number consists of 3 letters and 6 digits.'] - valid = { - 'ABC123458': 'ABC123458', - 'abc123458': 'ABC123458', - } - invalid = { - 'ABC123457': error_checksum, - 'abc123457': error_checksum, - 'a12Aaaaaa': error_format, - 'AA1234443': error_format, - } - self.assertFieldOutput(PLNationalIDCardNumberField, valid, invalid) - - def test_PLREGONField(self): - error_checksum = ['Wrong checksum for the National Business Register Number (REGON).'] - error_format = ['National Business Register Number (REGON) consists of 9 or 14 digits.'] - valid = { - '12345678512347': '12345678512347', - '590096454': '590096454', - } - invalid = { - '123456784': error_checksum, - '12345678412342': error_checksum, - '590096453': error_checksum, - '590096': error_format, - } - self.assertFieldOutput(PLREGONField, valid, invalid) diff --git a/tests/regressiontests/localflavor/pt/__init__.py b/tests/regressiontests/localflavor/pt/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/pt/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/pt/tests.py b/tests/regressiontests/localflavor/pt/tests.py deleted file mode 100644 index 051e78084b..0000000000 --- a/tests/regressiontests/localflavor/pt/tests.py +++ /dev/null @@ -1,33 +0,0 @@ -from __future__ import unicode_literals - -from django.contrib.localflavor.pt.forms import PTZipCodeField, PTPhoneNumberField - -from django.test import SimpleTestCase - - -class PTLocalFlavorTests(SimpleTestCase): - def test_PTZipCodeField(self): - error_format = ['Enter a zip code in the format XXXX-XXX.'] - valid = { - '3030-034': '3030-034', - '1003456': '1003-456', - } - invalid = { - '2A200': error_format, - '980001': error_format, - } - self.assertFieldOutput(PTZipCodeField, valid, invalid) - - def test_PTPhoneNumberField(self): - error_format = ['Phone numbers must have 9 digits, or start by + or 00.'] - valid = { - '917845189': '917845189', - '91 784 5189': '917845189', - '+351 91 111': '+35191111', - '00351873': '00351873', - } - invalid = { - '91 784 51 8': error_format, - '091 456 987 1': error_format, - } - self.assertFieldOutput(PTPhoneNumberField, valid, invalid) diff --git a/tests/regressiontests/localflavor/py/__init__.py b/tests/regressiontests/localflavor/py/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/py/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/py/tests.py b/tests/regressiontests/localflavor/py/tests.py deleted file mode 100644 index fb7836dc9a..0000000000 --- a/tests/regressiontests/localflavor/py/tests.py +++ /dev/null @@ -1,55 +0,0 @@ -from __future__ import unicode_literals - -from django.contrib.localflavor.py.forms import (PyDepartmentSelect, - PyNumberedDepartmentSelect) - -from django.test import SimpleTestCase - -class PYLocalFlavorTests(SimpleTestCase): - def test_PyDepartmentSelect(self): - py = PyDepartmentSelect() - out = '''<select name="department"> -<option value="AG">Alto Paraguay</option> -<option value="AA">Alto Paran\xe1</option> -<option value="AM">Amambay</option> -<option value="AS">Asunci\xf3n</option> -<option value="BQ">Boquer\xf3n</option> -<option value="CG">Caaguaz\xfa</option> -<option value="CZ">Caazap\xe1</option> -<option value="CY">Canindey\xfa</option> -<option value="CE">Central</option> -<option value="CN">Concepci\xf3n</option> -<option value="CR">Cordillera</option> -<option value="GU">Guair\xe1</option> -<option value="IT">Itap\xfaa</option> -<option value="MI">Misiones</option> -<option value="NE">\xd1eembuc\xfa</option> -<option value="PG">Paraguar\xed</option> -<option value="PH">Pdte. Hayes</option> -<option value="SP">San Pedro</option> -</select>''' - self.assertHTMLEqual(py.render('department', 'M'), out) - - def test_PyNumberedDepartmentSelect(self): - py = PyNumberedDepartmentSelect() - out = '''<select name="department"> -<option value="CN">I Concepci\xf3n</option> -<option value="SP">II San Pedro</option> -<option value="CR">III Cordillera</option> -<option value="GU">IV Guair\xe1</option> -<option value="CG">V Caaguaz\xfa</option> -<option value="CZ">VI Caazap\xe1</option> -<option value="IT">VII Itap\xfaa</option> -<option value="MI">VIII Misiones</option> -<option value="PG">IX Paraguar\xed</option> -<option value="AA">X Alto Paran\xe1</option> -<option value="CE">XI Central</option> -<option value="NE">XII \xd1eembuc\xfa</option> -<option value="AM" selected="selected">XIII Amambay</option> -<option value="CY">XIV Canindey\xfa</option> -<option value="PH">XV Pdte. Hayes</option> -<option value="AG">XVI Alto Paraguay</option> -<option value="BQ">XVII Boquer\xf3n</option> -<option value="AS">XVIII Asunci\xf3n</option> -</select>''' - self.assertHTMLEqual(py.render('department', 'AM'), out) diff --git a/tests/regressiontests/localflavor/ro/__init__.py b/tests/regressiontests/localflavor/ro/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/ro/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/ro/tests.py b/tests/regressiontests/localflavor/ro/tests.py deleted file mode 100644 index 2e63bdc619..0000000000 --- a/tests/regressiontests/localflavor/ro/tests.py +++ /dev/null @@ -1,144 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.contrib.localflavor.ro.forms import (ROCIFField, ROCNPField, - ROCountyField, ROCountySelect, ROIBANField, ROPhoneNumberField, - ROPostalCodeField) - -from django.test import SimpleTestCase - - -class ROLocalFlavorTests(SimpleTestCase): - def test_ROCountySelect(self): - f = ROCountySelect() - out = '''<select name="county"> -<option value="AB">Alba</option> -<option value="AR">Arad</option> -<option value="AG">Arge\u015f</option> -<option value="BC">Bac\u0103u</option> -<option value="BH">Bihor</option> -<option value="BN">Bistri\u0163a-N\u0103s\u0103ud</option> -<option value="BT">Boto\u015fani</option> -<option value="BV">Bra\u015fov</option> -<option value="BR">Br\u0103ila</option> -<option value="B">Bucure\u015fti</option> -<option value="BZ">Buz\u0103u</option> -<option value="CS">Cara\u015f-Severin</option> -<option value="CL">C\u0103l\u0103ra\u015fi</option> -<option value="CJ" selected="selected">Cluj</option> -<option value="CT">Constan\u0163a</option> -<option value="CV">Covasna</option> -<option value="DB">D\xe2mbovi\u0163a</option> -<option value="DJ">Dolj</option> -<option value="GL">Gala\u0163i</option> -<option value="GR">Giurgiu</option> -<option value="GJ">Gorj</option> -<option value="HR">Harghita</option> -<option value="HD">Hunedoara</option> -<option value="IL">Ialomi\u0163a</option> -<option value="IS">Ia\u015fi</option> -<option value="IF">Ilfov</option> -<option value="MM">Maramure\u015f</option> -<option value="MH">Mehedin\u0163i</option> -<option value="MS">Mure\u015f</option> -<option value="NT">Neam\u0163</option> -<option value="OT">Olt</option> -<option value="PH">Prahova</option> -<option value="SM">Satu Mare</option> -<option value="SJ">S\u0103laj</option> -<option value="SB">Sibiu</option> -<option value="SV">Suceava</option> -<option value="TR">Teleorman</option> -<option value="TM">Timi\u015f</option> -<option value="TL">Tulcea</option> -<option value="VS">Vaslui</option> -<option value="VL">V\xe2lcea</option> -<option value="VN">Vrancea</option> -</select>''' - self.assertHTMLEqual(f.render('county', 'CJ'), out) - - def test_ROCIFField(self): - error_invalid = ['Enter a valid CIF.'] - error_atmost = ['Ensure this value has at most 10 characters (it has 11).'] - error_atleast = ['Ensure this value has at least 2 characters (it has 1).'] - valid = { - '21694681': '21694681', - 'RO21694681': '21694681', - } - invalid = { - '21694680': error_invalid, - '21694680000': error_atmost, - '0': error_atleast + error_invalid, - } - self.assertFieldOutput(ROCIFField, valid, invalid) - - def test_ROCNPField(self): - error_invalid = ['Enter a valid CNP.'] - error_atleast = ['Ensure this value has at least 13 characters (it has 10).'] - error_atmost = ['Ensure this value has at most 13 characters (it has 14).'] - valid = { - '1981211204489': '1981211204489', - } - invalid = { - '1981211204487': error_invalid, - '1981232204489': error_invalid, - '9981211204489': error_invalid, - '9981211209': error_atleast + error_invalid, - '19812112044891': error_atmost, - } - self.assertFieldOutput(ROCNPField, valid, invalid) - - def test_ROCountyField(self): - error_format = ['Enter a Romanian county code or name.'] - valid = { - 'CJ': 'CJ', - 'cj': 'CJ', - 'Argeş': 'AG', - 'argeş': 'AG', - } - invalid = { - 'Arges': error_format, - } - self.assertFieldOutput(ROCountyField, valid, invalid) - - def test_ROIBANField(self): - error_invalid = ['Enter a valid IBAN in ROXX-XXXX-XXXX-XXXX-XXXX-XXXX format'] - error_atleast = ['Ensure this value has at least 24 characters (it has 23).'] - valid = { - 'RO56RZBR0000060003291177': 'RO56RZBR0000060003291177', - 'RO56-RZBR-0000-0600-0329-1177': 'RO56RZBR0000060003291177', - } - invalid = { - 'RO56RZBR0000060003291176': error_invalid, - 'AT61 1904 3002 3457 3201': error_invalid, - 'RO56RZBR000006000329117': error_atleast + error_invalid, - } - self.assertFieldOutput(ROIBANField, valid, invalid) - - def test_ROPhoneNumberField(self): - error_format = ['Phone numbers must be in XXXX-XXXXXX format.'] - error_atleast = ['Ensure this value has at least 10 characters (it has 9).'] - error_invalid = ['Phone numbers must be in XXXX-XXXXXX format.'] - valid = { - '0264485936': '0264485936', - '(0264)-485936': '0264485936', - } - invalid = { - '02644859368': error_format, - '026448593': error_atleast + error_invalid, - } - self.assertFieldOutput(ROPhoneNumberField, valid, invalid) - - def test_ROPostalCodeField(self): - error_atleast = ['Ensure this value has at least 6 characters (it has 5).'] - error_atmost = ['Ensure this value has at most 6 characters (it has 7).'] - error_invalid = ['Enter a valid postal code in the format XXXXXX'] - - valid = { - '400473': '400473', - } - invalid = { - '40047': error_atleast + error_invalid, - '4004731': error_atmost + error_invalid, - } - self.assertFieldOutput(ROPostalCodeField, valid, invalid) diff --git a/tests/regressiontests/localflavor/ru/__init__.py b/tests/regressiontests/localflavor/ru/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/ru/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/ru/tests.py b/tests/regressiontests/localflavor/ru/tests.py deleted file mode 100644 index 758c5ae7d8..0000000000 --- a/tests/regressiontests/localflavor/ru/tests.py +++ /dev/null @@ -1,150 +0,0 @@ -from __future__ import unicode_literals - -from django.contrib.localflavor.ru.forms import * - -from django.test import SimpleTestCase - - -class RULocalFlavorTests(SimpleTestCase): - - def test_RUPassportNumberField(self): - error = ['Enter a passport number in the format XXXX XXXXXX.'] - valid = { - '1981 211204': '1981 211204', - '0305 967876': '0305 967876', - } - invalid = { - '1981 2112044': error, - '1981 23220': error, - '9981211201': error, - } - self.assertFieldOutput(RUPassportNumberField, valid, invalid) - - def test_RUAlienPassportNumberField(self): - error = ['Enter a passport number in the format XX XXXXXXX.'] - valid = { - '19 8111204': '19 8111204', - '03 0567876': '03 0567876', - } - invalid = { - '198 1112044': error, - '19 81123220': error, - '99 812112': error, - } - self.assertFieldOutput(RUAlienPassportNumberField, valid, invalid) - - def test_RUPostalCodeField(self): - error = ['Enter a postal code in the format XXXXXX.'] - valid = { - '987654': '987654', - '123456': '123456' - } - invalid = { - '123 34': error, - '1234567': error, - '12345': error - } - self.assertFieldOutput(RUPostalCodeField, valid, invalid) - - def test_RUCountySelect(self): - f = RUCountySelect() - out = '''<select name="county"> -<option value="Central Federal County">Central Federal County</option> -<option value="South Federal County">South Federal County</option> -<option value="North-West Federal County">North-West Federal County</option> -<option value="Far-East Federal County">Far-East Federal County</option> -<option value="Siberian Federal County">Siberian Federal County</option> -<option value="Ural Federal County">Ural Federal County</option> -<option value="Privolzhsky Federal County">Privolzhsky Federal County</option> -<option value="North-Caucasian Federal County">North-Caucasian Federal County</option> -</select>''' - self.assertHTMLEqual(f.render('county', None), out) - - def test_RURegionSelect(self): - f = RURegionSelect() - out = '''<select name="region"> -<option value="77">Moskva</option> -<option value="78">Saint-Peterburg</option> -<option value="50">Moskovskaya oblast'</option> -<option value="01">Adygeya, Respublika</option> -<option value="02">Bashkortostan, Respublika</option> -<option value="03">Buryatia, Respublika</option> -<option value="04">Altay, Respublika</option> -<option value="05">Dagestan, Respublika</option> -<option value="06">Ingushskaya Respublika</option> -<option value="07">Kabardino-Balkarskaya Respublika</option> -<option value="08">Kalmykia, Respublika</option> -<option value="09">Karachaevo-Cherkesskaya Respublika</option> -<option value="10">Karelia, Respublika</option> -<option value="11">Komi, Respublika</option> -<option value="12">Mariy Ehl, Respublika</option> -<option value="13">Mordovia, Respublika</option> -<option value="14">Sakha, Respublika (Yakutiya)</option> -<option value="15">Severnaya Osetia, Respublika (Alania)</option> -<option value="16">Tatarstan, Respublika</option> -<option value="17">Tyva, Respublika (Tuva)</option> -<option value="18">Udmurtskaya Respublika</option> -<option value="19">Khakassiya, Respublika</option> -<option value="95">Chechenskaya Respublika</option> -<option value="21">Chuvashskaya Respublika</option> -<option value="22">Altayskiy Kray</option> -<option value="80">Zabaykalskiy Kray</option> -<option value="82">Kamchatskiy Kray</option> -<option value="23">Krasnodarskiy Kray</option> -<option value="24">Krasnoyarskiy Kray</option> -<option value="81">Permskiy Kray</option> -<option value="25">Primorskiy Kray</option> -<option value="26">Stavropol'siyy Kray</option> -<option value="27">Khabarovskiy Kray</option> -<option value="28">Amurskaya oblast'</option> -<option value="29">Arkhangel'skaya oblast'</option> -<option value="30">Astrakhanskaya oblast'</option> -<option value="31">Belgorodskaya oblast'</option> -<option value="32">Bryanskaya oblast'</option> -<option value="33">Vladimirskaya oblast'</option> -<option value="34">Volgogradskaya oblast'</option> -<option value="35">Vologodskaya oblast'</option> -<option value="36">Voronezhskaya oblast'</option> -<option value="37">Ivanovskaya oblast'</option> -<option value="38">Irkutskaya oblast'</option> -<option value="39">Kaliningradskaya oblast'</option> -<option value="40">Kaluzhskaya oblast'</option> -<option value="42">Kemerovskaya oblast'</option> -<option value="43">Kirovskaya oblast'</option> -<option value="44">Kostromskaya oblast'</option> -<option value="45">Kurganskaya oblast'</option> -<option value="46">Kurskaya oblast'</option> -<option value="47">Leningradskaya oblast'</option> -<option value="48">Lipeckaya oblast'</option> -<option value="49">Magadanskaya oblast'</option> -<option value="51">Murmanskaya oblast'</option> -<option value="52">Nizhegorodskaja oblast'</option> -<option value="53">Novgorodskaya oblast'</option> -<option value="54">Novosibirskaya oblast'</option> -<option value="55">Omskaya oblast'</option> -<option value="56">Orenburgskaya oblast'</option> -<option value="57">Orlovskaya oblast'</option> -<option value="58">Penzenskaya oblast'</option> -<option value="60">Pskovskaya oblast'</option> -<option value="61">Rostovskaya oblast'</option> -<option value="62">Rjazanskaya oblast'</option> -<option value="63">Samarskaya oblast'</option> -<option value="64">Saratovskaya oblast'</option> -<option value="65">Sakhalinskaya oblast'</option> -<option value="66">Sverdlovskaya oblast'</option> -<option value="67" selected="selected">Smolenskaya oblast'</option> -<option value="68">Tambovskaya oblast'</option> -<option value="69">Tverskaya oblast'</option> -<option value="70">Tomskaya oblast'</option> -<option value="71">Tul'skaya oblast'</option> -<option value="72">Tyumenskaya oblast'</option> -<option value="73">Ul'ianovskaya oblast'</option> -<option value="74">Chelyabinskaya oblast'</option> -<option value="76">Yaroslavskaya oblast'</option> -<option value="79">Evreyskaya avtonomnaja oblast'</option> -<option value="83">Neneckiy autonomnyy okrug</option> -<option value="86">Khanty-Mansiyskiy avtonomnyy okrug - Yugra</option> -<option value="87">Chukotskiy avtonomnyy okrug</option> -<option value="89">Yamalo-Neneckiy avtonomnyy okrug</option> -</select>''' - self.assertHTMLEqual(f.render('region', '67'), out) diff --git a/tests/regressiontests/localflavor/se/__init__.py b/tests/regressiontests/localflavor/se/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/se/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/se/tests.py b/tests/regressiontests/localflavor/se/tests.py deleted file mode 100644 index f61c61e9d4..0000000000 --- a/tests/regressiontests/localflavor/se/tests.py +++ /dev/null @@ -1,166 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.contrib.localflavor.se.forms import (SECountySelect, - SEOrganisationNumberField, SEPersonalIdentityNumberField, - SEPostalCodeField) -import datetime - -from django.test import SimpleTestCase - - -class SELocalFlavorTests(SimpleTestCase): - - def setUp(self): - # Mocking datetime.date to make sure - # localflavor.se.utils.validate_id_birthday works - class MockDate(datetime.date): - def today(cls): - return datetime.date(2008, 5, 14) - today = classmethod(today) - self._olddate = datetime.date - datetime.date = MockDate - - def tearDown(self): - datetime.date = self._olddate - - def test_SECountySelect(self): - f = SECountySelect() - out = '''<select name="swedish_county"> -<option value="AB">Stockholm</option> -<option value="AC">V\xe4sterbotten</option> -<option value="BD">Norrbotten</option> -<option value="C">Uppsala</option> -<option value="D">S\xf6dermanland</option> -<option value="E" selected="selected">\xd6sterg\xf6tland</option> -<option value="F">J\xf6nk\xf6ping</option> -<option value="G">Kronoberg</option> -<option value="H">Kalmar</option> -<option value="I">Gotland</option> -<option value="K">Blekinge</option> -<option value="M">Sk\xe5ne</option> -<option value="N">Halland</option> -<option value="O">V\xe4stra G\xf6taland</option> -<option value="S">V\xe4rmland</option> -<option value="T">\xd6rebro</option> -<option value="U">V\xe4stmanland</option> -<option value="W">Dalarna</option> -<option value="X">G\xe4vleborg</option> -<option value="Y">V\xe4sternorrland</option> -<option value="Z">J\xe4mtland</option> -</select>''' - self.assertHTMLEqual(f.render('swedish_county', 'E'), out) - - def test_SEOrganizationNumberField(self): - error_invalid = ['Enter a valid Swedish organisation number.'] - valid = { - '870512-1989': '198705121989', - '19870512-1989': '198705121989', - '870512-2128': '198705122128', - '081015-6315': '190810156315', - '081015+6315': '180810156315', - '0810156315': '190810156315', - # Test some different organisation numbers - # IKEA Linköping - '556074-7569': '5560747569', - # Volvo Personvagnar - '556074-3089': '5560743089', - # LJS (organisation) - '822001-5476': '8220015476', - # LJS (organisation) - '8220015476': '8220015476', - # Katedralskolan Linköping (school) - '2120000449': '2120000449', - # Faux organisation number, which tests that the checksum can be 0 - '232518-5060': '2325185060', - } - invalid = { - # Ordinary personal identity numbers for sole proprietors - # The same rules as for SEPersonalIdentityField applies here - '081015 6315': error_invalid, - '950231-4496': error_invalid, - '6914104499': error_invalid, - '950d314496': error_invalid, - 'invalid!!!': error_invalid, - '870514-1111': error_invalid, - # Co-ordination number checking - # Co-ordination numbers are not valid organisation numbers - '870574-1315': error_invalid, - '870573-1311': error_invalid, - # Volvo Personvagnar, bad format - '556074+3089': error_invalid, - # Invalid checksum - '2120000441': error_invalid, - # Valid checksum but invalid organisation type - '1120000441': error_invalid, - } - self.assertFieldOutput(SEOrganisationNumberField, valid, invalid) - - def test_SEPersonalIdentityNumberField(self): - error_invalid = ['Enter a valid Swedish personal identity number.'] - error_coord = ['Co-ordination numbers are not allowed.'] - valid = { - '870512-1989': '198705121989', - '870512-2128': '198705122128', - '19870512-1989': '198705121989', - '198705121989': '198705121989', - '081015-6315': '190810156315', - '0810156315': '190810156315', - # This is a "special-case" in the checksum calculation, - # where the sum is divisible by 10 (the checksum digit == 0) - '8705141060': '198705141060', - # + means that the person is older than 100 years - '081015+6315': '180810156315', - # Co-ordination number checking - '870574-1315': '198705741315', - '870574+1315': '188705741315', - '198705741315': '198705741315', - } - invalid = { - '081015 6315': error_invalid, - '950d314496': error_invalid, - 'invalid!!!': error_invalid, - # Invalid dates - # February 31st does not exist - '950231-4496': error_invalid, - # Month 14 does not exist - '6914104499': error_invalid, - # There are no Swedish personal id numbers where year < 1800 - '17430309-7135': error_invalid, - # Invalid checksum - '870514-1111': error_invalid, - # Co-ordination number with bad checksum - '870573-1311': error_invalid, - } - self.assertFieldOutput(SEPersonalIdentityNumberField, valid, invalid) - - valid = {} - invalid = { - # Check valid co-ordination numbers that should not be accepted - # because of coordination_number=False - '870574-1315': error_coord, - '870574+1315': error_coord, - '8705741315': error_coord, - # Invalid co-ordination numbers should be treated as invalid, and not - # as co-ordination numbers - '870573-1311': error_invalid, - } - kwargs = {'coordination_number': False,} - self.assertFieldOutput(SEPersonalIdentityNumberField, valid, invalid, - field_kwargs=kwargs) - - def test_SEPostalCodeField(self): - error_format = ['Enter a Swedish postal code in the format XXXXX.'] - valid = { - '589 37': '58937', - '58937': '58937', - } - invalid = { - 'abcasfassadf': error_format, - # Only one space is allowed for separation - '589 37': error_format, - # The postal code must not start with 0 - '01234': error_format, - - } - self.assertFieldOutput(SEPostalCodeField, valid, invalid) diff --git a/tests/regressiontests/localflavor/si/__init__.py b/tests/regressiontests/localflavor/si/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/si/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/si/tests.py b/tests/regressiontests/localflavor/si/tests.py deleted file mode 100644 index 123683bff4..0000000000 --- a/tests/regressiontests/localflavor/si/tests.py +++ /dev/null @@ -1,557 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from datetime import date - -from django.contrib.localflavor.si.forms import (SIEMSOField, SITaxNumberField, - SIPhoneNumberField, SIPostalCodeField, SIPostalCodeSelect) -from django.test import SimpleTestCase - - -class SILocalFlavorTests(SimpleTestCase): - def test_SITaxNumberField(self): - error_invalid = ['Enter a valid tax number in form SIXXXXXXXX'] - valid = { - '15012557': '15012557', - 'SI15012557': '15012557', - '22111310': '22111310', - } - invalid = { - '22241310': error_invalid, - '15012558': error_invalid, - '1501': error_invalid, - '1501123123123': error_invalid, - 'abcdabcd': error_invalid, - '01234579': error_invalid, - } - self.assertFieldOutput(SITaxNumberField, valid, invalid) - - def test_SIEMSOField(self): - error_invalid = ['This field should contain exactly 13 digits.'] - error_invalid_date = ['The first 7 digits of the EMSO must represent a valid past date.'] - error_invalid_chksum = ['The EMSO is not valid.'] - valid = { - '0205951500462': '0205951500462', - '2309002500068': '2309002500068', - '1010985500400': '1010985500400', - } - invalid = { - '0205951500463': error_invalid_chksum, - '020': error_invalid, - '020020595150046020595150046': error_invalid, - 'aaaabbbbccccd': error_invalid, - '1010985500800': error_invalid_chksum, - '2020095500070': error_invalid_date, - '5050095500078': error_invalid_date, - '1010889500408': error_invalid_date, - } - self.assertFieldOutput(SIEMSOField, valid, invalid) - - def test_SIEMSOField_info_dict(self): - valid = { - '0205951500462': {'nationality': 50, 'gender': 'male', 'birthdate': date(1951, 5, 2)}, - '2309002504063': {'nationality': 50, 'gender': 'male', 'birthdate': date(2002, 9, 23)}, - '1010985505402': {'nationality': 50, 'gender': 'female', 'birthdate': date(1985, 10, 10)}, - } - for input, info in valid.items(): - f = SIEMSOField() - f.clean(input) - self.assertEqual(f.info, info) - - def test_SIPhoneNumberField(self): - error_invalid = ['Enter phone number in form +386XXXXXXXX or 0XXXXXXXX.'] - valid = { - '+38640999999': '40999999', - '+3861999999': '1999999', - '0038640999999': '40999999', - '040999999': '40999999', - '01999999': '1999999', - '059099999': '59099999', - '059 09 99 99': '59099999', - '0590/999-99': '59099999', - } - invalid = { - '03861999999': error_invalid, - '3861999999': error_invalid, - } - self.assertFieldOutput(SIPhoneNumberField, valid, invalid) - - def test_SIPostalCodeField(self): - valid = { - '4000': '4000', - '1000': '1000' - } - invalid = { - '1113': ['Select a valid choice. 1113 is not one of the available choices.'], - '111': ['Select a valid choice. 111 is not one of the available choices.'], - } - self.assertFieldOutput(SIPostalCodeField, valid, invalid) - - def test_SIPostalCodeSelect(self): - f = SIPostalCodeSelect() - out = '''<select name="Kranj"> -<option value="8341">Adle\u0161i\u010di</option> -<option value="5270">Ajdov\u0161\u010dina</option> -<option value="6280">Ankaran - Ancarano</option> -<option value="9253">Apa\u010de</option> -<option value="8253">Arti\u010de</option> -<option value="4275">Begunje na Gorenjskem</option> -<option value="1382">Begunje pri Cerknici</option> -<option value="9231">Beltinci</option> -<option value="2234">Benedikt</option> -<option value="2345">Bistrica ob Dravi</option> -<option value="3256">Bistrica ob Sotli</option> -<option value="8259">Bizeljsko</option> -<option value="1223">Blagovica</option> -<option value="8283">Blanca</option> -<option value="4260">Bled</option> -<option value="4273">Blejska Dobrava</option> -<option value="9265">Bodonci</option> -<option value="9222">Bogojina</option> -<option value="4263">Bohinjska Bela</option> -<option value="4264">Bohinjska Bistrica</option> -<option value="4265">Bohinjsko jezero</option> -<option value="1353">Borovnica</option> -<option value="5230">Bovec</option> -<option value="8294">Bo\u0161tanj</option> -<option value="5295">Branik</option> -<option value="3314">Braslov\u010de</option> -<option value="5223">Breginj</option> -<option value="8280">Brestanica</option> -<option value="2354">Bresternica</option> -<option value="4243">Brezje</option> -<option value="1351">Brezovica pri Ljubljani</option> -<option value="8250">Bre\u017eice</option> -<option value="4210">Brnik - aerodrom</option> -<option value="8321">Brusnice</option> -<option value="3255">Bu\u010de</option> -<option value="8276">Bu\u010dka</option> -<option value="9261">Cankova</option> -<option value="3000">Celje</option> -<option value="4207">Cerklje na Gorenjskem</option> -<option value="8263">Cerklje ob Krki</option> -<option value="1380">Cerknica</option> -<option value="5282">Cerkno</option> -<option value="2236">Cerkvenjak</option> -<option value="2215">Cer\u0161ak</option> -<option value="2326">Cirkovce</option> -<option value="2282">Cirkulane</option> -<option value="5273">Col</option> -<option value="6271">Dekani</option> -<option value="5210">Deskle</option> -<option value="2253">Destrnik</option> -<option value="6215">Diva\u010da</option> -<option value="1233">Dob</option> -<option value="3224">Dobje pri Planini</option> -<option value="8257">Dobova</option> -<option value="1423">Dobovec</option> -<option value="5263">Dobravlje</option> -<option value="3204">Dobrna</option> -<option value="8211">Dobrni\u010d</option> -<option value="1356">Dobrova</option> -<option value="9223">Dobrovnik - Dobronak</option> -<option value="5212">Dobrovo v Brdih</option> -<option value="1431">Dol pri Hrastniku</option> -<option value="1262">Dol pri Ljubljani</option> -<option value="1273">Dole pri Litiji</option> -<option value="1331">Dolenja vas</option> -<option value="8350">Dolenjske Toplice</option> -<option value="1230">Dom\u017eale</option> -<option value="2252">Dornava</option> -<option value="5294">Dornberk</option> -<option value="1319">Draga</option> -<option value="8343">Dragatu\u0161</option> -<option value="3222">Dramlje</option> -<option value="2370">Dravograd</option> -<option value="4203">Duplje</option> -<option value="6221">Dutovlje</option> -<option value="8361">Dvor</option> -<option value="2343">Fala</option> -<option value="9208">Fokovci</option> -<option value="2313">Fram</option> -<option value="3213">Frankolovo</option> -<option value="1274">Gabrovka</option> -<option value="8254">Globoko</option> -<option value="5275">Godovi\u010d</option> -<option value="4204">Golnik</option> -<option value="3303">Gomilsko</option> -<option value="4224">Gorenja vas</option> -<option value="3263">Gorica pri Slivnici</option> -<option value="2272">Gori\u0161nica</option> -<option value="9250">Gornja Radgona</option> -<option value="3342">Gornji Grad</option> -<option value="4282">Gozd Martuljek</option> -<option value="9264">Grad</option> -<option value="8332">Gradac</option> -<option value="1384">Grahovo</option> -<option value="5242">Grahovo ob Ba\u010di</option> -<option value="6272">Gra\u010di\u0161\u010de</option> -<option value="5251">Grgar</option> -<option value="3302">Gri\u017ee</option> -<option value="3231">Grobelno</option> -<option value="1290">Grosuplje</option> -<option value="2288">Hajdina</option> -<option value="8362">Hinje</option> -<option value="9205">Hodo\u0161 - Hodos</option> -<option value="1354">Horjul</option> -<option value="1372">Hotedr\u0161ica</option> -<option value="2311">Ho\u010de</option> -<option value="1430">Hrastnik</option> -<option value="6225">Hru\u0161evje</option> -<option value="4276">Hru\u0161ica</option> -<option value="5280">Idrija</option> -<option value="1292">Ig</option> -<option value="6250">Ilirska Bistrica</option> -<option value="6251">Ilirska Bistrica - Trnovo</option> -<option value="2259">Ivanjkovci</option> -<option value="1295">Ivan\u010dna Gorica</option> -<option value="1411">Izlake</option> -<option value="6310">Izola - Isola</option> -<option value="2222">Jakobski Dol</option> -<option value="2221">Jarenina</option> -<option value="6254">Jel\u0161ane</option> -<option value="4270">Jesenice</option> -<option value="8261">Jesenice na Dolenjskem</option> -<option value="3273">Jurklo\u0161ter</option> -<option value="2223">Jurovski Dol</option> -<option value="2256">Jur\u0161inci</option> -<option value="5214">Kal nad Kanalom</option> -<option value="3233">Kalobje</option> -<option value="4246">Kamna Gorica</option> -<option value="2351">Kamnica</option> -<option value="1241">Kamnik</option> -<option value="5213">Kanal</option> -<option value="8258">Kapele</option> -<option value="2362">Kapla</option> -<option value="2325">Kidri\u010devo</option> -<option value="1412">Kisovec</option> -<option value="6253">Kne\u017eak</option> -<option value="5222">Kobarid</option> -<option value="9227">Kobilje</option> -<option value="2276">Kog</option> -<option value="5211">Kojsko</option> -<option value="6223">Komen</option> -<option value="1218">Komenda</option> -<option value="6000">Koper</option> -<option value="8282">Koprivnica</option> -<option value="5296">Kostanjevica na Krasu</option> -<option value="8311">Kostanjevica na Krki</option> -<option value="1336">Kostel</option> -<option value="2394">Kotlje</option> -<option value="6240">Kozina</option> -<option value="3260">Kozje</option> -<option value="1330">Ko\u010devje</option> -<option value="1338">Ko\u010devska Reka</option> -<option value="6256">Ko\u0161ana</option> -<option value="4000" selected="selected">Kranj</option> -<option value="4280">Kranjska Gora</option> -<option value="1281">Kresnice</option> -<option value="4294">Kri\u017ee</option> -<option value="9206">Kri\u017eevci</option> -<option value="9242">Kri\u017eevci pri Ljutomeru</option> -<option value="1301">Krka</option> -<option value="8296">Krmelj</option> -<option value="4245">Kropa</option> -<option value="8262">Kr\u0161ka vas</option> -<option value="8270">Kr\u0161ko</option> -<option value="9263">Kuzma</option> -<option value="2318">Laporje</option> -<option value="1219">Laze v Tuhinju</option> -<option value="3270">La\u0161ko</option> -<option value="2230">Lenart v Slovenskih goricah</option> -<option value="9220">Lendava - Lendva</option> -<option value="4248">Lesce</option> -<option value="3261">Lesi\u010dno</option> -<option value="8273">Leskovec pri Kr\u0161kem</option> -<option value="2372">Libeli\u010de</option> -<option value="2341">Limbu\u0161</option> -<option value="1270">Litija</option> -<option value="3202">Ljube\u010dna</option> -<option value="1000">Ljubljana</option> -<option value="3333">Ljubno ob Savinji</option> -<option value="9240">Ljutomer</option> -<option value="5231">Log pod Mangartom</option> -<option value="1358">Log pri Brezovici</option> -<option value="1370">Logatec</option> -<option value="1434">Loka pri Zidanem Mostu</option> -<option value="3223">Loka pri \u017dusmu</option> -<option value="6219">Lokev</option> -<option value="2324">Lovrenc na Dravskem polju</option> -<option value="2344">Lovrenc na Pohorju</option> -<option value="3215">Lo\u010de</option> -<option value="1318">Lo\u0161ki Potok</option> -<option value="1225">Lukovica</option> -<option value="3334">Lu\u010de</option> -<option value="2322">Maj\u0161perk</option> -<option value="2321">Makole</option> -<option value="9243">Mala Nedelja</option> -<option value="2229">Male\u010dnik</option> -<option value="6273">Marezige</option> -<option value="2000">Maribor</option> -<option value="2206">Marjeta na Dravskem polju</option> -<option value="2281">Markovci</option> -<option value="9221">Martjanci</option> -<option value="6242">Materija</option> -<option value="4211">Mav\u010di\u010de</option> -<option value="9202">Ma\u010dkovci</option> -<option value="1215">Medvode</option> -<option value="1234">Menge\u0161</option> -<option value="8330">Metlika</option> -<option value="2392">Me\u017eica</option> -<option value="2204">Miklav\u017e na Dravskem polju</option> -<option value="2275">Miklav\u017e pri Ormo\u017eu</option> -<option value="5291">Miren</option> -<option value="8233">Mirna</option> -<option value="8216">Mirna Pe\u010d</option> -<option value="2382">Mislinja</option> -<option value="4281">Mojstrana</option> -<option value="8230">Mokronog</option> -<option value="9226">Moravske Toplice</option> -<option value="1251">Morav\u010de</option> -<option value="5216">Most na So\u010di</option> -<option value="1221">Motnik</option> -<option value="3330">Mozirje</option> -<option value="9000">Murska Sobota</option> -<option value="2366">Muta</option> -<option value="4202">Naklo</option> -<option value="3331">Nazarje</option> -<option value="1357">Notranje Gorice</option> -<option value="3203">Nova Cerkev</option> -<option value="5000">Nova Gorica</option> -<option value="1385">Nova vas</option> -<option value="8000">Novo mesto</option> -<option value="6243">Obrov</option> -<option value="9233">Odranci</option> -<option value="2317">Oplotnica</option> -<option value="2312">Orehova vas</option> -<option value="2270">Ormo\u017e</option> -<option value="1316">Ortnek</option> -<option value="1337">Osilnica</option> -<option value="8222">Oto\u010dec</option> -<option value="2361">O\u017ebalt</option> -<option value="2231">Pernica</option> -<option value="2211">Pesnica pri Mariboru</option> -<option value="9203">Petrovci</option> -<option value="3301">Petrov\u010de</option> -<option value="6330">Piran - Pirano</option> -<option value="6257">Pivka</option> -<option value="8255">Pi\u0161ece</option> -<option value="6232">Planina</option> -<option value="3225">Planina pri Sevnici</option> -<option value="6276">Pobegi</option> -<option value="8312">Podbo\u010dje</option> -<option value="5243">Podbrdo</option> -<option value="2273">Podgorci</option> -<option value="6216">Podgorje</option> -<option value="2381">Podgorje pri Slovenj Gradcu</option> -<option value="6244">Podgrad</option> -<option value="1414">Podkum</option> -<option value="2286">Podlehnik</option> -<option value="5272">Podnanos</option> -<option value="4244">Podnart</option> -<option value="3241">Podplat</option> -<option value="3257">Podsreda</option> -<option value="2363">Podvelka</option> -<option value="3254">Pod\u010detrtek</option> -<option value="2208">Pohorje</option> -<option value="2257">Polen\u0161ak</option> -<option value="1355">Polhov Gradec</option> -<option value="4223">Poljane nad \u0160kofjo Loko</option> -<option value="2319">Polj\u010dane</option> -<option value="3313">Polzela</option> -<option value="1272">Pol\u0161nik</option> -<option value="3232">Ponikva</option> -<option value="6320">Portoro\u017e - Portorose</option> -<option value="6230">Postojna</option> -<option value="2331">Pragersko</option> -<option value="3312">Prebold</option> -<option value="4205">Preddvor</option> -<option value="6255">Prem</option> -<option value="1352">Preserje</option> -<option value="6258">Prestranek</option> -<option value="2391">Prevalje</option> -<option value="3262">Prevorje</option> -<option value="1276">Primskovo</option> -<option value="3253">Pristava pri Mestinju</option> -<option value="9207">Prosenjakovci - Partosfalva</option> -<option value="5297">Prva\u010dina</option> -<option value="2250">Ptuj</option> -<option value="2323">Ptujska Gora</option> -<option value="9201">Puconci</option> -<option value="9252">Radenci</option> -<option value="1433">Rade\u010de</option> -<option value="2360">Radlje ob Dravi</option> -<option value="1235">Radomlje</option> -<option value="4240">Radovljica</option> -<option value="8274">Raka</option> -<option value="1381">Rakek</option> -<option value="4283">Rate\u010de - Planica</option> -<option value="2390">Ravne na Koro\u0161kem</option> -<option value="2327">Ra\u010de</option> -<option value="5292">Ren\u010de</option> -<option value="3332">Re\u010dica ob Savinji</option> -<option value="1310">Ribnica</option> -<option value="2364">Ribnica na Pohorju</option> -<option value="3272">Rimske Toplice</option> -<option value="1314">Rob</option> -<option value="3252">Rogatec</option> -<option value="3250">Roga\u0161ka Slatina</option> -<option value="9262">Roga\u0161ovci</option> -<option value="1373">Rovte</option> -<option value="5215">Ro\u010dinj</option> -<option value="2342">Ru\u0161e</option> -<option value="1282">Sava</option> -<option value="4227">Selca</option> -<option value="2352">Selnica ob Dravi</option> -<option value="8333">Semi\u010d</option> -<option value="8281">Senovo</option> -<option value="6224">Seno\u017ee\u010de</option> -<option value="8290">Sevnica</option> -<option value="6333">Se\u010dovlje - Sicciole</option> -<option value="6210">Se\u017eana</option> -<option value="2214">Sladki vrh</option> -<option value="5283">Slap ob Idrijci</option> -<option value="2380">Slovenj Gradec</option> -<option value="2310">Slovenska Bistrica</option> -<option value="3210">Slovenske Konjice</option> -<option value="1216">Smlednik</option> -<option value="1317">Sodra\u017eica</option> -<option value="5250">Solkan</option> -<option value="3335">Sol\u010dava</option> -<option value="4229">Sorica</option> -<option value="4225">Sovodenj</option> -<option value="5232">So\u010da</option> -<option value="5281">Spodnja Idrija</option> -<option value="2241">Spodnji Duplek</option> -<option value="9245">Spodnji Ivanjci</option> -<option value="2277">Sredi\u0161\u010de ob Dravi</option> -<option value="4267">Srednja vas v Bohinju</option> -<option value="8256">Sromlje</option> -<option value="5224">Srpenica</option> -<option value="1242">Stahovica</option> -<option value="1332">Stara Cerkev</option> -<option value="8342">Stari trg ob Kolpi</option> -<option value="1386">Stari trg pri Lo\u017eu</option> -<option value="2205">Star\u0161e</option> -<option value="2289">Stoperce</option> -<option value="8322">Stopi\u010de</option> -<option value="3206">Stranice</option> -<option value="8351">Stra\u017ea</option> -<option value="1313">Struge</option> -<option value="8293">Studenec</option> -<option value="8331">Suhor</option> -<option value="2353">Sv. Duh na Ostrem Vrhu</option> -<option value="2233">Sveta Ana v Slovenskih goricah</option> -<option value="2235">Sveta Trojica v Slovenskih goricah</option> -<option value="9244">Sveti Jurij ob \u0160\u010davnici</option> -<option value="2258">Sveti Toma\u017e</option> -<option value="3264">Sveti \u0160tefan</option> -<option value="3304">Tabor</option> -<option value="3221">Teharje</option> -<option value="9251">Ti\u0161ina</option> -<option value="5220">Tolmin</option> -<option value="3326">Topol\u0161ica</option> -<option value="2371">Trbonje</option> -<option value="1420">Trbovlje</option> -<option value="8231">Trebelno</option> -<option value="8210">Trebnje</option> -<option value="5252">Trnovo pri Gorici</option> -<option value="2254">Trnovska vas</option> -<option value="1222">Trojane</option> -<option value="1236">Trzin</option> -<option value="4290">Tr\u017ei\u010d</option> -<option value="8295">Tr\u017ei\u0161\u010de</option> -<option value="1311">Turjak</option> -<option value="9224">Turni\u0161\u010de</option> -<option value="8323">Ur\u0161na sela</option> -<option value="1252">Va\u010de</option> -<option value="3320">Velenje - dostava</option> -<option value="3322">Velenje - po\u0161tni predali</option> -<option value="8212">Velika Loka</option> -<option value="2274">Velika Nedelja</option> -<option value="9225">Velika Polana</option> -<option value="1315">Velike La\u0161\u010de</option> -<option value="8213">Veliki Gaber</option> -<option value="9241">Ver\u017eej</option> -<option value="1312">Videm - Dobrepolje</option> -<option value="2284">Videm pri Ptuju</option> -<option value="8344">Vinica pri \u010crnomlju</option> -<option value="5271">Vipava</option> -<option value="4212">Visoko</option> -<option value="3205">Vitanje</option> -<option value="2255">Vitomarci</option> -<option value="1294">Vi\u0161nja Gora</option> -<option value="1217">Vodice</option> -<option value="3212">Vojnik</option> -<option value="2232">Voli\u010dina</option> -<option value="5293">Vol\u010dja Draga</option> -<option value="3305">Vransko</option> -<option value="6217">Vremski Britof</option> -<option value="1360">Vrhnika</option> -<option value="2365">Vuhred</option> -<option value="2367">Vuzenica</option> -<option value="8292">Zabukovje</option> -<option value="1410">Zagorje ob Savi</option> -<option value="1303">Zagradec</option> -<option value="2283">Zavr\u010d</option> -<option value="8272">Zdole</option> -<option value="4201">Zgornja Besnica</option> -<option value="2242">Zgornja Korena</option> -<option value="2201">Zgornja Kungota</option> -<option value="2316">Zgornja Lo\u017enica</option> -<option value="2314">Zgornja Polskava</option> -<option value="2213">Zgornja Velka</option> -<option value="4247">Zgornje Gorje</option> -<option value="4206">Zgornje Jezersko</option> -<option value="2285">Zgornji Leskovec</option> -<option value="1432">Zidani Most</option> -<option value="3214">Zre\u010de</option> -<option value="8251">\u010cate\u017e ob Savi</option> -<option value="1413">\u010cem\u0161enik</option> -<option value="5253">\u010cepovan</option> -<option value="9232">\u010cren\u0161ovci</option> -<option value="2393">\u010crna na Koro\u0161kem</option> -<option value="6275">\u010crni Kal</option> -<option value="5274">\u010crni Vrh nad Idrijo</option> -<option value="5262">\u010crni\u010de</option> -<option value="8340">\u010crnomelj</option> -<option value="9204">\u0160alovci</option> -<option value="5261">\u0160empas</option> -<option value="5290">\u0160empeter pri Gorici</option> -<option value="3311">\u0160empeter v Savinjski dolini</option> -<option value="2212">\u0160entilj v Slovenskih goricah</option> -<option value="8297">\u0160entjan\u017e</option> -<option value="2373">\u0160entjan\u017e pri Dravogradu</option> -<option value="8310">\u0160entjernej</option> -<option value="3230">\u0160entjur</option> -<option value="3271">\u0160entrupert</option> -<option value="8232">\u0160entrupert</option> -<option value="1296">\u0160entvid pri Sti\u010dni</option> -<option value="4208">\u0160en\u010dur</option> -<option value="8275">\u0160kocjan</option> -<option value="6281">\u0160kofije</option> -<option value="4220">\u0160kofja Loka</option> -<option value="3211">\u0160kofja vas</option> -<option value="1291">\u0160kofljica</option> -<option value="6274">\u0160marje</option> -<option value="1293">\u0160marje - Sap</option> -<option value="3240">\u0160marje pri Jel\u0161ah</option> -<option value="8220">\u0160marje\u0161ke Toplice</option> -<option value="2315">\u0160martno na Pohorju</option> -<option value="3341">\u0160martno ob Dreti</option> -<option value="3327">\u0160martno ob Paki</option> -<option value="1275">\u0160martno pri Litiji</option> -<option value="2383">\u0160martno pri Slovenj Gradcu</option> -<option value="3201">\u0160martno v Ro\u017eni dolini</option> -<option value="3325">\u0160o\u0161tanj</option> -<option value="6222">\u0160tanjel</option> -<option value="3220">\u0160tore</option> -<option value="4209">\u017dabnica</option> -<option value="3310">\u017dalec</option> -<option value="4228">\u017delezniki</option> -<option value="2287">\u017detale</option> -<option value="4226">\u017diri</option> -<option value="4274">\u017dirovnica</option> -<option value="8360">\u017du\u017eemberk</option> -</select>''' - self.assertHTMLEqual(f.render('Kranj', '4000'), out) diff --git a/tests/regressiontests/localflavor/sk/__init__.py b/tests/regressiontests/localflavor/sk/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/sk/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/sk/tests.py b/tests/regressiontests/localflavor/sk/tests.py deleted file mode 100644 index b51fee2681..0000000000 --- a/tests/regressiontests/localflavor/sk/tests.py +++ /dev/null @@ -1,118 +0,0 @@ -from __future__ import unicode_literals - -from django.contrib.localflavor.sk.forms import (SKRegionSelect, - SKPostalCodeField, SKDistrictSelect) - -from django.test import SimpleTestCase - - -class SKLocalFlavorTests(SimpleTestCase): - def test_SKRegionSelect(self): - f = SKRegionSelect() - out = '''<select name="regions"> -<option value="BB">Banska Bystrica region</option> -<option value="BA">Bratislava region</option> -<option value="KE">Kosice region</option> -<option value="NR">Nitra region</option> -<option value="PO">Presov region</option> -<option value="TN">Trencin region</option> -<option value="TT" selected="selected">Trnava region</option> -<option value="ZA">Zilina region</option> -</select>''' - self.assertHTMLEqual(f.render('regions', 'TT'), out) - - def test_SKDistrictSelect(self): - f = SKDistrictSelect() - out = '''<select name="Districts"> -<option value="BB">Banska Bystrica</option> -<option value="BS">Banska Stiavnica</option> -<option value="BJ">Bardejov</option> -<option value="BN">Banovce nad Bebravou</option> -<option value="BR">Brezno</option> -<option value="BA1">Bratislava I</option> -<option value="BA2">Bratislava II</option> -<option value="BA3">Bratislava III</option> -<option value="BA4">Bratislava IV</option> -<option value="BA5">Bratislava V</option> -<option value="BY">Bytca</option> -<option value="CA">Cadca</option> -<option value="DT">Detva</option> -<option value="DK">Dolny Kubin</option> -<option value="DS">Dunajska Streda</option> -<option value="GA">Galanta</option> -<option value="GL">Gelnica</option> -<option value="HC">Hlohovec</option> -<option value="HE">Humenne</option> -<option value="IL">Ilava</option> -<option value="KK">Kezmarok</option> -<option value="KN">Komarno</option> -<option value="KE1">Kosice I</option> -<option value="KE2">Kosice II</option> -<option value="KE3">Kosice III</option> -<option value="KE4">Kosice IV</option> -<option value="KEO">Kosice - okolie</option> -<option value="KA">Krupina</option> -<option value="KM">Kysucke Nove Mesto</option> -<option value="LV">Levice</option> -<option value="LE">Levoca</option> -<option value="LM">Liptovsky Mikulas</option> -<option value="LC">Lucenec</option> -<option value="MA">Malacky</option> -<option value="MT">Martin</option> -<option value="ML">Medzilaborce</option> -<option value="MI">Michalovce</option> -<option value="MY">Myjava</option> -<option value="NO">Namestovo</option> -<option value="NR">Nitra</option> -<option value="NM">Nove Mesto nad Vahom</option> -<option value="NZ">Nove Zamky</option> -<option value="PE">Partizanske</option> -<option value="PK">Pezinok</option> -<option value="PN">Piestany</option> -<option value="PT">Poltar</option> -<option value="PP">Poprad</option> -<option value="PB">Povazska Bystrica</option> -<option value="PO">Presov</option> -<option value="PD">Prievidza</option> -<option value="PU">Puchov</option> -<option value="RA">Revuca</option> -<option value="RS">Rimavska Sobota</option> -<option value="RV">Roznava</option> -<option value="RK" selected="selected">Ruzomberok</option> -<option value="SB">Sabinov</option> -<option value="SC">Senec</option> -<option value="SE">Senica</option> -<option value="SI">Skalica</option> -<option value="SV">Snina</option> -<option value="SO">Sobrance</option> -<option value="SN">Spisska Nova Ves</option> -<option value="SL">Stara Lubovna</option> -<option value="SP">Stropkov</option> -<option value="SK">Svidnik</option> -<option value="SA">Sala</option> -<option value="TO">Topolcany</option> -<option value="TV">Trebisov</option> -<option value="TN">Trencin</option> -<option value="TT">Trnava</option> -<option value="TR">Turcianske Teplice</option> -<option value="TS">Tvrdosin</option> -<option value="VK">Velky Krtis</option> -<option value="VT">Vranov nad Toplou</option> -<option value="ZM">Zlate Moravce</option> -<option value="ZV">Zvolen</option> -<option value="ZC">Zarnovica</option> -<option value="ZH">Ziar nad Hronom</option> -<option value="ZA">Zilina</option> -</select>''' - self.assertHTMLEqual(f.render('Districts', 'RK'), out) - - def test_SKPostalCodeField(self): - error_format = ['Enter a postal code in the format XXXXX or XXX XX.'] - valid = { - '91909': '91909', - '917 01': '91701', - } - invalid = { - '84545x': error_format, - } - self.assertFieldOutput(SKPostalCodeField, valid, invalid) diff --git a/tests/regressiontests/localflavor/tests.py b/tests/regressiontests/localflavor/tests.py index 856e518bed..52b771c405 100644 --- a/tests/regressiontests/localflavor/tests.py +++ b/tests/regressiontests/localflavor/tests.py @@ -1,45 +1,3 @@ from __future__ import absolute_import -from .ar.tests import ARLocalFlavorTests -from .at.tests import ATLocalFlavorTests -from .au.tests import AULocalflavorTests -from .be.tests import BELocalFlavorTests -from .br.tests import BRLocalFlavorTests -from .ca.tests import CALocalFlavorTests -from .ch.tests import CHLocalFlavorTests -from .cl.tests import CLLocalFlavorTests -from .cn.tests import CNLocalFlavorTests -from .co.tests import COLocalFlavorTests -from .cz.tests import CZLocalFlavorTests -from .de.tests import DELocalFlavorTests -from .ec.tests import ECLocalFlavorTests -from .es.tests import ESLocalFlavorTests -from .fi.tests import FILocalFlavorTests -from .fr.tests import FRLocalFlavorTests -from .gb.tests import GBLocalFlavorTests from .generic.tests import GenericLocalFlavorTests -from .hk.tests import HKLocalFlavorTests -from .hr.tests import HRLocalFlavorTests -from .id.tests import IDLocalFlavorTests -from .ie.tests import IELocalFlavorTests -from .il.tests import ILLocalFlavorTests -from .in_.tests import INLocalFlavorTests -from .is_.tests import ISLocalFlavorTests -from .it.tests import ITLocalFlavorTests -from .jp.tests import JPLocalFlavorTests -from .kw.tests import KWLocalFlavorTests -from .mk.tests import MKLocalFlavorTests -from .mx.tests import MXLocalFlavorTests -from .nl.tests import NLLocalFlavorTests -from .pl.tests import PLLocalFlavorTests -from .pt.tests import PTLocalFlavorTests -from .py.tests import PYLocalFlavorTests -from .ro.tests import ROLocalFlavorTests -from .ru.tests import RULocalFlavorTests -from .se.tests import SELocalFlavorTests -from .si.tests import SILocalFlavorTests -from .sk.tests import SKLocalFlavorTests -from .tr.tests import TRLocalFlavorTests -from .us.tests import USLocalFlavorTests -from .uy.tests import UYLocalFlavorTests -from .za.tests import ZALocalFlavorTests diff --git a/tests/regressiontests/localflavor/tr/__init__.py b/tests/regressiontests/localflavor/tr/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/tr/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/tr/tests.py b/tests/regressiontests/localflavor/tr/tests.py deleted file mode 100644 index 476efc12ba..0000000000 --- a/tests/regressiontests/localflavor/tr/tests.py +++ /dev/null @@ -1,75 +0,0 @@ -# Tests for the contrib/localflavor/ TR form fields. - -from django.contrib.localflavor.tr import forms as trforms -from django.core.exceptions import ValidationError -from django.utils import six -from django.utils.unittest import TestCase - - -class TRLocalFlavorTests(TestCase): - def test_TRPostalCodeField(self): - f = trforms.TRPostalCodeField() - self.assertEqual(f.clean("06531"), "06531") - self.assertEqual(f.clean("12345"), "12345") - six.assertRaisesRegex(self, ValidationError, - "Enter a postal code in the format XXXXX.", - f.clean, "a1234") - six.assertRaisesRegex(self, ValidationError, - "Enter a postal code in the format XXXXX.", - f.clean, "1234") - six.assertRaisesRegex(self, ValidationError, - "Enter a postal code in the format XXXXX.", - f.clean, "82123") - six.assertRaisesRegex(self, ValidationError, - "Enter a postal code in the format XXXXX.", - f.clean, "00123") - six.assertRaisesRegex(self, ValidationError, - "Enter a postal code in the format XXXXX.", - f.clean, "123456") - six.assertRaisesRegex(self, ValidationError, - "Enter a postal code in the format XXXXX.", - f.clean, "12 34") - self.assertRaises(ValidationError, f.clean, None) - - def test_TRPhoneNumberField(self): - f = trforms.TRPhoneNumberField() - self.assertEqual(f.clean("312 455 56 78"), "3124555678") - self.assertEqual(f.clean("312 4555678"), "3124555678") - self.assertEqual(f.clean("3124555678"), "3124555678") - self.assertEqual(f.clean("0312 455 5678"), "3124555678") - self.assertEqual(f.clean("0 312 455 5678"), "3124555678") - self.assertEqual(f.clean("0 (312) 455 5678"), "3124555678") - self.assertEqual(f.clean("+90 312 455 4567"), "3124554567") - self.assertEqual(f.clean("+90 312 455 45 67"), "3124554567") - self.assertEqual(f.clean("+90 (312) 4554567"), "3124554567") - six.assertRaisesRegex(self, ValidationError, - 'Phone numbers must be in 0XXX XXX XXXX format.', - f.clean, "1234 233 1234") - six.assertRaisesRegex(self, ValidationError, - 'Phone numbers must be in 0XXX XXX XXXX format.', - f.clean, "0312 233 12345") - six.assertRaisesRegex(self, ValidationError, - 'Phone numbers must be in 0XXX XXX XXXX format.', - f.clean, "0312 233 123") - six.assertRaisesRegex(self, ValidationError, - 'Phone numbers must be in 0XXX XXX XXXX format.', - f.clean, "0312 233 xxxx") - - def test_TRIdentificationNumberField(self): - f = trforms.TRIdentificationNumberField() - self.assertEqual(f.clean("10000000146"), "10000000146") - six.assertRaisesRegex(self, ValidationError, - 'Enter a valid Turkish Identification number.', - f.clean, "10000000136") - six.assertRaisesRegex(self, ValidationError, - 'Enter a valid Turkish Identification number.', - f.clean, "10000000147") - six.assertRaisesRegex(self, ValidationError, - 'Turkish Identification number must be 11 digits.', - f.clean, "123456789") - six.assertRaisesRegex(self, ValidationError, - 'Enter a valid Turkish Identification number.', - f.clean, "1000000014x") - six.assertRaisesRegex(self, ValidationError, - 'Enter a valid Turkish Identification number.', - f.clean, "x0000000146") diff --git a/tests/regressiontests/localflavor/us/__init__.py b/tests/regressiontests/localflavor/us/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/us/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/us/forms.py b/tests/regressiontests/localflavor/us/forms.py deleted file mode 100644 index fe925c3c7b..0000000000 --- a/tests/regressiontests/localflavor/us/forms.py +++ /dev/null @@ -1,11 +0,0 @@ -from __future__ import absolute_import - -from django.forms import ModelForm - -from .models import USPlace - - -class USPlaceForm(ModelForm): - - class Meta: - model = USPlace diff --git a/tests/regressiontests/localflavor/us/models.py b/tests/regressiontests/localflavor/us/models.py deleted file mode 100644 index ff48ed16bb..0000000000 --- a/tests/regressiontests/localflavor/us/models.py +++ /dev/null @@ -1,15 +0,0 @@ -from django.contrib.localflavor.us.models import USStateField, USPostalCodeField -from django.db import models - -# When creating models you need to remember to add a app_label as -# 'localflavor', so your model can be found - -class USPlace(models.Model): - state = USStateField(blank=True) - state_req = USStateField() - state_default = USStateField(default="CA", blank=True) - postal_code = USPostalCodeField(blank=True) - name = models.CharField(max_length=20) - - class Meta: - app_label = 'localflavor' diff --git a/tests/regressiontests/localflavor/us/tests.py b/tests/regressiontests/localflavor/us/tests.py deleted file mode 100644 index 45967cb9dc..0000000000 --- a/tests/regressiontests/localflavor/us/tests.py +++ /dev/null @@ -1,286 +0,0 @@ -from __future__ import absolute_import, unicode_literals - -from django.contrib.localflavor.us.forms import (USZipCodeField, - USPhoneNumberField, USStateField, USStateSelect, - USSocialSecurityNumberField) -from django.test import SimpleTestCase - -from .forms import USPlaceForm - - -class USLocalFlavorTests(SimpleTestCase): - - def setUp(self): - self.form = USPlaceForm({'state':'GA', 'state_req':'NC', 'postal_code': 'GA', 'name':'impossible'}) - - def test_get_display_methods(self): - """Test that the get_*_display() methods are added to the model instances.""" - place = self.form.save() - self.assertEqual(place.get_state_display(), 'Georgia') - self.assertEqual(place.get_state_req_display(), 'North Carolina') - - def test_required(self): - """Test that required USStateFields throw appropriate errors.""" - form = USPlaceForm({'state':'GA', 'name':'Place in GA'}) - self.assertFalse(form.is_valid()) - self.assertEqual(form.errors['state_req'], ['This field is required.']) - - def test_field_blank_option(self): - """Test that the empty option is there.""" - state_select_html = """\ -<select name="state" id="id_state"> -<option value="">---------</option> -<option value="AL">Alabama</option> -<option value="AK">Alaska</option> -<option value="AS">American Samoa</option> -<option value="AZ">Arizona</option> -<option value="AR">Arkansas</option> -<option value="AA">Armed Forces Americas</option> -<option value="AE">Armed Forces Europe</option> -<option value="AP">Armed Forces Pacific</option> -<option value="CA">California</option> -<option value="CO">Colorado</option> -<option value="CT">Connecticut</option> -<option value="DE">Delaware</option> -<option value="DC">District of Columbia</option> -<option value="FL">Florida</option> -<option value="GA" selected="selected">Georgia</option> -<option value="GU">Guam</option> -<option value="HI">Hawaii</option> -<option value="ID">Idaho</option> -<option value="IL">Illinois</option> -<option value="IN">Indiana</option> -<option value="IA">Iowa</option> -<option value="KS">Kansas</option> -<option value="KY">Kentucky</option> -<option value="LA">Louisiana</option> -<option value="ME">Maine</option> -<option value="MD">Maryland</option> -<option value="MA">Massachusetts</option> -<option value="MI">Michigan</option> -<option value="MN">Minnesota</option> -<option value="MS">Mississippi</option> -<option value="MO">Missouri</option> -<option value="MT">Montana</option> -<option value="NE">Nebraska</option> -<option value="NV">Nevada</option> -<option value="NH">New Hampshire</option> -<option value="NJ">New Jersey</option> -<option value="NM">New Mexico</option> -<option value="NY">New York</option> -<option value="NC">North Carolina</option> -<option value="ND">North Dakota</option> -<option value="MP">Northern Mariana Islands</option> -<option value="OH">Ohio</option> -<option value="OK">Oklahoma</option> -<option value="OR">Oregon</option> -<option value="PA">Pennsylvania</option> -<option value="PR">Puerto Rico</option> -<option value="RI">Rhode Island</option> -<option value="SC">South Carolina</option> -<option value="SD">South Dakota</option> -<option value="TN">Tennessee</option> -<option value="TX">Texas</option> -<option value="UT">Utah</option> -<option value="VT">Vermont</option> -<option value="VI">Virgin Islands</option> -<option value="VA">Virginia</option> -<option value="WA">Washington</option> -<option value="WV">West Virginia</option> -<option value="WI">Wisconsin</option> -<option value="WY">Wyoming</option> -</select>""" - self.assertHTMLEqual(str(self.form['state']), state_select_html) - - def test_full_postal_code_list(self): - """Test that the full USPS code field is really the full list.""" - usps_select_html = """\ -<select name="postal_code" id="id_postal_code"> -<option value="">---------</option> -<option value="AL">Alabama</option> -<option value="AK">Alaska</option> -<option value="AS">American Samoa</option> -<option value="AZ">Arizona</option> -<option value="AR">Arkansas</option> -<option value="AA">Armed Forces Americas</option> -<option value="AE">Armed Forces Europe</option> -<option value="AP">Armed Forces Pacific</option> -<option value="CA">California</option> -<option value="CO">Colorado</option> -<option value="CT">Connecticut</option> -<option value="DE">Delaware</option> -<option value="DC">District of Columbia</option> -<option value="FM">Federated States of Micronesia</option> -<option value="FL">Florida</option> -<option value="GA" selected="selected">Georgia</option> -<option value="GU">Guam</option> -<option value="HI">Hawaii</option> -<option value="ID">Idaho</option> -<option value="IL">Illinois</option> -<option value="IN">Indiana</option> -<option value="IA">Iowa</option> -<option value="KS">Kansas</option> -<option value="KY">Kentucky</option> -<option value="LA">Louisiana</option> -<option value="ME">Maine</option> -<option value="MH">Marshall Islands</option> -<option value="MD">Maryland</option> -<option value="MA">Massachusetts</option> -<option value="MI">Michigan</option> -<option value="MN">Minnesota</option> -<option value="MS">Mississippi</option> -<option value="MO">Missouri</option> -<option value="MT">Montana</option> -<option value="NE">Nebraska</option> -<option value="NV">Nevada</option> -<option value="NH">New Hampshire</option> -<option value="NJ">New Jersey</option> -<option value="NM">New Mexico</option> -<option value="NY">New York</option> -<option value="NC">North Carolina</option> -<option value="ND">North Dakota</option> -<option value="MP">Northern Mariana Islands</option> -<option value="OH">Ohio</option> -<option value="OK">Oklahoma</option> -<option value="OR">Oregon</option> -<option value="PW">Palau</option> -<option value="PA">Pennsylvania</option> -<option value="PR">Puerto Rico</option> -<option value="RI">Rhode Island</option> -<option value="SC">South Carolina</option> -<option value="SD">South Dakota</option> -<option value="TN">Tennessee</option> -<option value="TX">Texas</option> -<option value="UT">Utah</option> -<option value="VT">Vermont</option> -<option value="VI">Virgin Islands</option> -<option value="VA">Virginia</option> -<option value="WA">Washington</option> -<option value="WV">West Virginia</option> -<option value="WI">Wisconsin</option> -<option value="WY">Wyoming</option> -</select>""" - self.assertHTMLEqual(str(self.form['postal_code']), usps_select_html) - - def test_USStateSelect(self): - f = USStateSelect() - out = '''<select name="state"> -<option value="AL">Alabama</option> -<option value="AK">Alaska</option> -<option value="AS">American Samoa</option> -<option value="AZ">Arizona</option> -<option value="AR">Arkansas</option> -<option value="AA">Armed Forces Americas</option> -<option value="AE">Armed Forces Europe</option> -<option value="AP">Armed Forces Pacific</option> -<option value="CA">California</option> -<option value="CO">Colorado</option> -<option value="CT">Connecticut</option> -<option value="DE">Delaware</option> -<option value="DC">District of Columbia</option> -<option value="FL">Florida</option> -<option value="GA">Georgia</option> -<option value="GU">Guam</option> -<option value="HI">Hawaii</option> -<option value="ID">Idaho</option> -<option value="IL" selected="selected">Illinois</option> -<option value="IN">Indiana</option> -<option value="IA">Iowa</option> -<option value="KS">Kansas</option> -<option value="KY">Kentucky</option> -<option value="LA">Louisiana</option> -<option value="ME">Maine</option> -<option value="MD">Maryland</option> -<option value="MA">Massachusetts</option> -<option value="MI">Michigan</option> -<option value="MN">Minnesota</option> -<option value="MS">Mississippi</option> -<option value="MO">Missouri</option> -<option value="MT">Montana</option> -<option value="NE">Nebraska</option> -<option value="NV">Nevada</option> -<option value="NH">New Hampshire</option> -<option value="NJ">New Jersey</option> -<option value="NM">New Mexico</option> -<option value="NY">New York</option> -<option value="NC">North Carolina</option> -<option value="ND">North Dakota</option> -<option value="MP">Northern Mariana Islands</option> -<option value="OH">Ohio</option> -<option value="OK">Oklahoma</option> -<option value="OR">Oregon</option> -<option value="PA">Pennsylvania</option> -<option value="PR">Puerto Rico</option> -<option value="RI">Rhode Island</option> -<option value="SC">South Carolina</option> -<option value="SD">South Dakota</option> -<option value="TN">Tennessee</option> -<option value="TX">Texas</option> -<option value="UT">Utah</option> -<option value="VT">Vermont</option> -<option value="VI">Virgin Islands</option> -<option value="VA">Virginia</option> -<option value="WA">Washington</option> -<option value="WV">West Virginia</option> -<option value="WI">Wisconsin</option> -<option value="WY">Wyoming</option> -</select>''' - self.assertHTMLEqual(f.render('state', 'IL'), out) - - def test_USZipCodeField(self): - error_format = ['Enter a zip code in the format XXXXX or XXXXX-XXXX.'] - valid = { - '60606': '60606', - 60606: '60606', - '04000': '04000', - '60606-1234': '60606-1234', - } - invalid = { - '4000': error_format, - '6060-1234': error_format, - '60606-': error_format, - } - self.assertFieldOutput(USZipCodeField, valid, invalid) - - def test_USPhoneNumberField(self): - error_format = ['Phone numbers must be in XXX-XXX-XXXX format.'] - valid = { - '312-555-1212': '312-555-1212', - '3125551212': '312-555-1212', - '312 555-1212': '312-555-1212', - '(312) 555-1212': '312-555-1212', - '312 555 1212': '312-555-1212', - '312.555.1212': '312-555-1212', - '312.555-1212': '312-555-1212', - ' (312) 555.1212 ': '312-555-1212', - } - invalid = { - '555-1212': error_format, - '312-55-1212': error_format, - } - self.assertFieldOutput(USPhoneNumberField, valid, invalid) - - def test_USStateField(self): - error_invalid = ['Enter a U.S. state or territory.'] - valid = { - 'il': 'IL', - 'IL': 'IL', - 'illinois': 'IL', - ' illinois ': 'IL', - } - invalid = { - 60606: error_invalid, - } - self.assertFieldOutput(USStateField, valid, invalid) - - def test_USSocialSecurityNumberField(self): - error_invalid = ['Enter a valid U.S. Social Security number in XXX-XX-XXXX format.'] - - valid = { - '987-65-4330': '987-65-4330', - '987654330': '987-65-4330', - } - invalid = { - '078-05-1120': error_invalid, - } - self.assertFieldOutput(USSocialSecurityNumberField, valid, invalid) diff --git a/tests/regressiontests/localflavor/uy/__init__.py b/tests/regressiontests/localflavor/uy/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/uy/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/uy/tests.py b/tests/regressiontests/localflavor/uy/tests.py deleted file mode 100644 index 5bbbbe4122..0000000000 --- a/tests/regressiontests/localflavor/uy/tests.py +++ /dev/null @@ -1,53 +0,0 @@ -from __future__ import unicode_literals - -from django.contrib.localflavor.uy.forms import UYDepartamentSelect, UYCIField -from django.contrib.localflavor.uy.util import get_validation_digit - -from django.test import SimpleTestCase - - -class UYLocalFlavorTests(SimpleTestCase): - def test_UYDepartmentSelect(self): - f = UYDepartamentSelect() - out = '''<select name="departamentos"> -<option value="G">Artigas</option> -<option value="A">Canelones</option> -<option value="E">Cerro Largo</option> -<option value="L">Colonia</option> -<option value="Q">Durazno</option> -<option value="N">Flores</option> -<option value="O">Florida</option> -<option value="P">Lavalleja</option> -<option value="B">Maldonado</option> -<option value="S" selected="selected">Montevideo</option> -<option value="I">Paysand\xfa</option> -<option value="J">R\xedo Negro</option> -<option value="F">Rivera</option> -<option value="C">Rocha</option> -<option value="H">Salto</option> -<option value="M">San Jos\xe9</option> -<option value="K">Soriano</option> -<option value="R">Tacuaremb\xf3</option> -<option value="D">Treinta y Tres</option> -</select>''' - self.assertHTMLEqual(f.render('departamentos', 'S'), out) - - def test_UYCIField(self): - error_format = ['Enter a valid CI number in X.XXX.XXX-X,XXXXXXX-X or XXXXXXXX format.'] - error_invalid = ['Enter a valid CI number.'] - valid = { - '4098053': '4098053', - '409805-3': '409805-3', - '409.805-3': '409.805-3', - '10054112': '10054112', - '1005411-2': '1005411-2', - '1.005.411-2': '1.005.411-2', - } - invalid = { - 'foo': ['Enter a valid CI number in X.XXX.XXX-X,XXXXXXX-X or XXXXXXXX format.'], - '409805-2': ['Enter a valid CI number.'], - '1.005.411-5': ['Enter a valid CI number.'], - } - self.assertFieldOutput(UYCIField, valid, invalid) - self.assertEqual(get_validation_digit(409805), 3) - self.assertEqual(get_validation_digit(1005411), 2) diff --git a/tests/regressiontests/localflavor/za/__init__.py b/tests/regressiontests/localflavor/za/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/regressiontests/localflavor/za/__init__.py +++ /dev/null diff --git a/tests/regressiontests/localflavor/za/tests.py b/tests/regressiontests/localflavor/za/tests.py deleted file mode 100644 index 81e8d65eec..0000000000 --- a/tests/regressiontests/localflavor/za/tests.py +++ /dev/null @@ -1,31 +0,0 @@ -from __future__ import unicode_literals - -from django.contrib.localflavor.za.forms import ZAIDField, ZAPostCodeField - -from django.test import SimpleTestCase - - -class ZALocalFlavorTests(SimpleTestCase): - def test_ZAIDField(self): - error_invalid = ['Enter a valid South African ID number'] - valid = { - '0002290001003': '0002290001003', - '000229 0001 003': '0002290001003', - } - invalid = { - '0102290001001': error_invalid, - '811208': error_invalid, - '0002290001004': error_invalid, - } - self.assertFieldOutput(ZAIDField, valid, invalid) - - def test_ZAPostCodeField(self): - error_invalid = ['Enter a valid South African postal code'] - valid = { - '0000': '0000', - } - invalid = { - 'abcd': error_invalid, - ' 7530': error_invalid, - } - self.assertFieldOutput(ZAPostCodeField, valid, invalid) diff --git a/tests/regressiontests/logging_tests/logconfig.py b/tests/regressiontests/logging_tests/logconfig.py new file mode 100644 index 0000000000..fc5ea1a0bd --- /dev/null +++ b/tests/regressiontests/logging_tests/logconfig.py @@ -0,0 +1,8 @@ +import logging + +from django.conf import settings + +class MyHandler(logging.Handler): + def __init__(self): + logging.Handler.__init__(self) + self.config = settings.LOGGING diff --git a/tests/regressiontests/logging_tests/tests.py b/tests/regressiontests/logging_tests/tests.py index 4ae3c1b1a9..e40800efde 100644 --- a/tests/regressiontests/logging_tests/tests.py +++ b/tests/regressiontests/logging_tests/tests.py @@ -1,13 +1,17 @@ from __future__ import unicode_literals import copy +import logging import warnings from django.conf import compat_patch_logging_config from django.core import mail from django.test import TestCase, RequestFactory from django.test.utils import override_settings -from django.utils.log import CallbackFilter, RequireDebugFalse, getLogger +from django.utils.log import CallbackFilter, RequireDebugFalse +from django.utils.six import StringIO + +from ..admin_scripts.tests import AdminScriptTestCase # logging config prior to using filter with mail_admins @@ -106,6 +110,28 @@ class PatchLoggingConfigTest(TestCase): self.assertEqual(config, new_config) +class DefaultLoggingTest(TestCase): + def setUp(self): + self.logger = logging.getLogger('django') + self.old_stream = self.logger.handlers[0].stream + + def tearDown(self): + self.logger.handlers[0].stream = self.old_stream + + def test_django_logger(self): + """ + The 'django' base logger only output anything when DEBUG=True. + """ + output = StringIO() + self.logger.handlers[0].stream = output + self.logger.error("Hey, this is an error.") + self.assertEqual(output.getvalue(), '') + + with self.settings(DEBUG=True): + self.logger.error("Hey, this is an error.") + self.assertEqual(output.getvalue(), 'Hey, this is an error.\n') + + class CallbackFilterTest(TestCase): def test_sense(self): f_false = CallbackFilter(lambda r: False) @@ -128,6 +154,7 @@ class CallbackFilterTest(TestCase): class AdminEmailHandlerTest(TestCase): + logger = logging.getLogger('django.request') def get_admin_email_handler(self, logger): # Inspired from regressiontests/views/views.py: send_log() @@ -153,14 +180,13 @@ class AdminEmailHandlerTest(TestCase): token1 = 'ping' token2 = 'pong' - logger = getLogger('django.request') - admin_email_handler = self.get_admin_email_handler(logger) + admin_email_handler = self.get_admin_email_handler(self.logger) # Backup then override original filters orig_filters = admin_email_handler.filters try: admin_email_handler.filters = [] - logger.error(message, token1, token2) + self.logger.error(message, token1, token2) self.assertEqual(len(mail.outbox), 1) self.assertEqual(mail.outbox[0].to, ['admin@example.com']) @@ -184,15 +210,14 @@ class AdminEmailHandlerTest(TestCase): token1 = 'ping' token2 = 'pong' - logger = getLogger('django.request') - admin_email_handler = self.get_admin_email_handler(logger) + admin_email_handler = self.get_admin_email_handler(self.logger) # Backup then override original filters orig_filters = admin_email_handler.filters try: admin_email_handler.filters = [] rf = RequestFactory() request = rf.get('/') - logger.error(message, token1, token2, + self.logger.error(message, token1, token2, extra={ 'status_code': 403, 'request': request, @@ -222,8 +247,7 @@ class AdminEmailHandlerTest(TestCase): self.assertEqual(len(mail.outbox), 0) - logger = getLogger('django.request') - logger.error(message) + self.logger.error(message) self.assertEqual(len(mail.outbox), 1) self.assertFalse('\n' in mail.outbox[0].subject) @@ -247,8 +271,34 @@ class AdminEmailHandlerTest(TestCase): self.assertEqual(len(mail.outbox), 0) - logger = getLogger('django.request') - logger.error(message) + self.logger.error(message) self.assertEqual(len(mail.outbox), 1) self.assertEqual(mail.outbox[0].subject, expected_subject) + + +class SettingsConfigTest(AdminScriptTestCase): + """ + Test that accessing settings in a custom logging handler does not trigger + a circular import error. + """ + def setUp(self): + log_config = """{ + 'version': 1, + 'handlers': { + 'custom_handler': { + 'level': 'INFO', + 'class': 'logging_tests.logconfig.MyHandler', + } + } +}""" + self.write_settings('settings.py', sdict={'LOGGING': log_config}) + + def tearDown(self): + self.remove_settings('settings.py') + + def test_circular_dependency(self): + # validate is just an example command to trigger settings configuration + out, err = self.run_manage(['validate']) + self.assertNoOutput(err) + self.assertOutput(out, "0 errors found") diff --git a/tests/regressiontests/mail/tests.py b/tests/regressiontests/mail/tests.py index 3e9ae84650..33898cc1d5 100644 --- a/tests/regressiontests/mail/tests.py +++ b/tests/regressiontests/mail/tests.py @@ -498,6 +498,11 @@ class LocmemBackendTests(BaseEmailBackendTests, TestCase): connection2.send_messages([email]) self.assertEqual(len(mail.outbox), 2) + def test_validate_multiline_headers(self): + # Ticket #18861 - Validate emails when using the locmem backend + with self.assertRaises(BadHeaderError): + send_mail('Subject\nMultiline', 'Content', 'from@example.com', ['to@example.com']) + class FileBackendTests(BaseEmailBackendTests, TestCase): email_backend = 'django.core.mail.backends.filebased.EmailBackend' diff --git a/tests/regressiontests/managers_regress/models.py b/tests/regressiontests/managers_regress/models.py index 892505f24a..d72970d86e 100644 --- a/tests/regressiontests/managers_regress/models.py +++ b/tests/regressiontests/managers_regress/models.py @@ -10,14 +10,17 @@ class OnlyFred(models.Manager): def get_query_set(self): return super(OnlyFred, self).get_query_set().filter(name='fred') + class OnlyBarney(models.Manager): def get_query_set(self): return super(OnlyBarney, self).get_query_set().filter(name='barney') + class Value42(models.Manager): def get_query_set(self): return super(Value42, self).get_query_set().filter(value=42) + class AbstractBase1(models.Model): name = models.CharField(max_length=50) @@ -29,6 +32,7 @@ class AbstractBase1(models.Model): manager2 = OnlyBarney() objects = models.Manager() + class AbstractBase2(models.Model): value = models.IntegerField() @@ -38,6 +42,7 @@ class AbstractBase2(models.Model): # Custom manager restricted = Value42() + # No custom manager on this class to make sure the default case doesn't break. class AbstractBase3(models.Model): comment = models.CharField(max_length=50) @@ -45,6 +50,7 @@ class AbstractBase3(models.Model): class Meta: abstract = True + @python_2_unicode_compatible class Parent(models.Model): name = models.CharField(max_length=50) @@ -54,6 +60,7 @@ class Parent(models.Model): def __str__(self): return self.name + # Managers from base classes are inherited and, if no manager is specified # *and* the parent has a manager specified, the first one (in the MRO) will # become the default. @@ -64,6 +71,7 @@ class Child1(AbstractBase1): def __str__(self): return self.data + @python_2_unicode_compatible class Child2(AbstractBase1, AbstractBase2): data = models.CharField(max_length=25) @@ -71,6 +79,7 @@ class Child2(AbstractBase1, AbstractBase2): def __str__(self): return self.data + @python_2_unicode_compatible class Child3(AbstractBase1, AbstractBase3): data = models.CharField(max_length=25) @@ -78,6 +87,7 @@ class Child3(AbstractBase1, AbstractBase3): def __str__(self): return self.data + @python_2_unicode_compatible class Child4(AbstractBase1): data = models.CharField(max_length=25) @@ -89,6 +99,7 @@ class Child4(AbstractBase1): def __str__(self): return self.data + @python_2_unicode_compatible class Child5(AbstractBase3): name = models.CharField(max_length=25) @@ -99,10 +110,12 @@ class Child5(AbstractBase3): def __str__(self): return self.name + # Will inherit managers from AbstractBase1, but not Child4. class Child6(Child4): value = models.IntegerField() + # Will not inherit default manager from parent. class Child7(Parent): pass diff --git a/tests/regressiontests/managers_regress/tests.py b/tests/regressiontests/managers_regress/tests.py index dd6cb66857..f3721a4c01 100644 --- a/tests/regressiontests/managers_regress/tests.py +++ b/tests/regressiontests/managers_regress/tests.py @@ -1,26 +1,42 @@ from __future__ import absolute_import +import copy +from django.conf import settings +from django.db import models +from django.db.models.loading import cache from django.test import TestCase +from django.test.utils import override_settings -from .models import Child1, Child2, Child3, Child4, Child5, Child6, Child7 +from .models import ( + Child1, + Child2, + Child3, + Child4, + Child5, + Child6, + Child7, + AbstractBase1, + AbstractBase2, + AbstractBase3, +) class ManagersRegressionTests(TestCase): def test_managers(self): - a1 = Child1.objects.create(name='fred', data='a1') - a2 = Child1.objects.create(name='barney', data='a2') - b1 = Child2.objects.create(name='fred', data='b1', value=1) - b2 = Child2.objects.create(name='barney', data='b2', value=42) - c1 = Child3.objects.create(name='fred', data='c1', comment='yes') - c2 = Child3.objects.create(name='barney', data='c2', comment='no') - d1 = Child4.objects.create(name='fred', data='d1') - d2 = Child4.objects.create(name='barney', data='d2') - e1 = Child5.objects.create(name='fred', comment='yes') - e2 = Child5.objects.create(name='barney', comment='no') - f1 = Child6.objects.create(name='fred', data='f1', value=42) - f2 = Child6.objects.create(name='barney', data='f2', value=42) - g1 = Child7.objects.create(name='fred') - g2 = Child7.objects.create(name='barney') + Child1.objects.create(name='fred', data='a1') + Child1.objects.create(name='barney', data='a2') + Child2.objects.create(name='fred', data='b1', value=1) + Child2.objects.create(name='barney', data='b2', value=42) + Child3.objects.create(name='fred', data='c1', comment='yes') + Child3.objects.create(name='barney', data='c2', comment='no') + Child4.objects.create(name='fred', data='d1') + Child4.objects.create(name='barney', data='d2') + Child5.objects.create(name='fred', comment='yes') + Child5.objects.create(name='barney', comment='no') + Child6.objects.create(name='fred', data='f1', value=42) + Child6.objects.create(name='barney', data='f2', value=42) + Child7.objects.create(name='fred') + Child7.objects.create(name='barney') self.assertQuerysetEqual(Child1.manager1.all(), ["<Child1: a1>"]) self.assertQuerysetEqual(Child1.manager2.all(), ["<Child1: a2>"]) @@ -54,3 +70,125 @@ class ManagersRegressionTests(TestCase): "<Child7: fred>" ] ) + + def test_abstract_manager(self): + # Accessing the manager on an abstract model should + # raise an attribute error with an appropriate message. + try: + AbstractBase3.objects.all() + self.fail('Should raise an AttributeError') + except AttributeError as e: + # This error message isn't ideal, but if the model is abstract and + # a lot of the class instantiation logic isn't invoked; if the + # manager is implied, then we don't get a hook to install the + # error-raising manager. + self.assertEqual(str(e), "type object 'AbstractBase3' has no attribute 'objects'") + + def test_custom_abstract_manager(self): + # Accessing the manager on an abstract model with an custom + # manager should raise an attribute error with an appropriate + # message. + try: + AbstractBase2.restricted.all() + self.fail('Should raise an AttributeError') + except AttributeError as e: + self.assertEqual(str(e), "Manager isn't available; AbstractBase2 is abstract") + + def test_explicit_abstract_manager(self): + # Accessing the manager on an abstract model with an explicit + # manager should raise an attribute error with an appropriate + # message. + try: + AbstractBase1.objects.all() + self.fail('Should raise an AttributeError') + except AttributeError as e: + self.assertEqual(str(e), "Manager isn't available; AbstractBase1 is abstract") + + def test_swappable_manager(self): + try: + # This test adds dummy models to the app cache. These + # need to be removed in order to prevent bad interactions + # with the flush operation in other tests. + old_app_models = copy.deepcopy(cache.app_models) + old_app_store = copy.deepcopy(cache.app_store) + + settings.TEST_SWAPPABLE_MODEL = 'managers_regress.Parent' + + class SwappableModel(models.Model): + class Meta: + swappable = 'TEST_SWAPPABLE_MODEL' + + # Accessing the manager on a swappable model should + # raise an attribute error with a helpful message + try: + SwappableModel.objects.all() + self.fail('Should raise an AttributeError') + except AttributeError as e: + self.assertEqual(str(e), "Manager isn't available; SwappableModel has been swapped for 'managers_regress.Parent'") + + finally: + del settings.TEST_SWAPPABLE_MODEL + cache.app_models = old_app_models + cache.app_store = old_app_store + + def test_custom_swappable_manager(self): + try: + # This test adds dummy models to the app cache. These + # need to be removed in order to prevent bad interactions + # with the flush operation in other tests. + old_app_models = copy.deepcopy(cache.app_models) + old_app_store = copy.deepcopy(cache.app_store) + + settings.TEST_SWAPPABLE_MODEL = 'managers_regress.Parent' + + class SwappableModel(models.Model): + + stuff = models.Manager() + + class Meta: + swappable = 'TEST_SWAPPABLE_MODEL' + + # Accessing the manager on a swappable model with an + # explicit manager should raise an attribute error with a + # helpful message + try: + SwappableModel.stuff.all() + self.fail('Should raise an AttributeError') + except AttributeError as e: + self.assertEqual(str(e), "Manager isn't available; SwappableModel has been swapped for 'managers_regress.Parent'") + + finally: + del settings.TEST_SWAPPABLE_MODEL + cache.app_models = old_app_models + cache.app_store = old_app_store + + def test_explicit_swappable_manager(self): + try: + # This test adds dummy models to the app cache. These + # need to be removed in order to prevent bad interactions + # with the flush operation in other tests. + old_app_models = copy.deepcopy(cache.app_models) + old_app_store = copy.deepcopy(cache.app_store) + + settings.TEST_SWAPPABLE_MODEL = 'managers_regress.Parent' + + class SwappableModel(models.Model): + + objects = models.Manager() + + class Meta: + swappable = 'TEST_SWAPPABLE_MODEL' + + # Accessing the manager on a swappable model with an + # explicit manager should raise an attribute error with a + # helpful message + try: + SwappableModel.objects.all() + self.fail('Should raise an AttributeError') + except AttributeError as e: + self.assertEqual(str(e), "Manager isn't available; SwappableModel has been swapped for 'managers_regress.Parent'") + + finally: + del settings.TEST_SWAPPABLE_MODEL + cache.app_models = old_app_models + cache.app_store = old_app_store diff --git a/tests/regressiontests/middleware/tests.py b/tests/regressiontests/middleware/tests.py index eb66f2bbf3..de901f4a80 100644 --- a/tests/regressiontests/middleware/tests.py +++ b/tests/regressiontests/middleware/tests.py @@ -8,7 +8,7 @@ from io import BytesIO from django.conf import settings from django.core import mail from django.http import HttpRequest -from django.http import HttpResponse +from django.http import HttpResponse, StreamingHttpResponse from django.middleware.clickjacking import XFrameOptionsMiddleware from django.middleware.common import CommonMiddleware from django.middleware.http import ConditionalGetMiddleware @@ -322,6 +322,12 @@ class ConditionalGetMiddlewareTest(TestCase): self.assertTrue('Content-Length' in self.resp) self.assertEqual(int(self.resp['Content-Length']), content_length) + def test_content_length_header_not_added(self): + resp = StreamingHttpResponse('content') + self.assertFalse('Content-Length' in resp) + resp = ConditionalGetMiddleware().process_response(self.req, resp) + self.assertFalse('Content-Length' in resp) + def test_content_length_header_not_changed(self): bad_content_length = len(self.resp.content) + 10 self.resp['Content-Length'] = bad_content_length @@ -351,6 +357,29 @@ class ConditionalGetMiddlewareTest(TestCase): self.resp = ConditionalGetMiddleware().process_response(self.req, self.resp) self.assertEqual(self.resp.status_code, 200) + @override_settings(USE_ETAGS=True) + def test_etag(self): + req = HttpRequest() + res = HttpResponse('content') + self.assertTrue( + CommonMiddleware().process_response(req, res).has_header('ETag')) + + @override_settings(USE_ETAGS=True) + def test_etag_streaming_response(self): + req = HttpRequest() + res = StreamingHttpResponse(['content']) + res['ETag'] = 'tomatoes' + self.assertEqual( + CommonMiddleware().process_response(req, res).get('ETag'), + 'tomatoes') + + @override_settings(USE_ETAGS=True) + def test_no_etag_streaming_response(self): + req = HttpRequest() + res = StreamingHttpResponse(['content']) + self.assertFalse( + CommonMiddleware().process_response(req, res).has_header('ETag')) + # Tests for the Last-Modified header def test_if_modified_since_and_no_last_modified(self): @@ -511,6 +540,7 @@ class GZipMiddlewareTest(TestCase): short_string = b"This string is too short to be worth compressing." compressible_string = b'a' * 500 uncompressible_string = b''.join(six.int2byte(random.randint(0, 255)) for _ in xrange(500)) + sequence = [b'a' * 500, b'b' * 200, b'a' * 300] def setUp(self): self.req = HttpRequest() @@ -525,6 +555,8 @@ class GZipMiddlewareTest(TestCase): self.resp.status_code = 200 self.resp.content = self.compressible_string self.resp['Content-Type'] = 'text/html; charset=UTF-8' + self.stream_resp = StreamingHttpResponse(self.sequence) + self.stream_resp['Content-Type'] = 'text/html; charset=UTF-8' @staticmethod def decompress(gzipped_string): @@ -539,6 +571,15 @@ class GZipMiddlewareTest(TestCase): self.assertEqual(r.get('Content-Encoding'), 'gzip') self.assertEqual(r.get('Content-Length'), str(len(r.content))) + def test_compress_streaming_response(self): + """ + Tests that compression is performed on responses with streaming content. + """ + r = GZipMiddleware().process_response(self.req, self.stream_resp) + self.assertEqual(self.decompress(b''.join(r)), b''.join(self.sequence)) + self.assertEqual(r.get('Content-Encoding'), 'gzip') + self.assertFalse(r.has_header('Content-Length')) + def test_compress_non_200_response(self): """ Tests that compression is performed on responses with a status other than 200. diff --git a/tests/regressiontests/model_fields/models.py b/tests/regressiontests/model_fields/models.py index d9c123fb39..1d20f44fae 100644 --- a/tests/regressiontests/model_fields/models.py +++ b/tests/regressiontests/model_fields/models.py @@ -66,6 +66,11 @@ class BooleanModel(models.Model): bfield = models.BooleanField() string = models.CharField(max_length=10, default='abc') +class FksToBooleans(models.Model): + """Model wih FKs to models with {Null,}BooleanField's, #15040""" + bf = models.ForeignKey(BooleanModel) + nbf = models.ForeignKey(NullBooleanModel) + class RenamedField(models.Model): modelname = models.IntegerField(name="fieldname", choices=((1,'One'),)) diff --git a/tests/regressiontests/model_fields/tests.py b/tests/regressiontests/model_fields/tests.py index 526aca4f98..a49894e36c 100644 --- a/tests/regressiontests/model_fields/tests.py +++ b/tests/regressiontests/model_fields/tests.py @@ -12,7 +12,8 @@ from django.utils import six from django.utils import unittest from .models import (Foo, Bar, Whiz, BigD, BigS, Image, BigInt, Post, - NullBooleanModel, BooleanModel, Document, RenamedField, VerboseNameField) + NullBooleanModel, BooleanModel, Document, RenamedField, VerboseNameField, + FksToBooleans) from .imagefield import (ImageFieldTests, ImageFieldTwoDimensionsTests, TwoImageFieldTests, ImageFieldNoDimensionsTests, @@ -218,6 +219,43 @@ class BooleanFieldTests(unittest.TestCase): select={'string_col': 'string'})[0] self.assertFalse(isinstance(b5.pk, bool)) + def test_select_related(self): + """ + Test type of boolean fields when retrieved via select_related() (MySQL, + #15040) + """ + bmt = BooleanModel.objects.create(bfield=True) + bmf = BooleanModel.objects.create(bfield=False) + nbmt = NullBooleanModel.objects.create(nbfield=True) + nbmf = NullBooleanModel.objects.create(nbfield=False) + + m1 = FksToBooleans.objects.create(bf=bmt, nbf=nbmt) + m2 = FksToBooleans.objects.create(bf=bmf, nbf=nbmf) + + # Test select_related('fk_field_name') + ma = FksToBooleans.objects.select_related('bf').get(pk=m1.id) + # verify types -- should't be 0/1 + self.assertIsInstance(ma.bf.bfield, bool) + self.assertIsInstance(ma.nbf.nbfield, bool) + # verify values + self.assertEqual(ma.bf.bfield, True) + self.assertEqual(ma.nbf.nbfield, True) + + # Test select_related() + mb = FksToBooleans.objects.select_related().get(pk=m1.id) + mc = FksToBooleans.objects.select_related().get(pk=m2.id) + # verify types -- shouldn't be 0/1 + self.assertIsInstance(mb.bf.bfield, bool) + self.assertIsInstance(mb.nbf.nbfield, bool) + self.assertIsInstance(mc.bf.bfield, bool) + self.assertIsInstance(mc.nbf.nbfield, bool) + # verify values + self.assertEqual(mb.bf.bfield, True) + self.assertEqual(mb.nbf.nbfield, True) + self.assertEqual(mc.bf.bfield, False) + self.assertEqual(mc.nbf.nbfield, False) + + class ChoicesTests(test.TestCase): def test_choices_and_field_display(self): """ diff --git a/tests/regressiontests/multiple_database/tests.py b/tests/regressiontests/multiple_database/tests.py index 782fe2bfc6..79fe6beebd 100644 --- a/tests/regressiontests/multiple_database/tests.py +++ b/tests/regressiontests/multiple_database/tests.py @@ -4,13 +4,13 @@ import datetime import pickle from operator import attrgetter -from django.conf import settings from django.contrib.auth.models import User from django.contrib.contenttypes.models import ContentType from django.core import management from django.db import connections, router, DEFAULT_DB_ALIAS from django.db.models import signals from django.test import TestCase +from django.test.utils import override_settings from django.utils.six import StringIO from .models import Book, Person, Pet, Review, UserProfile @@ -652,7 +652,8 @@ class QueryTestCase(TestCase): new_bob_profile = UserProfile(flavor="spring surprise") - charlie = User(username='charlie',email='charlie@example.com') + # assigning a profile requires a explicit pk as the object isn't saved + charlie = User(pk=51, username='charlie', email='charlie@example.com') charlie.set_unusable_password() # initially, no db assigned @@ -1619,20 +1620,11 @@ class AuthTestCase(TestCase): command_output = new_io.getvalue().strip() self.assertTrue('"email": "alice@example.com",' in command_output) -_missing = object() -class UserProfileTestCase(TestCase): - def setUp(self): - self.old_auth_profile_module = getattr(settings, 'AUTH_PROFILE_MODULE', _missing) - settings.AUTH_PROFILE_MODULE = 'multiple_database.UserProfile' - def tearDown(self): - if self.old_auth_profile_module is _missing: - del settings.AUTH_PROFILE_MODULE - else: - settings.AUTH_PROFILE_MODULE = self.old_auth_profile_module +@override_settings(AUTH_PROFILE_MODULE='multiple_database.UserProfile') +class UserProfileTestCase(TestCase): def test_user_profiles(self): - alice = User.objects.create_user('alice', 'alice@example.com') bob = User.objects.db_manager('other').create_user('bob', 'bob@example.com') diff --git a/tests/regressiontests/one_to_one_regress/tests.py b/tests/regressiontests/one_to_one_regress/tests.py index eced88598b..615536ba38 100644 --- a/tests/regressiontests/one_to_one_regress/tests.py +++ b/tests/regressiontests/one_to_one_regress/tests.py @@ -202,3 +202,43 @@ class OneToOneRegressionTests(TestCase): with self.assertNumQueries(0): with self.assertRaises(UndergroundBar.DoesNotExist): self.p1.undergroundbar + + def test_get_reverse_on_unsaved_object(self): + """ + Regression for #18153 and #19089. + + Accessing the reverse relation on an unsaved object + always raises an exception. + """ + p = Place() + + # When there's no instance of the origin of the one-to-one + with self.assertNumQueries(0): + with self.assertRaises(UndergroundBar.DoesNotExist): + p.undergroundbar + + UndergroundBar.objects.create() + + # When there's one instance of the origin + # (p.undergroundbar used to return that instance) + with self.assertNumQueries(0): + with self.assertRaises(UndergroundBar.DoesNotExist): + p.undergroundbar + + UndergroundBar.objects.create() + + # When there are several instances of the origin + with self.assertNumQueries(0): + with self.assertRaises(UndergroundBar.DoesNotExist): + p.undergroundbar + + def test_set_reverse_on_unsaved_object(self): + """ + Writing to the reverse relation on an unsaved object + is impossible too. + """ + p = Place() + b = UndergroundBar.objects.create() + with self.assertNumQueries(0): + with self.assertRaises(ValueError): + p.undergroundbar = b diff --git a/tests/regressiontests/queries/tests.py b/tests/regressiontests/queries/tests.py index 71ac107486..c2a4ad1caf 100644 --- a/tests/regressiontests/queries/tests.py +++ b/tests/regressiontests/queries/tests.py @@ -1698,6 +1698,13 @@ class EmptyQuerySetTests(TestCase): [] ) + def test_ticket_19151(self): + # #19151 -- Calling .values() or .values_list() on an EmptyQuerySet + # should return EmptyQuerySet and not cause an error. + q = EmptyQuerySet() + self.assertQuerysetEqual(q.values(), []) + self.assertQuerysetEqual(q.values_list(), []) + class ValuesQuerysetTests(BaseQuerysetTest): def test_flat_values_lits(self): diff --git a/tests/regressiontests/requests/tests.py b/tests/regressiontests/requests/tests.py index f9e1112b2e..6522620d5f 100644 --- a/tests/regressiontests/requests/tests.py +++ b/tests/regressiontests/requests/tests.py @@ -5,10 +5,11 @@ import warnings from datetime import datetime, timedelta from io import BytesIO -from django.conf import settings +from django.core.exceptions import SuspiciousOperation from django.core.handlers.wsgi import WSGIRequest, LimitedStream from django.http import HttpRequest, HttpResponse, parse_cookie, build_request_repr, UnreadablePostError -from django.test.utils import str_prefix +from django.test.client import FakePayload +from django.test.utils import override_settings, str_prefix from django.utils import unittest from django.utils.http import cookie_date from django.utils.timezone import utc @@ -56,7 +57,7 @@ class RequestsTests(unittest.TestCase): str_prefix("<WSGIRequest\npath:/otherpath/,\nGET:{%(_)s'a': %(_)s'b'},\nPOST:{%(_)s'c': %(_)s'd'},\nCOOKIES:{%(_)s'e': %(_)s'f'},\nMETA:{%(_)s'g': %(_)s'h'}>")) def test_parse_cookie(self): - self.assertEqual(parse_cookie('invalid:key=true'), {}) + self.assertEqual(parse_cookie('invalid@key=true'), {}) def test_httprequest_location(self): request = HttpRequest() @@ -68,93 +69,146 @@ class RequestsTests(unittest.TestCase): self.assertEqual(request.build_absolute_uri(location="/path/with:colons"), 'http://www.example.com/path/with:colons') + @override_settings(USE_X_FORWARDED_HOST=False) def test_http_get_host(self): - old_USE_X_FORWARDED_HOST = settings.USE_X_FORWARDED_HOST - try: - settings.USE_X_FORWARDED_HOST = False + # Check if X_FORWARDED_HOST is provided. + request = HttpRequest() + request.META = { + 'HTTP_X_FORWARDED_HOST': 'forward.com', + 'HTTP_HOST': 'example.com', + 'SERVER_NAME': 'internal.com', + 'SERVER_PORT': 80, + } + # X_FORWARDED_HOST is ignored. + self.assertEqual(request.get_host(), 'example.com') - # Check if X_FORWARDED_HOST is provided. - request = HttpRequest() - request.META = { - 'HTTP_X_FORWARDED_HOST': 'forward.com', - 'HTTP_HOST': 'example.com', - 'SERVER_NAME': 'internal.com', - 'SERVER_PORT': 80, - } - # X_FORWARDED_HOST is ignored. - self.assertEqual(request.get_host(), 'example.com') + # Check if X_FORWARDED_HOST isn't provided. + request = HttpRequest() + request.META = { + 'HTTP_HOST': 'example.com', + 'SERVER_NAME': 'internal.com', + 'SERVER_PORT': 80, + } + self.assertEqual(request.get_host(), 'example.com') - # Check if X_FORWARDED_HOST isn't provided. - request = HttpRequest() - request.META = { - 'HTTP_HOST': 'example.com', - 'SERVER_NAME': 'internal.com', - 'SERVER_PORT': 80, - } - self.assertEqual(request.get_host(), 'example.com') + # Check if HTTP_HOST isn't provided. + request = HttpRequest() + request.META = { + 'SERVER_NAME': 'internal.com', + 'SERVER_PORT': 80, + } + self.assertEqual(request.get_host(), 'internal.com') - # Check if HTTP_HOST isn't provided. - request = HttpRequest() - request.META = { - 'SERVER_NAME': 'internal.com', - 'SERVER_PORT': 80, - } - self.assertEqual(request.get_host(), 'internal.com') + # Check if HTTP_HOST isn't provided, and we're on a nonstandard port + request = HttpRequest() + request.META = { + 'SERVER_NAME': 'internal.com', + 'SERVER_PORT': 8042, + } + self.assertEqual(request.get_host(), 'internal.com:8042') + + # Poisoned host headers are rejected as suspicious + legit_hosts = [ + 'example.com', + 'example.com:80', + '12.34.56.78', + '12.34.56.78:443', + '[2001:19f0:feee::dead:beef:cafe]', + '[2001:19f0:feee::dead:beef:cafe]:8080', + ] - # Check if HTTP_HOST isn't provided, and we're on a nonstandard port + poisoned_hosts = [ + 'example.com@evil.tld', + 'example.com:dr.frankenstein@evil.tld', + 'example.com:someone@somestie.com:80', + 'example.com:80/badpath' + ] + + for host in legit_hosts: request = HttpRequest() request.META = { - 'SERVER_NAME': 'internal.com', - 'SERVER_PORT': 8042, + 'HTTP_HOST': host, } - self.assertEqual(request.get_host(), 'internal.com:8042') + request.get_host() - finally: - settings.USE_X_FORWARDED_HOST = old_USE_X_FORWARDED_HOST + for host in poisoned_hosts: + with self.assertRaises(SuspiciousOperation): + request = HttpRequest() + request.META = { + 'HTTP_HOST': host, + } + request.get_host() + @override_settings(USE_X_FORWARDED_HOST=True) def test_http_get_host_with_x_forwarded_host(self): - old_USE_X_FORWARDED_HOST = settings.USE_X_FORWARDED_HOST - try: - settings.USE_X_FORWARDED_HOST = True + # Check if X_FORWARDED_HOST is provided. + request = HttpRequest() + request.META = { + 'HTTP_X_FORWARDED_HOST': 'forward.com', + 'HTTP_HOST': 'example.com', + 'SERVER_NAME': 'internal.com', + 'SERVER_PORT': 80, + } + # X_FORWARDED_HOST is obeyed. + self.assertEqual(request.get_host(), 'forward.com') - # Check if X_FORWARDED_HOST is provided. - request = HttpRequest() - request.META = { - 'HTTP_X_FORWARDED_HOST': 'forward.com', - 'HTTP_HOST': 'example.com', - 'SERVER_NAME': 'internal.com', - 'SERVER_PORT': 80, - } - # X_FORWARDED_HOST is obeyed. - self.assertEqual(request.get_host(), 'forward.com') + # Check if X_FORWARDED_HOST isn't provided. + request = HttpRequest() + request.META = { + 'HTTP_HOST': 'example.com', + 'SERVER_NAME': 'internal.com', + 'SERVER_PORT': 80, + } + self.assertEqual(request.get_host(), 'example.com') - # Check if X_FORWARDED_HOST isn't provided. - request = HttpRequest() - request.META = { - 'HTTP_HOST': 'example.com', - 'SERVER_NAME': 'internal.com', - 'SERVER_PORT': 80, - } - self.assertEqual(request.get_host(), 'example.com') + # Check if HTTP_HOST isn't provided. + request = HttpRequest() + request.META = { + 'SERVER_NAME': 'internal.com', + 'SERVER_PORT': 80, + } + self.assertEqual(request.get_host(), 'internal.com') - # Check if HTTP_HOST isn't provided. - request = HttpRequest() - request.META = { - 'SERVER_NAME': 'internal.com', - 'SERVER_PORT': 80, - } - self.assertEqual(request.get_host(), 'internal.com') + # Check if HTTP_HOST isn't provided, and we're on a nonstandard port + request = HttpRequest() + request.META = { + 'SERVER_NAME': 'internal.com', + 'SERVER_PORT': 8042, + } + self.assertEqual(request.get_host(), 'internal.com:8042') + + # Poisoned host headers are rejected as suspicious + legit_hosts = [ + 'example.com', + 'example.com:80', + '12.34.56.78', + '12.34.56.78:443', + '[2001:19f0:feee::dead:beef:cafe]', + '[2001:19f0:feee::dead:beef:cafe]:8080', + ] - # Check if HTTP_HOST isn't provided, and we're on a nonstandard port + poisoned_hosts = [ + 'example.com@evil.tld', + 'example.com:dr.frankenstein@evil.tld', + 'example.com:dr.frankenstein@evil.tld:80', + 'example.com:80/badpath' + ] + + for host in legit_hosts: request = HttpRequest() request.META = { - 'SERVER_NAME': 'internal.com', - 'SERVER_PORT': 8042, + 'HTTP_HOST': host, } - self.assertEqual(request.get_host(), 'internal.com:8042') + request.get_host() + + for host in poisoned_hosts: + with self.assertRaises(SuspiciousOperation): + request = HttpRequest() + request.META = { + 'HTTP_HOST': host, + } + request.get_host() - finally: - settings.USE_X_FORWARDED_HOST = old_USE_X_FORWARDED_HOST def test_near_expiration(self): "Cookie will expire when an near expiration time is provided" @@ -263,10 +317,11 @@ class RequestsTests(unittest.TestCase): self.assertEqual(stream.read(), b'') def test_stream(self): - payload = b'name=value' + payload = FakePayload('name=value') request = WSGIRequest({'REQUEST_METHOD': 'POST', + 'CONTENT_TYPE': 'application/x-www-form-urlencoded', 'CONTENT_LENGTH': len(payload), - 'wsgi.input': BytesIO(payload)}) + 'wsgi.input': payload}) self.assertEqual(request.read(), b'name=value') def test_read_after_value(self): @@ -274,10 +329,11 @@ class RequestsTests(unittest.TestCase): Reading from request is allowed after accessing request contents as POST or body. """ - payload = b'name=value' + payload = FakePayload('name=value') request = WSGIRequest({'REQUEST_METHOD': 'POST', + 'CONTENT_TYPE': 'application/x-www-form-urlencoded', 'CONTENT_LENGTH': len(payload), - 'wsgi.input': BytesIO(payload)}) + 'wsgi.input': payload}) self.assertEqual(request.POST, {'name': ['value']}) self.assertEqual(request.body, b'name=value') self.assertEqual(request.read(), b'name=value') @@ -287,10 +343,11 @@ class RequestsTests(unittest.TestCase): Construction of POST or body is not allowed after reading from request. """ - payload = b'name=value' + payload = FakePayload('name=value') request = WSGIRequest({'REQUEST_METHOD': 'POST', + 'CONTENT_TYPE': 'application/x-www-form-urlencoded', 'CONTENT_LENGTH': len(payload), - 'wsgi.input': BytesIO(payload)}) + 'wsgi.input': payload}) self.assertEqual(request.read(2), b'na') self.assertRaises(Exception, lambda: request.body) self.assertEqual(request.POST, {}) @@ -302,17 +359,17 @@ class RequestsTests(unittest.TestCase): # Because multipart is used for large amounts fo data i.e. file uploads, # we don't want the data held in memory twice, and we don't want to # silence the error by setting body = '' either. - payload = "\r\n".join([ + payload = FakePayload("\r\n".join([ '--boundary', 'Content-Disposition: form-data; name="name"', '', 'value', '--boundary--' - '']).encode('utf-8') + ''])) request = WSGIRequest({'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': 'multipart/form-data; boundary=boundary', 'CONTENT_LENGTH': len(payload), - 'wsgi.input': BytesIO(payload)}) + 'wsgi.input': payload}) self.assertEqual(request.POST, {'name': ['value']}) self.assertRaises(Exception, lambda: request.body) @@ -324,34 +381,54 @@ class RequestsTests(unittest.TestCase): # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13 # Every request.POST with Content-Length >= 0 is a valid request, # this test ensures that we handle Content-Length == 0. - payload = "\r\n".join([ + payload = FakePayload("\r\n".join([ '--boundary', 'Content-Disposition: form-data; name="name"', '', 'value', '--boundary--' - '']).encode('utf-8') + ''])) request = WSGIRequest({'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': 'multipart/form-data; boundary=boundary', 'CONTENT_LENGTH': 0, - 'wsgi.input': BytesIO(payload)}) + 'wsgi.input': payload}) + self.assertEqual(request.POST, {}) + + def test_POST_binary_only(self): + payload = b'\r\n\x01\x00\x00\x00ab\x00\x00\xcd\xcc,@' + environ = {'REQUEST_METHOD': 'POST', + 'CONTENT_TYPE': 'application/octet-stream', + 'CONTENT_LENGTH': len(payload), + 'wsgi.input': BytesIO(payload)} + request = WSGIRequest(environ) self.assertEqual(request.POST, {}) + self.assertEqual(request.FILES, {}) + self.assertEqual(request.body, payload) + + # Same test without specifying content-type + environ.update({'CONTENT_TYPE': '', 'wsgi.input': BytesIO(payload)}) + request = WSGIRequest(environ) + self.assertEqual(request.POST, {}) + self.assertEqual(request.FILES, {}) + self.assertEqual(request.body, payload) def test_read_by_lines(self): - payload = b'name=value' + payload = FakePayload('name=value') request = WSGIRequest({'REQUEST_METHOD': 'POST', + 'CONTENT_TYPE': 'application/x-www-form-urlencoded', 'CONTENT_LENGTH': len(payload), - 'wsgi.input': BytesIO(payload)}) + 'wsgi.input': payload}) self.assertEqual(list(request), [b'name=value']) def test_POST_after_body_read(self): """ POST should be populated even if body is read first """ - payload = b'name=value' + payload = FakePayload('name=value') request = WSGIRequest({'REQUEST_METHOD': 'POST', + 'CONTENT_TYPE': 'application/x-www-form-urlencoded', 'CONTENT_LENGTH': len(payload), - 'wsgi.input': BytesIO(payload)}) + 'wsgi.input': payload}) raw_data = request.body self.assertEqual(request.POST, {'name': ['value']}) @@ -360,10 +437,11 @@ class RequestsTests(unittest.TestCase): POST should be populated even if body is read first, and then the stream is read second. """ - payload = b'name=value' + payload = FakePayload('name=value') request = WSGIRequest({'REQUEST_METHOD': 'POST', + 'CONTENT_TYPE': 'application/x-www-form-urlencoded', 'CONTENT_LENGTH': len(payload), - 'wsgi.input': BytesIO(payload)}) + 'wsgi.input': payload}) raw_data = request.body self.assertEqual(request.read(1), b'n') self.assertEqual(request.POST, {'name': ['value']}) @@ -373,17 +451,17 @@ class RequestsTests(unittest.TestCase): POST should be populated even if body is read first, and then the stream is read second. Using multipart/form-data instead of urlencoded. """ - payload = "\r\n".join([ + payload = FakePayload("\r\n".join([ '--boundary', 'Content-Disposition: form-data; name="name"', '', 'value', '--boundary--' - '']).encode('utf-8') + ''])) request = WSGIRequest({'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': 'multipart/form-data; boundary=boundary', 'CONTENT_LENGTH': len(payload), - 'wsgi.input': BytesIO(payload)}) + 'wsgi.input': payload}) raw_data = request.body # Consume enough data to mess up the parsing: self.assertEqual(request.read(13), b'--boundary\r\nC') @@ -393,11 +471,11 @@ class RequestsTests(unittest.TestCase): """ HttpRequest.raw_post_body should be the same as HttpRequest.body """ - payload = b'Hello There!' + payload = FakePayload('Hello There!') request = WSGIRequest({ 'REQUEST_METHOD': 'POST', 'CONTENT_LENGTH': len(payload), - 'wsgi.input': BytesIO(payload) + 'wsgi.input': payload, }) with warnings.catch_warnings(record=True): @@ -414,6 +492,7 @@ class RequestsTests(unittest.TestCase): payload = b'name=value' request = WSGIRequest({'REQUEST_METHOD': 'POST', + 'CONTENT_TYPE': 'application/x-www-form-urlencoded', 'CONTENT_LENGTH': len(payload), 'wsgi.input': ExplodingBytesIO(payload)}) diff --git a/tests/regressiontests/servers/tests.py b/tests/regressiontests/servers/tests.py index c90c785a6e..f54e34ce28 100644 --- a/tests/regressiontests/servers/tests.py +++ b/tests/regressiontests/servers/tests.py @@ -1,6 +1,9 @@ +# -*- encoding: utf-8 -*- """ Tests for django.core.servers. """ +from __future__ import unicode_literals + import os try: from urllib.request import urlopen, HTTPError @@ -11,6 +14,7 @@ from django.core.exceptions import ImproperlyConfigured from django.test import LiveServerTestCase from django.core.servers.basehttp import WSGIServerException from django.test.utils import override_settings +from django.utils.http import urlencode from .models import Person @@ -134,6 +138,10 @@ class LiveServerViews(LiveServerBase): f = self.urlopen('/media/example_media_file.txt') self.assertEqual(f.read().rstrip(b'\r\n'), b'example media file') + def test_environ(self): + f = self.urlopen('/environ_view/?%s' % urlencode({'q': 'тест'})) + self.assertIn(b"QUERY_STRING: 'q=%D1%82%D0%B5%D1%81%D1%82'", f.read()) + class LiveServerDatabase(LiveServerBase): diff --git a/tests/regressiontests/servers/urls.py b/tests/regressiontests/servers/urls.py index c8ca1ac7a4..a857c45f95 100644 --- a/tests/regressiontests/servers/urls.py +++ b/tests/regressiontests/servers/urls.py @@ -9,4 +9,5 @@ urlpatterns = patterns('', url(r'^example_view/$', views.example_view), url(r'^model_view/$', views.model_view), url(r'^create_model_instance/$', views.create_model_instance), -)
\ No newline at end of file + url(r'^environ_view/$', views.environ_view), +) diff --git a/tests/regressiontests/servers/views.py b/tests/regressiontests/servers/views.py index 94a4f2d9ef..00baf4b5ac 100644 --- a/tests/regressiontests/servers/views.py +++ b/tests/regressiontests/servers/views.py @@ -14,4 +14,8 @@ def model_view(request): def create_model_instance(request): person = Person(name='emily') person.save() - return HttpResponse('')
\ No newline at end of file + return HttpResponse('') + + +def environ_view(request): + return HttpResponse("\n".join(["%s: %r" % (k, v) for k, v in request.environ.items()])) diff --git a/tests/regressiontests/syndication/feeds.py b/tests/regressiontests/syndication/feeds.py index 748420c9d2..04a67f4bdb 100644 --- a/tests/regressiontests/syndication/feeds.py +++ b/tests/regressiontests/syndication/feeds.py @@ -46,6 +46,14 @@ class TestRss091Feed(TestRss2Feed): feed_type = feedgenerator.RssUserland091Feed +class TestNoPubdateFeed(views.Feed): + title = 'Test feed' + link = '/feed/' + + def items(self): + return Entry.objects.all() + + class TestAtomFeed(TestRss2Feed): feed_type = feedgenerator.Atom1Feed subtitle = TestRss2Feed.description diff --git a/tests/regressiontests/syndication/tests.py b/tests/regressiontests/syndication/tests.py index 1790d8cae6..10413b4ddd 100644 --- a/tests/regressiontests/syndication/tests.py +++ b/tests/regressiontests/syndication/tests.py @@ -226,6 +226,14 @@ class SyndicationFeedTest(FeedTestCase): updated = doc.getElementsByTagName('updated')[0].firstChild.wholeText self.assertEqual(updated[-6:], '+00:42') + def test_feed_last_modified_time(self): + response = self.client.get('/syndication/naive-dates/') + self.assertEqual(response['Last-Modified'], 'Thu, 03 Jan 2008 19:30:00 GMT') + + # No last-modified when feed has no item_pubdate + response = self.client.get('/syndication/no_pubdate/') + self.assertFalse(response.has_header('Last-Modified')) + def test_feed_url(self): """ Test that the feed_url can be overridden. diff --git a/tests/regressiontests/syndication/urls.py b/tests/regressiontests/syndication/urls.py index 2199e29f06..57f9d81a73 100644 --- a/tests/regressiontests/syndication/urls.py +++ b/tests/regressiontests/syndication/urls.py @@ -9,6 +9,7 @@ urlpatterns = patterns('django.contrib.syndication.views', (r'^syndication/complex/(?P<foo>.*)/$', feeds.ComplexFeed()), (r'^syndication/rss2/$', feeds.TestRss2Feed()), (r'^syndication/rss091/$', feeds.TestRss091Feed()), + (r'^syndication/no_pubdate/$', feeds.TestNoPubdateFeed()), (r'^syndication/atom/$', feeds.TestAtomFeed()), (r'^syndication/custom/$', feeds.TestCustomFeed()), (r'^syndication/naive-dates/$', feeds.NaiveDatesFeed()), diff --git a/tests/regressiontests/templates/tests.py b/tests/regressiontests/templates/tests.py index 41f40e7467..c95b5bfa3c 100644 --- a/tests/regressiontests/templates/tests.py +++ b/tests/regressiontests/templates/tests.py @@ -155,16 +155,8 @@ class UTF8Class: def __str__(self): return 'ŠĐĆŽćžšđ' +@override_settings(MEDIA_URL="/media/", STATIC_URL="/static/") class Templates(unittest.TestCase): - def setUp(self): - self.old_static_url = settings.STATIC_URL - self.old_media_url = settings.MEDIA_URL - settings.STATIC_URL = "/static/" - settings.MEDIA_URL = "/media/" - - def tearDown(self): - settings.STATIC_URL = self.old_static_url - settings.MEDIA_URL = self.old_media_url def test_loaders_security(self): ad_loader = app_directories.Loader() @@ -229,11 +221,11 @@ class Templates(unittest.TestCase): loader.template_source_loaders = (filesystem.Loader(),) # We rely on the fact that runtests.py sets up TEMPLATE_DIRS to - # point to a directory containing a 404.html file. Also that + # point to a directory containing a login.html file. Also that # the file system and app directories loaders both inherit the # load_template method from the BaseLoader class, so we only need # to test one of them. - load_name = '404.html' + load_name = 'login.html' template = loader.get_template(load_name) template_name = template.nodelist[0].source[0].name self.assertTrue(template_name.endswith(load_name), diff --git a/tests/regressiontests/test_client_regress/tests.py b/tests/regressiontests/test_client_regress/tests.py index d80293b358..f424321663 100644 --- a/tests/regressiontests/test_client_regress/tests.py +++ b/tests/regressiontests/test_client_regress/tests.py @@ -16,6 +16,7 @@ from django.test import Client, TestCase from django.test.client import encode_file, RequestFactory from django.test.utils import ContextList, override_settings, str_prefix from django.template.response import SimpleTemplateResponse +from django.utils.translation import ugettext_lazy from django.http import HttpResponse @@ -129,6 +130,14 @@ class AssertContainsTests(TestCase): self.assertNotContains(r, 'はたけ') self.assertNotContains(r, b'\xe3\x81\xaf\xe3\x81\x9f\xe3\x81\x91'.decode('utf-8')) + def test_nontext_contains(self): + r = self.client.get('/test_client_regress/no_template_view/') + self.assertContains(r, ugettext_lazy('once')) + + def test_nontext_not_contains(self): + r = self.client.get('/test_client_regress/no_template_view/') + self.assertNotContains(r, ugettext_lazy('never')) + def test_assert_contains_renders_template_response(self): """ Test that we can pass in an unrendered SimpleTemplateReponse without throwing an error. @@ -490,11 +499,11 @@ class AssertFormErrorTests(TestCase): try: self.assertFormError(response, 'form', 'email', 'Some error.') except AssertionError as e: - self.assertIn(str_prefix("The field 'email' on form 'form' in context 0 does not contain the error 'Some error.' (actual errors: [%(_)s'Enter a valid e-mail address.'])"), str(e)) + self.assertIn(str_prefix("The field 'email' on form 'form' in context 0 does not contain the error 'Some error.' (actual errors: [%(_)s'Enter a valid email address.'])"), str(e)) try: self.assertFormError(response, 'form', 'email', 'Some error.', msg_prefix='abc') except AssertionError as e: - self.assertIn(str_prefix("abc: The field 'email' on form 'form' in context 0 does not contain the error 'Some error.' (actual errors: [%(_)s'Enter a valid e-mail address.'])"), str(e)) + self.assertIn(str_prefix("abc: The field 'email' on form 'form' in context 0 does not contain the error 'Some error.' (actual errors: [%(_)s'Enter a valid email address.'])"), str(e)) def test_unknown_nonfield_error(self): """ @@ -619,15 +628,6 @@ class TemplateExceptionTests(TestCase): if hasattr(template_loader, 'reset'): template_loader.reset() - @override_settings(TEMPLATE_DIRS=(),) - def test_no_404_template(self): - "Missing templates are correctly reported by test client" - try: - response = self.client.get("/no_such_view/") - self.fail("Should get error about missing template") - except TemplateDoesNotExist: - pass - @override_settings( TEMPLATE_DIRS=(os.path.join(os.path.dirname(__file__), 'bad_templates'),) ) diff --git a/tests/regressiontests/test_utils/tests.py b/tests/regressiontests/test_utils/tests.py index 468af77f44..95913b5aab 100644 --- a/tests/regressiontests/test_utils/tests.py +++ b/tests/regressiontests/test_utils/tests.py @@ -450,6 +450,46 @@ class HTMLEqualTests(TestCase): self.assertContains(response, '<p class="help">Some help text for the title (with unicode ŠĐĆŽćžšđ)</p>', html=True) +class XMLEqualTests(TestCase): + def test_simple_equal(self): + xml1 = "<elem attr1='a' attr2='b' />" + xml2 = "<elem attr1='a' attr2='b' />" + self.assertXMLEqual(xml1, xml2) + + def test_simple_equal_unordered(self): + xml1 = "<elem attr1='a' attr2='b' />" + xml2 = "<elem attr2='b' attr1='a' />" + self.assertXMLEqual(xml1, xml2) + + def test_simple_equal_raise(self): + xml1 = "<elem attr1='a' />" + xml2 = "<elem attr2='b' attr1='a' />" + with self.assertRaises(AssertionError): + self.assertXMLEqual(xml1, xml2) + + def test_simple_not_equal(self): + xml1 = "<elem attr1='a' attr2='c' />" + xml2 = "<elem attr1='a' attr2='b' />" + self.assertXMLNotEqual(xml1, xml2) + + def test_simple_not_equal_raise(self): + xml1 = "<elem attr1='a' attr2='b' />" + xml2 = "<elem attr2='b' attr1='a' />" + with self.assertRaises(AssertionError): + self.assertXMLNotEqual(xml1, xml2) + + def test_parsing_errors(self): + xml_unvalid = "<elem attr1='a attr2='b' />" + xml2 = "<elem attr2='b' attr1='a' />" + with self.assertRaises(AssertionError): + self.assertXMLNotEqual(xml_unvalid, xml2) + + def test_comment_root(self): + xml1 = "<?xml version='1.0'?><!-- comment1 --><elem attr1='a' attr2='b' />" + xml2 = "<?xml version='1.0'?><!-- comment2 --><elem attr2='b' attr1='a' />" + self.assertXMLEqual(xml1, xml2) + + class SkippingExtraTests(TestCase): fixtures = ['should_not_be_loaded.json'] @@ -476,7 +516,7 @@ class AssertRaisesMsgTest(SimpleTestCase): class AssertFieldOutputTests(SimpleTestCase): def test_assert_field_output(self): - error_invalid = ['Enter a valid e-mail address.'] + error_invalid = ['Enter a valid email address.'] self.assertFieldOutput(EmailField, {'a@a.com': 'a@a.com'}, {'aaa': error_invalid}) self.assertRaises(AssertionError, self.assertFieldOutput, EmailField, {'a@a.com': 'a@a.com'}, {'aaa': error_invalid + ['Another error']}) self.assertRaises(AssertionError, self.assertFieldOutput, EmailField, {'a@a.com': 'Wrong output'}, {'aaa': error_invalid}) diff --git a/tests/regressiontests/urlpatterns_reverse/namespace_urls.py b/tests/regressiontests/urlpatterns_reverse/namespace_urls.py index fa892a4346..ab2e77af24 100644 --- a/tests/regressiontests/urlpatterns_reverse/namespace_urls.py +++ b/tests/regressiontests/urlpatterns_reverse/namespace_urls.py @@ -28,6 +28,7 @@ otherobj2 = URLObject('nodefault', 'other-ns2') urlpatterns = patterns('regressiontests.urlpatterns_reverse.views', url(r'^normal/$', 'empty_view', name='normal-view'), url(r'^normal/(?P<arg1>\d+)/(?P<arg2>\d+)/$', 'empty_view', name='normal-view'), + url(r'^resolver_match/$', 'pass_resolver_match_view', name='test-resolver-match'), url(r'^\+\\\$\*/$', 'empty_view', name='special-view'), diff --git a/tests/regressiontests/urlpatterns_reverse/tests.py b/tests/regressiontests/urlpatterns_reverse/tests.py index 0ea5ffe380..234897d267 100644 --- a/tests/regressiontests/urlpatterns_reverse/tests.py +++ b/tests/regressiontests/urlpatterns_reverse/tests.py @@ -512,6 +512,11 @@ class ResolverMatchTests(TestCase): self.assertEqual(match[1], args) self.assertEqual(match[2], kwargs) + def test_resolver_match_on_request(self): + response = self.client.get('/resolver_match/') + resolver_match = response.resolver_match + self.assertEqual(resolver_match.url_name, 'test-resolver-match') + class ErroneousViewTests(TestCase): urls = 'regressiontests.urlpatterns_reverse.erroneous_urls' diff --git a/tests/regressiontests/urlpatterns_reverse/views.py b/tests/regressiontests/urlpatterns_reverse/views.py index f631acf3ec..88d169a118 100644 --- a/tests/regressiontests/urlpatterns_reverse/views.py +++ b/tests/regressiontests/urlpatterns_reverse/views.py @@ -19,6 +19,11 @@ def defaults_view(request, arg1, arg2): def erroneous_view(request): import non_existent +def pass_resolver_match_view(request, *args, **kwargs): + response = HttpResponse('') + response.resolver_match = request.resolver_match + return response + uncallable = "Can I be a view? Pleeeease?" class ViewClass(object): diff --git a/tests/regressiontests/utils/datastructures.py b/tests/regressiontests/utils/datastructures.py index dbc65d37a8..f65fc5c770 100644 --- a/tests/regressiontests/utils/datastructures.py +++ b/tests/regressiontests/utils/datastructures.py @@ -128,6 +128,12 @@ class SortedDictTests(SimpleTestCase): self.assertEqual(self.d1, {}) self.assertEqual(self.d1.keyOrder, []) + def test_reversed(self): + self.assertEqual(list(self.d1), [7, 1, 9]) + self.assertEqual(list(self.d2), [1, 9, 0, 7]) + self.assertEqual(list(reversed(self.d1)), [9, 1, 7]) + self.assertEqual(list(reversed(self.d2)), [7, 0, 9, 1]) + def test_insert(self): d = SortedDict() with warnings.catch_warnings(record=True) as w: @@ -206,19 +212,18 @@ class MultiValueDictTests(SimpleTestCase): self.assertEqual(d['name'], 'Simon') self.assertEqual(d.get('name'), 'Simon') self.assertEqual(d.getlist('name'), ['Adrian', 'Simon']) - self.assertEqual(list(six.iteritems(d)), - [('position', 'Developer'), ('name', 'Simon')]) + self.assertEqual(sorted(list(six.iteritems(d))), + [('name', 'Simon'), ('position', 'Developer')]) - self.assertEqual(list(six.iterlists(d)), - [('position', ['Developer']), - ('name', ['Adrian', 'Simon'])]) + self.assertEqual(sorted(list(six.iterlists(d))), + [('name', ['Adrian', 'Simon']), + ('position', ['Developer'])]) # MultiValueDictKeyError: "Key 'lastname' not found in # <MultiValueDict: {'position': ['Developer'], # 'name': ['Adrian', 'Simon']}>" - self.assertRaisesMessage(MultiValueDictKeyError, - '"Key \'lastname\' not found in <MultiValueDict: {\'position\':'\ - ' [\'Developer\'], \'name\': [\'Adrian\', \'Simon\']}>"', + six.assertRaisesRegex(self, MultiValueDictKeyError, + r'"Key \'lastname\' not found in <MultiValueDict', d.__getitem__, 'lastname') self.assertEqual(d.get('lastname'), None) @@ -229,8 +234,8 @@ class MultiValueDictTests(SimpleTestCase): d.setlist('lastname', ['Holovaty', 'Willison']) self.assertEqual(d.getlist('lastname'), ['Holovaty', 'Willison']) - self.assertEqual(list(six.itervalues(d)), - ['Developer', 'Simon', 'Willison']) + self.assertEqual(sorted(list(six.itervalues(d))), + ['Developer', 'Simon', 'Willison']) def test_appendlist(self): d = MultiValueDict() diff --git a/tests/regressiontests/utils/dateformat.py b/tests/regressiontests/utils/dateformat.py index 0f18bb2a4d..0f4fd67f6f 100644 --- a/tests/regressiontests/utils/dateformat.py +++ b/tests/regressiontests/utils/dateformat.py @@ -72,6 +72,11 @@ class DateFormatTests(unittest.TestCase): self.assertEqual(dateformat.format(my_birthday, 'a'), 'p.m.') + def test_microsecond(self): + # Regression test for #18951 + dt = datetime(2009, 5, 16, microsecond=123) + self.assertEqual(dateformat.format(dt, 'u'), '000123') + def test_date_formats(self): my_birthday = datetime(1979, 7, 8, 22, 00) timestamp = datetime(2008, 5, 19, 11, 45, 23, 123456) diff --git a/tests/regressiontests/utils/html.py b/tests/regressiontests/utils/html.py index 98df80a5e2..6a93dff85e 100644 --- a/tests/regressiontests/utils/html.py +++ b/tests/regressiontests/utils/html.py @@ -154,4 +154,4 @@ class TestUtilsHtml(unittest.TestCase): ("<a>x</a> <p><b>y</b></p>", "a b", "x <p>y</p>"), ) for value, tags, output in items: - self.assertEquals(f(value, tags), output) + self.assertEqual(f(value, tags), output) diff --git a/tests/regressiontests/utils/http.py b/tests/regressiontests/utils/http.py index f22e05496d..6d3bc025af 100644 --- a/tests/regressiontests/utils/http.py +++ b/tests/regressiontests/utils/http.py @@ -1,3 +1,4 @@ +from datetime import datetime import sys from django.http import HttpResponse, utils @@ -7,6 +8,7 @@ from django.utils import http from django.utils import six from django.utils import unittest + class TestUtilsHttp(unittest.TestCase): def test_same_origin_true(self): @@ -132,3 +134,30 @@ class TestUtilsHttp(unittest.TestCase): for n, b36 in [(0, '0'), (1, '1'), (42, '16'), (818469960, 'django')]: self.assertEqual(http.int_to_base36(n), b36) self.assertEqual(http.base36_to_int(b36), n) + + +class ETagProcessingTests(unittest.TestCase): + def testParsing(self): + etags = http.parse_etags(r'"", "etag", "e\"t\"ag", "e\\tag", W/"weak"') + self.assertEqual(etags, ['', 'etag', 'e"t"ag', r'e\tag', 'weak']) + + def testQuoting(self): + quoted_etag = http.quote_etag(r'e\t"ag') + self.assertEqual(quoted_etag, r'"e\\t\"ag"') + + +class HttpDateProcessingTests(unittest.TestCase): + def testParsingRfc1123(self): + parsed = http.parse_http_date('Sun, 06 Nov 1994 08:49:37 GMT') + self.assertEqual(datetime.utcfromtimestamp(parsed), + datetime(1994, 11, 6, 8, 49, 37)) + + def testParsingRfc850(self): + parsed = http.parse_http_date('Sunday, 06-Nov-94 08:49:37 GMT') + self.assertEqual(datetime.utcfromtimestamp(parsed), + datetime(1994, 11, 6, 8, 49, 37)) + + def testParsingAsctime(self): + parsed = http.parse_http_date('Sun Nov 6 08:49:37 1994') + self.assertEqual(datetime.utcfromtimestamp(parsed), + datetime(1994, 11, 6, 8, 49, 37)) diff --git a/tests/regressiontests/utils/numberformat.py b/tests/regressiontests/utils/numberformat.py new file mode 100644 index 0000000000..f9d9031e48 --- /dev/null +++ b/tests/regressiontests/utils/numberformat.py @@ -0,0 +1,47 @@ +from unittest import TestCase +from django.utils.numberformat import format as nformat +from sys import float_info + + +class TestNumberFormat(TestCase): + + def test_format_number(self): + self.assertEqual(nformat(1234, '.'), '1234') + self.assertEqual(nformat(1234.2, '.'), '1234.2') + self.assertEqual(nformat(1234, '.', decimal_pos=2), '1234.00') + self.assertEqual(nformat(1234, '.', grouping=2, thousand_sep=','), + '1234') + self.assertEqual(nformat(1234, '.', grouping=2, thousand_sep=',', + force_grouping=True), '12,34') + self.assertEqual(nformat(-1234.33, '.', decimal_pos=1), '-1234.3') + + def test_format_string(self): + self.assertEqual(nformat('1234', '.'), '1234') + self.assertEqual(nformat('1234.2', '.'), '1234.2') + self.assertEqual(nformat('1234', '.', decimal_pos=2), '1234.00') + self.assertEqual(nformat('1234', '.', grouping=2, thousand_sep=','), + '1234') + self.assertEqual(nformat('1234', '.', grouping=2, thousand_sep=',', + force_grouping=True), '12,34') + self.assertEqual(nformat('-1234.33', '.', decimal_pos=1), '-1234.3') + + def test_large_number(self): + most_max = ('{0}179769313486231570814527423731704356798070567525844996' + '598917476803157260780028538760589558632766878171540458953' + '514382464234321326889464182768467546703537516986049910576' + '551282076245490090389328944075868508455133942304583236903' + '222948165808559332123348274797826204144723168738177180919' + '29988125040402618412485836{1}') + most_max2 = ('{0}35953862697246314162905484746340871359614113505168999' + '31978349536063145215600570775211791172655337563430809179' + '07028764928468642653778928365536935093407075033972099821' + '15310256415249098018077865788815173701691026788460916647' + '38064458963316171186642466965495956524082894463374763543' + '61838599762500808052368249716736') + int_max = int(float_info.max) + self.assertEqual(nformat(int_max, '.'), most_max.format('', '8')) + self.assertEqual(nformat(int_max + 1, '.'), most_max.format('', '9')) + self.assertEqual(nformat(int_max * 2, '.'), most_max2.format('')) + self.assertEqual(nformat(0 - int_max, '.'), most_max.format('-', '8')) + self.assertEqual(nformat(-1 - int_max, '.'), most_max.format('-', '9')) + self.assertEqual(nformat(-2 * int_max, '.'), most_max2.format('-')) diff --git a/tests/regressiontests/utils/tests.py b/tests/regressiontests/utils/tests.py index 061c669eb7..11dd7c320e 100644 --- a/tests/regressiontests/utils/tests.py +++ b/tests/regressiontests/utils/tests.py @@ -17,10 +17,11 @@ from .encoding import TestEncodingUtils from .feedgenerator import FeedgeneratorTest from .functional import FunctionalTestCase from .html import TestUtilsHtml -from .http import TestUtilsHttp +from .http import TestUtilsHttp, ETagProcessingTests, HttpDateProcessingTests from .ipv6 import TestUtilsIPv6 from .jslex import JsToCForGettextTest, JsTokensTest from .module_loading import CustomLoader, DefaultLoader, EggLoader +from .numberformat import TestNumberFormat from .os_utils import SafeJoinTests from .regex_helper import NormalizeTests from .simplelazyobject import TestUtilsSimpleLazyObject diff --git a/tests/regressiontests/views/tests/__init__.py b/tests/regressiontests/views/tests/__init__.py index 63db5da2a3..12d0c59014 100644 --- a/tests/regressiontests/views/tests/__init__.py +++ b/tests/regressiontests/views/tests/__init__.py @@ -7,4 +7,4 @@ from .defaults import DefaultsTests from .i18n import JsI18NTests, I18NTests, JsI18NTestsMultiPackage from .shortcuts import ShortcutTests from .specials import URLHandling -from .static import StaticHelperTest, StaticTests +from .static import StaticHelperTest, StaticUtilsTests, StaticTests diff --git a/tests/regressiontests/views/tests/debug.py b/tests/regressiontests/views/tests/debug.py index 8592b07efe..e616d184b8 100644 --- a/tests/regressiontests/views/tests/debug.py +++ b/tests/regressiontests/views/tests/debug.py @@ -1,3 +1,6 @@ +# -*- coding: utf-8 -*- +# This coding header is significant for tests, as the debug view is parsing +# files to search for such a header to decode the source file content from __future__ import absolute_import, unicode_literals import inspect diff --git a/tests/regressiontests/views/tests/defaults.py b/tests/regressiontests/views/tests/defaults.py index 2dd40b4a1a..3ca7f79136 100644 --- a/tests/regressiontests/views/tests/defaults.py +++ b/tests/regressiontests/views/tests/defaults.py @@ -1,7 +1,8 @@ -from __future__ import absolute_import +from __future__ import absolute_import, unicode_literals -from django.test import TestCase from django.contrib.contenttypes.models import ContentType +from django.test import TestCase +from django.test.utils import setup_test_template_loader, restore_template_loaders from ..models import Author, Article, UrlArticle @@ -71,6 +72,23 @@ class DefaultsTests(TestCase): response = self.client.get('/views/server_error/') self.assertEqual(response.status_code, 500) + def test_custom_templates(self): + """ + Test that 404.html and 500.html templates are picked by their respective + handler. + """ + setup_test_template_loader( + {'404.html': 'This is a test template for a 404 error.', + '500.html': 'This is a test template for a 500 error.'} + ) + try: + for code, url in ((404, '/views/non_existing_url/'), (500, '/views/server_error/')): + response = self.client.get(url) + self.assertContains(response, "test template for a %d error" % code, + status_code=code) + finally: + restore_template_loaders() + def test_get_absolute_url_attributes(self): "A model can set attributes on the get_absolute_url method" self.assertTrue(getattr(UrlArticle.get_absolute_url, 'purge', False), diff --git a/tests/regressiontests/views/tests/static.py b/tests/regressiontests/views/tests/static.py index 9d87ade137..8b8ef8ba9b 100644 --- a/tests/regressiontests/views/tests/static.py +++ b/tests/regressiontests/views/tests/static.py @@ -2,54 +2,59 @@ from __future__ import absolute_import import mimetypes from os import path +import unittest -from django.conf import settings from django.conf.urls.static import static -from django.test import TestCase from django.http import HttpResponseNotModified +from django.test import TestCase +from django.test.utils import override_settings +from django.utils.http import http_date +from django.views.static import was_modified_since from .. import urls from ..urls import media_dir +@override_settings(DEBUG=True) class StaticTests(TestCase): """Tests django views in django/views/static.py""" - def setUp(self): - self.prefix = 'site_media' - self.old_debug = settings.DEBUG - settings.DEBUG = True - - def tearDown(self): - settings.DEBUG = self.old_debug + prefix = 'site_media' def test_serve(self): "The static view can serve static media" media_files = ['file.txt', 'file.txt.gz'] for filename in media_files: response = self.client.get('/views/%s/%s' % (self.prefix, filename)) + response_content = b''.join(response) + response.close() file_path = path.join(media_dir, filename) with open(file_path, 'rb') as fp: - self.assertEqual(fp.read(), response.content) - self.assertEqual(len(response.content), int(response['Content-Length'])) + self.assertEqual(fp.read(), response_content) + self.assertEqual(len(response_content), int(response['Content-Length'])) self.assertEqual(mimetypes.guess_type(file_path)[1], response.get('Content-Encoding', None)) def test_unknown_mime_type(self): response = self.client.get('/views/%s/file.unknown' % self.prefix) + response.close() self.assertEqual('application/octet-stream', response['Content-Type']) def test_copes_with_empty_path_component(self): file_name = 'file.txt' response = self.client.get('/views/%s//%s' % (self.prefix, file_name)) + response_content = b''.join(response) + response.close() with open(path.join(media_dir, file_name), 'rb') as fp: - self.assertEqual(fp.read(), response.content) + self.assertEqual(fp.read(), response_content) def test_is_modified_since(self): file_name = 'file.txt' response = self.client.get('/views/%s/%s' % (self.prefix, file_name), HTTP_IF_MODIFIED_SINCE='Thu, 1 Jan 1970 00:00:00 GMT') + response_content = b''.join(response) + response.close() with open(path.join(media_dir, file_name), 'rb') as fp: - self.assertEqual(fp.read(), response.content) + self.assertEqual(fp.read(), response_content) def test_not_modified_since(self): file_name = 'file.txt' @@ -71,9 +76,11 @@ class StaticTests(TestCase): invalid_date = 'Mon, 28 May 999999999999 28:25:26 GMT' response = self.client.get('/views/%s/%s' % (self.prefix, file_name), HTTP_IF_MODIFIED_SINCE=invalid_date) + response_content = b''.join(response) + response.close() with open(path.join(media_dir, file_name), 'rb') as fp: - self.assertEqual(fp.read(), response.content) - self.assertEqual(len(response.content), + self.assertEqual(fp.read(), response_content) + self.assertEqual(len(response_content), int(response['Content-Length'])) def test_invalid_if_modified_since2(self): @@ -86,9 +93,11 @@ class StaticTests(TestCase): invalid_date = ': 1291108438, Wed, 20 Oct 2010 14:05:00 GMT' response = self.client.get('/views/%s/%s' % (self.prefix, file_name), HTTP_IF_MODIFIED_SINCE=invalid_date) + response_content = b''.join(response) + response.close() with open(path.join(media_dir, file_name), 'rb') as fp: - self.assertEqual(fp.read(), response.content) - self.assertEqual(len(response.content), + self.assertEqual(fp.read(), response_content) + self.assertEqual(len(response_content), int(response['Content-Length'])) @@ -98,10 +107,20 @@ class StaticHelperTest(StaticTests): """ def setUp(self): super(StaticHelperTest, self).setUp() - self.prefix = 'media' self._old_views_urlpatterns = urls.urlpatterns[:] urls.urlpatterns += static('/media/', document_root=media_dir) def tearDown(self): super(StaticHelperTest, self).tearDown() urls.urlpatterns = self._old_views_urlpatterns + + +class StaticUtilsTests(unittest.TestCase): + def test_was_modified_since_fp(self): + """ + Test that a floating point mtime does not disturb was_modified_since. + (#18675) + """ + mtime = 1343416141.107817 + header = http_date(mtime) + self.assertFalse(was_modified_since(header, mtime)) diff --git a/tests/templates/404.html b/tests/templates/404.html deleted file mode 100644 index da627e2222..0000000000 --- a/tests/templates/404.html +++ /dev/null @@ -1 +0,0 @@ -Django Internal Tests: 404 Error
\ No newline at end of file diff --git a/tests/templates/500.html b/tests/templates/500.html deleted file mode 100644 index ff028cbeb0..0000000000 --- a/tests/templates/500.html +++ /dev/null @@ -1 +0,0 @@ -Django Internal Tests: 500 Error
\ No newline at end of file |
