authentik.core.tests.test_models

authentik core models tests

  1"""authentik core models tests"""
  2
  3from collections.abc import Callable
  4from datetime import timedelta
  5from unittest.mock import patch
  6
  7from django.test import RequestFactory, TestCase
  8from django.utils.timezone import now
  9from freezegun import freeze_time
 10from guardian.shortcuts import get_anonymous_user
 11
 12from authentik.core.models import Provider, Source, Token
 13from authentik.events.models import Event, EventAction
 14from authentik.flows.models import Flow
 15from authentik.lib.generators import generate_id
 16from authentik.lib.utils.reflection import all_subclasses
 17
 18
 19class TestModels(TestCase):
 20    """Test Models"""
 21
 22    def test_token_expire(self):
 23        """Test token expiring"""
 24        with freeze_time() as freeze:
 25            token = Token.objects.create(expires=now(), user=get_anonymous_user())
 26            freeze.tick(timedelta(seconds=1))
 27            self.assertTrue(token.is_expired)
 28
 29    def test_token_expire_no_expire(self):
 30        """Test token expiring with "expiring" set"""
 31        with freeze_time() as freeze:
 32            token = Token.objects.create(expires=now(), user=get_anonymous_user(), expiring=False)
 33            freeze.tick(timedelta(seconds=1))
 34            self.assertFalse(token.is_expired)
 35
 36    def test_filter_not_expired_warning(self):
 37        """Test filter_not_expired's deprecation message"""
 38        id = generate_id()
 39        Token.objects.create(
 40            expires=now() - timedelta(hours=1),
 41            expiring=True,
 42            user=get_anonymous_user(),
 43            identifier=id,
 44        )
 45        self.assertFalse(Token.filter_not_expired(identifier=id).exists())
 46        event = Event.objects.filter(action=EventAction.CONFIGURATION_WARNING).first()
 47        self.assertIsNotNone(event)
 48        self.assertEqual(
 49            event.context["deprecation"], "authentik.core.models.Token.filter_not_expired"
 50        )
 51
 52    @patch("authentik.core.models.get_file_manager")
 53    def test_source_icon_url_can_bypass_cache(self, get_file_manager):
 54        request = RequestFactory().get("/")
 55        manager = get_file_manager.return_value
 56        manager.file_url.return_value = "/files/media/public/source-icons/icon.svg?token=fresh"
 57
 58        source = Source(icon="source-icons/icon.svg")
 59
 60        self.assertEqual(
 61            source.get_icon_url(request, use_cache=False),
 62            "/files/media/public/source-icons/icon.svg?token=fresh",
 63        )
 64        manager.file_url.assert_called_once_with(
 65            "source-icons/icon.svg",
 66            request,
 67            use_cache=False,
 68        )
 69
 70    @patch("authentik.flows.models.get_file_manager")
 71    def test_flow_background_urls_can_bypass_cache(self, get_file_manager):
 72        request = RequestFactory().get("/")
 73        manager = get_file_manager.return_value
 74        manager.file_url.return_value = "/files/media/public/background.svg?token=fresh"
 75        manager.themed_urls.return_value = {
 76            "light": "/files/media/public/background-light.svg?token=fresh",
 77            "dark": "/files/media/public/background-dark.svg?token=fresh",
 78        }
 79
 80        flow = Flow(background="background-%(theme)s.svg")
 81
 82        self.assertEqual(
 83            flow.background_url(request, use_cache=False),
 84            "/files/media/public/background.svg?token=fresh",
 85        )
 86        self.assertEqual(
 87            flow.background_themed_urls(request, use_cache=False),
 88            {
 89                "light": "/files/media/public/background-light.svg?token=fresh",
 90                "dark": "/files/media/public/background-dark.svg?token=fresh",
 91            },
 92        )
 93        manager.file_url.assert_called_once_with(
 94            "background-%(theme)s.svg",
 95            request,
 96            use_cache=False,
 97        )
 98        manager.themed_urls.assert_called_once_with(
 99            "background-%(theme)s.svg",
100            request,
101            use_cache=False,
102        )
103
104
105def source_tester_factory(test_model: type[Source]) -> Callable:
106    """Test source"""
107
108    factory = RequestFactory()
109    request = factory.get("/")
110
111    def tester(self: TestModels):
112        model_class = None
113        if test_model._meta.abstract:
114            return
115        else:
116            model_class = test_model()
117        model_class.slug = "test"
118        self.assertIsNotNone(model_class.component)
119        model_class.ui_login_button(request)
120        model_class.ui_user_settings()
121
122    return tester
123
124
125def provider_tester_factory(test_model: type[Provider]) -> Callable:
126    """Test provider"""
127
128    def tester(self: TestModels):
129        model_class = None
130        if test_model._meta.abstract:  # pragma: no cover
131            return
132        model_class = test_model()
133        self.assertIsNotNone(model_class.component)
134
135    return tester
136
137
138for model in all_subclasses(Source):
139    setattr(TestModels, f"test_source_{model.__name__}", source_tester_factory(model))
140for model in all_subclasses(Provider):
141    setattr(TestModels, f"test_provider_{model.__name__}", provider_tester_factory(model))
class TestModels(django.test.testcases.TestCase):
 20class TestModels(TestCase):
 21    """Test Models"""
 22
 23    def test_token_expire(self):
 24        """Test token expiring"""
 25        with freeze_time() as freeze:
 26            token = Token.objects.create(expires=now(), user=get_anonymous_user())
 27            freeze.tick(timedelta(seconds=1))
 28            self.assertTrue(token.is_expired)
 29
 30    def test_token_expire_no_expire(self):
 31        """Test token expiring with "expiring" set"""
 32        with freeze_time() as freeze:
 33            token = Token.objects.create(expires=now(), user=get_anonymous_user(), expiring=False)
 34            freeze.tick(timedelta(seconds=1))
 35            self.assertFalse(token.is_expired)
 36
 37    def test_filter_not_expired_warning(self):
 38        """Test filter_not_expired's deprecation message"""
 39        id = generate_id()
 40        Token.objects.create(
 41            expires=now() - timedelta(hours=1),
 42            expiring=True,
 43            user=get_anonymous_user(),
 44            identifier=id,
 45        )
 46        self.assertFalse(Token.filter_not_expired(identifier=id).exists())
 47        event = Event.objects.filter(action=EventAction.CONFIGURATION_WARNING).first()
 48        self.assertIsNotNone(event)
 49        self.assertEqual(
 50            event.context["deprecation"], "authentik.core.models.Token.filter_not_expired"
 51        )
 52
 53    @patch("authentik.core.models.get_file_manager")
 54    def test_source_icon_url_can_bypass_cache(self, get_file_manager):
 55        request = RequestFactory().get("/")
 56        manager = get_file_manager.return_value
 57        manager.file_url.return_value = "/files/media/public/source-icons/icon.svg?token=fresh"
 58
 59        source = Source(icon="source-icons/icon.svg")
 60
 61        self.assertEqual(
 62            source.get_icon_url(request, use_cache=False),
 63            "/files/media/public/source-icons/icon.svg?token=fresh",
 64        )
 65        manager.file_url.assert_called_once_with(
 66            "source-icons/icon.svg",
 67            request,
 68            use_cache=False,
 69        )
 70
 71    @patch("authentik.flows.models.get_file_manager")
 72    def test_flow_background_urls_can_bypass_cache(self, get_file_manager):
 73        request = RequestFactory().get("/")
 74        manager = get_file_manager.return_value
 75        manager.file_url.return_value = "/files/media/public/background.svg?token=fresh"
 76        manager.themed_urls.return_value = {
 77            "light": "/files/media/public/background-light.svg?token=fresh",
 78            "dark": "/files/media/public/background-dark.svg?token=fresh",
 79        }
 80
 81        flow = Flow(background="background-%(theme)s.svg")
 82
 83        self.assertEqual(
 84            flow.background_url(request, use_cache=False),
 85            "/files/media/public/background.svg?token=fresh",
 86        )
 87        self.assertEqual(
 88            flow.background_themed_urls(request, use_cache=False),
 89            {
 90                "light": "/files/media/public/background-light.svg?token=fresh",
 91                "dark": "/files/media/public/background-dark.svg?token=fresh",
 92            },
 93        )
 94        manager.file_url.assert_called_once_with(
 95            "background-%(theme)s.svg",
 96            request,
 97            use_cache=False,
 98        )
 99        manager.themed_urls.assert_called_once_with(
100            "background-%(theme)s.svg",
101            request,
102            use_cache=False,
103        )

