import copy from django import forms from django.db import models from django.conf import settings from django.test import TestCase from django.db.utils import IntegrityError from django.utils.text import slugify from localized_fields.fields import ( LocalizedField, LocalizedUniqueSlugField ) from .fake_model import get_fake_model class LocalizedSlugFieldTestCase(TestCase): """Tests the localized slug classes.""" AutoSlugModel = None Model = None @classmethod def setUpClass(cls): """Creates the test models in the database.""" super(LocalizedSlugFieldTestCase, cls).setUpClass() cls.Model = get_fake_model( { 'title': LocalizedField(), 'name': models.CharField(max_length=255), 'slug': LocalizedUniqueSlugField(populate_from='title') } ) @staticmethod def test_unique_slug_with_time(): """Tests whether the primary key is included in the slug when the 'use_pk' option is enabled.""" title = 'myuniquetitle' PkModel = get_fake_model( { 'title': LocalizedField(), 'slug': LocalizedUniqueSlugField(populate_from='title', include_time=True) } ) obj = PkModel() obj.title.en = title obj.save() assert obj.slug.en.startswith('%s-' % title) @classmethod def test_uniue_slug_no_change(cls): """Tests whether slugs are not re-generated if not needed.""" NoChangeSlugModel = get_fake_model( { 'title': LocalizedField(), 'slug': LocalizedUniqueSlugField(populate_from='title', include_time=True) } ) title = 'myuniquetitle' obj = NoChangeSlugModel() obj.title.en = title obj.title.nl = title obj.save() old_slug_en = copy.deepcopy(obj.slug.en) old_slug_nl = copy.deepcopy(obj.slug.nl) obj.title.nl += 'beer' obj.save() assert old_slug_en == obj.slug.en assert old_slug_nl != obj.slug.nl @classmethod def test_unique_slug_update(cls): obj = cls.Model.objects.create(title={settings.LANGUAGE_CODE: 'mytitle'}) assert obj.slug.get() == 'mytitle' obj.title.set(settings.LANGUAGE_CODE, 'othertitle') obj.save() assert obj.slug.get() == 'othertitle' @classmethod def test_unique_slug_unique_max_retries(cls): """Tests whether the unique slug implementation doesn't try to find a slug forever and gives up after a while.""" title = 'myuniquetitle' obj = cls.Model() obj.title.en = title obj.save() with cls.assertRaises(cls, IntegrityError): for _ in range(0, settings.LOCALIZED_FIELDS_MAX_RETRIES + 1): another_obj = cls.Model() another_obj.title.en = title another_obj.save() @classmethod def test_populate(cls): """Tests whether the populating feature works correctly.""" obj = cls.Model() obj.title.en = 'this is my title' obj.save() assert obj.slug.get('en') == slugify(obj.title) @classmethod def test_populate_callable(cls): """Tests whether the populating feature works correctly when you specify a callable.""" def generate_slug(instance): return instance.title get_fake_model({ 'title': LocalizedField(), 'slug': LocalizedUniqueSlugField(populate_from=generate_slug) }) obj = cls.Model() for lang_code, lang_name in settings.LANGUAGES: obj.title.set(lang_code, 'title %s' % lang_name) obj.save() for lang_code, lang_name in settings.LANGUAGES: assert obj.slug.get(lang_code) == 'title-%s' % lang_name.lower() @staticmethod def test_populate_multiple_from_fields(): """Tests whether populating the slug from multiple fields works correctly.""" model = get_fake_model( { 'title': LocalizedField(), 'name': models.CharField(max_length=255), 'slug': LocalizedUniqueSlugField(populate_from=('title', 'name')) } ) obj = model() for lang_code, lang_name in settings.LANGUAGES: obj.name = 'swen' obj.title.set(lang_code, 'title %s' % lang_name) obj.save() for lang_code, lang_name in settings.LANGUAGES: assert obj.slug.get(lang_code) == 'title-%s-swen' % lang_name.lower() @staticmethod def test_populate_multiple_from_fields_fk(): """Tests whether populating the slug from multiple fields works correctly.""" model_fk = get_fake_model( { 'name': LocalizedField(), } ) model = get_fake_model( { 'title': LocalizedField(), 'other': models.ForeignKey(model_fk, on_delete=models.CASCADE), 'slug': LocalizedUniqueSlugField(populate_from=('title', 'other.name')) } ) other = model_fk.objects.create(name={settings.LANGUAGE_CODE: 'swen'}) obj = model() for lang_code, lang_name in settings.LANGUAGES: obj.other_id = other.id obj.title.set(lang_code, 'title %s' % lang_name) obj.save() for lang_code, lang_name in settings.LANGUAGES: assert obj.slug.get(lang_code) == 'title-%s-swen' % lang_name.lower() @classmethod def test_populate_multiple_languages(cls): """Tests whether the populating feature correctly works for all languages.""" obj = cls.Model() for lang_code, lang_name in settings.LANGUAGES: obj.title.set(lang_code, 'title %s' % lang_name) obj.save() for lang_code, lang_name in settings.LANGUAGES: assert obj.slug.get(lang_code) == 'title-%s' % lang_name.lower() @classmethod def test_unique_slug(cls): """Tests whether unique slugs are properly generated.""" title = 'myuniquetitle' obj = cls.Model() obj.title.en = title obj.save() for i in range(1, settings.LOCALIZED_FIELDS_MAX_RETRIES - 1): another_obj = cls.Model() another_obj.title.en = title another_obj.save() assert another_obj.slug.en == '%s-%d' % (title, i) @classmethod def test_unique_slug_utf(cls): """Tests whether generating a slug works when the value consists completely out of non-ASCII characters.""" obj = cls.Model() obj.title.en = 'مكاتب للايجار بشارع بورسعيد' obj.save() assert obj.slug.en == 'مكاتب-للايجار-بشارع-بورسعيد' @staticmethod def test_deconstruct(): """Tests whether the :see:deconstruct function properly retains options specified in the constructor.""" field = LocalizedUniqueSlugField(populate_from='title') _, _, _, kwargs = field.deconstruct() assert 'populate_from' in kwargs assert kwargs['populate_from'] == field.populate_from @staticmethod def test_formfield(): """Tests whether the :see:formfield method returns a valid form field that is hidden.""" form_field = LocalizedUniqueSlugField(populate_from='title').formfield() assert isinstance(form_field, forms.CharField) assert isinstance(form_field.widget, forms.HiddenInput)