1. """
    
  2. The citext PostgreSQL extension supports indexing of case-insensitive text
    
  3. strings and thus eliminates the need for operations such as iexact and other
    
  4. modifiers to enforce use of an index.
    
  5. """
    
  6. from django.db import IntegrityError
    
  7. from django.test.utils import modify_settings
    
  8. 
    
  9. from . import PostgreSQLTestCase
    
  10. from .models import CITestModel
    
  11. 
    
  12. 
    
  13. @modify_settings(INSTALLED_APPS={"append": "django.contrib.postgres"})
    
  14. class CITextTestCase(PostgreSQLTestCase):
    
  15.     case_sensitive_lookups = ("contains", "startswith", "endswith", "regex")
    
  16. 
    
  17.     @classmethod
    
  18.     def setUpTestData(cls):
    
  19.         cls.john = CITestModel.objects.create(
    
  20.             name="JoHn",
    
  21.             email="[email protected]",
    
  22.             description="Average Joe named JoHn",
    
  23.             array_field=["JoE", "jOhn"],
    
  24.         )
    
  25. 
    
  26.     def test_equal_lowercase(self):
    
  27.         """
    
  28.         citext removes the need for iexact as the index is case-insensitive.
    
  29.         """
    
  30.         self.assertEqual(
    
  31.             CITestModel.objects.filter(name=self.john.name.lower()).count(), 1
    
  32.         )
    
  33.         self.assertEqual(
    
  34.             CITestModel.objects.filter(email=self.john.email.lower()).count(), 1
    
  35.         )
    
  36.         self.assertEqual(
    
  37.             CITestModel.objects.filter(
    
  38.                 description=self.john.description.lower()
    
  39.             ).count(),
    
  40.             1,
    
  41.         )
    
  42. 
    
  43.     def test_fail_citext_primary_key(self):
    
  44.         """
    
  45.         Creating an entry for a citext field used as a primary key which
    
  46.         clashes with an existing value isn't allowed.
    
  47.         """
    
  48.         with self.assertRaises(IntegrityError):
    
  49.             CITestModel.objects.create(name="John")
    
  50. 
    
  51.     def test_array_field(self):
    
  52.         instance = CITestModel.objects.get()
    
  53.         self.assertEqual(instance.array_field, self.john.array_field)
    
  54.         self.assertTrue(
    
  55.             CITestModel.objects.filter(array_field__contains=["joe"]).exists()
    
  56.         )
    
  57. 
    
  58.     def test_lookups_name_char(self):
    
  59.         for lookup in self.case_sensitive_lookups:
    
  60.             with self.subTest(lookup=lookup):
    
  61.                 query = {"name__{}".format(lookup): "john"}
    
  62.                 self.assertSequenceEqual(
    
  63.                     CITestModel.objects.filter(**query), [self.john]
    
  64.                 )
    
  65. 
    
  66.     def test_lookups_description_text(self):
    
  67.         for lookup, string in zip(
    
  68.             self.case_sensitive_lookups, ("average", "average joe", "john", "Joe.named")
    
  69.         ):
    
  70.             with self.subTest(lookup=lookup, string=string):
    
  71.                 query = {"description__{}".format(lookup): string}
    
  72.                 self.assertSequenceEqual(
    
  73.                     CITestModel.objects.filter(**query), [self.john]
    
  74.                 )
    
  75. 
    
  76.     def test_lookups_email(self):
    
  77.         for lookup, string in zip(
    
  78.             self.case_sensitive_lookups, ("john", "john", "john.com", "john.com")
    
  79.         ):
    
  80.             with self.subTest(lookup=lookup, string=string):
    
  81.                 query = {"email__{}".format(lookup): string}
    
  82.                 self.assertSequenceEqual(
    
  83.                     CITestModel.objects.filter(**query), [self.john]
    
  84.                 )