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:
cătălin 2025-03-05 11:34:44 +01:00
commit 152546982c
No known key found for this signature in database
46 changed files with 2328 additions and 700 deletions

View file

@ -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()