Test Models

def test_token_expire(self):
23    def test_token_expire(self):
24        """Test token expiring"""
25        with freeze_time() as freeze:
26            token = Token.objects.create(expires=now(), user=get_anonymous_user())
27            freeze.tick(timedelta(seconds=1))
28            self.assertTrue(token.is_expired)

Test token expiring

def test_token_expire_no_expire(self):
30    def test_token_expire_no_expire(self):
31        """Test token expiring with "expiring" set"""
32        with freeze_time() as freeze:
33            token = Token.objects.create(expires=now(), user=get_anonymous_user(), expiring=False)
34            freeze.tick(timedelta(seconds=1))
35            self.assertFalse(token.is_expired)

Test token expiring with "expiring" set

def test_filter_not_expired_warning(self):
37    def test_filter_not_expired_warning(self):
38        """Test filter_not_expired's deprecation message"""
39        id = generate_id()
40        Token.objects.create(
41            expires=now() - timedelta(hours=1),
42            expiring=True,
43            user=get_anonymous_user(),
44            identifier=id,
45        )
46        self.assertFalse(Token.filter_not_expired(identifier=id).exists())
47        event = Event.objects.filter(action=EventAction.CONFIGURATION_WARNING).first()
48        self.assertIsNotNone(event)
49        self.assertEqual(
50            event.context["deprecation"], "authentik.core.models.Token.filter_not_expired"
51        )

Test filter_not_expired's deprecation message

@patch('authentik.core.models.get_file_manager')
def test_source_icon_url_can_bypass_cache(self, get_file_manager):
53    @patch("authentik.core.models.get_file_manager")
54    def test_source_icon_url_can_bypass_cache(self, get_file_manager):
55        request = RequestFactory().get("/")
56        manager = get_file_manager.return_value
57        manager.file_url.return_value = "/files/media/public/source-icons/icon.svg?token=fresh"
58
59        source = Source(icon="source-icons/icon.svg")
60
61        self.assertEqual(
62            source.get_icon_url(request, use_cache=False),
63            "/files/media/public/source-icons/icon.svg?token=fresh",
64        )
65        manager.file_url.assert_called_once_with(
66            "source-icons/icon.svg",
67            request,
68            use_cache=False,
69        )
@patch('authentik.flows.models.get_file_manager')
def test_flow_background_urls_can_bypass_cache(self, get_file_manager):
 71    @patch("authentik.flows.models.get_file_manager")
 72    def test_flow_background_urls_can_bypass_cache(self, get_file_manager):
 73        request = RequestFactory().get("/")
 74        manager = get_file_manager.return_value
 75        manager.file_url.return_value = "/files/media/public/background.svg?token=fresh"
 76        manager.themed_urls.return_value = {
 77            "light": "/files/media/public/background-light.svg?token=fresh",
 78            "dark": "/files/media/public/background-dark.svg?token=fresh",
 79        }
 80
 81        flow = Flow(background="background-%(theme)s.svg")
 82
 83        self.assertEqual(
 84            flow.background_url(request, use_cache=False),
 85            "/files/media/public/background.svg?token=fresh",
 86        )
 87        self.assertEqual(
 88            flow.background_themed_urls(request, use_cache=False),
 89            {
 90                "light": "/files/media/public/background-light.svg?token=fresh",
 91                "dark": "/files/media/public/background-dark.svg?token=fresh",
 92            },
 93        )
 94        manager.file_url.assert_called_once_with(
 95            "background-%(theme)s.svg",
 96            request,
 97            use_cache=False,
 98        )
 99        manager.themed_urls.assert_called_once_with(
100            "background-%(theme)s.svg",
101            request,
102            use_cache=False,
103        )
def test_source_AppleOAuthSource(self: TestModels):
112    def tester(self: TestModels):
113        model_class = None
114        if test_model._meta.abstract:
115            return
116        else:
117            model_class = test_model()
118        model_class.slug = "test"
119        self.assertIsNotNone(model_class.component)
120        model_class.ui_login_button(request)
121        model_class.ui_user_settings()

The type of the None singleton.

def test_source_AzureADOAuthSource(self: TestModels):
112    def tester(self: TestModels):
113        model_class = None
114        if test_model._meta.abstract:
115            return
116        else:
117            model_class = test_model()
118        model_class.slug = "test"
119        self.assertIsNotNone(model_class.component)
120        model_class.ui_login_button(request)
121        model_class.ui_user_settings()

The type of the None singleton.

def test_source_DiscordOAuthSource(self: TestModels):
112    def tester(self: TestModels):
113        model_class = None
114        if test_model._meta.abstract:
115            return
116        else:
117            model_class = test_model()
118        model_class.slug = "test"
119        self.assertIsNotNone(model_class.component)
120        model_class.ui_login_button(request)
121        model_class.ui_user_settings()

