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

243
tests/test_actions.py Normal file
View 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
View 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"

View file

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

View file

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