authentik.api.tests.test_ordering

 1from django.db.models import OrderBy
 2from django.test import TestCase
 3from rest_framework.request import Request
 4from rest_framework.test import APIRequestFactory
 5
 6from authentik.api.ordering import NullsAwareOrderingFilter
 7from authentik.core.models import Token, User
 8
 9
10class MockView:
11    ordering_fields = "__all__"
12    ordering = None
13
14
15class TestNullsAwareOrderingFilter(TestCase):
16
17    def setUp(self):
18        self.filter = NullsAwareOrderingFilter()
19        self.view = MockView()
20        factory = APIRequestFactory()
21        self._req = lambda ordering: Request(factory.get("/", {"ordering": ordering}))
22
23    def _order_by(self, model, ordering):
24        qs = model.objects.all()
25        return self.filter.filter_queryset(self._req(ordering), qs, self.view).query.order_by
26
27    def test_nullable_asc_nulls_first(self):
28        """Ascending sort on a nullable field rewrites to nulls_first=True."""
29        (expr,) = self._order_by(User, "last_login")
30        self.assertIsInstance(expr, OrderBy)
31        self.assertFalse(expr.descending)
32        self.assertTrue(expr.nulls_first)
33
34    def test_nullable_desc_nulls_last(self):
35        """Descending sort on a nullable field rewrites to nulls_last=True."""
36        (expr,) = self._order_by(User, "-last_login")
37        self.assertIsInstance(expr, OrderBy)
38        self.assertTrue(expr.descending)
39        self.assertTrue(expr.nulls_last)
40
41    def test_non_nullable_passes_through(self):
42        """Non-nullable fields are left as plain string terms."""
43        (expr,) = self._order_by(User, "username")
44        self.assertEqual(expr, "username")
45
46    def test_mixed_ordering(self):
47        """Only nullable terms are rewritten; non-nullable terms pass through unchanged."""
48        first, second = self._order_by(User, "username,-last_login")
49        self.assertEqual(first, "username")
50        self.assertIsInstance(second, OrderBy)
51        self.assertTrue(second.descending)
52        self.assertTrue(second.nulls_last)
53
54    def test_expires_nullable(self):
55        """expires on ExpiringModel is nullable and is rewritten correctly."""
56        (expr,) = self._order_by(Token, "-expires")
57        self.assertIsInstance(expr, OrderBy)
58        self.assertTrue(expr.descending)
59        self.assertTrue(expr.nulls_last)
class MockView:
11class MockView:
12    ordering_fields = "__all__"
13    ordering = None
ordering_fields = '__all__'
ordering = None
class TestNullsAwareOrderingFilter(django.test.testcases.TestCase):
16class TestNullsAwareOrderingFilter(TestCase):
17
18    def setUp(self):
19        self.filter = NullsAwareOrderingFilter()
20        self.view = MockView()
21        factory = APIRequestFactory()
22        self._req = lambda ordering: Request(factory.get("/", {"ordering": ordering}))
23
24    def _order_by(self, model, ordering):
25        qs = model.objects.all()
26        return self.filter.filter_queryset(self._req(ordering), qs, self.view).query.order_by
27
28    def test_nullable_asc_nulls_first(self):
29        """Ascending sort on a nullable field rewrites to nulls_first=True."""
30        (expr,) = self._order_by(User, "last_login")
31        self.assertIsInstance(expr, OrderBy)
32        self.assertFalse(expr.descending)
33        self.assertTrue(expr.nulls_first)
34
35    def test_nullable_desc_nulls_last(self):
36        """Descending sort on a nullable field rewrites to nulls_last=True."""
37        (expr,) = self._order_by(User, "-last_login")
38        self.assertIsInstance(expr, OrderBy)
39        self.assertTrue(expr.descending)
40        self.assertTrue(expr.nulls_last)
41
42    def test_non_nullable_passes_through(self):
43        """Non-nullable fields are left as plain string terms."""
44        (expr,) = self._order_by(User, "username")
45        self.assertEqual(expr, "username")
46
47    def test_mixed_ordering(self):
48        """Only nullable terms are rewritten; non-nullable terms pass through unchanged."""
49        first, second = self._order_by(User, "username,-last_login")
50        self.assertEqual(first, "username")
51        self.assertIsInstance(second, OrderBy)
52        self.assertTrue(second.descending)
53        self.assertTrue(second.nulls_last)
54
55    def test_expires_nullable(self):
56        """expires on ExpiringModel is nullable and is rewritten correctly."""
57        (expr,) = self._order_by(Token, "-expires")
58        self.assertIsInstance(expr, OrderBy)
59        self.assertTrue(expr.descending)
60        self.assertTrue(expr.nulls_last)

Similar to TransactionTestCase, but use transaction.atomic() to achieve test isolation.

In most situations, TestCase should be preferred to TransactionTestCase as it allows faster execution. However, there are some situations where using TransactionTestCase might be necessary (e.g. testing some transactional behavior).

On database backends with no transaction support, TestCase behaves as TransactionTestCase.

def setUp(self):
18    def setUp(self):
19        self.filter = NullsAwareOrderingFilter()
20        self.view = MockView()
21        factory = APIRequestFactory()
22        self._req = lambda ordering: Request(factory.get("/", {"ordering": ordering}))

Hook method for setting up the test fixture before exercising it.

def test_nullable_asc_nulls_first(self):
28    def test_nullable_asc_nulls_first(self):
29        """Ascending sort on a nullable field rewrites to nulls_first=True."""
30        (expr,) = self._order_by(User, "last_login")
31        self.assertIsInstance(expr, OrderBy)
32        self.assertFalse(expr.descending)
33        self.assertTrue(expr.nulls_first)

Ascending sort on a nullable field rewrites to nulls_first=True.

def test_nullable_desc_nulls_last(self):
35    def test_nullable_desc_nulls_last(self):
36        """Descending sort on a nullable field rewrites to nulls_last=True."""
37        (expr,) = self._order_by(User, "-last_login")
38        self.assertIsInstance(expr, OrderBy)
39        self.assertTrue(expr.descending)
40        self.assertTrue(expr.nulls_last)

Descending sort on a nullable field rewrites to nulls_last=True.

def test_non_nullable_passes_through(self):
42    def test_non_nullable_passes_through(self):
43        """Non-nullable fields are left as plain string terms."""
44        (expr,) = self._order_by(User, "username")
45        self.assertEqual(expr, "username")

Non-nullable fields are left as plain string terms.

def test_mixed_ordering(self):
47    def test_mixed_ordering(self):
48        """Only nullable terms are rewritten; non-nullable terms pass through unchanged."""
49        first, second = self._order_by(User, "username,-last_login")
50        self.assertEqual(first, "username")
51        self.assertIsInstance(second, OrderBy)
52        self.assertTrue(second.descending)
53        self.assertTrue(second.nulls_last)

Only nullable terms are rewritten; non-nullable terms pass through unchanged.

def test_expires_nullable(self):
55    def test_expires_nullable(self):
56        """expires on ExpiringModel is nullable and is rewritten correctly."""
57        (expr,) = self._order_by(Token, "-expires")
58        self.assertIsInstance(expr, OrderBy)
59        self.assertTrue(expr.descending)
60        self.assertTrue(expr.nulls_last)

expires on ExpiringModel is nullable and is rewritten correctly.