refactor: many changes
- Add missing actions and make a clear boundary between actions, services and nfra (i.e: actions shouldn't use stuff from infra/) - Delete stuff not in use: tts, gtts, etc - Add a ton of tests
This commit is contained in:
parent
b2185f4174
commit
152546982c
46 changed files with 2328 additions and 700 deletions
|
|
@ -1,27 +1,49 @@
|
|||
from pathlib import Path
|
||||
from uuid import UUID
|
||||
|
||||
import pytest
|
||||
from caribou.migrate import Database as CaribouDatabase
|
||||
from caribou.migrate import load_migrations
|
||||
from polyfactory.factories.pydantic_factory import ModelFactory
|
||||
from polyfactory.pytest_plugin import register_fixture
|
||||
from pydantic import BaseModel
|
||||
|
||||
from huesoporro.infra.db import Database
|
||||
from huesoporro.models import ChatbotSettings, Quote, User
|
||||
from huesoporro.infra.repos import ChatbotRepo, IRepo, QuoteRepo, UserRepo
|
||||
from huesoporro.models import Chatbot, Quote, TwitchAuth, User
|
||||
from huesoporro.settings import Settings
|
||||
from huesoporro.svc.backoff_service import BackoffService
|
||||
from huesoporro.svc.chatbot_svcs import (
|
||||
CreateChatbotSvc,
|
||||
GetChatbotByUserIdSvc,
|
||||
UpdateChatbotSvc,
|
||||
)
|
||||
from huesoporro.svc.hello import HelloGeneratorSvc
|
||||
from huesoporro.svc.is_mod import IsModSvc
|
||||
from huesoporro.svc.quotes_svcs import CreateQuoteSvc, GetRandomQuoteSvc
|
||||
from huesoporro.svc.users_svcs import (
|
||||
CreateUserSvc,
|
||||
DeleteUserSvc,
|
||||
GetTwitchAuthByAuthCodeSvc,
|
||||
GetUserByIdSvc,
|
||||
GetUserByUsernameSvc,
|
||||
UpdateUserSvc,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def user() -> User:
|
||||
return User(
|
||||
user="huesoporro",
|
||||
external_auth={
|
||||
"twitch": {"token": "twitch_token"},
|
||||
"discord": {"token": "discord_token"},
|
||||
},
|
||||
)
|
||||
@register_fixture()
|
||||
class TwitchAuthFactory(ModelFactory[TwitchAuth]): ...
|
||||
|
||||
|
||||
@register_fixture()
|
||||
class ChatbotFactory(ModelFactory[Chatbot]): ...
|
||||
|
||||
|
||||
@register_fixture()
|
||||
class UserFactory(ModelFactory[User]): ...
|
||||
|
||||
|
||||
@register_fixture()
|
||||
class QuoteFactory(ModelFactory[Quote]): ...
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
|
@ -32,31 +54,169 @@ def s(tmp_path: Path, user: User) -> Settings:
|
|||
twitch_client_id="test_client_id",
|
||||
twitch_client_secret="test_client_secret", # type: ignore[arg-type] # noqa: S106
|
||||
jwt_secret="test_jwt_secret", # type: ignore[arg-type] # noqa: S106
|
||||
allowed_users=[user.user],
|
||||
allowed_users=[user.username],
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def db(s) -> Database:
|
||||
def db(s, cdb):
|
||||
class BogusRepo(IRepo[BaseModel]):
|
||||
async def get_by_id(self, obj_id: UUID, auto_commit=True) -> BaseModel | None:
|
||||
pass
|
||||
|
||||
async def list( # type: ignore[empty-body]
|
||||
self, obj: BaseModel, offset: int = 0, limit: int = 10, auto_commit=True
|
||||
) -> list[BaseModel]:
|
||||
pass
|
||||
|
||||
async def create(self, obj: BaseModel, auto_commit: bool = True) -> BaseModel: # type: ignore[empty-body]
|
||||
pass
|
||||
|
||||
async def update(self, obj: BaseModel, auto_commit=True) -> BaseModel: # type: ignore[empty-body]
|
||||
pass
|
||||
|
||||
async def delete(self, obj: BaseModel, auto_commit=True) -> None: # type: ignore[empty-body]
|
||||
pass
|
||||
|
||||
async def get_by_user(self, user: str) -> BaseModel: # type: ignore[empty-body]
|
||||
pass
|
||||
|
||||
return BogusRepo(s=s).get_client
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def cdb(s) -> CaribouDatabase:
|
||||
cdb = CaribouDatabase(
|
||||
db_url=s.db_filepath,
|
||||
)
|
||||
cdb.initialize_version_control()
|
||||
migrations = load_migrations(Path(__file__).parents[1] / "migrations")
|
||||
cdb.upgrade(migrations)
|
||||
return Database(s=s)
|
||||
return cdb
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def is_mod_svc(db) -> IsModSvc:
|
||||
return IsModSvc(db=db)
|
||||
async def user_repo(s, db):
|
||||
return UserRepo(s=s)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def chatbot_settings(db: Database, user) -> ChatbotSettings:
|
||||
cbs = ChatbotSettings(mods=[user.user, "allowed_user"])
|
||||
await db.save_chatbot_settings(user=user, chatbot_settings=cbs)
|
||||
return cbs
|
||||
def twitch_auth(twitch_auth_factory):
|
||||
return twitch_auth_factory.build(
|
||||
userinfo={
|
||||
"aud": twitch_auth_factory.__faker__.pystr(),
|
||||
"exp": twitch_auth_factory.__faker__.pyint(),
|
||||
"iat": twitch_auth_factory.__faker__.pyint(),
|
||||
"iss": "https://id.twitch.tv/oauth2",
|
||||
"sub": twitch_auth_factory.__faker__.pystr(),
|
||||
"azp": twitch_auth_factory.__faker__.pystr(),
|
||||
"preferred_username": twitch_auth_factory.__faker__.user_name(),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def user(user_factory: UserFactory, twitch_auth) -> User:
|
||||
return user_factory.build(external_auth={"twitch": twitch_auth})
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def persisted_user(user_repo: UserRepo, user: User) -> User:
|
||||
return await user_repo.create(user)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def create_user_svc(user_repo):
|
||||
return CreateUserSvc(user_repo=user_repo)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def update_user_svc(user_repo):
|
||||
return UpdateUserSvc(user_repo=user_repo)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def delete_user_svc(user_repo):
|
||||
return DeleteUserSvc(user_repo=user_repo)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def get_user_by_id_svc(user_repo):
|
||||
return GetUserByIdSvc(user_repo=user_repo)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def get_user_by_username_svc(user_repo):
|
||||
return GetUserByUsernameSvc(user_repo=user_repo)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def get_twitch_auth_by_auth_code_svc(
|
||||
twitch_authenticator, fake_twitch_authenticator, user_repo, s
|
||||
):
|
||||
svc = GetTwitchAuthByAuthCodeSvc(authenticator=twitch_authenticator, s=s)
|
||||
svc.authenticator = fake_twitch_authenticator
|
||||
return svc
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def chatbot_repo(s, db):
|
||||
return ChatbotRepo(s=s)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def chatbot(chatbot_factory, user):
|
||||
return chatbot_factory.build(user_id=user.id)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def persisted_chatbot(chatbot_repo, chatbot, persisted_user):
|
||||
return await chatbot_repo.create(chatbot)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def create_chatbot_svc(chatbot_repo):
|
||||
return CreateChatbotSvc(repo=chatbot_repo)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def get_chatbot_by_user_id_svc(chatbot_repo):
|
||||
return GetChatbotByUserIdSvc(repo=chatbot_repo)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def update_chatbot_svc(chatbot_repo):
|
||||
return UpdateChatbotSvc(repo=chatbot_repo)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def is_mod_svc(chatbot_repo):
|
||||
return IsModSvc(repo=chatbot_repo)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def quote_repo(s, db):
|
||||
return QuoteRepo(s=s)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def quote(quote_factory):
|
||||
return quote_factory.build()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def persisted_quote(quote_repo, quote):
|
||||
return await quote_repo.create(quote)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def create_quote_svc(quote_repo):
|
||||
return CreateQuoteSvc(repo=quote_repo)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def get_random_quote_svc(quote_repo):
|
||||
return GetRandomQuoteSvc(repo=quote_repo)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
|
@ -83,10 +243,6 @@ async def backoff_svc(backoff_callable, async_backoff_callable):
|
|||
return backoff_svc
|
||||
|
||||
|
||||
@register_fixture()
|
||||
class QuoteFactory(ModelFactory[Quote]): ...
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def quote(quote_factory):
|
||||
return quote_factory.build()
|
||||
async def hello_generator_svc():
|
||||
return HelloGeneratorSvc()
|
||||
|
|
|
|||
243
tests/test_actions.py
Normal file
243
tests/test_actions.py
Normal file
|
|
@ -0,0 +1,243 @@
|
|||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
from huesoporro.actions.quotes.create_quote_action import CreateQuoteAction
|
||||
from huesoporro.actions.quotes.get_random_quote import GetRandomQuoteAction
|
||||
from huesoporro.actions.users.authenticate_user import AuthenticateUserAction
|
||||
from huesoporro.actions.users.get_user_by_jwt import GetUserByJWTAction
|
||||
from huesoporro.actions.users.refresh_user_jwt import RefreshUserJwtAction
|
||||
from huesoporro.infra.authenticator import TwitchAuthenticator
|
||||
from huesoporro.models import Quote, TwitchAuth
|
||||
from huesoporro.svc.users_svcs import IsValidTokenSvc, RefreshTokenSvc
|
||||
|
||||
|
||||
class AsyncMock(MagicMock):
|
||||
async def __call__(self, *args, **kwargs):
|
||||
return super().__call__(*args, **kwargs)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def twitch_authenticator(s):
|
||||
return TwitchAuthenticator(s=s)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def fake_twitch_authenticator():
|
||||
return AsyncMock()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def refresh_token_svc(twitch_authenticator, fake_twitch_authenticator, s):
|
||||
svc = RefreshTokenSvc(twitch_authenticator=twitch_authenticator)
|
||||
svc.twitch_authenticator = fake_twitch_authenticator
|
||||
return svc
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def is_valid_svc(twitch_authenticator, fake_twitch_authenticator):
|
||||
svc = IsValidTokenSvc(authenticator=twitch_authenticator)
|
||||
svc.authenticator = fake_twitch_authenticator
|
||||
return svc
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def get_user_by_jwt_action(
|
||||
s, get_user_by_username_svc, update_user_svc, is_valid_svc, refresh_token_svc
|
||||
):
|
||||
return GetUserByJWTAction(
|
||||
get_user_by_username_svc=get_user_by_username_svc,
|
||||
update_user_svc=update_user_svc,
|
||||
refresh_token_svc=refresh_token_svc,
|
||||
is_valid_token_svc=is_valid_svc,
|
||||
s=s,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def refresh_user_jwt_action(
|
||||
s, get_user_by_username_svc, update_user_svc, is_valid_svc, refresh_token_svc
|
||||
):
|
||||
return RefreshUserJwtAction(
|
||||
get_user_by_username_svc=get_user_by_username_svc,
|
||||
update_user_svc=update_user_svc,
|
||||
refresh_token_svc=refresh_token_svc,
|
||||
is_valid_token_svc=is_valid_svc,
|
||||
s=s,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def authenticate_user_action( # noqa: PLR0913
|
||||
s,
|
||||
get_user_by_username_svc,
|
||||
get_twitch_auth_by_auth_code_svc,
|
||||
update_user_svc,
|
||||
create_user_svc,
|
||||
twitch_authenticator,
|
||||
):
|
||||
return AuthenticateUserAction(
|
||||
get_user_by_username_svc=get_user_by_username_svc,
|
||||
update_user_svc=update_user_svc,
|
||||
create_user_svc=create_user_svc,
|
||||
get_tokens_by_auth_code_svc=get_twitch_auth_by_auth_code_svc,
|
||||
s=s,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def get_random_quote_action(get_random_quote_svc):
|
||||
return GetRandomQuoteAction(get_random_quote_svc=get_random_quote_svc)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def create_random_quote_action(create_quote_svc, is_mod_svc):
|
||||
return CreateQuoteAction(create_quote_svc=create_quote_svc, is_mod_svc=is_mod_svc)
|
||||
|
||||
|
||||
async def test_get_user_by_jwt_action_raises_value_error(
|
||||
get_user_by_jwt_action: GetUserByJWTAction, user, s
|
||||
):
|
||||
with pytest.raises(ValueError, match=f"User {user.username} not found"):
|
||||
await get_user_by_jwt_action.run(jwt_token=user.encode(settings=s))
|
||||
|
||||
|
||||
async def test_get_user_by_jwt_returns_user(
|
||||
get_user_by_jwt_action: GetUserByJWTAction,
|
||||
persisted_user,
|
||||
s,
|
||||
fake_twitch_authenticator,
|
||||
):
|
||||
fake_twitch_authenticator.token_is_valid.return_value = True
|
||||
jwt = persisted_user.encode(settings=s)
|
||||
assert await get_user_by_jwt_action.run(jwt_token=jwt)
|
||||
|
||||
|
||||
async def test_get_user_by_jwt_returns_refreshed_user(
|
||||
get_user_by_jwt_action: GetUserByJWTAction,
|
||||
persisted_user,
|
||||
s,
|
||||
fake_twitch_authenticator,
|
||||
):
|
||||
jwt = persisted_user.encode(settings=s)
|
||||
fake_twitch_authenticator.token_is_valid.return_value = False
|
||||
fake_twitch_authenticator.refresh_token.return_value = TwitchAuth(
|
||||
access_token="mocked", # noqa: S106
|
||||
refresh_token="mocked", # noqa: S106
|
||||
userinfo={},
|
||||
)
|
||||
assert await get_user_by_jwt_action.run(jwt_token=jwt)
|
||||
|
||||
|
||||
async def test_refresh_user_jwt_returns_none_on_valid_token(
|
||||
refresh_user_jwt_action: RefreshUserJwtAction,
|
||||
persisted_user,
|
||||
s,
|
||||
fake_twitch_authenticator,
|
||||
):
|
||||
fake_twitch_authenticator.token_is_valid.return_value = True
|
||||
assert await refresh_user_jwt_action.run(user=persisted_user) is None
|
||||
|
||||
|
||||
async def test_refresh_user_jwt_returns_updated_user(
|
||||
refresh_user_jwt_action: RefreshUserJwtAction,
|
||||
persisted_user,
|
||||
s,
|
||||
fake_twitch_authenticator,
|
||||
):
|
||||
fake_twitch_authenticator.token_is_valid.return_value = False
|
||||
fake_twitch_authenticator.refresh_token.return_value = TwitchAuth(
|
||||
access_token="mocked", # noqa: S106
|
||||
refresh_token="mocked", # noqa: S106
|
||||
userinfo={},
|
||||
)
|
||||
user = await refresh_user_jwt_action.run(user=persisted_user)
|
||||
assert user
|
||||
assert user.twitch_access_token == "mocked" # noqa: S105
|
||||
assert user.twitch_refresh_token == "mocked" # noqa: S105
|
||||
|
||||
|
||||
async def test_authenticate_existing_user_returns_user(
|
||||
persisted_user, authenticate_user_action, fake_twitch_authenticator
|
||||
):
|
||||
fake_twitch_authenticator.get_token.return_value = TwitchAuth(
|
||||
access_token="mocked", # noqa: S106
|
||||
refresh_token="mocked", # noqa: S106
|
||||
userinfo={"preferred_username": persisted_user.username},
|
||||
)
|
||||
user = await authenticate_user_action.run(auth_code="mocked")
|
||||
assert user.id == persisted_user.id
|
||||
assert user.username == persisted_user.username
|
||||
assert user.twitch_access_token == "mocked" != persisted_user.twitch_access_token # noqa: S105
|
||||
assert (
|
||||
user.twitch_refresh_token
|
||||
== "mocked" # noqa: S105
|
||||
!= persisted_user.external_auth["twitch"].refresh_token
|
||||
)
|
||||
|
||||
|
||||
async def test_authenticate_raises_value_error_on_not_allowed_user(
|
||||
authenticate_user_action, fake_twitch_authenticator
|
||||
):
|
||||
fake_twitch_authenticator.get_token.return_value = TwitchAuth(
|
||||
access_token="mocked", # noqa: S106
|
||||
refresh_token="mocked", # noqa: S106
|
||||
userinfo={"preferred_username": "not_allowed"},
|
||||
)
|
||||
with pytest.raises(ValueError, match="User not_allowed is not allowed"):
|
||||
await authenticate_user_action.run(auth_code="mocked")
|
||||
|
||||
|
||||
async def test_authenticate_user(
|
||||
authenticate_user_action, fake_twitch_authenticator, user
|
||||
):
|
||||
fake_twitch_authenticator.get_token.return_value = TwitchAuth(
|
||||
access_token="mocked", # noqa: S106
|
||||
refresh_token="mocked", # noqa: S106
|
||||
userinfo={"preferred_username": user.username},
|
||||
)
|
||||
user = await authenticate_user_action.run(auth_code="mocked")
|
||||
assert user.username == user.username
|
||||
|
||||
|
||||
async def test_get_random_quote_action(
|
||||
get_random_quote_action: GetRandomQuoteAction, persisted_quote: Quote
|
||||
):
|
||||
assert (
|
||||
await get_random_quote_action.run(persisted_quote.channel_name)
|
||||
== persisted_quote
|
||||
)
|
||||
|
||||
|
||||
async def test_create_quote_action_returns_none_on_not_mod_user(
|
||||
create_random_quote_action: CreateQuoteAction, user
|
||||
):
|
||||
assert (
|
||||
await create_random_quote_action.run(
|
||||
user=user,
|
||||
channel=user.username,
|
||||
quote="mocked",
|
||||
author="mocked",
|
||||
username="mocked",
|
||||
)
|
||||
is None
|
||||
)
|
||||
|
||||
|
||||
async def test_create_quote_action(
|
||||
create_random_quote_action: CreateQuoteAction, user, quote: Quote, persisted_user
|
||||
):
|
||||
quote.channel_name = persisted_user.username
|
||||
|
||||
new_quote = await create_random_quote_action.run(
|
||||
user=persisted_user,
|
||||
username=user.username,
|
||||
channel=user.username,
|
||||
quote=quote.quote,
|
||||
author=quote.author,
|
||||
)
|
||||
assert new_quote
|
||||
quote.id = new_quote.id
|
||||
quote.created_at = new_quote.created_at
|
||||
quote.last_updated_at = new_quote.last_updated_at
|
||||
assert quote == new_quote
|
||||
21
tests/test_models.py
Normal file
21
tests/test_models.py
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
from tests.conftest import ChatbotFactory, QuoteFactory
|
||||
|
||||
|
||||
def test_chatbot_format_mods_from_string_validator(chatbot_factory: ChatbotFactory):
|
||||
chatbot = chatbot_factory.build(mods="foo,bar")
|
||||
assert chatbot.mods == ["foo", "bar"]
|
||||
|
||||
|
||||
def test_chatbot_mods_as_string_returns_empty_string(chatbot_factory: ChatbotFactory):
|
||||
modsless_chatbot = chatbot_factory.build(mods=[])
|
||||
assert modsless_chatbot.mods_as_string == ""
|
||||
|
||||
|
||||
def test_quote_as_pretty(quote_factory: QuoteFactory):
|
||||
quote = quote_factory.build(quote="Foo", author="Bar")
|
||||
assert quote.as_pretty() == "«Foo» - Bar"
|
||||
|
||||
|
||||
def test_quote_as_pretty_saved(quote_factory: QuoteFactory):
|
||||
quote = quote_factory.build(quote="Foo", author="Bar")
|
||||
assert quote.as_pretty_saved() == "He añadido la cita «Foo» de Bar"
|
||||
|
|
@ -1,75 +1,95 @@
|
|||
import json
|
||||
import uuid
|
||||
|
||||
import pytest
|
||||
|
||||
from huesoporro.infra.repos import QuoteRepo, UserRepo
|
||||
from huesoporro.models import User
|
||||
from huesoporro.models import TwitchAuth, User
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def user_repo(s, db, user: User):
|
||||
async with db.get_client() as client:
|
||||
await client.execute(
|
||||
"INSERT INTO users (user, external_auth) VALUES (?, ?)",
|
||||
(user.user, json.dumps(user.external_auth)),
|
||||
)
|
||||
|
||||
return UserRepo(s=s)
|
||||
async def test_create_user_raises_value_error_for_existing_user(
|
||||
user_repo: UserRepo, persisted_user: User
|
||||
):
|
||||
with pytest.raises(
|
||||
ValueError, match=f"User {persisted_user.username} already exists"
|
||||
):
|
||||
await user_repo.create(persisted_user)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def quote_repo(s, db):
|
||||
async with db.get_client() as client:
|
||||
await client.execute(
|
||||
"INSERT INTO quotes (channel, quote, author) VALUES (?, ?, ?)",
|
||||
("channel", "quote", "author"),
|
||||
)
|
||||
return QuoteRepo(s=s)
|
||||
|
||||
|
||||
async def test_get_user(user_repo: UserRepo, user: User):
|
||||
db_user = await user_repo.get_by_user(user.user)
|
||||
assert db_user == user
|
||||
async def test_get_user_by_username(user_repo: UserRepo, persisted_user: User):
|
||||
db_user = await user_repo.get_by_username(persisted_user.username)
|
||||
assert db_user == persisted_user
|
||||
|
||||
|
||||
async def test_get_user_returns_none(user_repo: UserRepo):
|
||||
assert await user_repo.get_by_user("unknown_user") is None
|
||||
assert await user_repo.get_by_username("unknown_user") is None
|
||||
|
||||
|
||||
async def test_create_user(user_repo: UserRepo):
|
||||
new_user = User(
|
||||
user="new_user", external_auth={"twitch": {"token": "twitch_token"}}
|
||||
)
|
||||
assert await user_repo.create(new_user) == new_user
|
||||
async def test_get_user_by_id(user_repo: UserRepo, persisted_user: User):
|
||||
db_user = await user_repo.get_by_id(persisted_user.id)
|
||||
assert db_user == persisted_user
|
||||
|
||||
|
||||
async def test_update_users_tokens(user_repo: UserRepo, user: User):
|
||||
new_tokens = {"twitch": {"token": "new_tokens"}}
|
||||
user.external_auth = new_tokens # type: ignore[assignment]
|
||||
assert await user_repo.update(user) == user
|
||||
async def test_get_user_by_id_returns_none(user_repo: UserRepo):
|
||||
assert await user_repo.get_by_id(uuid.uuid4()) is None
|
||||
|
||||
|
||||
async def test_update_non_existing_user_raises_value_error(user_repo: UserRepo):
|
||||
with pytest.raises(ValueError, match="User unknown_user does not exist"):
|
||||
await user_repo.update(
|
||||
User(
|
||||
user="unknown_user", external_auth={"twitch": {"token": "twitch_token"}}
|
||||
)
|
||||
async def test_update_users_tokens(
|
||||
user_repo: UserRepo, twitch_auth: TwitchAuth, persisted_user: User
|
||||
):
|
||||
twitch_auth.access_token = uuid.uuid4().hex
|
||||
twitch_auth.refresh_token = uuid.uuid4().hex
|
||||
new_tokens = {"twitch": twitch_auth}
|
||||
persisted_user.external_auth = new_tokens # type: ignore[assignment]
|
||||
assert await user_repo.update(persisted_user) == persisted_user
|
||||
|
||||
|
||||
async def test_update_username(user_repo: UserRepo, persisted_user: User):
|
||||
persisted_user.username = "new_username"
|
||||
assert await user_repo.update(persisted_user) == persisted_user
|
||||
|
||||
|
||||
async def test_update_non_existing_user_raises_value_error(
|
||||
user_repo: UserRepo, user: User
|
||||
):
|
||||
with pytest.raises(ValueError, match=f"User {user.username} does not exist"):
|
||||
await user_repo.update(user)
|
||||
|
||||
|
||||
async def test_delete_user(user_repo: UserRepo, persisted_user: User):
|
||||
assert await user_repo.delete(persisted_user) is None
|
||||
assert await user_repo.get_by_id(persisted_user.id) is None
|
||||
|
||||
|
||||
async def test_create_chatbot_raises_value_error_for_existing_chatbot(
|
||||
chatbot_repo, chatbot_factory, persisted_chatbot
|
||||
):
|
||||
with pytest.raises(
|
||||
ValueError, match=f"Chatbot {persisted_chatbot.user_id} already exists"
|
||||
):
|
||||
await chatbot_repo.create(
|
||||
chatbot_factory.build(user_id=persisted_chatbot.user_id)
|
||||
)
|
||||
|
||||
|
||||
async def test_delete_user(user_repo: UserRepo, user: User):
|
||||
assert await user_repo.delete(user) is None
|
||||
assert await user_repo.get_by_user(user.user) is None
|
||||
async def test_update_chatbot(persisted_chatbot, faker, chatbot_repo):
|
||||
persisted_chatbot.automatic_generation_timer = faker.pyint()
|
||||
persisted_chatbot.automatic_quote_timer = faker.pyint()
|
||||
persisted_chatbot.mods = ["mod1", "mod2"]
|
||||
|
||||
updated_chatbot = await chatbot_repo.update(persisted_chatbot)
|
||||
persisted_chatbot.last_updated_at = updated_chatbot.last_updated_at
|
||||
assert updated_chatbot == persisted_chatbot
|
||||
|
||||
|
||||
async def test_get_random_quote(quote_repo: QuoteRepo):
|
||||
quote = await quote_repo.get_random("channel")
|
||||
async def test_update_chatbot_raises_value_error_on_non_existing_chatbot(
|
||||
chatbot_repo, chatbot
|
||||
):
|
||||
with pytest.raises(ValueError, match=f"Chatbot {chatbot.user_id} does not exist"):
|
||||
await chatbot_repo.update(chatbot)
|
||||
|
||||
|
||||
async def test_get_random_quote(quote_repo: QuoteRepo, persisted_quote):
|
||||
quote = await quote_repo.get_random(persisted_quote.channel_name)
|
||||
assert quote
|
||||
assert quote.author.user == "author"
|
||||
assert quote.channel.user == "channel"
|
||||
|
||||
|
||||
async def test_create_quote(quote, quote_repo):
|
||||
new_quote = await quote_repo.create(quote)
|
||||
assert new_quote == quote
|
||||
assert quote.author == persisted_quote.author
|
||||
assert quote.channel_name == persisted_quote.channel_name
|
||||
|
|
|
|||
|
|
@ -1,12 +1,54 @@
|
|||
import asyncio
|
||||
import time
|
||||
import uuid
|
||||
|
||||
import pytest
|
||||
|
||||
from huesoporro.models import ChatbotSettings, User
|
||||
from huesoporro.models import Chatbot, User
|
||||
from huesoporro.svc.is_mod import IsModSvc
|
||||
|
||||
|
||||
async def test_create_user_svc_returns_user(create_user_svc, user):
|
||||
created_user = await create_user_svc.run(user=user)
|
||||
assert created_user == user
|
||||
|
||||
|
||||
async def test_update_user_svc_returns_user(update_user_svc, persisted_user):
|
||||
persisted_user.username = "new_username"
|
||||
updated_user = await update_user_svc.run(user=persisted_user)
|
||||
assert updated_user == persisted_user
|
||||
|
||||
|
||||
async def test_update_user_svc_raises_value_error_for_non_existing_user(
|
||||
update_user_svc, user
|
||||
):
|
||||
with pytest.raises(ValueError, match=f"User {user.username} does not exist"):
|
||||
await update_user_svc.run(user=user)
|
||||
|
||||
|
||||
async def test_delete_user_svc_returns_none(delete_user_svc, persisted_user):
|
||||
assert await delete_user_svc.run(user=persisted_user) is None
|
||||
|
||||
|
||||
async def test_get_user_by_id_svc_returns_user(get_user_by_id_svc, persisted_user):
|
||||
assert await get_user_by_id_svc.run(user_id=persisted_user.id) == persisted_user
|
||||
|
||||
|
||||
async def test_get_user_by_id_returns_none(get_user_by_id_svc):
|
||||
assert await get_user_by_id_svc.run(user_id=uuid.uuid4()) is None
|
||||
|
||||
|
||||
async def test_get_user_by_username(get_user_by_username_svc, persisted_user):
|
||||
assert (
|
||||
await get_user_by_username_svc.run(username=persisted_user.username)
|
||||
== persisted_user
|
||||
)
|
||||
|
||||
|
||||
async def test_get_user_by_username_returns_none(get_user_by_username_svc):
|
||||
assert await get_user_by_username_svc.run(username="unknown_user") is None
|
||||
|
||||
|
||||
async def test_is_mod_svc_returns_true_for_channel(is_mod_svc: IsModSvc, user: User):
|
||||
is_mod = await is_mod_svc.run(user=user, username="TestUser", channel="TestUser")
|
||||
assert is_mod
|
||||
|
|
@ -14,27 +56,30 @@ async def test_is_mod_svc_returns_true_for_channel(is_mod_svc: IsModSvc, user: U
|
|||
|
||||
async def test_is_mod_svc_returns_true_for_user_in_modlist(
|
||||
is_mod_svc: IsModSvc,
|
||||
user: User,
|
||||
chatbot_settings: ChatbotSettings,
|
||||
persisted_user: User,
|
||||
persisted_chatbot: Chatbot,
|
||||
):
|
||||
is_mod = await is_mod_svc.run(
|
||||
user=user, username=chatbot_settings.mods[1], channel=user.user
|
||||
)
|
||||
assert is_mod
|
||||
assert persisted_chatbot.mods
|
||||
for mod in persisted_chatbot.mods:
|
||||
is_mod = await is_mod_svc.run(
|
||||
user=persisted_user, username=mod, channel=persisted_user.username
|
||||
)
|
||||
assert is_mod
|
||||
|
||||
|
||||
async def test_is_mod_svc_returns_false_for_settingless_user(
|
||||
async def test_is_mod_svc_returns_false_for_chatbotless_user(
|
||||
is_mod_svc: IsModSvc, user: User
|
||||
):
|
||||
is_mod = await is_mod_svc.run(user=user, username="TestUser", channel="TestUser2")
|
||||
assert not is_mod
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("chatbot_settings")
|
||||
async def test_is_mod_svc_returns_false_for_user_not_in_modlist(
|
||||
is_mod_svc: IsModSvc, user: User
|
||||
is_mod_svc: IsModSvc, persisted_user: User, persisted_chatbot
|
||||
):
|
||||
is_mod = await is_mod_svc.run(user=user, username="TestUser2", channel=user.user)
|
||||
is_mod = await is_mod_svc.run(
|
||||
user=persisted_user, username="TestUser2", channel=persisted_user.username
|
||||
)
|
||||
assert not is_mod
|
||||
|
||||
|
||||
|
|
@ -94,3 +139,54 @@ async def test_backoff_svc_raises_value_error_for_sync_called_from_async(
|
|||
):
|
||||
with pytest.raises(ValueError, match="Cannot call async function with .call()"):
|
||||
backoff_svc.call(async_backoff_callable)
|
||||
|
||||
|
||||
async def test_create_quote_svc(create_quote_svc, quote):
|
||||
created_quote = await create_quote_svc.run(quote)
|
||||
assert created_quote == quote
|
||||
|
||||
|
||||
async def test_get_random_quote_svc_returns_random_quote(
|
||||
get_random_quote_svc, persisted_quote
|
||||
):
|
||||
random_quote = await get_random_quote_svc.run(
|
||||
channel_name=persisted_quote.channel_name
|
||||
)
|
||||
assert random_quote == persisted_quote
|
||||
|
||||
|
||||
def test_generate_hello_svc_returns_greeting(hello_generator_svc, user):
|
||||
greeting = hello_generator_svc.run(username=user.username)
|
||||
assert greeting.split()[0] in hello_generator_svc.hellos
|
||||
|
||||
|
||||
def test_generate_hello_svc_returns_none_on_already_greeted_user(
|
||||
hello_generator_svc, user
|
||||
):
|
||||
assert hello_generator_svc.run(username=user.username)
|
||||
assert not hello_generator_svc.run(username=user.username)
|
||||
|
||||
|
||||
async def test_create_chatbot_svc_returns_chatbot(create_chatbot_svc, chatbot):
|
||||
created_chatbot = await create_chatbot_svc.run(chatbot)
|
||||
assert created_chatbot == chatbot
|
||||
|
||||
|
||||
async def test_get_chatbot_by_user_id_svc_returns_chatbot(
|
||||
get_chatbot_by_user_id_svc, persisted_chatbot
|
||||
):
|
||||
existing_chatbot = await get_chatbot_by_user_id_svc.run(
|
||||
user_id=persisted_chatbot.user_id
|
||||
)
|
||||
assert existing_chatbot == persisted_chatbot
|
||||
|
||||
|
||||
async def test_update_chatbot_svc_returns_chatbot(
|
||||
update_chatbot_svc, persisted_chatbot, faker
|
||||
):
|
||||
persisted_chatbot.automatic_quote_timer = faker.pyint()
|
||||
persisted_chatbot.automatic_quote_timer = faker.pyint()
|
||||
persisted_chatbot.mods = [faker.word() for _ in range(5)]
|
||||
updated_chatbot = await update_chatbot_svc.run(chatbot=persisted_chatbot)
|
||||
persisted_chatbot.last_updated_at = updated_chatbot.last_updated_at
|
||||
assert updated_chatbot == persisted_chatbot
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue