fischer-agentkit/tests/unit/auth/providers/test_base.py

113 lines
3.9 KiB
Python

"""Tests for the AuthProvider protocol and the DI factory (U11)."""
from __future__ import annotations
import pytest
from agentkit.server.auth.providers import (
AuthProvider,
LocalAuthProvider,
StubOIDCProvider,
get_auth_provider,
reset_auth_provider,
)
from agentkit.server.auth.providers.base import AuthProvider as AuthProviderFromBase
from agentkit.server.auth.providers.exceptions import (
AuthProviderError,
InvalidCredentials,
ProviderNotImplemented,
)
class TestProtocolConformance:
"""The runtime_checkable Protocol accepts both real implementations."""
def test_local_passes_isinstance_check(self):
provider = LocalAuthProvider()
assert isinstance(provider, AuthProvider)
assert isinstance(provider, AuthProviderFromBase)
def test_stub_passes_isinstance_check(self):
provider = StubOIDCProvider()
assert isinstance(provider, AuthProvider)
assert isinstance(provider, AuthProviderFromBase)
class TestProviderNames:
def test_local_provider_name(self):
assert LocalAuthProvider.name == "local"
def test_stub_oidc_provider_name(self):
assert StubOIDCProvider.name == "oidc-stub"
class TestDiFactory:
"""``get_auth_provider`` is a memoized singleton, env-driven."""
def setup_method(self):
"""Reset cache and env before each test."""
reset_auth_provider()
self._saved_env = {}
for key in ("AGENTKIT_AUTH_PROVIDER",):
self._saved_env[key] = __import__("os").environ.pop(key, None)
def teardown_method(self):
for key, value in self._saved_env.items():
if value is not None:
__import__("os").environ[key] = value
reset_auth_provider()
def test_default_provider_is_local(self):
provider = get_auth_provider()
assert isinstance(provider, LocalAuthProvider)
assert provider.name == "local"
def test_oidc_stub_provider(self, monkeypatch):
monkeypatch.setenv("AGENTKIT_AUTH_PROVIDER", "oidc-stub")
reset_auth_provider()
provider = get_auth_provider()
assert isinstance(provider, StubOIDCProvider)
assert provider.name == "oidc-stub"
def test_unknown_provider_raises_value_error(self, monkeypatch):
monkeypatch.setenv("AGENTKIT_AUTH_PROVIDER", "ldap-unknown")
reset_auth_provider()
with pytest.raises(ValueError, match="unknown auth provider"):
get_auth_provider()
def test_factory_is_memoized(self):
first = get_auth_provider()
second = get_auth_provider()
assert first is second
def test_reset_clears_cache(self, monkeypatch):
first = get_auth_provider()
reset_auth_provider()
monkeypatch.setenv("AGENTKIT_AUTH_PROVIDER", "oidc-stub")
second = get_auth_provider()
assert first is not second
assert isinstance(second, StubOIDCProvider)
class TestExceptionHierarchy:
def test_invalid_credentials_inherits_auth_provider_error(self):
assert issubclass(InvalidCredentials, AuthProviderError)
assert issubclass(InvalidCredentials, Exception)
def test_provider_not_implemented_inherits_auth_provider_error(self):
assert issubclass(ProviderNotImplemented, AuthProviderError)
assert issubclass(ProviderNotImplemented, Exception)
def test_invalid_credentials_can_be_raised_and_caught(self):
with pytest.raises(InvalidCredentials):
raise InvalidCredentials("test message")
def test_invalid_credentials_caught_as_base(self):
"""Route layer catches AuthProviderError to handle all provider errors."""
with pytest.raises(AuthProviderError):
raise InvalidCredentials("test")
def test_provider_not_implemented_caught_as_base(self):
with pytest.raises(AuthProviderError):
raise ProviderNotImplemented("test")