ForcePilot/backend/test/unit/channels/test_twitch_auth_provider.py

326 lines
11 KiB
Python
Raw Normal View History

from __future__ import annotations
from unittest.mock import AsyncMock, patch
import pytest
from yuxi.channels.adapters.twitch.auth_provider import (
AuthProvider,
RefreshingAuthProvider,
StaticAuthProvider,
create_auth_provider,
)
class TestStaticAuthProvider:
def test_returns_access_token(self):
provider = StaticAuthProvider(client_id="cid", access_token="tok")
result = provider._access_token
assert result == "tok"
@pytest.mark.asyncio
async def test_get_access_token(self):
provider = StaticAuthProvider(client_id="cid", access_token="tok")
token = await provider.get_access_token()
assert token == "tok"
@pytest.mark.asyncio
async def test_get_client_id(self):
provider = StaticAuthProvider(client_id="cid", access_token="tok")
cid = await provider.get_client_id()
assert cid == "cid"
@pytest.mark.asyncio
async def test_validate_with_valid_token(self):
provider = StaticAuthProvider(client_id="cid", access_token="tok")
with patch("yuxi.channels.adapters.twitch.auth_provider.validate_token") as mock_validate:
mock_validate.return_value = {"id": "123"}
result = await provider.validate()
assert result is True
@pytest.mark.asyncio
async def test_validate_with_invalid_token(self):
provider = StaticAuthProvider(client_id="cid", access_token="tok")
with patch("yuxi.channels.adapters.twitch.auth_provider.validate_token") as mock_validate:
mock_validate.return_value = None
result = await provider.validate()
assert result is False
@pytest.mark.asyncio
async def test_validate_missing_credentials(self):
provider = StaticAuthProvider(client_id="", access_token="")
result = await provider.validate()
assert result is False
@pytest.mark.asyncio
async def test_get_access_token_returns_none_when_empty(self):
provider = StaticAuthProvider(client_id="cid", access_token="")
token = await provider.get_access_token()
assert token is None
class TestRefreshingAuthProvider:
def test_initial_state(self):
provider = RefreshingAuthProvider(
client_id="cid",
client_secret="secret",
access_token="tok",
refresh_token="rtok",
)
assert provider._access_token == "tok"
assert provider._refresh_token == "rtok"
assert provider._client_id == "cid"
assert provider._client_secret == "secret"
assert provider._token_expires_in == 0
assert provider._token_expires_at is None
@pytest.mark.asyncio
async def test_get_access_token_not_expired(self):
provider = RefreshingAuthProvider(
client_id="cid",
client_secret="secret",
access_token="tok",
refresh_token="rtok",
)
provider._token_expires_at = None
token = await provider.get_access_token()
assert token == "tok"
@pytest.mark.asyncio
async def test_get_client_id(self):
provider = RefreshingAuthProvider(
client_id="cid",
client_secret="secret",
access_token="tok",
refresh_token="rtok",
)
cid = await provider.get_client_id()
assert cid == "cid"
@pytest.mark.asyncio
async def test_validate_with_valid_token(self):
provider = RefreshingAuthProvider(
client_id="cid",
client_secret="secret",
access_token="tok",
refresh_token="rtok",
)
with patch("yuxi.channels.adapters.twitch.auth_provider.validate_token") as mock_validate:
mock_validate.return_value = {"id": "123"}
result = await provider.validate()
assert result is True
@pytest.mark.asyncio
async def test_validate_with_empty_credentials(self):
provider = RefreshingAuthProvider(
client_id="",
client_secret="secret",
access_token="",
refresh_token="rtok",
)
result = await provider.validate()
assert result is False
@pytest.mark.asyncio
async def test_refresh_successful(self):
provider = RefreshingAuthProvider(
client_id="cid",
client_secret="secret",
access_token="old_tok",
refresh_token="rtok",
)
with patch("yuxi.channels.adapters.twitch.auth_provider.refresh_access_token") as mock_refresh:
mock_refresh.return_value = {
"access_token": "new_tok",
"refresh_token": "new_rtok",
"expires_in": 14400,
}
result = await provider._refresh()
assert result is True
assert provider._access_token == "new_tok"
assert provider._refresh_token == "new_rtok"
assert provider._token_expires_in == 14400
assert provider._token_expires_at is not None
@pytest.mark.asyncio
async def test_refresh_no_new_access_token(self):
provider = RefreshingAuthProvider(
client_id="cid",
client_secret="secret",
access_token="old_tok",
refresh_token="rtok",
)
with patch("yuxi.channels.adapters.twitch.auth_provider.refresh_access_token") as mock_refresh:
mock_refresh.return_value = {
"refresh_token": "new_rtok",
"expires_in": 14400,
}
result = await provider._refresh()
assert result is True
@pytest.mark.asyncio
async def test_refresh_failure_single_attempt(self):
provider = RefreshingAuthProvider(
client_id="cid",
client_secret="secret",
access_token="old_tok",
refresh_token="rtok",
)
with patch("yuxi.channels.adapters.twitch.auth_provider.refresh_access_token") as mock_refresh:
mock_refresh.return_value = None
result = await provider._refresh()
assert result is False
@pytest.mark.asyncio
async def test_refresh_missing_client_secret(self):
provider = RefreshingAuthProvider(
client_id="cid",
client_secret="",
access_token="old_tok",
refresh_token="rtok",
)
result = await provider._refresh()
assert result is False
@pytest.mark.asyncio
async def test_refresh_missing_refresh_token(self):
provider = RefreshingAuthProvider(
client_id="cid",
client_secret="secret",
access_token="old_tok",
refresh_token="",
)
result = await provider._refresh()
assert result is False
@pytest.mark.asyncio
async def test_is_expired_when_none(self):
provider = RefreshingAuthProvider(
client_id="cid",
client_secret="secret",
access_token="tok",
refresh_token="rtok",
)
provider._token_expires_at = None
assert provider._is_expired() is False
@pytest.mark.asyncio
async def test_is_expired_when_future(self):
import time
provider = RefreshingAuthProvider(
client_id="cid",
client_secret="secret",
access_token="tok",
refresh_token="rtok",
)
provider._token_expires_at = time.time() + 3600
assert provider._is_expired() is False
@pytest.mark.asyncio
async def test_is_expired_when_past(self):
import time
provider = RefreshingAuthProvider(
client_id="cid",
client_secret="secret",
access_token="tok",
refresh_token="rtok",
)
provider._token_expires_at = time.time() - 1
assert provider._is_expired() is True
@pytest.mark.asyncio
async def test_get_access_token_expired_and_refreshes(self):
import time
provider = RefreshingAuthProvider(
client_id="cid",
client_secret="secret",
access_token="old_tok",
refresh_token="rtok",
)
provider._token_expires_at = time.time() - 1
with patch("yuxi.channels.adapters.twitch.auth_provider.refresh_access_token") as mock_refresh:
mock_refresh.return_value = {
"access_token": "new_tok",
"refresh_token": "new_rtok",
"expires_in": 14400,
}
token = await provider.get_access_token()
assert token == "new_tok"
@pytest.mark.asyncio
async def test_get_access_token_expired_refresh_fails(self):
import time
provider = RefreshingAuthProvider(
client_id="cid",
client_secret="secret",
access_token="old_tok",
refresh_token="rtok",
)
provider._token_expires_at = time.time() - 1
with patch("yuxi.channels.adapters.twitch.auth_provider.refresh_access_token") as mock_refresh:
mock_refresh.return_value = None
token = await provider.get_access_token()
assert token is None
@pytest.mark.asyncio
async def test_expires_at_property(self):
provider = RefreshingAuthProvider(
client_id="cid",
client_secret="secret",
access_token="tok",
refresh_token="rtok",
)
provider._token_expires_at = 12345.0
assert provider.expires_at == 12345.0
@pytest.mark.asyncio
async def test_expires_in_property(self):
provider = RefreshingAuthProvider(
client_id="cid",
client_secret="secret",
access_token="tok",
refresh_token="rtok",
)
provider._token_expires_in = 3600
assert provider.expires_in == 3600
class TestCreateAuthProvider:
def test_creates_refreshing_when_secret_and_refresh_present(self):
config = {
"client_id": "cid",
"client_secret": "secret",
"access_token": "tok",
"refresh_token": "rtok",
}
provider = create_auth_provider(config)
assert isinstance(provider, RefreshingAuthProvider)
def test_creates_static_when_no_secret(self):
config = {
"client_id": "cid",
"access_token": "tok",
}
provider = create_auth_provider(config)
assert isinstance(provider, StaticAuthProvider)
def test_creates_static_when_no_refresh_token(self):
config = {
"client_id": "cid",
"client_secret": "secret",
"access_token": "tok",
}
provider = create_auth_provider(config)
assert isinstance(provider, StaticAuthProvider)
def test_creates_static_when_empty_config(self):
config = {}
provider = create_auth_provider(config)
assert isinstance(provider, StaticAuthProvider)
def test_auth_provider_is_abstract(self):
assert hasattr(AuthProvider, "__abstractmethods__")