The type of the None singleton.

def test_source_EntraIDOAuthSource(self: TestModels):
112    def tester(self: TestModels):
113        model_class = None
114        if test_model._meta.abstract:
115            return
116        else:
117            model_class = test_model()
118        model_class.slug = "test"
119        self.assertIsNotNone(model_class.component)
120        model_class.ui_login_button(request)
121        model_class.ui_user_settings()

The type of the None singleton.

def test_source_FacebookOAuthSource(self: TestModels):
112    def tester(self: TestModels):
113        model_class = None
114        if test_model._meta.abstract:
115            return
116        else:
117            model_class = test_model()
118        model_class.slug = "test"
119        self.assertIsNotNone(model_class.component)
120        model_class.ui_login_button(request)
121        model_class.ui_user_settings()

The type of the None singleton.

def test_source_GitHubOAuthSource(self: TestModels):
112    def tester(self: TestModels):
113        model_class = None
114        if test_model._meta.abstract:
115            return
116        else:
117            model_class = test_model()
118        model_class.slug = "test"
119        self.assertIsNotNone(model_class.component)
120        model_class.ui_login_button(request)
121        model_class.ui_user_settings()

The type of the None singleton.

def test_source_GitLabOAuthSource(self: TestModels):
112    def tester(self: TestModels):
113        model_class = None
114        if test_model._meta.abstract:
115            return
116        else:
117            model_class = test_model()
118        model_class.slug = "test"
119        self.assertIsNotNone(model_class.component)
120        model_class.ui_login_button(request)
121        model_class.ui_user_settings()

The type of the None singleton.

def test_source_GoogleOAuthSource(self: TestModels):
112    def tester(self: TestModels):
113        model_class = None
114        if test_model._meta.abstract:
115            return
116        else:
117            model_class = test_model()
118        model_class.slug = "test"
119        self.assertIsNotNone(model_class.component)
120        model_class.ui_login_button(request)
121        model_class.ui_user_settings()

The type of the None singleton.

def test_source_IncomingSyncSource(self: TestModels):
112    def tester(self: TestModels):
113        model_class = None
114        if test_model._meta.abstract:
115            return
116        else:
117            model_class = test_model()
118        model_class.slug = "test"
119        self.assertIsNotNone(model_class.component)
120        model_class.ui_login_button(request)
121        model_class.ui_user_settings()

The type of the None singleton.

def test_source_KerberosSource(self: TestModels):
112    def tester(self: TestModels):
113        model_class = None
114        if test_model._meta.abstract:
115            return
116        else:
117            model_class = test_model()
118        model_class.slug = "test"
119        self.assertIsNotNone(model_class.component)
120        model_class.ui_login_button(request)
121        model_class.ui_user_settings()

The type of the None singleton.

def test_source_LDAPSource(self: TestModels):
112    def tester(self: TestModels):
113        model_class = None
114        if test_model._meta.abstract:
115            return
116        else:
117            model_class = test_model()
118        model_class.slug = "test"
119        self.assertIsNotNone(model_class.component)
120        model_class.ui_login_button(request)
121        model_class.ui_user_settings()

The type of the None singleton.

def test_source_MailcowOAuthSource(self: TestModels):
112    def tester(self: TestModels):
113        model_class = None
114        if test_model._meta.abstract:
115            return
116        else:
117            model_class = test_model()
118        model_class.slug = "test"
119        self.assertIsNotNone(model_class.component)
120        model_class.ui_login_button(request)
121        model_class.ui_user_settings()

The type of the None singleton.

def test_source_OAuthSource(self: TestModels):
112    def tester(self: TestModels):
113        model_class = None
114        if test_model._meta.abstract:
115            return
116        else:
117            model_class = test_model()
118        model_class.slug = "test"
119        self.assertIsNotNone(model_class.component)
120        model_class.ui_login_button(request)
121        model_class.ui_user_settings()

The type of the None singleton.

def test_source_OktaOAuthSource(self: TestModels):
112    def tester(self: TestModels):
113        model_class = None
114        if test_model._meta.abstract:
115            return
116        else:
117            model_class = test_model()
118        model_class.slug = "test"
119        self.assertIsNotNone(model_class.component)
120        model_class.ui_login_button(request)
121        model_class.ui_user_settings()

The type of the None singleton.

