1. from datetime import datetime
    
  2. 
    
  3. from django.contrib.admin.options import IncorrectLookupParameters
    
  4. from django.contrib.auth.models import User
    
  5. from django.test import RequestFactory, TestCase
    
  6. from django.utils.timezone import make_aware
    
  7. 
    
  8. from .admin import EventAdmin
    
  9. from .admin import site as custom_site
    
  10. from .models import Event
    
  11. 
    
  12. 
    
  13. class DateHierarchyTests(TestCase):
    
  14.     factory = RequestFactory()
    
  15. 
    
  16.     @classmethod
    
  17.     def setUpTestData(cls):
    
  18.         cls.superuser = User.objects.create_superuser(
    
  19.             username="super", email="[email protected]", password="xxx"
    
  20.         )
    
  21. 
    
  22.     def assertDateParams(self, query, expected_from_date, expected_to_date):
    
  23.         query = {"date__%s" % field: val for field, val in query.items()}
    
  24.         request = self.factory.get("/", query)
    
  25.         request.user = self.superuser
    
  26.         changelist = EventAdmin(Event, custom_site).get_changelist_instance(request)
    
  27.         _, _, lookup_params, *_ = changelist.get_filters(request)
    
  28.         self.assertEqual(lookup_params["date__gte"], expected_from_date)
    
  29.         self.assertEqual(lookup_params["date__lt"], expected_to_date)
    
  30. 
    
  31.     def test_bounded_params(self):
    
  32.         tests = (
    
  33.             ({"year": 2017}, datetime(2017, 1, 1), datetime(2018, 1, 1)),
    
  34.             ({"year": 2017, "month": 2}, datetime(2017, 2, 1), datetime(2017, 3, 1)),
    
  35.             ({"year": 2017, "month": 12}, datetime(2017, 12, 1), datetime(2018, 1, 1)),
    
  36.             (
    
  37.                 {"year": 2017, "month": 12, "day": 15},
    
  38.                 datetime(2017, 12, 15),
    
  39.                 datetime(2017, 12, 16),
    
  40.             ),
    
  41.             (
    
  42.                 {"year": 2017, "month": 12, "day": 31},
    
  43.                 datetime(2017, 12, 31),
    
  44.                 datetime(2018, 1, 1),
    
  45.             ),
    
  46.             (
    
  47.                 {"year": 2017, "month": 2, "day": 28},
    
  48.                 datetime(2017, 2, 28),
    
  49.                 datetime(2017, 3, 1),
    
  50.             ),
    
  51.         )
    
  52.         for query, expected_from_date, expected_to_date in tests:
    
  53.             with self.subTest(query=query):
    
  54.                 self.assertDateParams(query, expected_from_date, expected_to_date)
    
  55. 
    
  56.     def test_bounded_params_with_time_zone(self):
    
  57.         with self.settings(USE_TZ=True, TIME_ZONE="Asia/Jerusalem"):
    
  58.             self.assertDateParams(
    
  59.                 {"year": 2017, "month": 2, "day": 28},
    
  60.                 make_aware(datetime(2017, 2, 28)),
    
  61.                 make_aware(datetime(2017, 3, 1)),
    
  62.             )
    
  63. 
    
  64.     def test_bounded_params_with_dst_time_zone(self):
    
  65.         tests = [
    
  66.             # Northern hemisphere.
    
  67.             ("Asia/Jerusalem", 3),
    
  68.             ("Asia/Jerusalem", 10),
    
  69.             # Southern hemisphere.
    
  70.             ("Pacific/Chatham", 4),
    
  71.             ("Pacific/Chatham", 9),
    
  72.         ]
    
  73.         for time_zone, month in tests:
    
  74.             with self.subTest(time_zone=time_zone, month=month):
    
  75.                 with self.settings(USE_TZ=True, TIME_ZONE=time_zone):
    
  76.                     self.assertDateParams(
    
  77.                         {"year": 2019, "month": month},
    
  78.                         make_aware(datetime(2019, month, 1)),
    
  79.                         make_aware(datetime(2019, month + 1, 1)),
    
  80.                     )
    
  81. 
    
  82.     def test_invalid_params(self):
    
  83.         tests = (
    
  84.             {"year": "x"},
    
  85.             {"year": 2017, "month": "x"},
    
  86.             {"year": 2017, "month": 12, "day": "x"},
    
  87.             {"year": 2017, "month": 13},
    
  88.             {"year": 2017, "month": 12, "day": 32},
    
  89.             {"year": 2017, "month": 0},
    
  90.             {"year": 2017, "month": 12, "day": 0},
    
  91.         )
    
  92.         for invalid_query in tests:
    
  93.             with self.subTest(query=invalid_query), self.assertRaises(
    
  94.                 IncorrectLookupParameters
    
  95.             ):
    
  96.                 self.assertDateParams(invalid_query, None, None)