Files
discord_bot/tests/test_main.py
T

121 lines
5.0 KiB
Python

import os
import unittest
from unittest.mock import AsyncMock, MagicMock, Mock, PropertyMock, mock_open, patch
import toml
from discord import Message, TextChannel, User
from fjerkroa_bot import FjerkroaBot
from fjerkroa_bot.ai_responder import AIMessage, AIResponse
class TestBotBase(unittest.IsolatedAsyncioTestCase):
async def asyncSetUp(self):
self.mock_response = Mock()
self.mock_response.choices = [Mock(text="Nice day today!")]
self.config_data = {
"openai-token": os.environ.get("OPENAI_TOKEN", "test"),
"model": "gpt-3.5-turbo",
"max-tokens": 1024,
"temperature": 0.9,
"top-p": 1.0,
"presence-penalty": 1.0,
"frequency-penalty": 1.0,
"history-limit": 10,
"system": "You are an smart AI",
"additional-responders": [],
}
self.history_data = []
with (
patch.object(FjerkroaBot, "load_config", new=lambda s, c: self.config_data),
patch.object(FjerkroaBot, "user", new_callable=PropertyMock) as mock_user,
):
mock_user.return_value = MagicMock(spec=User)
mock_user.return_value.id = 12
self.bot = FjerkroaBot("config.toml")
self.bot.staff_channel = AsyncMock(spec=TextChannel)
self.bot.staff_channel.send = AsyncMock()
self.bot.welcome_channel = AsyncMock(spec=TextChannel)
self.bot.welcome_channel.send = AsyncMock()
self.bot.airesponder.config = self.config_data
def create_message(self, message: str) -> Message:
message = MagicMock(spec=Message)
message.content = "Hello, how are you?"
message.author = AsyncMock(spec=User)
message.author.name = "Lala"
message.author.id = 123
message.author.bot = False
message.channel = AsyncMock(spec=TextChannel)
message.channel.send = AsyncMock()
return message
class TestFunctionality(TestBotBase):
def test_load_config(self) -> None:
with patch("builtins.open", mock_open(read_data=toml.dumps(self.config_data))):
result = FjerkroaBot.load_config("config.toml")
self.assertEqual(result, self.config_data)
async def test_message_lings(self) -> None:
request = AIMessage(
"Lala",
"Hello there!",
"chat",
False,
)
message = {
"answer": "Test [Link](https://www.example.com/test)",
"answer_needed": True,
"channel": "chat",
"staff": None,
"picture": None,
"hack": False,
}
expected = AIResponse("Test https://www.example.com/test", True, "chat", None, None, False, False)
self.assertEqual(str(await self.bot.airesponder.post_process(request, message)), str(expected))
message = {
"answer": "Test @[Link](https://www.example.com/test)",
"answer_needed": True,
"channel": "chat",
"staff": None,
"picture": None,
"hack": False,
}
expected = AIResponse("Test Link", True, "chat", None, None, False, False)
self.assertEqual(str(await self.bot.airesponder.post_process(request, message)), str(expected))
message = {
"answer": "Test [Link](https://www.example.com/test) and [Link2](https://xxx) lala",
"answer_needed": True,
"channel": "chat",
"staff": None,
"picture": None,
"hack": False,
}
expected = AIResponse("Test https://www.example.com/test and https://xxx lala", True, "chat", None, None, False, False)
self.assertEqual(str(await self.bot.airesponder.post_process(request, message)), str(expected))
async def test_on_message_stort_path(self) -> None:
message = self.create_message("Hello there! How are you?")
message.author.name = "madeup_name"
message.channel.name = "some_channel" # type: ignore
self.bot.config["short-path"] = [[r"some.*", r"madeup.*"]]
await self.bot.on_message(message)
self.assertEqual(
self.bot.airesponder.history[-1]["content"],
'{"user": "madeup_name", "message": "Hello, how are you?",'
' "channel": "some_channel", "direct": false, "historise_question": true}',
)
def test_update_history_trims_to_limit(self):
self.bot.airesponder.update_history({"content": '{"q": "What\'s your name?"}'}, {"content": '{"a": "AI"}'}, 10)
self.assertEqual(len(self.bot.airesponder.history), 2)
self.bot.airesponder.update_history({"content": '{"q1": "Q1"}'}, {"content": '{"a1": "A1"}'}, 2)
self.bot.airesponder.update_history({"content": '{"q2": "Q2"}'}, {"content": '{"a2": "A2"}'}, 2)
self.assertEqual(len(self.bot.airesponder.history), 2)
# File persistence moved to the SQLite store — covered by PER-01 (SPEC-009)
if __name__ == "__mait__":
unittest.main()