django-localized-fields/tests/test_slug_fields.py

318 lines
9.2 KiB
Python

import copy
import pytest
from django import forms
from django.conf import settings
from django.db import models
from django.db.utils import IntegrityError
from django.test import TestCase
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_disable(cls):
"""Tests whether disabling auto-slugging works."""
Model = get_fake_model(
{
"title": LocalizedField(),
"slug": LocalizedUniqueSlugField(
populate_from="title", enabled=False
),
}
)
obj = Model()
obj.title = "test"
# should raise IntegrityError because auto-slugging
# is disabled and the slug field is NULL
with pytest.raises(IntegrityError):
obj.save()
@classmethod
def test_allows_override_when_immutable(cls):
"""Tests whether setting a value manually works and does not get
overriden."""
Model = get_fake_model(
{
"title": LocalizedField(),
"name": models.CharField(max_length=255),
"slug": LocalizedUniqueSlugField(
populate_from="title", immutable=True
),
}
)
obj = Model()
for lang_code, lang_name in settings.LANGUAGES:
obj.slug.set(lang_code, "my value %s" % lang_code)
obj.title.set(lang_code, "my title %s" % lang_code)
obj.save()
for lang_code, lang_name in settings.LANGUAGES:
assert obj.slug.get(lang_code) == "my value %s" % lang_code
@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(
enabled=False, immutable=True, populate_from="title"
)
_, _, _, kwargs = field.deconstruct()
assert not kwargs["enabled"]
assert kwargs["immutable"]
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)