def test_source_OpenIDConnectOAuthSource(self: TestModels):
112    def tester(self: TestModels):
113        model_class = None
114        if test_model._meta.abstract:
115            return
116        else:
117            model_class = test_model()
118        model_class.slug = "test"
119        self.assertIsNotNone(model_class.component)
120        model_class.ui_login_button(request)
121        model_class.ui_user_settings()

The type of the None singleton.

def test_source_PatreonOAuthSource(self: TestModels):
112    def tester(self: TestModels):
113        model_class = None
114        if test_model._meta.abstract:
115            return
116        else:
117            model_class = test_model()
118        model_class.slug = "test"
119        self.assertIsNotNone(model_class.component)
120        model_class.ui_login_button(request)
121        model_class.ui_user_settings()

The type of the None singleton.

def test_source_PlexSource(self: TestModels):
112    def tester(self: TestModels):
113        model_class = None
114        if test_model._meta.abstract:
115            return
116        else:
117            model_class = test_model()
118        model_class.slug = "test"
119        self.assertIsNotNone(model_class.component)
120        model_class.ui_login_button(request)
121        model_class.ui_user_settings()

The type of the None singleton.

def test_source_RedditOAuthSource(self: TestModels):
112    def tester(self: TestModels):
113        model_class = None
114        if test_model._meta.abstract:
115            return
116        else:
117            model_class = test_model()
118        model_class.slug = "test"
119        self.assertIsNotNone(model_class.component)
120        model_class.ui_login_button(request)
121        model_class.ui_user_settings()

The type of the None singleton.

def test_source_SAMLSource(self: TestModels):
112    def tester(self: TestModels):
113        model_class = None
114        if test_model._meta.abstract:
115            return
116        else:
117            model_class = test_model()
118        model_class.slug = "test"
119        self.assertIsNotNone(model_class.component)
120        model_class.ui_login_button(request)
121        model_class.ui_user_settings()

The type of the None singleton.

def test_source_SCIMSource(self: TestModels):
112    def tester(self: TestModels):
113        model_class = None
114        if test_model._meta.abstract:
115            return
116        else:
117            model_class = test_model()
118        model_class.slug = "test"
119        self.assertIsNotNone(model_class.component)
120        model_class.ui_login_button(request)
121        model_class.ui_user_settings()

The type of the None singleton.

def test_source_SlackOAuthSource(self: TestModels):
112    def tester(self: TestModels):
113        model_class = None
114        if test_model._meta.abstract:
115            return
116        else:
117            model_class = test_model()
118        model_class.slug = "test"
119        self.assertIsNotNone(model_class.component)
120        model_class.ui_login_button(request)
121        model_class.ui_user_settings()

The type of the None singleton.

def test_source_TelegramSource(self: TestModels):
112    def tester(self: TestModels):
113        model_class = None
114        if test_model._meta.abstract:
115            return
116        else:
117            model_class = test_model()
118        model_class.slug = "test"
119        self.assertIsNotNone(model_class.component)
120        model_class.ui_login_button(request)
121        model_class.ui_user_settings()

The type of the None singleton.

def test_source_TwitchOAuthSource(self: TestModels):
112    def tester(self: TestModels):
113        model_class = None
114        if test_model._meta.abstract:
115            return
116        else:
117            model_class = test_model()
118        model_class.slug = "test"
119        self.assertIsNotNone(model_class.component)
120        model_class.ui_login_button(request)
121        model_class.ui_user_settings()

The type of the None singleton.

def test_source_TwitterOAuthSource(self: TestModels):
112    def tester(self: TestModels):
113        model_class = None
114        if test_model._meta.abstract:
115            return
116        else:
117            model_class = test_model()
118        model_class.slug = "test"
119        self.assertIsNotNone(model_class.component)
120        model_class.ui_login_button(request)
121        model_class.ui_user_settings()

The type of the None singleton.

def test_source_WeChatOAuthSource(self: TestModels):
112    def tester(self: TestModels):
113        model_class = None
114        if test_model._meta.abstract:
115            return
116        else:
117            model_class = test_model()
118        model_class.slug = "test"
119        self.assertIsNotNone(model_class.component)
120        model_class.ui_login_button(request)
121        model_class.ui_user_settings()

The type of the None singleton.

def test_provider_BackchannelProvider(self: TestModels):
129    def tester(self: TestModels):
130        model_class = None
131        if test_model._meta.abstract:  # pragma: no cover
132            return
133        model_class = test_model()
134        self.assertIsNotNone(model_class.component)

The type of the None singleton.

