diff options
Diffstat (limited to 'tests/contenttypes_tests')
| -rw-r--r-- | tests/contenttypes_tests/tests.py | 303 |
1 files changed, 301 insertions, 2 deletions
diff --git a/tests/contenttypes_tests/tests.py b/tests/contenttypes_tests/tests.py index 1f0af709cb..624e60d7a5 100644 --- a/tests/contenttypes_tests/tests.py +++ b/tests/contenttypes_tests/tests.py @@ -1,9 +1,14 @@ -from __future__ import unicode_literals +# -*- coding: utf-8 -*- +from __future__ import absolute_import, unicode_literals -from django.apps.registry import Apps +from django.apps.registry import Apps, apps +from django.contrib.contenttypes import generic from django.contrib.contenttypes.models import ContentType +from django.core import checks from django.db import models from django.test import TestCase +from django.test.utils import override_settings +from django.utils.encoding import force_str from .models import Author, Article @@ -67,3 +72,297 @@ class ContentTypesViewsTests(TestCase): self.assertEqual(ct.app_label, 'my_great_app') self.assertEqual(ct.model, 'modelcreatedonthefly') self.assertEqual(ct.name, 'a model created on the fly') + + +class IsolatedModelsTestCase(TestCase): + def setUp(self): + # The unmanaged models need to be removed after the test in order to + # prevent bad interactions with the flush operation in other tests. + self._old_models = apps.app_configs['contenttypes_tests'].models.copy() + + def tearDown(self): + apps.app_configs['contenttypes_tests'].models = self._old_models + apps.all_models['contenttypes_tests'] = self._old_models + apps.clear_cache() + + +class GenericForeignKeyTests(IsolatedModelsTestCase): + + def test_str(self): + class Model(models.Model): + field = generic.GenericForeignKey() + expected = "contenttypes_tests.Model.field" + actual = force_str(Model.field) + self.assertEqual(expected, actual) + + def test_missing_content_type_field(self): + class TaggedItem(models.Model): + # no content_type field + object_id = models.PositiveIntegerField() + content_object = generic.GenericForeignKey() + + errors = TaggedItem.content_object.check() + expected = [ + checks.Error( + 'The field refers to TaggedItem.content_type field which is missing.', + hint=None, + obj=TaggedItem.content_object, + id='contenttypes.E005', + ) + ] + self.assertEqual(errors, expected) + + def test_invalid_content_type_field(self): + class Model(models.Model): + content_type = models.IntegerField() # should be ForeignKey + object_id = models.PositiveIntegerField() + content_object = generic.GenericForeignKey( + 'content_type', 'object_id') + + errors = Model.content_object.check() + expected = [ + checks.Error( + ('"content_type" field is used by a GenericForeignKey ' + 'as content type field and therefore it must be ' + 'a ForeignKey.'), + hint=None, + obj=Model.content_object, + id='contenttypes.E006', + ) + ] + self.assertEqual(errors, expected) + + def test_content_type_field_pointing_to_wrong_model(self): + class Model(models.Model): + content_type = models.ForeignKey('self') # should point to ContentType + object_id = models.PositiveIntegerField() + content_object = generic.GenericForeignKey( + 'content_type', 'object_id') + + errors = Model.content_object.check() + expected = [ + checks.Error( + ('"content_type" field is used by a GenericForeignKey ' + 'as content type field and therefore it must be ' + 'a ForeignKey to ContentType.'), + hint=None, + obj=Model.content_object, + id='contenttypes.E007', + ) + ] + self.assertEqual(errors, expected) + + def test_missing_object_id_field(self): + class TaggedItem(models.Model): + content_type = models.ForeignKey(ContentType) + # missing object_id field + content_object = generic.GenericForeignKey() + + errors = TaggedItem.content_object.check() + expected = [ + checks.Error( + 'The field refers to "object_id" field which is missing.', + hint=None, + obj=TaggedItem.content_object, + id='contenttypes.E001', + ) + ] + self.assertEqual(errors, expected) + + def test_field_name_ending_with_underscore(self): + class Model(models.Model): + content_type = models.ForeignKey(ContentType) + object_id = models.PositiveIntegerField() + content_object_ = generic.GenericForeignKey( + 'content_type', 'object_id') + + errors = Model.content_object_.check() + expected = [ + checks.Error( + 'Field names must not end with underscores.', + hint=None, + obj=Model.content_object_, + id='contenttypes.E002', + ) + ] + self.assertEqual(errors, expected) + + def test_generic_foreign_key_checks_are_performed(self): + class MyGenericForeignKey(generic.GenericForeignKey): + def check(self, **kwargs): + return ['performed!'] + + class Model(models.Model): + content_object = MyGenericForeignKey() + + errors = checks.run_checks() + self.assertEqual(errors, ['performed!']) + + +class GenericRelationshipTests(IsolatedModelsTestCase): + + def test_valid_generic_relationship(self): + class TaggedItem(models.Model): + content_type = models.ForeignKey(ContentType) + object_id = models.PositiveIntegerField() + content_object = generic.GenericForeignKey() + + class Bookmark(models.Model): + tags = generic.GenericRelation('TaggedItem') + + errors = Bookmark.tags.field.check() + self.assertEqual(errors, []) + + def test_valid_generic_relationship_with_explicit_fields(self): + class TaggedItem(models.Model): + custom_content_type = models.ForeignKey(ContentType) + custom_object_id = models.PositiveIntegerField() + content_object = generic.GenericForeignKey( + 'custom_content_type', 'custom_object_id') + + class Bookmark(models.Model): + tags = generic.GenericRelation('TaggedItem', + content_type_field='custom_content_type', + object_id_field='custom_object_id') + + errors = Bookmark.tags.field.check() + self.assertEqual(errors, []) + + def test_pointing_to_missing_model(self): + class Model(models.Model): + rel = generic.GenericRelation('MissingModel') + + errors = Model.rel.field.check() + expected = [ + checks.Error( + ('The field has a relation with model MissingModel, ' + 'which has either not been installed or is abstract.'), + hint=('Ensure that you did not misspell the model name and ' + 'the model is not abstract. Does your INSTALLED_APPS ' + 'setting contain the app where MissingModel is defined?'), + obj=Model.rel.field, + id='E030', + ) + ] + self.assertEqual(errors, expected) + + def test_valid_self_referential_generic_relationship(self): + class Model(models.Model): + rel = generic.GenericRelation('Model') + content_type = models.ForeignKey(ContentType) + object_id = models.PositiveIntegerField() + content_object = generic.GenericForeignKey( + 'content_type', 'object_id') + + errors = Model.rel.field.check() + self.assertEqual(errors, []) + + def test_missing_content_type_field(self): + class TaggedItem(models.Model): + # no content_type field + object_id = models.PositiveIntegerField() + content_object = generic.GenericForeignKey() + + class Bookmark(models.Model): + tags = generic.GenericRelation('TaggedItem') + + errors = Bookmark.tags.field.check() + expected = [ + checks.Error( + 'The field refers to TaggedItem.content_type field which is missing.', + hint=None, + obj=Bookmark.tags.field, + id='contenttypes.E005', + ) + ] + self.assertEqual(errors, expected) + + def test_missing_object_id_field(self): + class TaggedItem(models.Model): + content_type = models.ForeignKey(ContentType) + # missing object_id field + content_object = generic.GenericForeignKey() + + class Bookmark(models.Model): + tags = generic.GenericRelation('TaggedItem') + + errors = Bookmark.tags.field.check() + expected = [ + checks.Error( + 'The field refers to TaggedItem.object_id field which is missing.', + hint=None, + obj=Bookmark.tags.field, + id='contenttypes.E003', + ) + ] + self.assertEqual(errors, expected) + + def test_missing_generic_foreign_key(self): + class TaggedItem(models.Model): + content_type = models.ForeignKey(ContentType) + object_id = models.PositiveIntegerField() + + class Bookmark(models.Model): + tags = generic.GenericRelation('TaggedItem') + + errors = Bookmark.tags.field.check() + expected = [ + checks.Warning( + ('The field defines a generic relation with the model ' + 'contenttypes_tests.TaggedItem, but the model lacks ' + 'GenericForeignKey.'), + hint=None, + obj=Bookmark.tags.field, + id='contenttypes.E004', + ) + ] + self.assertEqual(errors, expected) + + @override_settings(TEST_SWAPPED_MODEL='contenttypes_tests.Replacement') + def test_pointing_to_swapped_model(self): + class Replacement(models.Model): + pass + + class SwappedModel(models.Model): + content_type = models.ForeignKey(ContentType) + object_id = models.PositiveIntegerField() + content_object = generic.GenericForeignKey() + + class Meta: + swappable = 'TEST_SWAPPED_MODEL' + + class Model(models.Model): + rel = generic.GenericRelation('SwappedModel') + + errors = Model.rel.field.check() + expected = [ + checks.Error( + ('The field defines a relation with the model ' + 'contenttypes_tests.SwappedModel, ' + 'which has been swapped out.'), + hint='Update the relation to point at settings.TEST_SWAPPED_MODEL', + obj=Model.rel.field, + id='E029', + ) + ] + self.assertEqual(errors, expected) + + def test_field_name_ending_with_underscore(self): + class TaggedItem(models.Model): + content_type = models.ForeignKey(ContentType) + object_id = models.PositiveIntegerField() + content_object = generic.GenericForeignKey() + + class InvalidBookmark(models.Model): + tags_ = generic.GenericRelation('TaggedItem') + + errors = InvalidBookmark.tags_.field.check() + expected = [ + checks.Error( + 'Field names must not end with underscores.', + hint=None, + obj=InvalidBookmark.tags_.field, + id='E001', + ) + ] + self.assertEqual(errors, expected) |
