diff --git a/kdb-bot/test/ui_tests/config/appsettings.json b/kdb-bot/test/ui_tests/config/appsettings.json index 58762bc5..c57061b5 100644 --- a/kdb-bot/test/ui_tests/config/appsettings.json +++ b/kdb-bot/test/ui_tests/config/appsettings.json @@ -11,6 +11,32 @@ "ConsoleLogLevel": "ERROR", "FileLogLevel": "WARN" }, + "BotLoggingSettings": { + "Api": { + "Path": "logs/$date_now/", + "Filename": "api.log", + "ConsoleLogLevel": "INFO", + "FileLogLevel": "DEBUG" + }, + "Command": { + "Path": "logs/$date_now/", + "Filename": "commands.log", + "ConsoleLogLevel": "INFO", + "FileLogLevel": "DEBUG" + }, + "Database": { + "Path": "logs/$date_now/", + "Filename": "database.log", + "ConsoleLogLevel": "INFO", + "FileLogLevel": "DEBUG" + }, + "Message": { + "Path": "logs/$date_now/", + "Filename": "message.log", + "ConsoleLogLevel": "INFO", + "FileLogLevel": "DEBUG" + } + }, "Translation": { "DefaultLanguage": "de", "Languages": [ diff --git a/kdb-bot/test/ui_tests/startup.py b/kdb-bot/test/ui_tests/startup.py index 4abb1cb1..04cce01a 100644 --- a/kdb-bot/test/ui_tests/startup.py +++ b/kdb-bot/test/ui_tests/startup.py @@ -4,13 +4,46 @@ from typing import Optional from cpl_core.application import StartupABC from cpl_core.configuration import ConfigurationABC from cpl_core.database import DatabaseSettings -from cpl_core.database.context import DatabaseContext -from cpl_core.dependency_injection import ServiceProviderABC, ServiceCollectionABC +from cpl_core.dependency_injection import ServiceCollectionABC +from cpl_core.dependency_injection import ServiceProviderABC from cpl_core.environment import ApplicationEnvironment from cpl_discord import get_discord_collection from cpl_discord.discord_event_types_enum import DiscordEventTypesEnum from dotenv import load_dotenv +from bot.startup_settings_extension import StartupSettingsExtension +from bot_core.abc.client_utils_service_abc import ClientUtilsServiceABC +from bot_core.abc.custom_file_logger_abc import CustomFileLoggerABC +from bot_core.abc.message_service_abc import MessageServiceABC +from bot_core.configuration.bot_logging_settings import BotLoggingSettings +from bot_core.logging.command_logger import CommandLogger +from bot_core.logging.database_logger import DatabaseLogger +from bot_core.logging.message_logger import MessageLogger +from bot_core.pipes.date_time_offset_pipe import DateTimeOffsetPipe +from bot_core.service.client_utils_service import ClientUtilsService +from bot_core.service.message_service import MessageService +from bot_data.abc.auth_user_repository_abc import AuthUserRepositoryABC +from bot_data.abc.auto_role_repository_abc import AutoRoleRepositoryABC +from bot_data.abc.client_repository_abc import ClientRepositoryABC +from bot_data.abc.known_user_repository_abc import KnownUserRepositoryABC +from bot_data.abc.level_repository_abc import LevelRepositoryABC +from bot_data.abc.server_repository_abc import ServerRepositoryABC +from bot_data.abc.statistic_repository_abc import StatisticRepositoryABC +from bot_data.abc.user_joined_server_repository_abc import UserJoinedServerRepositoryABC +from bot_data.abc.user_joined_voice_channel_abc import UserJoinedVoiceChannelRepositoryABC +from bot_data.abc.user_repository_abc import UserRepositoryABC +from bot_data.db_context import DBContext +from bot_data.service.auth_user_repository_service import AuthUserRepositoryService +from bot_data.service.auto_role_repository_service import AutoRoleRepositoryService +from bot_data.service.client_repository_service import ClientRepositoryService +from bot_data.service.known_user_repository_service import KnownUserRepositoryService +from bot_data.service.level_repository_service import LevelRepositoryService +from bot_data.service.seeder_service import SeederService +from bot_data.service.server_repository_service import ServerRepositoryService +from bot_data.service.statistic_repository_service import StatisticRepositoryService +from bot_data.service.user_joined_server_repository_service import UserJoinedServerRepositoryService +from bot_data.service.user_joined_voice_channel_service import UserJoinedVoiceChannelRepositoryService +from bot_data.service.user_repository_service import UserRepositoryService from ui_tests.test_on_ready_event import TestOnReadyEvent @@ -30,11 +63,17 @@ class Startup(StartupABC): configuration.add_json_file(f'{cwd}/config/appsettings.json', optional=False) configuration.add_json_file(f'{cwd}/config/appsettings.{environment.host_name}.json', optional=True) + StartupSettingsExtension._configure_settings_with_sub_settings(configuration, BotLoggingSettings, lambda x: x.files, lambda x: x.key) + self._config = configuration return configuration def configure_services(self, services: ServiceCollectionABC, environment: ApplicationEnvironment) -> ServiceProviderABC: services.add_logging() + services.add_singleton(CustomFileLoggerABC, CommandLogger) + services.add_singleton(CustomFileLoggerABC, DatabaseLogger) + services.add_singleton(CustomFileLoggerABC, MessageLogger) + services.add_translation() db_settings: DatabaseSettings = self._config.get_configuration(DatabaseSettings) db_settings_with_pw = DatabaseSettings() @@ -49,10 +88,31 @@ class Startup(StartupABC): "Buffered": db_settings.buffered, "AuthPlugin": db_settings.auth_plugin }) - services.add_db_context(DatabaseContext, db_settings_with_pw) + services.add_db_context(DBContext, db_settings_with_pw) services.add_discord() dc = get_discord_collection(services) dc.add_event(DiscordEventTypesEnum.on_ready.value, TestOnReadyEvent) + # bot_core stuff + services.add_transient(MessageServiceABC, MessageService) + services.add_transient(ClientUtilsServiceABC, ClientUtilsService) + + # pipes + services.add_transient(DateTimeOffsetPipe) + + # data stuff + services.add_transient(AuthUserRepositoryABC, AuthUserRepositoryService) + services.add_transient(ServerRepositoryABC, ServerRepositoryService) + services.add_transient(UserRepositoryABC, UserRepositoryService) + services.add_transient(ClientRepositoryABC, ClientRepositoryService) + services.add_transient(KnownUserRepositoryABC, KnownUserRepositoryService) + services.add_transient(UserJoinedServerRepositoryABC, UserJoinedServerRepositoryService) + services.add_transient(UserJoinedVoiceChannelRepositoryABC, UserJoinedVoiceChannelRepositoryService) + services.add_transient(AutoRoleRepositoryABC, AutoRoleRepositoryService) + services.add_transient(LevelRepositoryABC, LevelRepositoryService) + services.add_transient(StatisticRepositoryABC, StatisticRepositoryService) + + services.add_transient(SeederService) + return services.build_service_provider() diff --git a/kdb-bot/test/ui_tests_shared/command_selectors_enum.py b/kdb-bot/test/ui_tests_shared/command_selectors_enum.py index a9eceaf7..7f8f7fd3 100644 --- a/kdb-bot/test/ui_tests_shared/command_selectors_enum.py +++ b/kdb-bot/test/ui_tests_shared/command_selectors_enum.py @@ -6,8 +6,10 @@ class CommandSelectorsEnum(Enum): cmd_chat_input = '/html/body/div[1]/div[2]/div/div[1]/div/div[2]/div/div[1]/div/div/div[3]/div/main/form/div/div[2]/div/div[2]/div/div' msg_input = '/html/body/div[1]/div[2]/div/div[1]/div/div[2]/div/div[1]/div/div/div[3]/div[2]/main/form/div/div[1]/div/div[3]/div/div/div' - ping = '/html/body/div[1]/div[2]/div/div[1]/div/div[2]/div/div[1]/div/div/div[3]/div[2]/main/form/div/div[2]/div/div/div[5]/div' - info = '/html/body/div[1]/div[2]/div/div[1]/div/div[2]/div/div[1]/div/div/div[3]/div[2]/main/form/div/div[2]/div/div/div[5]/div' - help = '/html/body/div[1]/div[2]/div/div[1]/div/div[2]/div/div[1]/div/div/div[3]/div[2]/main/form/div/div[2]/div/div/div[5]/div' - afk = '/html/body/div[1]/div[2]/div/div[1]/div/div[2]/div/div[1]/div/div/div[3]/div[2]/main/form/div/div[2]/div/div/div[2]/div' - purge = '/html/body/div[1]/div[2]/div/div[1]/div/div[2]/div/div[1]/div/div/div[3]/div[2]/main/form/div/div[2]/div/div/div[3]/div' + kdb_test = "//*[contains (text(), 'Krümmelmonster-test')]" + + ping = kdb_test + info = kdb_test + help = kdb_test + afk = kdb_test + purge = kdb_test diff --git a/kdb-bot/test/ui_tests_shared/command_test_case_with_app.py b/kdb-bot/test/ui_tests_shared/command_test_case_with_app.py index 93fe4853..a1ca5d08 100644 --- a/kdb-bot/test/ui_tests_shared/command_test_case_with_app.py +++ b/kdb-bot/test/ui_tests_shared/command_test_case_with_app.py @@ -40,10 +40,11 @@ class CommandTestCaseWithApp(TestCaseWithApp): UI.driver.find_element(By.XPATH, CommandSelectorsEnum.msg_input.value).send_keys(Keys.ENTER) @classmethod - def send_command(cls, cmd: str, selector: CommandSelectorsEnum): - if UI.driver.current_url != cls._test_settings.cmd_url: + def send_command(cls, cmd: str, selector: CommandSelectorsEnum, reload=True): + if reload or UI.driver.current_url != cls._test_settings.cmd_url: UI.driver.get(cls._test_settings.cmd_url) - time.sleep(2) + + time.sleep(2) cmd_element_ident = (By.XPATH, CommandSelectorsEnum.cmd_chat.value) cmd_element = UI.driver.find_element(*cmd_element_ident) diff --git a/kdb-bot/test/ui_tests_shared/decorators.py b/kdb-bot/test/ui_tests_shared/decorators.py index 070305f1..9d7c7a2b 100644 --- a/kdb-bot/test/ui_tests_shared/decorators.py +++ b/kdb-bot/test/ui_tests_shared/decorators.py @@ -7,9 +7,12 @@ class Async: @classmethod def async_func(cls, coro): def wrapper(*args, **kwargs): - if cls._loop is None: - cls._loop = asyncio.get_event_loop() + try: + if cls._loop is None: + cls._loop = asyncio.get_event_loop() - return cls._loop.run_until_complete(coro(*args, **kwargs)) + return cls._loop.run_until_complete(coro(*args, **kwargs)) + except Exception as e: + return return wrapper diff --git a/kdb-bot/test/ui_tests_shared/test_case_with_app.py b/kdb-bot/test/ui_tests_shared/test_case_with_app.py index b2fdc67a..86b0b6b5 100644 --- a/kdb-bot/test/ui_tests_shared/test_case_with_app.py +++ b/kdb-bot/test/ui_tests_shared/test_case_with_app.py @@ -16,6 +16,7 @@ class TestCaseWithApp(unittest.TestCase): _config: Optional[ConfigurationABC] = None _services: Optional[ServiceProviderABC] = None _test_settings: Optional[TestSettings] = None + _loop = None @classmethod def setUpClass(cls): @@ -24,7 +25,11 @@ class TestCaseWithApp(unittest.TestCase): import nest_asyncio nest_asyncio.apply() - asyncio.run(app.run_async()) + if cls._loop is None: + cls._loop = asyncio.get_event_loop() + + cls._loop.run_until_complete(app.run_async()) + # asyncio.run(app.run_async()) cls._config = Declarations.app.config cls._services = Declarations.app.services diff --git a/kdb-bot/test/ui_tests_tests/commands/common/afk_command_test_case.py b/kdb-bot/test/ui_tests_tests/commands/common/afk_command_test_case.py index 86bab1c9..0658f1a9 100644 --- a/kdb-bot/test/ui_tests_tests/commands/common/afk_command_test_case.py +++ b/kdb-bot/test/ui_tests_tests/commands/common/afk_command_test_case.py @@ -9,14 +9,22 @@ from ui_tests_shared.ui import UI class AFKCommandTestCase(CommandTestCaseWithApp): + @classmethod + def tearDownClass(cls): + btn = UI.driver.find_elements(By.XPATH, '/html/body/div[1]/div[2]/div/div[1]/div/div[2]/div/div[1]/div/div/div[1]/section/div[1]/div/div[1]/div[2]/button') + if len(btn) == 0: + return + + btn[0].click() + @Async.async_func async def test_error_message(self): correct_response = self._t.transform('modules.base.afk_command_channel_missing_message') self.assertIsNotNone(correct_response) - self.send_command('afk', CommandSelectorsEnum.afk) + self.send_command('afk', CommandSelectorsEnum.afk, reload=False) def check(m: discord.Message): - return m.content == correct_response and m.author.id == self._test_settings.bot_id + return m.author.id == self._test_settings.bot_id response = await self._bot.wait_for('message', check=check, timeout=10) self.assertEqual(response.content, correct_response) @@ -30,12 +38,11 @@ class AFKCommandTestCase(CommandTestCaseWithApp): return member.id == self._test_settings.test_user_id and after is not None and after.channel.id == 911578760476762153 res = await self._bot.wait_for('voice_state_update', check=check1, timeout=10) - self.send_command('afk', CommandSelectorsEnum.afk) + self.send_command('afk', CommandSelectorsEnum.afk, reload=False) def check2(member: discord.Member, before: discord.VoiceState, after: discord.VoiceState): return member.id == self._test_settings.test_user_id and after is not None and after.channel.id == 910199452915093594 member, before, after = await self._bot.wait_for('voice_state_update', check=check2, timeout=10) - UI.driver.find_element(By.XPATH, '/html/body/div[1]/div[2]/div/div[1]/div/div[2]/div/div[1]/div/div/div[1]/section/div[1]/div/div[1]/div[2]/button').click() self.assertIsNotNone(after.channel) self.assertEqual(after.channel.id, 910199452915093594) # self.assertEqual(response.content, correct_response) diff --git a/kdb-bot/test/ui_tests_tests/commands/common/help_command_test_case.py b/kdb-bot/test/ui_tests_tests/commands/common/help_command_test_case.py index 78bf5580..079ac99c 100644 --- a/kdb-bot/test/ui_tests_tests/commands/common/help_command_test_case.py +++ b/kdb-bot/test/ui_tests_tests/commands/common/help_command_test_case.py @@ -13,8 +13,8 @@ class HelpCommandTestCase(CommandTestCaseWithApp): self.send_command('help', CommandSelectorsEnum.help) def check(m: discord.Message): - return m.content == correct_response and m.author.id == self._test_settings.bot_id + return m.author.id == self._test_settings.bot_id - response = await self._bot.wait_for('message', check=check) + response = await self._bot.wait_for('message', check=check, timeout=10) self.assertEqual(response.content, correct_response) await self._bot.close() diff --git a/kdb-bot/test/ui_tests_tests/commands/common/info_command_test_case.py b/kdb-bot/test/ui_tests_tests/commands/common/info_command_test_case.py index 36c1e56e..e98e4284 100644 --- a/kdb-bot/test/ui_tests_tests/commands/common/info_command_test_case.py +++ b/kdb-bot/test/ui_tests_tests/commands/common/info_command_test_case.py @@ -1,4 +1,6 @@ from datetime import datetime +from unittest import skip + import discord import bot @@ -12,7 +14,7 @@ class InfoCommandTestCase(CommandTestCaseWithApp): def get_embed(self) -> discord.Embed: client_utils: ClientUtilsServiceABC = self._services.get_service(ClientUtilsServiceABC) - client = client_utils.get_client(self._bot.user.id, self._test_settings.guild_id) + client = client_utils.get_client(self._test_settings.bot_id, self._test_settings.guild_id) embed = discord.Embed( title=self._t.transform('modules.base.info.title'), description=self._t.transform('modules.base.info.description'), @@ -20,7 +22,8 @@ class InfoCommandTestCase(CommandTestCaseWithApp): ) embed.add_field(name=self._t.transform('modules.base.info.fields.version'), value=bot.__version__) - start_time = self._config.get_configuration('Bot_StartTime') + # start_time = self._config.get_configuration('Bot_StartTime') + start_time = str(datetime.now()) ontime = round((datetime.now() - datetime.strptime(start_time, '%Y-%m-%d %H:%M:%S.%f')).total_seconds() / 3600, 2) embed.add_field(name=self._t.transform('modules.base.info.fields.ontime'), value=f'{ontime}h') embed.add_field(name=self._t.transform('modules.base.info.fields.sent_message_count'), value=client.sent_message_count, inline=False) @@ -34,6 +37,7 @@ class InfoCommandTestCase(CommandTestCaseWithApp): embed.add_field(name=self._t.transform('modules.base.info.fields.modules'), value='\n'.join(modules), inline=False) return embed + @skip('stage db not ready yet') @Async.async_func async def test_info(self): correct_response = self.get_embed() @@ -42,7 +46,7 @@ class InfoCommandTestCase(CommandTestCaseWithApp): def check(m: discord.Message): return m.embeds[0] == correct_response and m.author.id == self._test_settings.bot_id - response: discord.Message = await self._bot.wait_for('message', check=check) + response: discord.Message = await self._bot.wait_for('message', check=check, timeout=10) self.assertEqual(len(response.embeds), 1) self.assertEqual(response.embeds[0], correct_response) diff --git a/kdb-bot/test/ui_tests_tests/commands/common/ping_command_test_case.py b/kdb-bot/test/ui_tests_tests/commands/common/ping_command_test_case.py index e0553742..803d56bf 100644 --- a/kdb-bot/test/ui_tests_tests/commands/common/ping_command_test_case.py +++ b/kdb-bot/test/ui_tests_tests/commands/common/ping_command_test_case.py @@ -14,7 +14,7 @@ class PingCommandTestCase(CommandTestCaseWithApp): self.send_command('ping', CommandSelectorsEnum.ping) def check(m: discord.Message): - return m.content == correct_response and m.author.id == self._test_settings.bot_id + return m.author.id == self._test_settings.bot_id - response = await self._bot.wait_for('message', check=check) + response = await self._bot.wait_for('message', check=check, timeout=10) self.assertEqual(response.content, correct_response) diff --git a/kdb-bot/test/ui_tests_tests/commands/common/purge_command_test_case.py b/kdb-bot/test/ui_tests_tests/commands/common/purge_command_test_case.py index efdb5bd1..79c5e0ed 100644 --- a/kdb-bot/test/ui_tests_tests/commands/common/purge_command_test_case.py +++ b/kdb-bot/test/ui_tests_tests/commands/common/purge_command_test_case.py @@ -22,9 +22,9 @@ class PurgeCommandTestCase(CommandTestCaseWithApp): self.send_command('purge', CommandSelectorsEnum.purge) def check(m: discord.Message): - return m.content == correct_response and m.author.id == self._test_settings.bot_id + return m.author.id == self._test_settings.bot_id - response = await self._bot.wait_for('message', check=check) + response = await self._bot.wait_for('message', check=check, timeout=10) self.assertEqual(response.content, correct_response) time.sleep(20) channel = self._bot.get_channel(911578680998895687)