def test_provider_GoogleWorkspaceProvider(self: TestModels):
129    def tester(self: TestModels):
130        model_class = None
131        if test_model._meta.abstract:  # pragma: no cover
132            return
133        model_class = test_model()
134        self.assertIsNotNone(model_class.component)

The type of the None singleton.

def test_provider_LDAPProvider(self: TestModels):
129    def tester(self: TestModels):
130        model_class = None
131        if test_model._meta.abstract:  # pragma: no cover
132            return
133        model_class = test_model()
134        self.assertIsNotNone(model_class.component)

The type of the None singleton.

def test_provider_MicrosoftEntraProvider(self: TestModels):
129    def tester(self: TestModels):
130        model_class = None
131        if test_model._meta.abstract:  # pragma: no cover
132            return
133        model_class = test_model()
134        self.assertIsNotNone(model_class.component)

The type of the None singleton.

def test_provider_OAuth2Provider(self: TestModels):
129    def tester(self: TestModels):
130        model_class = None
131        if test_model._meta.abstract:  # pragma: no cover
132            return
133        model_class = test_model()
134        self.assertIsNotNone(model_class.component)

The type of the None singleton.

def test_provider_ProxyProvider(self: TestModels):
129    def tester(self: TestModels):
130        model_class = None
131        if test_model._meta.abstract:  # pragma: no cover
132            return
133        model_class = test_model()
134        self.assertIsNotNone(model_class.component)

The type of the None singleton.

def test_provider_RACProvider(self: TestModels):
129    def tester(self: TestModels):
130        model_class = None
131        if test_model._meta.abstract:  # pragma: no cover
132            return
133        model_class = test_model()
134        self.assertIsNotNone(model_class.component)

The type of the None singleton.

def test_provider_RadiusProvider(self: TestModels):
129    def tester(self: TestModels):
130        model_class = None
131        if test_model._meta.abstract:  # pragma: no cover
132            return
133        model_class = test_model()
134        self.assertIsNotNone(model_class.component)

The type of the None singleton.

def test_provider_SAMLProvider(self: TestModels):
129    def tester(self: TestModels):
130        model_class = None
131        if test_model._meta.abstract:  # pragma: no cover
132            return
133        model_class = test_model()
134        self.assertIsNotNone(model_class.component)

The type of the None singleton.

def test_provider_SAMLProviderImportModel(self: TestModels):
129    def tester(self: TestModels):
130        model_class = None
131        if test_model._meta.abstract:  # pragma: no cover
132            return
133        model_class = test_model()
134        self.assertIsNotNone(model_class.component)

The type of the None singleton.

def test_provider_SCIMProvider(self: TestModels):
129    def tester(self: TestModels):
130        model_class = None
131        if test_model._meta.abstract:  # pragma: no cover
132            return
133        model_class = test_model()
134        self.assertIsNotNone(model_class.component)

The type of the None singleton.

def test_provider_SSFProvider(self: TestModels):
129    def tester(self: TestModels):
130        model_class = None
131        if test_model._meta.abstract:  # pragma: no cover
132            return
133        model_class = test_model()
134        self.assertIsNotNone(model_class.component)

The type of the None singleton.

def test_provider_WSFederationProvider(self: TestModels):
129    def tester(self: TestModels):
130        model_class = None
131        if test_model._meta.abstract:  # pragma: no cover
132            return
133        model_class = test_model()
134        self.assertIsNotNone(model_class.component)

The type of the None singleton.

def source_tester_factory(test_model: type[authentik.core.models.Source]) -> Callable:
106def source_tester_factory(test_model: type[Source]) -> Callable:
107    """Test source"""
108
109    factory = RequestFactory()
110    request = factory.get("/")
111
112    def tester(self: TestModels):
113        model_class = None
114        if test_model._meta.abstract:
115            return
116        else:
117            model_class = test_model()
118        model_class.slug = "test"
119        self.assertIsNotNone(model_class.component)
120        model_class.ui_login_button(request)
121        model_class.ui_user_settings()
122
123    return tester

Test source

def provider_tester_factory(test_model: type[authentik.core.models.Provider]) -> Callable:
126def provider_tester_factory(test_model: type[Provider]) -> Callable:
127    """Test provider"""
128
129    def tester(self: TestModels):
130        model_class = None
131        if test_model._meta.abstract:  # pragma: no cover
132            return
133        model_class = test_model()
134        self.assertIsNotNone(model_class.component)
135
136    return tester

Test provider