aboutsummaryrefslogtreecommitdiffstats
path: root/tests/cogs
diff options
context:
space:
mode:
Diffstat (limited to 'tests/cogs')
-rw-r--r--tests/cogs/test_ai.py83
-rw-r--r--tests/cogs/test_assistant.py66
-rw-r--r--tests/cogs/test_compression_conversion.py139
-rw-r--r--tests/cogs/test_cron.py147
-rw-r--r--tests/cogs/test_cron_integration.py39
-rw-r--r--tests/cogs/test_downloader.py93
-rw-r--r--tests/cogs/test_downloader_integration.py37
-rw-r--r--tests/cogs/test_math_commands.py55
-rw-r--r--tests/cogs/test_music_audio.py93
-rw-r--r--tests/cogs/test_music_external_play.py109
-rw-r--r--tests/cogs/test_music_integration.py46
-rw-r--r--tests/cogs/test_music_join.py56
-rw-r--r--tests/cogs/test_music_play.py104
-rw-r--r--tests/cogs/test_qr.py75
-rw-r--r--tests/cogs/test_say.py38
-rw-r--r--tests/cogs/test_search.py83
-rw-r--r--tests/cogs/test_trigger.py106
-rw-r--r--tests/cogs/test_trigger_integration.py54
-rw-r--r--tests/cogs/test_tts.py58
-rw-r--r--tests/cogs/test_uploader.py226
-rw-r--r--tests/cogs/test_vclogs.py88
-rw-r--r--tests/cogs/test_vclogs_integration.py86
-rw-r--r--tests/cogs/test_voice.py79
-rw-r--r--tests/cogs/test_web.py57
24 files changed, 0 insertions, 2017 deletions
diff --git a/tests/cogs/test_ai.py b/tests/cogs/test_ai.py
deleted file mode 100644
index 6d92f55..0000000
--- a/tests/cogs/test_ai.py
+++ /dev/null
@@ -1,83 +0,0 @@
1import pytest
2from unittest.mock import AsyncMock, patch, MagicMock
3import discord
4import httpx
5from conftest import MockApplicationContext
6
7
8@pytest.fixture
9def ai_cog(bot):
10 from cogs.ai import AI
11 cog = AI(bot)
12 return cog
13
14
15@pytest.fixture
16def mock_ai_response():
17 return {
18 "choices": [
19 {
20 "message": {
21 "content": "Test response from AI"
22 }
23 }
24 ]
25 }
26
27
28@pytest.mark.asyncio
29async def test_senator_command_success(ai_cog, mock_channel, mock_guild, bot, mock_ai_response):
30 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
31
32 mock_response = MagicMock()
33 mock_response.json = MagicMock(return_value=mock_ai_response)
34
35 mock_client = MagicMock()
36 mock_client.post = AsyncMock(return_value=mock_response)
37 mock_client.__aenter__ = AsyncMock(return_value=mock_response)
38 mock_client.__aexit__ = AsyncMock(return_value=None)
39
40 with patch('cogs.ai.httpx.AsyncClient') as mock_httpx:
41 instance = mock_httpx.return_value.__aenter__.return_value
42 instance.post = AsyncMock(return_value=mock_response)
43 with patch.object(ctx, 'send_followup', new_callable=AsyncMock) as mock_followup:
44 await ai_cog.senator.callback(ai_cog, ctx, text="Hello", tts=False)
45 mock_followup.assert_called_once_with("Test response from AI")
46
47
48@pytest.mark.asyncio
49async def test_senator_command_empty_choices(ai_cog, mock_channel, mock_guild, bot):
50 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
51
52 mock_response = MagicMock()
53 mock_response.json = MagicMock(return_value={"choices": []})
54
55 mock_client = MagicMock()
56 mock_client.post = AsyncMock(return_value=mock_response)
57 mock_client.__aenter__ = AsyncMock(return_value=mock_response)
58 mock_client.__aexit__ = AsyncMock(return_value=None)
59
60 with patch('cogs.ai.httpx.AsyncClient') as mock_httpx:
61 instance = mock_httpx.return_value.__aenter__.return_value
62 instance.post = AsyncMock(return_value=mock_response)
63 with patch.object(ctx, 'send_followup', new_callable=AsyncMock) as mock_followup:
64 await ai_cog.senator.callback(ai_cog, ctx, text="Hello", tts=False)
65 mock_followup.assert_called_once_with("bot siem zesroł")
66
67
68@pytest.mark.asyncio
69async def test_senator_command_no_choices_key(ai_cog, mock_channel, mock_guild, bot):
70 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
71
72 mock_response = MagicMock()
73 mock_response.json = MagicMock(return_value={})
74
75 with patch('cogs.ai.httpx.AsyncClient') as mock_httpx:
76 instance = mock_httpx.return_value.__aenter__.return_value
77 instance.post = AsyncMock(return_value=mock_response)
78 with patch('cogs.ai.logger') as mock_logger:
79 try:
80 await ai_cog.senator.callback(ai_cog, ctx, text="Hello", tts=False)
81 except KeyError:
82 pass
83 assert mock_logger.info.called
diff --git a/tests/cogs/test_assistant.py b/tests/cogs/test_assistant.py
deleted file mode 100644
index 056a868..0000000
--- a/tests/cogs/test_assistant.py
+++ /dev/null
@@ -1,66 +0,0 @@
1import pytest
2from unittest.mock import AsyncMock, patch, MagicMock
3from conftest import MockApplicationContext
4
5
6@pytest.fixture
7def assistant_cog():
8 with patch('os.getenv', return_value="test_keyword"):
9 from cogs.assistant import Jarvis
10
11 mock_bot = MagicMock()
12 mock_bot.user = MagicMock()
13 mock_bot.user.id = 111
14
15 cog = Jarvis(mock_bot)
16 return cog
17
18
19def test_assistant_keyword_default(assistant_cog):
20 assert assistant_cog.keyword == "test_keyword"
21
22
23@pytest.mark.asyncio
24async def test_assistant_on_message_ignored_bot_message(assistant_cog):
25 mock_author = MagicMock()
26 mock_author.id = 456
27 mock_author.bot = True
28
29 mock_message = MagicMock()
30 mock_message.author = mock_author
31
32 with patch.object(assistant_cog, 'assistant', new_callable=AsyncMock) as mock_assistant:
33 await assistant_cog.on_message(mock_message)
34 mock_assistant.assert_not_called()
35
36
37@pytest.mark.asyncio
38async def test_assistant_on_message_mentions_bot(assistant_cog):
39 mock_message = MagicMock()
40 mock_message.author = MagicMock()
41 mock_message.author.id = 123
42
43 mock_mention = MagicMock()
44 mock_mention.id = 111
45 mock_message.mentions = [mock_mention]
46 mock_message.content = "test"
47
48 with patch.object(assistant_cog, 'assistant', new_callable=AsyncMock) as mock_assistant:
49 await assistant_cog.on_message(mock_message)
50 mock_assistant.assert_called_once_with(mock_message)
51
52
53@pytest.mark.asyncio
54async def test_assistant_on_message_keyword_match(assistant_cog):
55 assistant_cog.keyword = "test"
56
57 mock_message = MagicMock()
58 mock_message.author = MagicMock()
59 mock_message.author.id = 123
60
61 mock_message.mentions = []
62 mock_message.content = "test message with test keyword"
63
64 with patch.object(assistant_cog, 'assistant', new_callable=AsyncMock) as mock_assistant:
65 await assistant_cog.on_message(mock_message)
66 mock_assistant.assert_called_once_with(mock_message)
diff --git a/tests/cogs/test_compression_conversion.py b/tests/cogs/test_compression_conversion.py
deleted file mode 100644
index 892482b..0000000
--- a/tests/cogs/test_compression_conversion.py
+++ /dev/null
@@ -1,139 +0,0 @@
1import pytest
2from unittest.mock import AsyncMock, patch, MagicMock
3import os
4import discord
5from conftest import MockApplicationContext
6
7
8def test_compression_filetype_video():
9 from cogs.compression import filetype
10 assert filetype("test.mp4") == "Video"
11 assert filetype("test.avi") == "Video"
12
13
14def test_compression_filetype_audio():
15 from cogs.compression import filetype
16 assert filetype("test.mp3") == "Audio"
17 assert filetype("test.wav") == "Audio"
18
19
20def test_compression_filetype_image():
21 from cogs.compression import filetype
22 assert filetype("test.jpg") == "Image"
23 assert filetype("test.png") == "Image"
24
25
26def test_conversion_filetype():
27 from cogs.conversion import filetype
28 assert filetype("test.mp4") == "Video"
29 assert filetype("test.mp3") == "Audio"
30 assert filetype("test.jpg") == "Image"
31 assert filetype("test.xyz") == "Unknown"
32
33
34@pytest.mark.asyncio
35async def test_build_conversion_command_video():
36 with patch('os.getenv', return_value="https://example.com"):
37 with patch('cogs.utils.temp.get_temp_dir', return_value="/tmp"):
38 with patch('cogs.utils.settings.get_baseurl', return_value="https://example.com"):
39 import importlib
40 import cogs.conversion
41 importlib.reload(cogs.conversion)
42 from cogs.conversion import Conversion
43
44 cog = Conversion.__new__(Conversion)
45 cog._baseurl = "https://example.com"
46 cog._uploadurl = "https://example.com"
47
48 cmd = cog._build_conversion_command("Video", "/tmp/test.mp4", "/tmp/output.mp4", "")
49 assert cmd is not None
50 assert "ffmpeg" in cmd
51
52
53@pytest.mark.asyncio
54async def test_build_conversion_command_image():
55 with patch('os.getenv', return_value="https://example.com"):
56 with patch('cogs.utils.temp.get_temp_dir', return_value="/tmp"):
57 with patch('cogs.utils.settings.get_baseurl', return_value="https://example.com"):
58 import importlib
59 import cogs.conversion
60 importlib.reload(cogs.conversion)
61 from cogs.conversion import Conversion
62
63 cog = Conversion.__new__(Conversion)
64 cog._baseurl = "https://example.com"
65 cog._uploadurl = "https://example.com"
66
67 cmd = cog._build_conversion_command("Image", "/tmp/test.jpg", "/tmp/output.png", "")
68 assert cmd is not None
69 assert "magick" in cmd
70
71
72@pytest.mark.asyncio
73async def test_build_conversion_command_unknown():
74 with patch('os.getenv', return_value="https://example.com"):
75 with patch('cogs.utils.temp.get_temp_dir', return_value="/tmp"):
76 with patch('cogs.utils.settings.get_baseurl', return_value="https://example.com"):
77 import importlib
78 import cogs.conversion
79 importlib.reload(cogs.conversion)
80 from cogs.conversion import Conversion
81
82 cog = Conversion.__new__(Conversion)
83 cog._baseurl = "https://example.com"
84 cog._uploadurl = "https://example.com"
85
86 cmd = cog._build_conversion_command("Unknown", "/tmp/test.xyz", "/tmp/output.abc", "")
87 assert cmd is None
88
89
90@pytest.mark.asyncio
91async def test_compression_get_command_video():
92 with patch('os.getenv', return_value="https://example.com"):
93 with patch('cogs.utils.temp.get_temp_dir', return_value="/tmp"):
94 with patch('cogs.utils.settings.get_baseurl', return_value="https://example.com"):
95 import importlib
96 import cogs.compression
97 importlib.reload(cogs.compression)
98 from cogs.compression import Compression
99
100 cog = Compression.__new__(Compression)
101 cog.temp_dir = "/tmp"
102
103 cmd = cog._get_compression_command("Video", "/tmp/test.mp4", "/tmp/output.mp4")
104 assert cmd is not None
105 assert "ffmpeg" in cmd
106
107
108@pytest.mark.asyncio
109async def test_compression_get_command_image():
110 with patch('os.getenv', return_value="https://example.com"):
111 with patch('cogs.utils.temp.get_temp_dir', return_value="/tmp"):
112 with patch('cogs.utils.settings.get_baseurl', return_value="https://example.com"):
113 import importlib
114 import cogs.compression
115 importlib.reload(cogs.compression)
116 from cogs.compression import Compression
117
118 cog = Compression.__new__(Compression)
119 cog.temp_dir = "/tmp"
120
121 cmd = cog._get_compression_command("Image", "/tmp/test.jpg", "/tmp/output.jpg")
122 assert cmd is not None
123
124
125@pytest.mark.asyncio
126async def test_compression_get_command_unknown():
127 with patch('os.getenv', return_value="https://example.com"):
128 with patch('cogs.utils.temp.get_temp_dir', return_value="/tmp"):
129 with patch('cogs.utils.settings.get_baseurl', return_value="https://example.com"):
130 import importlib
131 import cogs.compression
132 importlib.reload(cogs.compression)
133 from cogs.compression import Compression
134
135 cog = Compression.__new__(Compression)
136 cog.temp_dir = "/tmp"
137
138 cmd = cog._get_compression_command("Unknown", "/tmp/test.xyz", "/tmp/output.xyz")
139 assert cmd is None
diff --git a/tests/cogs/test_cron.py b/tests/cogs/test_cron.py
deleted file mode 100644
index 28ccfe1..0000000
--- a/tests/cogs/test_cron.py
+++ /dev/null
@@ -1,147 +0,0 @@
1import pytest
2from datetime import datetime
3from unittest.mock import MagicMock, patch
4
5from cogs.cron import Cron
6from cogs.utils.database import _ConnectionContextManager
7
8
9@pytest.fixture
10def mock_bot():
11 bot = MagicMock()
12 bot.loop = MagicMock()
13 bot.is_closed = MagicMock(return_value=False)
14 bot.wait_until_ready = MagicMock()
15 bot.loop.create_task = MagicMock(return_value=MagicMock())
16 return bot
17
18
19def create_cog(mock_bot):
20 with patch.object(Cron, "__init__", lambda self, bot: None):
21 with patch("cogs.cron.init_database"):
22 cog = Cron.__new__(Cron)
23 cog.bot = mock_bot
24 cog.scheduled_tasks = []
25 cog.task = MagicMock()
26 return cog
27
28
29class TestLoadTasks:
30 def test_load_tasks_with_data(self, mock_bot):
31 mock_conn = MagicMock()
32 mock_cursor = MagicMock()
33 mock_cursor.fetchall.return_value = [
34 (1, "* * * * *", "audio", 123, 1, None, "test message")
35 ]
36 mock_conn.cursor.return_value = mock_cursor
37
38 # Create a context manager mock
39 mock_ctx = MagicMock()
40 mock_ctx.__enter__ = MagicMock(return_value=mock_conn)
41 mock_ctx.__exit__ = MagicMock(return_value=False)
42
43 with patch("cogs.cron.get_connection", return_value=mock_ctx):
44 cog = Cron.__new__(Cron)
45 cog.bot = mock_bot
46 cog.scheduled_tasks = []
47 cog.task = MagicMock()
48 cog.load_tasks()
49 assert len(cog.scheduled_tasks) == 1
50 assert cog.scheduled_tasks[0]["id"] == 1
51
52class TestSaveTasks:
53 def test_save_tasks(self, mock_bot):
54 cog = create_cog(mock_bot)
55 cog.scheduled_tasks = [{"id": 1, "cron_expression": "* * * * *", "type": "audio", "channel_id": 123, "active": True}]
56
57 mock_conn = MagicMock()
58 mock_cursor = MagicMock()
59 mock_conn.cursor.return_value = mock_cursor
60
61 # Create a context manager mock
62 mock_ctx = MagicMock()
63 mock_ctx.__enter__ = MagicMock(return_value=mock_conn)
64 mock_ctx.__exit__ = MagicMock(return_value=False)
65
66 with patch("cogs.cron.get_connection", return_value=mock_ctx):
67 cog.save_tasks()
68 assert len(cog.scheduled_tasks) == 1
69
70class TestShouldRunTask:
71 def test_should_run_task_invalid_cron(self, mock_bot):
72 cog = create_cog(mock_bot)
73 task = {"cron_expression": "invalid"}
74 now = datetime.now()
75 result = cog.should_run_task(task, now)
76 assert result is False
77
78 def test_should_run_task_missing_cron_expression(self, mock_bot):
79 cog = create_cog(mock_bot)
80 task = {}
81 now = datetime.now()
82 result = cog.should_run_task(task, now)
83 assert result is False
84
85class TestCogUnload:
86 def test_cog_unload_cancels_task(self, mock_bot):
87 with patch.object(Cron, "__init__", lambda self, bot: None):
88 cog = Cron.__new__(Cron)
89 cog.bot = mock_bot
90 cog.task = MagicMock()
91
92 cog.cog_unload()
93 cog.task.cancel.assert_called_once()
94
95class TestTaskManagement:
96 def test_add_task_increments_id(self, mock_bot):
97 cog = create_cog(mock_bot)
98 cog.scheduled_tasks = [
99 {"id": 1, "cron_expression": "* * * * *"},
100 {"id": 2, "cron_expression": "0 * * * *"},
101 ]
102
103 new_id = max([t["id"] for t in cog.scheduled_tasks], default=0) + 1
104 assert new_id == 3
105
106 def test_find_task_by_id(self, mock_bot):
107 cog = create_cog(mock_bot)
108 cog.scheduled_tasks = [
109 {"id": 1, "cron_expression": "* * * * *"},
110 {"id": 2, "cron_expression": "0 * * * *"},
111 ]
112
113 found_task = next((t for t in cog.scheduled_tasks if t["id"] == 2), None)
114 assert found_task is not None
115 assert found_task["cron_expression"] == "0 * * * *"
116
117 def test_remove_task_by_index(self, mock_bot):
118 cog = create_cog(mock_bot)
119 cog.scheduled_tasks = [
120 {"id": 1, "cron_expression": "* * * * *"},
121 {"id": 2, "cron_expression": "0 * * * *"},
122 ]
123
124 cog.scheduled_tasks.pop(0)
125 assert len(cog.scheduled_tasks) == 1
126 assert cog.scheduled_tasks[0]["id"] == 2
127
128 def test_toggle_task_active(self, mock_bot):
129 cog = create_cog(mock_bot)
130 cog.scheduled_tasks = [{"id": 1, "active": True}]
131
132 cog.scheduled_tasks[0]["active"] = False
133 assert cog.scheduled_tasks[0]["active"] is False
134
135 cog.scheduled_tasks[0]["active"] = True
136 assert cog.scheduled_tasks[0]["active"] is True
137
138class TestTaskTypes:
139 def test_task_type_audio_aliases(self, mock_bot):
140 audio_types = ("zagraj_audio", "audio")
141 for task_type in audio_types:
142 assert task_type in ("zagraj_audio", "audio")
143
144 def test_task_type_message_aliases(self, mock_bot):
145 message_types = ("wyślij_wiadomość", "send_message")
146 for task_type in message_types:
147 assert task_type in ("wyślij_wiadomość", "send_message")
diff --git a/tests/cogs/test_cron_integration.py b/tests/cogs/test_cron_integration.py
deleted file mode 100644
index f56fc46..0000000
--- a/tests/cogs/test_cron_integration.py
+++ /dev/null
@@ -1,39 +0,0 @@
1import pytest
2import time
3from unittest.mock import MagicMock, AsyncMock, patch
4
5
6@pytest.fixture
7def cron_cog(bot):
8 # Patch create_task to prevent background task creation
9 with patch.object(bot.loop, 'create_task', return_value=MagicMock()):
10 from cogs.cron import Cron
11 cog = Cron(bot)
12 yield cog
13
14
15@pytest.mark.slow
16@pytest.mark.asyncio
17async def test_cron_job_execution(cron_cog):
18 """Test cron job executes when due."""
19 cog = cron_cog
20
21 job = {
22 "id": "test_job",
23 "cron_expression": "* * * * *",
24 "type": "message",
25 "channel_id": 456,
26 "active": True,
27 "message": "Test",
28 }
29 cog.scheduled_tasks.append(job)
30
31 # Mock the execute_task method
32 with patch.object(cog, 'execute_task', new_callable=AsyncMock) as mock_exec:
33 # Mock should_run_task to return True
34 with patch.object(cog, 'should_run_task', return_value=True):
35 # Test single iteration of schedule_checker logic
36 for task in cog.scheduled_tasks:
37 if task.get("active", True) and cog.should_run_task(task, None):
38 await cog.execute_task(task)
39 mock_exec.assert_called_once_with(job) \ No newline at end of file
diff --git a/tests/cogs/test_downloader.py b/tests/cogs/test_downloader.py
deleted file mode 100644
index 125a103..0000000
--- a/tests/cogs/test_downloader.py
+++ /dev/null
@@ -1,93 +0,0 @@
1import pytest
2from unittest.mock import AsyncMock, patch, MagicMock
3import discord
4from conftest import MockApplicationContext, MockMessage
5
6
7@pytest.fixture
8def downloader_cog(bot):
9 from cogs.downloader import Downloader
10 cog = Downloader(bot)
11 return cog
12
13
14@pytest.mark.asyncio
15async def test_download_command_success_file(downloader_cog, mock_channel, mock_guild, bot):
16 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
17
18 mock_file_path = "/tmp/test_video.mp4"
19
20 with patch('cogs.downloader.Downloader.download_standalone', return_value={
21 "status": "success",
22 "type": "file",
23 "content": mock_file_path,
24 "filename": "test_video.mp4"
25 }):
26 with patch('discord.File', return_value=MagicMock()) as mock_file:
27 with patch.object(ctx, 'respond', new_callable=AsyncMock) as mock_respond:
28 await downloader_cog.download.callback(downloader_cog, ctx, url="https://example.com/video", catbox=False, fformat="mp4", filename_user=None)
29 mock_respond.assert_called_once()
30 call_args = mock_respond.call_args
31 assert 'file' in str(call_args) or mock_file.called
32
33
34@pytest.mark.asyncio
35async def test_download_command_success_url(downloader_cog, mock_channel, mock_guild, bot):
36 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
37
38 with patch('cogs.downloader.Downloader.download_standalone', return_value={
39 "status": "success",
40 "type": "url",
41 "content": "https://catbox.2137697.xyz/sperma/test.mp4"
42 }):
43 with patch.object(ctx, 'respond', new_callable=AsyncMock) as mock_respond:
44 await downloader_cog.download.callback(downloader_cog, ctx, url="https://example.com/video", catbox=True, fformat="mp4", filename_user=None)
45 mock_respond.assert_called_once()
46 call_args = mock_respond.call_args
47 assert "pobioron" in str(call_args)
48
49
50@pytest.mark.asyncio
51async def test_download_command_error(downloader_cog, mock_channel, mock_guild, bot):
52 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
53
54 with patch('cogs.downloader.Downloader.download_standalone', return_value={
55 "status": "error",
56 "type": "error",
57 "content": "Download failed",
58 "details": "Connection timeout"
59 }):
60 with patch('cogs.downloader.logger') as mock_logger:
61 await downloader_cog.download.callback(downloader_cog, ctx, url="https://badurl.com", catbox=False, fformat="mp4", filename_user=None)
62 assert mock_logger.error.called
63
64
65@pytest.mark.asyncio
66async def test_message_download_with_url(downloader_cog, mock_channel, mock_guild, bot, mock_user):
67 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
68
69 mock_message = MagicMock()
70 mock_message.content = "Check this out https://example.com/video"
71
72 with patch('cogs.downloader.Downloader.download_standalone', return_value={
73 "status": "success",
74 "type": "file",
75 "content": "/tmp/test.mp4"
76 }):
77 with patch.object(downloader_cog, 'download', new_callable=AsyncMock) as mock_download:
78 await downloader_cog.message_download.callback(downloader_cog, ctx, message=mock_message)
79 mock_download.assert_called_once()
80
81
82@pytest.mark.asyncio
83async def test_message_download_no_url(downloader_cog, mock_channel, mock_guild, bot):
84 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
85
86 mock_message = MagicMock()
87 mock_message.content = "No URL here"
88
89 with patch.object(ctx, 'respond', new_callable=AsyncMock) as mock_respond:
90 await downloader_cog.message_download.callback(downloader_cog, ctx, message=mock_message)
91 mock_respond.assert_called_once()
92 call_args = mock_respond.call_args
93 assert "Brak" in str(call_args)
diff --git a/tests/cogs/test_downloader_integration.py b/tests/cogs/test_downloader_integration.py
deleted file mode 100644
index c7c9790..0000000
--- a/tests/cogs/test_downloader_integration.py
+++ /dev/null
@@ -1,37 +0,0 @@
1import pytest
2from unittest.mock import MagicMock, AsyncMock, patch
3
4
5@pytest.fixture
6def downloader_cog(bot):
7 from cogs.downloader import Downloader
8 cog = Downloader(bot)
9 return cog
10
11
12@pytest.mark.slow
13@pytest.mark.asyncio
14async def test_download_command_flow(downloader_cog, bot):
15 """Test download command with URL processing."""
16 cog = downloader_cog
17
18 ctx = MagicMock()
19 ctx.author = MagicMock()
20 ctx.guild = MagicMock()
21 ctx.channel = MagicMock()
22 ctx.respond = AsyncMock()
23 ctx.defer = AsyncMock()
24 ctx.followup = AsyncMock()
25 ctx.voice_client = None
26
27 # Mock the download_standalone static method
28 mock_response = {
29 "status": "success",
30 "type": "url",
31 "content": "http://example.com/video.mp4"
32 }
33
34 with patch.object(cog, 'download_standalone', new_callable=AsyncMock, return_value=mock_response):
35 await cog.download.callback(cog, ctx, url="http://youtube.com/test")
36
37 ctx.respond.assert_called_once()
diff --git a/tests/cogs/test_math_commands.py b/tests/cogs/test_math_commands.py
deleted file mode 100644
index 21e9a2e..0000000
--- a/tests/cogs/test_math_commands.py
+++ /dev/null
@@ -1,55 +0,0 @@
1import pytest
2from unittest.mock import AsyncMock, patch, MagicMock
3from conftest import MockApplicationContext
4
5
6@pytest.fixture
7def math_cog(bot):
8 from cogs.math_commands import Math
9 cog = Math(bot)
10 return cog
11
12
13@pytest.mark.asyncio
14async def test_math_command_valid_expression(math_cog, mock_channel, mock_guild, bot):
15 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
16
17 mock_process = MagicMock()
18 mock_process.returncode = 0
19 mock_process.communicate = AsyncMock(return_value=(b"4", b""))
20
21 with patch('cogs.math_commands.asyncio.create_subprocess_exec', return_value=mock_process) as mock_subprocess:
22 with patch('cogs.math_commands.re.search', return_value=None):
23 with patch.object(ctx, 'respond', new_callable=AsyncMock) as mock_respond:
24 await math_cog.math.callback(math_cog, ctx, equation="2+2")
25 mock_subprocess.assert_called_once()
26 mock_respond.assert_called_once()
27
28
29@pytest.mark.asyncio
30async def test_math_command_invalid_expression(math_cog, mock_channel, mock_guild, bot):
31 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
32
33 with patch('cogs.math_commands.re.search', return_value=MagicMock()):
34 with patch.object(ctx, 'respond', new_callable=AsyncMock) as mock_respond:
35 await math_cog.math.callback(math_cog, ctx, equation="eval(1)")
36 mock_respond.assert_called_once()
37 args = mock_respond.call_args
38 assert "Invalid" in str(args)
39
40
41@pytest.mark.asyncio
42async def test_math_command_process_error(math_cog, mock_channel, mock_guild, bot):
43 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
44
45 mock_process = MagicMock()
46 mock_process.returncode = 1
47 mock_process.communicate = AsyncMock(return_value=(b"", b"Error: invalid expression"))
48
49 with patch('cogs.math_commands.asyncio.create_subprocess_exec', return_value=mock_process):
50 with patch('cogs.math_commands.re.search', return_value=None):
51 with patch.object(ctx, 'respond', new_callable=AsyncMock) as mock_respond:
52 await math_cog.math.callback(math_cog, ctx, equation="2++")
53 mock_respond.assert_called_once()
54 args = mock_respond.call_args
55 assert "error" in str(args).lower() or "Error" in str(args)
diff --git a/tests/cogs/test_music_audio.py b/tests/cogs/test_music_audio.py
deleted file mode 100644
index 98c6f6b..0000000
--- a/tests/cogs/test_music_audio.py
+++ /dev/null
@@ -1,93 +0,0 @@
1import pytest
2from unittest.mock import AsyncMock, patch, MagicMock
3import os
4from conftest import MockApplicationContext
5
6
7@pytest.mark.asyncio
8async def test_validate_voice_channel_not_in_voice():
9 from cogs.voice import VoiceManager as AudioPlaybackManager
10
11 mock_ctx = MagicMock()
12 mock_ctx.author.voice = None
13 mock_ctx.respond = AsyncMock()
14
15 result = await AudioPlaybackManager.validate_voice_channel(mock_ctx)
16
17 assert result is None
18 mock_ctx.respond.assert_called_once()
19
20
21@pytest.mark.asyncio
22async def test_validate_voice_channel_in_voice():
23 from cogs.voice import VoiceManager as AudioPlaybackManager
24
25 mock_channel = MagicMock()
26 mock_ctx = MagicMock()
27 mock_ctx.author.voice = MagicMock()
28 mock_ctx.author.voice.channel = mock_channel
29 mock_ctx.respond = AsyncMock()
30
31 result = await AudioPlaybackManager.validate_voice_channel(mock_ctx)
32
33 assert result == mock_channel
34
35
36@pytest.mark.asyncio
37async def test_prepare_file_source_file_not_found():
38 from cogs.voice import VoiceManager as AudioPlaybackManager
39
40 display_name, absolute_path = await AudioPlaybackManager.prepare_file_source("/nonexistent/file.mp3")
41
42 assert display_name is None
43 assert absolute_path is None
44
45
46@pytest.mark.asyncio
47async def test_prepare_file_source_absolute_path():
48 from cogs.voice import VoiceManager as AudioPlaybackManager
49
50 with patch('os.path.exists', return_value=True):
51 with patch('os.path.isabs', return_value=True):
52 display_name, absolute_path = await AudioPlaybackManager.prepare_file_source("/tmp/test.mp3")
53
54 assert display_name == "test"
55 assert absolute_path == "/tmp/test.mp3"
56
57
58@pytest.mark.asyncio
59async def test_prepare_source_url():
60 from cogs.voice import VoiceManager as AudioPlaybackManager
61
62 source, _, is_url = await AudioPlaybackManager.prepare_source("https://example.com/stream")
63
64 assert is_url == True
65 assert source == "https://example.com/stream"
66
67
68@pytest.mark.asyncio
69async def test_prepare_source_local_file():
70 from cogs.voice import VoiceManager as AudioPlaybackManager
71
72 with patch('os.path.exists', return_value=True):
73 source, display_name, is_url = await AudioPlaybackManager.prepare_source("/tmp/test.mp3")
74
75 assert is_url == False
76 assert display_name == "test"
77
78
79@pytest.mark.asyncio
80async def test_cleanup_temp_file():
81 from cogs.voice import VoiceManager as AudioPlaybackManager
82
83 with patch('os.path.exists', return_value=True):
84 with patch('os.remove'):
85 await AudioPlaybackManager.cleanup_temp_file("/tmp/test.mp3")
86
87
88@pytest.mark.asyncio
89async def test_cleanup_temp_file_not_exists():
90 from cogs.voice import VoiceManager as AudioPlaybackManager
91
92 with patch('os.path.exists', return_value=False):
93 await AudioPlaybackManager.cleanup_temp_file("/nonexistent/file.mp3")
diff --git a/tests/cogs/test_music_external_play.py b/tests/cogs/test_music_external_play.py
deleted file mode 100644
index 8e19423..0000000
--- a/tests/cogs/test_music_external_play.py
+++ /dev/null
@@ -1,109 +0,0 @@
1import pytest
2import os
3import asyncio
4import tempfile
5from unittest.mock import AsyncMock, patch, MagicMock
6from conftest import MockApplicationContext
7
8
9@pytest.fixture
10def play_commands_cog(bot):
11 with patch('cogs.utils.temp.get_temp_dir', return_value="/tmp"):
12 from cogs.music.play_commands import PlayCommands
13 cog = PlayCommands(bot)
14 return cog
15
16
17@pytest.fixture
18def temp_mp3_file():
19 with tempfile.NamedTemporaryFile(suffix='.mp3', delete=False) as f:
20 f.write(b'fake mp3 content')
21 temp_path = f.name
22 yield temp_path
23 if os.path.exists(temp_path):
24 os.remove(temp_path)
25
26
27@pytest.mark.asyncio
28async def test_external_url_pattern_matches_youtube(play_commands_cog):
29 from cogs.music.play_commands import EXTERNAL_URL_PATTERN
30
31 assert EXTERNAL_URL_PATTERN.match("https://youtube.com/watch?v=test")
32 assert EXTERNAL_URL_PATTERN.match("https://youtu.be/test")
33 assert EXTERNAL_URL_PATTERN.match("https://www.youtube.com/watch?v=test")
34
35
36@pytest.mark.asyncio
37async def test_external_url_pattern_matches_soundcloud(play_commands_cog):
38 from cogs.music.play_commands import EXTERNAL_URL_PATTERN
39
40 assert EXTERNAL_URL_PATTERN.match("https://soundcloud.com/artist/track")
41 assert EXTERNAL_URL_PATTERN.match("https://api.soundcloud.com/tracks")
42
43
44@pytest.mark.asyncio
45async def test_external_url_pattern_matches_bandcamp(play_commands_cog):
46 from cogs.music.play_commands import EXTERNAL_URL_PATTERN
47
48 assert EXTERNAL_URL_PATTERN.match("https://artist.bandcamp.com/track")
49
50
51@pytest.mark.asyncio
52async def test_external_url_pattern_rejects_copyparty(play_commands_cog):
53 from cogs.music.play_commands import EXTERNAL_URL_PATTERN
54
55 assert not EXTERNAL_URL_PATTERN.match("https://catbox.2137697.xyz/sperma/file.mp3")
56 assert not EXTERNAL_URL_PATTERN.match("some search query")
57
58
59@pytest.mark.asyncio
60async def test_play_command_calls_external_handler(play_commands_cog, mock_channel, mock_guild, bot):
61 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
62
63 with patch.object(play_commands_cog, '_handle_external_url_play', new_callable=AsyncMock) as mock_handler:
64 mock_handler.return_value = None
65 mock_defer = AsyncMock()
66 ctx.defer = mock_defer
67 ctx.respond = AsyncMock()
68
69 await play_commands_cog.play.callback(
70 play_commands_cog, ctx,
71 melodia="https://youtube.com/watch?v=test",
72 file=None, compressed=False
73 )
74
75 mock_handler.assert_called_once_with(ctx, "https://youtube.com/watch?v=test")
76
77
78@pytest.mark.asyncio
79async def test_play_command_calls_local_handler(play_commands_cog, mock_channel, mock_guild, bot):
80 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
81
82 with patch.object(play_commands_cog, '_handle_local_file_play', new_callable=AsyncMock) as mock_handler:
83 mock_handler.return_value = None
84 mock_defer = AsyncMock()
85 ctx.defer = mock_defer
86 ctx.respond = AsyncMock()
87
88 await play_commands_cog.play.callback(
89 play_commands_cog, ctx,
90 melodia="some search query",
91 file=None, compressed=False
92 )
93
94 mock_handler.assert_called_once_with(ctx, "some search query", False)
95
96
97@pytest.mark.asyncio
98async def test_upload_to_copyparty_async(play_commands_cog, temp_mp3_file, monkeypatch):
99 monkeypatch.setenv("COPYPARTY_URL_UPLOAD", "https://catbox.2137697.xyz/sperma/")
100 monkeypatch.setenv("COPYPARTY_PASSWORD", "testpassword")
101
102 mock_response = MagicMock()
103 mock_response.status_code = 200
104 mock_response.text = '{"fileurl": "https://example.com/file.mp3"}'
105 mock_response.json = MagicMock(return_value={"fileurl": "https://example.com/file.mp3"})
106
107 with patch('cogs.music.play_commands.requests.post', return_value=mock_response) as mock_post:
108 await play_commands_cog._upload_to_copyparty_async(temp_mp3_file)
109 mock_post.assert_called_once()
diff --git a/tests/cogs/test_music_integration.py b/tests/cogs/test_music_integration.py
deleted file mode 100644
index 692e1c1..0000000
--- a/tests/cogs/test_music_integration.py
+++ /dev/null
@@ -1,46 +0,0 @@
1import pytest
2from unittest.mock import MagicMock, AsyncMock, patch, PropertyMock
3import sys
4sys.path.insert(0, '/home/salmon/Documents/botcode/senator-sperma/tests')
5from conftest import MockApplicationContext
6
7
8@pytest.fixture
9def music_cog(bot):
10 from cogs.music.play_commands import PlayCommands
11 cog = PlayCommands(bot)
12 return cog
13
14
15@pytest.mark.slow
16@pytest.mark.asyncio
17async def test_music_join_stop(music_cog, bot):
18 """Test music join and stop commands."""
19 from cogs.music.join import Join
20 from cogs.music.stop import Stop
21
22 join_cog = Join(bot)
23 stop_cog = Stop(bot)
24
25 ctx = MockApplicationContext(bot=bot)
26 ctx.author.voice = MagicMock()
27 ctx.author.voice.channel = MagicMock()
28 ctx.guild = MagicMock()
29
30 # Test join
31 mock_vm = MagicMock()
32 mock_vm.connect = AsyncMock()
33 with patch('cogs.music.join.get_voice_manager', return_value=mock_vm):
34 with patch.object(ctx, 'respond', new_callable=AsyncMock):
35 with patch.object(ctx.interaction, 'delete_original_response', new_callable=AsyncMock):
36 await join_cog.join.callback(join_cog, ctx)
37 mock_vm.connect.assert_called_once_with(ctx.author.voice.channel)
38
39 # Test stop
40 mock_vm_stop = MagicMock()
41 mock_vm_stop.disconnect = AsyncMock()
42 with patch('cogs.music.stop.get_voice_manager', return_value=mock_vm_stop):
43 with patch.object(ctx, 'respond', new_callable=AsyncMock):
44 with patch.object(ctx.interaction, 'delete_original_response', new_callable=AsyncMock):
45 await stop_cog.stop.callback(stop_cog, ctx)
46 mock_vm_stop.disconnect.assert_called_once_with(ctx.guild)
diff --git a/tests/cogs/test_music_join.py b/tests/cogs/test_music_join.py
deleted file mode 100644
index b40d93a..0000000
--- a/tests/cogs/test_music_join.py
+++ /dev/null
@@ -1,56 +0,0 @@
1import pytest
2from unittest.mock import AsyncMock, patch, MagicMock
3from conftest import MockApplicationContext
4
5
6@pytest.fixture
7def join_cog(bot):
8 from cogs.music.join import Join
9 cog = Join(bot)
10 return cog
11
12
13@pytest.fixture
14def stop_cog(bot):
15 from cogs.music.stop import Stop
16 cog = Stop(bot)
17 return cog
18
19
20@pytest.mark.asyncio
21async def test_join_command_success(join_cog, mock_channel, mock_guild, bot, mock_user):
22 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
23 ctx.user = mock_user
24 ctx.author = mock_user
25
26 mock_voice_channel = MagicMock()
27 ctx.author.voice = MagicMock()
28 ctx.author.voice.channel = mock_voice_channel
29
30 with patch('cogs.music.join.get_voice_manager') as mock_get_vm:
31 mock_vm = MagicMock()
32 mock_vm.connect = AsyncMock()
33 mock_get_vm.return_value = mock_vm
34
35 with patch.object(ctx, 'respond', new_callable=AsyncMock):
36 with patch.object(ctx.interaction, 'delete_original_response', new_callable=AsyncMock):
37 await join_cog.join.callback(join_cog, ctx)
38 mock_vm.connect.assert_called_once_with(mock_voice_channel)
39
40
41@pytest.mark.asyncio
42async def test_stop_command_success(stop_cog, mock_channel, mock_guild, bot, mock_user):
43 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
44 ctx.user = mock_user
45 ctx.author = mock_user
46
47 with patch('cogs.music.stop.get_voice_manager') as mock_get_vm:
48 mock_vm = MagicMock()
49 mock_vm.disconnect = AsyncMock()
50 mock_get_vm.return_value = mock_vm
51
52 with patch.object(ctx, 'respond', new_callable=AsyncMock):
53 with patch.object(ctx.interaction, 'delete_original_response', new_callable=AsyncMock):
54 await stop_cog.stop.callback(stop_cog, ctx)
55
56 mock_vm.disconnect.assert_called_once_with(mock_guild)
diff --git a/tests/cogs/test_music_play.py b/tests/cogs/test_music_play.py
deleted file mode 100644
index 7684729..0000000
--- a/tests/cogs/test_music_play.py
+++ /dev/null
@@ -1,104 +0,0 @@
1import pytest
2from unittest.mock import AsyncMock, patch, MagicMock
3import os
4from conftest import MockApplicationContext
5
6
7@pytest.fixture
8def play_commands_cog(bot):
9 with patch('cogs.utils.temp.get_temp_dir', return_value="/tmp"):
10 from cogs.music.play_commands import PlayCommands
11 cog = PlayCommands(bot)
12 return cog
13
14
15@pytest.fixture
16def loop_cog(bot):
17 from cogs.music.loop import Loop
18 cog = Loop(bot)
19 return cog
20
21
22@pytest.mark.asyncio
23async def test_create_search_embed_empty(play_commands_cog):
24 embed, view = await play_commands_cog._create_search_embed([])
25
26 assert embed.title == "Wyniki wyszukiwania"
27 assert len(view.children) == 0
28
29
30@pytest.mark.asyncio
31async def test_create_search_embed_with_candidates(play_commands_cog):
32 candidates = [
33 "https://example.com/test1.mp3",
34 "https://example.com/test2.mp3"
35 ]
36
37 embed, view = await play_commands_cog._create_search_embed(candidates)
38
39 assert embed.title == "Wyniki wyszukiwania"
40 assert len(embed.fields) == 2
41
42
43@pytest.mark.asyncio
44async def test_play_command_no_file_or_search(play_commands_cog, mock_channel, mock_guild, bot):
45 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
46
47 with patch.object(ctx, 'respond', new_callable=AsyncMock) as mock_respond:
48 await play_commands_cog.play.callback(play_commands_cog, ctx, melodia=None, file=None, compressed=False)
49 mock_respond.assert_called_once()
50 args = mock_respond.call_args
51 assert "Musisz podać" in str(args)
52
53
54@pytest.mark.asyncio
55async def test_play_command_both_file_and_search(play_commands_cog, mock_channel, mock_guild, bot):
56 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
57
58 mock_file = MagicMock()
59 mock_file.filename = "test.mp3"
60
61 with patch.object(ctx, 'respond', new_callable=AsyncMock) as mock_respond:
62 await play_commands_cog.play.callback(play_commands_cog, ctx, melodia="test", file=mock_file, compressed=False)
63 mock_respond.assert_called_once()
64 args = mock_respond.call_args
65 assert "nie oba" in str(args) or "LUB" in str(args)
66
67
68def test_loop_cog_is_looping_initial(loop_cog):
69 assert loop_cog.is_looping(123) == False
70
71
72def test_loop_cog_set_looping(loop_cog):
73 loop_cog.set_looping(123, True)
74 assert loop_cog.is_looping(123) == True
75
76
77@pytest.mark.asyncio
78async def test_loop_command_toggle_on(loop_cog, mock_channel, mock_guild, bot, mock_user):
79 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
80 ctx.user = mock_user
81 ctx.author = mock_user
82 ctx.guild.id = 123
83
84 with patch.object(ctx, 'respond', new_callable=AsyncMock) as mock_respond:
85 await loop_cog.loop.callback(loop_cog, ctx)
86 mock_respond.assert_called_once()
87 args = mock_respond.call_args
88 assert "włączony" in str(args)
89
90
91@pytest.mark.asyncio
92async def test_loop_command_toggle_off(loop_cog, mock_channel, mock_guild, bot, mock_user):
93 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
94 ctx.user = mock_user
95 ctx.author = mock_user
96 ctx.guild.id = 456
97
98 loop_cog.set_looping(456, True)
99
100 with patch.object(ctx, 'respond', new_callable=AsyncMock) as mock_respond:
101 await loop_cog.loop.callback(loop_cog, ctx)
102 mock_respond.assert_called_once()
103 args = mock_respond.call_args
104 assert "wyłączony" in str(args)
diff --git a/tests/cogs/test_qr.py b/tests/cogs/test_qr.py
deleted file mode 100644
index b5cb31f..0000000
--- a/tests/cogs/test_qr.py
+++ /dev/null
@@ -1,75 +0,0 @@
1import pytest
2from unittest.mock import AsyncMock, patch, MagicMock, mock_open
3import os
4from cogs.qr import QR
5from conftest import MockApplicationContext
6
7
8@pytest.fixture
9def qr_cog(bot):
10 cog = QR(bot)
11 return cog
12
13
14@pytest.fixture
15def mock_temp_file():
16 with patch('tempfile.NamedTemporaryFile') as mock:
17 mock_file = MagicMock()
18 mock_file.name = "/tmp/test_qr.png"
19 mock.return_value = mock_file
20 yield mock_file
21
22
23@pytest.mark.asyncio
24async def test_qr_generate_success(qr_cog, mock_channel, mock_guild, bot, mock_temp_file):
25 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
26
27 with patch('cogs.qr.QR._generate_qr') as mock_generate:
28 with patch.object(ctx, 'respond', new_callable=AsyncMock) as mock_respond:
29 with patch('os.path.exists', return_value=True):
30 with patch('os.unlink'):
31 await qr_cog.qr.callback(qr_cog, ctx, text="https://example.com")
32 mock_generate.assert_called_once()
33 mock_respond.assert_called_once()
34
35
36@pytest.mark.asyncio
37async def test_qr_generate_empty_text(qr_cog, mock_channel, mock_guild, bot):
38 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
39
40 with patch('cogs.qr.QR._generate_qr'):
41 with patch.object(ctx, 'respond', new_callable=AsyncMock) as mock_respond:
42 with patch('os.path.exists', return_value=False):
43 await qr_cog.qr.callback(qr_cog, ctx, text="")
44 mock_respond.assert_called_once()
45
46
47@pytest.mark.asyncio
48async def test_qr_decode_not_available(qr_cog, mock_channel, mock_guild, bot):
49 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
50
51 mock_attachment = MagicMock()
52 mock_attachment.url = "https://example.com/qr.png"
53
54 with patch('cogs.qr._ensure_qr', return_value=False):
55 with patch.object(ctx, 'respond', new_callable=AsyncMock) as mock_respond:
56 await qr_cog.decode.callback(qr_cog, ctx, image=mock_attachment)
57 mock_respond.assert_called_once()
58 args = mock_respond.call_args
59 assert "nie jest dostępne" in str(args) or "not available" in str(args).lower()
60
61
62@pytest.mark.asyncio
63async def test_qr_decode_download_failure(qr_cog, mock_channel, mock_guild, bot):
64 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
65
66 mock_attachment = MagicMock()
67 mock_attachment.url = "https://example.com/qr.png"
68
69 with patch('cogs.qr._ensure_qr', return_value=True):
70 with patch.object(qr_cog, '_download_image', return_value=None):
71 with patch.object(ctx, 'respond', new_callable=AsyncMock) as mock_respond:
72 await qr_cog.decode.callback(qr_cog, ctx, image=mock_attachment)
73 mock_respond.assert_called_once()
74 args = mock_respond.call_args
75 assert "Nie udało się" in str(args) or "failed" in str(args).lower()
diff --git a/tests/cogs/test_say.py b/tests/cogs/test_say.py
deleted file mode 100644
index 76f1b94..0000000
--- a/tests/cogs/test_say.py
+++ /dev/null
@@ -1,38 +0,0 @@
1import pytest
2from unittest.mock import AsyncMock, patch
3from cogs.say import Say
4from conftest import MockApplicationContext
5
6
7@pytest.fixture
8def say_cog(bot):
9 cog = Say(bot)
10 return cog
11
12
13@pytest.mark.asyncio
14async def test_say_command(say_cog, mock_channel, mock_guild, bot):
15 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
16
17 with patch.object(ctx, 'send', new_callable=AsyncMock) as mock_send:
18 await say_cog.say.callback(say_cog, ctx, "Hello World")
19 mock_send.assert_called_once_with(content="Hello World")
20
21
22@pytest.mark.asyncio
23async def test_say_command_empty_text(say_cog, mock_channel, mock_guild, bot):
24 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
25
26 with patch.object(ctx, 'send', new_callable=AsyncMock) as mock_send:
27 await say_cog.say.callback(say_cog, ctx, "")
28 mock_send.assert_called_once_with(content="")
29
30
31@pytest.mark.asyncio
32async def test_say_command_long_text(say_cog, mock_channel, mock_guild, bot):
33 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
34 long_text = "A" * 2000
35
36 with patch.object(ctx, 'send', new_callable=AsyncMock) as mock_send:
37 await say_cog.say.callback(say_cog, ctx, long_text)
38 mock_send.assert_called_once_with(content=long_text)
diff --git a/tests/cogs/test_search.py b/tests/cogs/test_search.py
deleted file mode 100644
index c9c7d0e..0000000
--- a/tests/cogs/test_search.py
+++ /dev/null
@@ -1,83 +0,0 @@
1import pytest
2from unittest.mock import AsyncMock, patch, MagicMock
3import discord
4from conftest import MockApplicationContext
5
6
7@pytest.fixture
8def search_cog(bot):
9 from cogs.search import Search
10 cog = Search(bot)
11 return cog
12
13
14@pytest.mark.asyncio
15async def test_search_command_success(search_cog, mock_channel, mock_guild, bot, mock_user):
16 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
17 ctx.user = mock_user
18 ctx.author = mock_user
19
20 search_cog._cached_results[mock_user.id] = {
21 "testfile.mp4": "https://example.com/files/testfile.mp4"
22 }
23
24 with patch.object(ctx, 'send_followup', new_callable=AsyncMock) as mock_followup:
25 await search_cog.search.callback(search_cog, ctx, filename="testfile.mp4")
26 mock_followup.assert_called_once_with("https://example.com/files/testfile.mp4")
27 assert mock_user.id not in search_cog._cached_results
28
29
30@pytest.mark.asyncio
31async def test_search_command_no_cache(search_cog, mock_channel, mock_guild, bot, mock_user):
32 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
33 ctx.user = mock_user
34 ctx.author = mock_user
35
36 with patch.object(ctx, 'send_followup', new_callable=AsyncMock) as mock_followup:
37 await search_cog.search.callback(search_cog, ctx, filename="testfile.mp4")
38 mock_followup.assert_called_once_with("Search results expired. Please search again.")
39
40
41@pytest.mark.asyncio
42async def test_search_command_file_not_found(search_cog, mock_channel, mock_guild, bot, mock_user):
43 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
44 ctx.user = mock_user
45 ctx.author = mock_user
46
47 search_cog._cached_results[mock_user.id] = {
48 "testfile.mp4": "https://example.com/files/testfile.mp4"
49 }
50
51 with patch.object(ctx, 'send_followup', new_callable=AsyncMock) as mock_followup:
52 await search_cog.search.callback(search_cog, ctx, filename="nonexistent.mp4")
53 mock_followup.assert_called_once_with("File 'nonexistent.mp4' not found.")
54
55
56@pytest.mark.asyncio
57async def test_search_command_empty_filename(search_cog, mock_channel, mock_guild, bot, mock_user):
58 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
59 ctx.user = mock_user
60 ctx.author = mock_user
61
62 with patch.object(ctx, 'reply', new_callable=AsyncMock) as mock_reply:
63 await search_cog.search.callback(search_cog, ctx, filename="")
64 mock_reply.assert_called_once_with("Please select a file from the autocomplete options.")
65
66
67@pytest.mark.asyncio
68async def test_file_autocomplete(search_cog, mock_channel, mock_guild, bot, mock_user):
69 mock_autocomplete_ctx = MagicMock()
70 mock_autocomplete_ctx.value = "test"
71 mock_autocomplete_ctx.interaction = MagicMock()
72 mock_autocomplete_ctx.interaction.user = mock_user
73
74 with patch('cogs.utils.file_search.UniversalSearcher.search_copyparty_autocomplete', new_callable=AsyncMock) as mock_search:
75 mock_search.return_value = [
76 "https://example.com/files/test1.mp4",
77 "https://example.com/files/test2.mp4"
78 ]
79
80 choices = await search_cog.file_autocomplete(mock_autocomplete_ctx)
81
82 assert len(choices) == 2
83 assert mock_user.id in search_cog._cached_results
diff --git a/tests/cogs/test_trigger.py b/tests/cogs/test_trigger.py
deleted file mode 100644
index a60a139..0000000
--- a/tests/cogs/test_trigger.py
+++ /dev/null
@@ -1,106 +0,0 @@
1import pytest
2from unittest.mock import AsyncMock, patch, MagicMock
3import sqlite3
4from conftest import MockApplicationContext
5
6
7@pytest.fixture
8def trigger_cog(bot):
9 with patch('cogs.trigger.get_connection') as mock_conn:
10 mock_conn.return_value.__enter__ = MagicMock(return_value=MagicMock())
11 mock_conn.return_value.__exit__ = MagicMock(return_value=False)
12 from cogs.trigger import Trigger
13 cog = Trigger(bot)
14 return cog
15
16
17@pytest.fixture
18def mock_db_connection():
19 with patch('cogs.trigger.get_connection') as mock_get_conn:
20 mock_conn = MagicMock()
21 mock_cursor = MagicMock()
22 mock_conn.cursor.return_value = mock_cursor
23 mock_get_conn.return_value.__enter__ = MagicMock(return_value=mock_conn)
24 mock_get_conn.return_value.__exit__ = MagicMock(return_value=False)
25 yield mock_conn, mock_cursor
26
27
28@pytest.mark.asyncio
29async def test_trigger_create_command(trigger_cog, mock_channel, mock_guild, bot, mock_db_connection):
30 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
31
32 mock_conn, mock_cursor = mock_db_connection
33 mock_cursor.fetchone.return_value = None
34
35 with patch('cogs.trigger.get_connection') as mock_get_conn:
36 mock_conn = MagicMock()
37 mock_cursor = MagicMock()
38 mock_conn.cursor.return_value = mock_cursor
39 mock_get_conn.return_value.__enter__ = MagicMock(return_value=mock_conn)
40 mock_get_conn.return_value.__exit__ = MagicMock(return_value=False)
41
42 with patch.object(ctx, 'respond', new_callable=AsyncMock) as mock_respond:
43 await trigger_cog.create.callback(trigger_cog, ctx, name="test_trigger")
44 mock_respond.assert_called_once_with("trigger added")
45
46
47@pytest.mark.asyncio
48async def test_trigger_add_command(trigger_cog, mock_channel, mock_guild, bot, mock_db_connection):
49 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
50
51 with patch('cogs.trigger.get_connection') as mock_get_conn:
52 mock_conn = MagicMock()
53 mock_cursor = MagicMock()
54 mock_cursor.fetchone.return_value = (1,) # trigger exists
55 mock_conn.cursor.return_value = mock_cursor
56 mock_get_conn.return_value.__enter__ = MagicMock(return_value=mock_conn)
57 mock_get_conn.return_value.__exit__ = MagicMock(return_value=False)
58
59 with patch.object(ctx, 'respond', new_callable=AsyncMock) as mock_respond:
60 await trigger_cog.add.callback(trigger_cog, ctx, name="test_trigger", trigger="hello", response="Hi there!")
61 mock_respond.assert_called_once_with("trigger updated")
62
63
64@pytest.mark.asyncio
65async def test_trigger_add_command_not_found(trigger_cog, mock_channel, mock_guild, bot, mock_db_connection):
66 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
67
68 with patch('cogs.trigger.get_connection') as mock_get_conn:
69 mock_conn = MagicMock()
70 mock_cursor = MagicMock()
71 mock_cursor.fetchone.return_value = None # trigger not found
72 mock_conn.cursor.return_value = mock_cursor
73 mock_get_conn.return_value.__enter__ = MagicMock(return_value=mock_conn)
74 mock_get_conn.return_value.__exit__ = MagicMock(return_value=False)
75
76 with patch.object(ctx, 'respond', new_callable=AsyncMock) as mock_respond:
77 await trigger_cog.add.callback(trigger_cog, ctx, name="nonexistent", trigger="hello", response="Hi")
78 mock_respond.assert_called_once_with("Trigger not found.")
79
80
81@pytest.mark.asyncio
82async def test_trigger_delete_command(trigger_cog, mock_channel, mock_guild, bot, mock_db_connection):
83 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
84
85 with patch('cogs.trigger.get_connection') as mock_get_conn:
86 mock_conn = MagicMock()
87 mock_cursor = MagicMock()
88 mock_cursor.fetchone.return_value = (1,) # trigger exists
89 mock_conn.cursor.return_value = mock_cursor
90 mock_get_conn.return_value.__enter__ = MagicMock(return_value=mock_conn)
91 mock_get_conn.return_value.__exit__ = MagicMock(return_value=False)
92
93 with patch.object(ctx, 'respond', new_callable=AsyncMock) as mock_respond:
94 await trigger_cog.delete.callback(trigger_cog, ctx, name="test_trigger")
95 mock_respond.assert_called_once_with("trigger deleted")
96
97
98@pytest.mark.asyncio
99async def test_trigger_help_command(trigger_cog, mock_channel, mock_guild, bot):
100 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
101
102 with patch.object(ctx, 'respond', new_callable=AsyncMock) as mock_respond:
103 await trigger_cog.help.callback(trigger_cog, ctx)
104 mock_respond.assert_called_once()
105 args = mock_respond.call_args
106 assert "Trigger create" in str(args)
diff --git a/tests/cogs/test_trigger_integration.py b/tests/cogs/test_trigger_integration.py
deleted file mode 100644
index 4828387..0000000
--- a/tests/cogs/test_trigger_integration.py
+++ /dev/null
@@ -1,54 +0,0 @@
1import pytest
2from unittest.mock import MagicMock, AsyncMock, patch
3from cogs.trigger import Trigger
4
5
6@pytest.fixture
7def trigger_cog(bot):
8 from cogs.utils.database import init_database
9 init_database()
10 from cogs.trigger import Trigger
11 cog = Trigger(bot)
12 return cog
13
14
15@pytest.mark.slow
16@pytest.mark.asyncio
17async def test_trigger_response_flow(trigger_cog):
18 """Test trigger creation and response in a simulated message flow."""
19 cog = trigger_cog
20
21 ctx = MagicMock()
22 ctx.author = MagicMock()
23 ctx.author.id = 123
24 ctx.guild = MagicMock()
25 ctx.guild.id = 456
26 ctx.respond = AsyncMock()
27
28 # Create a trigger using the create command
29 await cog.create.callback(cog, ctx, name="test_trigger")
30
31 # Add a keyword and response
32 await cog.add.callback(cog, ctx, name="test_trigger", trigger="hello", response="world")
33
34 # Verify trigger was created - check DB
35 from cogs.utils.database import get_connection
36 with get_connection() as conn:
37 c = conn.cursor()
38 c.execute("SELECT id FROM triggers WHERE name=?", ("test_trigger",))
39 result = c.fetchone()
40 assert result is not None
41
42 # Simulate a message that should trigger
43 message = MagicMock()
44 message.author = ctx.author
45 message.author.bot = False
46 message.guild = ctx.guild
47 message.content = "say hello to me"
48 message.channel.send = AsyncMock() # Make send awaitable
49
50 # Check if trigger matches using the static method
51 await Trigger.trigger(message)
52
53 # Verify message.channel.send was called with the response
54 message.channel.send.assert_called_once_with("world")
diff --git a/tests/cogs/test_tts.py b/tests/cogs/test_tts.py
deleted file mode 100644
index c6563e6..0000000
--- a/tests/cogs/test_tts.py
+++ /dev/null
@@ -1,58 +0,0 @@
1import pytest
2from unittest.mock import AsyncMock, patch, MagicMock
3import discord
4from conftest import MockApplicationContext
5
6
7@pytest.fixture
8def tts_cog(bot):
9 from cogs.tts import TTS
10 cog = TTS(bot)
11 return cog
12
13
14@pytest.mark.asyncio
15async def test_tts_file_output(tts_cog, mock_channel, mock_guild, bot, mock_user):
16 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
17 ctx.user = mock_user
18 ctx.author = mock_user
19
20 "/tmp/test_tts.mp3"
21
22 with patch('cogs.tts.gTTS') as _:
23 with patch('os.path.exists', return_value=True):
24 with patch('os.unlink'):
25 with patch.object(ctx, 'respond', new_callable=AsyncMock) as mock_respond:
26 with patch('cogs.tts.get_volume', return_value=1.0):
27 await tts_cog.tts.callback(tts_cog, ctx, text="Hello", output="file")
28 mock_respond.assert_called_once()
29
30
31@pytest.mark.asyncio
32async def test_tts_voice_output_not_in_channel(tts_cog, mock_channel, mock_guild, bot, mock_user):
33 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
34 ctx.user = mock_user
35 ctx.author = mock_user
36 ctx.author.voice = None
37
38 with patch('cogs.tts.gTTS'):
39 with patch('os.path.exists', return_value=True):
40 with patch('os.unlink'):
41 with patch.object(ctx, 'respond', new_callable=AsyncMock) as mock_respond:
42 with patch('cogs.tts.get_volume', return_value=1.0):
43 await tts_cog.tts.callback(tts_cog, ctx, text="Hello", output="vc")
44
45
46@pytest.mark.asyncio
47async def test_tts_error_handling(tts_cog, mock_channel, mock_guild, bot, mock_user):
48 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
49 ctx.user = mock_user
50 ctx.author = mock_user
51
52 with patch('cogs.tts.gTTS', side_effect=Exception("TTS Error")):
53 with patch('os.path.exists', return_value=False):
54 with patch.object(ctx, 'respond', new_callable=AsyncMock) as mock_respond:
55 await tts_cog.tts.callback(tts_cog, ctx, text="Hello", output="file")
56 mock_respond.assert_called_once()
57 args = mock_respond.call_args
58 assert "Error" in str(args) or "eror" in str(args)
diff --git a/tests/cogs/test_uploader.py b/tests/cogs/test_uploader.py
deleted file mode 100644
index 0777126..0000000
--- a/tests/cogs/test_uploader.py
+++ /dev/null
@@ -1,226 +0,0 @@
1import pytest
2from unittest.mock import AsyncMock, patch, MagicMock
3import os
4import discord
5from conftest import MockApplicationContext, MockMessage, MockUser
6
7
8@pytest.fixture
9def uploader_cog(bot):
10 with patch('cogs.utils.temp.get_temp_dir', return_value='/tmp/test'):
11 from cogs.uploader import Uploader
12 cog = Uploader(bot)
13 return cog
14
15
16@pytest.mark.asyncio
17async def test_file_autocomplete(uploader_cog):
18 mock_autocomplete_ctx = MagicMock()
19 mock_autocomplete_ctx.value = "test"
20 mock_interaction = MagicMock()
21 mock_user = MockUser(id=12345)
22 mock_interaction.user = mock_user
23 mock_autocomplete_ctx.interaction = mock_interaction
24
25 with patch('cogs.utils.file_search.UniversalSearcher.search_copyparty_autocomplete', new_callable=AsyncMock) as mock_search:
26 mock_search.return_value = [
27 "https://copyparty.local/testfile1.mp3",
28 "https://copyparty.local/testfile2.mp3"
29 ]
30 result = await uploader_cog._file_autocomplete(mock_autocomplete_ctx)
31 assert len(result) == 2
32 assert result[0].name == "testfile1.mp3"
33
34
35@pytest.mark.asyncio
36async def test_file_autocomplete_empty_query(uploader_cog):
37 mock_autocomplete_ctx = MagicMock()
38 mock_autocomplete_ctx.value = ""
39 mock_interaction = MagicMock()
40 mock_interaction.user = MockUser(id=12345)
41 mock_autocomplete_ctx.interaction = mock_interaction
42
43 with patch('cogs.utils.file_search.UniversalSearcher.search_copyparty_autocomplete', new_callable=AsyncMock) as mock_search:
44 result = await uploader_cog._file_autocomplete(mock_autocomplete_ctx)
45 mock_search.assert_called_once_with("", max_results=25)
46
47
48@pytest.mark.asyncio
49async def test_download_from_url_success(uploader_cog):
50 with patch('requests.get') as mock_get:
51 mock_response = MagicMock()
52 mock_response.status_code = 200
53 mock_response.content = b"test file content"
54 mock_get.return_value = mock_response
55
56 mock_file = MagicMock()
57 mock_file.write = AsyncMock()
58
59 mock_cm = AsyncMock()
60 mock_cm.__aenter__ = AsyncMock(return_value=mock_file)
61 mock_cm.__aexit__ = AsyncMock(return_value=None)
62
63 with patch('cogs.uploader.aiofiles.open', return_value=mock_cm):
64 result = await uploader_cog._download_from_url("https://copyparty.local/file.txt")
65
66 assert result is not None
67 assert "file.txt" in result
68 mock_file.write.assert_called_once_with(b"test file content")
69
70
71@pytest.mark.asyncio
72async def test_download_from_url_failure(uploader_cog):
73 with patch('requests.get') as mock_get:
74 mock_response = MagicMock()
75 mock_response.status_code = 404
76 mock_get.return_value = mock_response
77
78 result = await uploader_cog._download_from_url("https://copyparty.local/notfound.txt")
79
80 assert result is None
81
82
83@pytest.mark.asyncio
84async def test_upload_to_copyparty_success(uploader_cog):
85 mock_file = MagicMock()
86 mock_file.read = AsyncMock(return_value=b"test content")
87
88 mock_cm = AsyncMock()
89 mock_cm.__aenter__ = AsyncMock(return_value=mock_file)
90 mock_cm.__aexit__ = AsyncMock(return_value=None)
91
92 with patch('cogs.uploader.aiofiles.open', return_value=mock_cm):
93 with patch('requests.post') as mock_post:
94 mock_response = MagicMock()
95 mock_response.status_code = 200
96 mock_response.json.return_value = {"fileurl": "https://copyparty.local/uploaded.txt"}
97 mock_post.return_value = mock_response
98
99 with patch.dict(os.environ, {"COPYPARTY_PASSWORD": "testpass"}):
100 result = await uploader_cog._upload_to_copyparty("/tmp/testfile.txt")
101
102 assert result == "https://copyparty.local/uploaded.txt"
103
104
105@pytest.mark.asyncio
106async def test_upload_to_copyparty_failure(uploader_cog):
107 mock_file = MagicMock()
108 mock_file.read = AsyncMock(return_value=b"test content")
109
110 mock_cm = AsyncMock()
111 mock_cm.__aenter__ = AsyncMock(return_value=mock_file)
112 mock_cm.__aexit__ = AsyncMock(return_value=None)
113
114 with patch('cogs.uploader.aiofiles.open', return_value=mock_cm):
115 with patch('requests.post') as mock_post:
116 mock_response = MagicMock()
117 mock_response.status_code = 500
118 mock_post.return_value = mock_response
119
120 result = await uploader_cog._upload_to_copyparty("/tmp/testfile.txt")
121
122 assert result is None
123
124
125@pytest.mark.asyncio
126async def test_upload_file_no_url(uploader_cog):
127 uploader_cog._uploadurl = None
128
129 result = await uploader_cog._upload_file("/tmp/test.txt")
130
131 assert result is None
132
133
134@pytest.mark.asyncio
135async def test_message_upload_no_attachments(uploader_cog, mock_channel, mock_guild, bot):
136 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
137
138 mock_message = MagicMock()
139 mock_message.attachments = []
140
141 with patch.object(ctx, 'respond', new_callable=AsyncMock) as mock_respond:
142 await uploader_cog.message_upload.callback(uploader_cog, ctx, message=mock_message)
143 mock_respond.assert_called_once_with("Brak załączników w wiadomości", ephemeral=True)
144
145
146@pytest.mark.asyncio
147async def test_message_upload_success(uploader_cog, mock_channel, mock_guild, bot):
148 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
149
150 mock_attachment = MagicMock()
151 mock_attachment.filename = "test.txt"
152 mock_attachment.save = AsyncMock()
153
154 mock_message = MagicMock()
155 mock_message.attachments = [mock_attachment]
156
157 with patch.object(uploader_cog, '_upload_file', new_callable=AsyncMock) as mock_upload:
158 mock_upload.return_value = "https://copyparty.local/uploaded.txt"
159
160 with patch('os.path.exists', return_value=True):
161 with patch('os.remove'):
162 with patch.object(ctx, 'defer', new_callable=AsyncMock):
163 with patch.object(ctx, 'respond', new_callable=AsyncMock) as mock_respond:
164 await uploader_cog.message_upload.callback(uploader_cog, ctx, message=mock_message)
165 mock_respond.assert_called_once()
166 assert "Wysłano" in str(mock_respond.call_args)
167
168
169@pytest.mark.asyncio
170async def test_message_upload_all_failed(uploader_cog, mock_channel, mock_guild, bot):
171 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
172
173 mock_attachment = MagicMock()
174 mock_attachment.filename = "test.txt"
175 mock_attachment.save = AsyncMock()
176
177 mock_message = MagicMock()
178 mock_message.attachments = [mock_attachment]
179
180 with patch.object(uploader_cog, '_upload_file', new_callable=AsyncMock) as mock_upload:
181 mock_upload.return_value = None
182
183 with patch('os.path.exists', return_value=True):
184 with patch('os.remove'):
185 with patch.object(ctx, 'defer', new_callable=AsyncMock):
186 with patch.object(ctx, 'respond', new_callable=AsyncMock) as mock_respond:
187 await uploader_cog.message_upload.callback(uploader_cog, ctx, message=mock_message)
188 mock_respond.assert_called_once_with("Nie udało się wysłać żadnych plików", ephemeral=True)
189
190
191@pytest.mark.asyncio
192async def test_upload_slash_command_success(uploader_cog, mock_channel, mock_guild, bot):
193 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
194
195 mock_attachment = MagicMock()
196 mock_attachment.filename = "test.txt"
197 mock_attachment.save = AsyncMock()
198
199 with patch.object(uploader_cog, '_upload_file', new_callable=AsyncMock) as mock_upload:
200 mock_upload.return_value = "https://copyparty.local/uploaded.txt"
201
202 with patch('os.path.exists', return_value=True):
203 with patch('os.remove'):
204 with patch.object(ctx, 'defer', new_callable=AsyncMock):
205 with patch.object(ctx, 'respond', new_callable=AsyncMock) as mock_respond:
206 await uploader_cog.upload.callback(uploader_cog, ctx, zalacznik=mock_attachment)
207 mock_respond.assert_called_once_with("https://copyparty.local/uploaded.txt")
208
209
210@pytest.mark.asyncio
211async def test_upload_slash_command_failure(uploader_cog, mock_channel, mock_guild, bot):
212 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
213
214 mock_attachment = MagicMock()
215 mock_attachment.filename = "test.txt"
216 mock_attachment.save = AsyncMock()
217
218 with patch.object(uploader_cog, '_upload_file', new_callable=AsyncMock) as mock_upload:
219 mock_upload.return_value = None
220
221 with patch('os.path.exists', return_value=True):
222 with patch('os.remove'):
223 with patch.object(ctx, 'defer', new_callable=AsyncMock):
224 with patch.object(ctx, 'respond', new_callable=AsyncMock) as mock_respond:
225 await uploader_cog.upload.callback(uploader_cog, ctx, zalacznik=mock_attachment)
226 mock_respond.assert_called_once_with("Nie udało się wysłać pliku", ephemeral=True) \ No newline at end of file
diff --git a/tests/cogs/test_vclogs.py b/tests/cogs/test_vclogs.py
deleted file mode 100644
index 17ff839..0000000
--- a/tests/cogs/test_vclogs.py
+++ /dev/null
@@ -1,88 +0,0 @@
1import pytest
2from unittest.mock import AsyncMock, patch, MagicMock
3from conftest import MockApplicationContext
4
5
6def test_format_duration():
7 from cogs.vclogs import format_duration
8
9 assert format_duration(30) == "30s"
10 assert format_duration(90) == "1m 30s"
11 assert format_duration(3661) == "1h 1m 1s"
12
13
14def test_load_activity_data():
15 with patch("cogs.vclogs.get_connection") as mock_conn:
16 mock_cursor = MagicMock()
17 mock_conn.return_value.cursor.return_value = mock_cursor
18 mock_conn.return_value.close.return_value = None
19 mock_cursor.fetchall.return_value = []
20
21 from cogs.vclogs import load_activity_data
22 data = load_activity_data()
23 assert isinstance(data, dict)
24
25
26def test_save_activity_data():
27 with patch("cogs.vclogs.get_connection") as mock_conn:
28 mock_cursor = MagicMock()
29 mock_conn.return_value.cursor.return_value = mock_cursor
30 mock_conn.return_value.commit.return_value = None
31 mock_conn.return_value.close.return_value = None
32
33 from cogs.vclogs import save_activity_data
34 save_activity_data({"123": {"active": True}})
35
36
37@pytest.fixture
38def vclogs_cog(bot):
39 with patch('cogs.vclogs.get_voice_manager'):
40 with patch('cogs.vclogs.get_volume', return_value=1.0):
41 with patch('cogs.vclogs.save_settings'):
42 from cogs.vclogs import VcLogs
43 cog = VcLogs(bot)
44 return cog
45
46
47@pytest.mark.asyncio
48async def test_handle_state_change_deaf_true(vclogs_cog):
49 mock_member = MagicMock()
50 mock_member.display_name = "TestUser"
51 mock_channel = MagicMock()
52
53 tts_text, channel = await vclogs_cog.handle_state_change(mock_member, mock_channel, 'deaf', True, None)
54
55 assert "jest bity przez ojca" in tts_text
56
57
58@pytest.mark.asyncio
59async def test_handle_state_change_deaf_false(vclogs_cog):
60 mock_member = MagicMock()
61 mock_member.display_name = "TestUser"
62 mock_channel = MagicMock()
63
64 tts_text, channel = await vclogs_cog.handle_state_change(mock_member, mock_channel, 'deaf', False, None)
65
66 assert "uciek od ojca" in tts_text
67
68
69@pytest.mark.asyncio
70async def test_handle_state_change_mute_true(vclogs_cog):
71 mock_member = MagicMock()
72 mock_member.display_name = "TestUser"
73 mock_channel = MagicMock()
74
75 tts_text, channel = await vclogs_cog.handle_state_change(mock_member, mock_channel, 'mute', True, None)
76
77 assert "idzie robić jajecznice" in tts_text
78
79
80@pytest.mark.asyncio
81async def test_handle_state_change_mute_false(vclogs_cog):
82 mock_member = MagicMock()
83 mock_member.display_name = "TestUser"
84 mock_channel = MagicMock()
85
86 tts_text, channel = await vclogs_cog.handle_state_change(mock_member, mock_channel, 'mute', False, None)
87
88 assert "zrobił jajecznice" in tts_text \ No newline at end of file
diff --git a/tests/cogs/test_vclogs_integration.py b/tests/cogs/test_vclogs_integration.py
deleted file mode 100644
index 9391876..0000000
--- a/tests/cogs/test_vclogs_integration.py
+++ /dev/null
@@ -1,86 +0,0 @@
1import pytest
2import asyncio
3from unittest.mock import MagicMock, AsyncMock, patch
4
5
6@pytest.fixture
7def vclogs_cog(bot):
8 from cogs.vclogs import VcLogs
9 cog = VcLogs(bot)
10 return cog
11
12
13@pytest.mark.slow
14@pytest.mark.asyncio
15async def test_full_voice_session_tracking(vclogs_cog, monkeypatch):
16 """Test complete voice session with AFK transitions using real time sleeps."""
17 cog = vclogs_cog
18
19 # Set up environment
20 monkeypatch.setenv("STATUS_CHANNEL_ID", "123456")
21
22 member = MagicMock()
23 member.id = 123
24 member.guild.id = 456
25 member.bot = False
26 member.display_name = "TestUser"
27 member.guild.get_member.return_value = member
28
29 # Create a mock log channel
30 log_channel = MagicMock()
31 log_channel.send = AsyncMock(return_value=MagicMock())
32
33 # Mock bot.get_channel to return our log channel
34 with patch.object(vclogs_cog.bot, 'get_channel', return_value=log_channel):
35 # Join voice
36 before = MagicMock()
37 before.channel = None
38 after_join = MagicMock()
39 after_join.channel = MagicMock()
40 after_join.channel.id = 789
41 after_join.channel.name = "Test Voice"
42 after_join.self_deaf = False
43 after_join.self_mute = False
44 after_join.deaf = False
45 after_join.mute = False
46 await cog.on_voice_state_update(member, before, after_join)
47
48 await asyncio.sleep(2) # Simulate 2s active
49
50 # Go AFK (self_deaf)
51 before_afk = after_join
52 after_afk = MagicMock()
53 after_afk.channel = before_afk.channel
54 after_afk.self_deaf = True
55 after_afk.self_mute = False
56 after_afk.deaf = True
57 after_afk.mute = False
58 await cog.on_voice_state_update(member, before_afk, after_afk)
59
60 await asyncio.sleep(3) # Simulate 3s AFK
61
62 # Return from AFK
63 before_back = after_afk
64 after_back = MagicMock()
65 after_back.channel = before_back.channel
66 after_back.self_deaf = False
67 after_back.self_mute = False
68 after_back.deaf = False
69 after_back.mute = False
70 await cog.on_voice_state_update(member, before_back, after_back)
71
72 await asyncio.sleep(1) # Simulate 1s active
73
74 # Leave voice
75 before_leave = after_back
76 after_leave = MagicMock()
77 after_leave.channel = None
78 after_leave.self_deaf = False
79 after_leave.self_mute = False
80 await cog.on_voice_state_update(member, before_leave, after_leave)
81
82 # Verify activity was saved (check DB)
83 from cogs.vclogs import load_activity_data
84 activity_data = load_activity_data()
85 # After leaving, data should be deleted, so check the log channel was called
86 assert log_channel.send.called
diff --git a/tests/cogs/test_voice.py b/tests/cogs/test_voice.py
deleted file mode 100644
index 6eb226b..0000000
--- a/tests/cogs/test_voice.py
+++ /dev/null
@@ -1,79 +0,0 @@
1import pytest
2from unittest.mock import AsyncMock, patch, MagicMock
3import asyncio
4from conftest import MockApplicationContext
5
6
7@pytest.mark.asyncio
8async def test_get_voice_manager():
9 from cogs.voice import get_voice_manager, VoiceManager
10
11 mock_bot = MagicMock()
12 mock_bot.user = MagicMock()
13 mock_bot.user.id = 12345
14
15 manager1 = get_voice_manager(mock_bot)
16 manager2 = get_voice_manager(mock_bot)
17
18 assert isinstance(manager1, VoiceManager)
19 assert manager1 is manager2
20
21
22@pytest.mark.asyncio
23async def test_voice_manager_join_channel_not_found():
24 from cogs.voice import VoiceManager
25
26 mock_bot = MagicMock()
27 mock_bot.get_channel.return_value = None
28
29 manager = VoiceManager(mock_bot)
30 result = await manager.join_by_channel_id(999)
31
32 assert result is None
33
34
35@pytest.mark.asyncio
36async def test_voice_manager_join_invalid_channel():
37 from cogs.voice import VoiceManager
38
39 mock_bot = MagicMock()
40 mock_channel = MagicMock()
41 mock_bot.get_channel.return_value = mock_channel
42
43 manager = VoiceManager(mock_bot)
44 result = await manager.join_by_channel_id(999)
45
46 assert result is None
47
48
49@pytest.mark.asyncio
50async def test_voice_manager_get_voice_status_not_connected():
51 from cogs.voice import VoiceManager
52
53 mock_bot = MagicMock()
54 mock_guild = MagicMock()
55
56 with patch('cogs.voice.VoiceManager.get_client', return_value=None):
57 manager = VoiceManager(mock_bot)
58 voice_client, is_connected, is_playing = await manager.get_voice_status(mock_guild)
59
60 assert voice_client is None
61 assert is_connected == False
62 assert is_playing == False
63
64
65@pytest.mark.asyncio
66async def test_voice_manager_stop():
67 from cogs.voice import VoiceManager
68
69 mock_bot = MagicMock()
70 mock_guild = MagicMock()
71 mock_voice_client = MagicMock()
72 mock_voice_client.disconnect = AsyncMock()
73
74 with patch('cogs.voice.VoiceManager.get_client', return_value=mock_voice_client):
75 manager = VoiceManager(mock_bot)
76 await manager.stop(mock_guild)
77
78 mock_voice_client.stop.assert_called_once()
79 mock_voice_client.disconnect.assert_called_once()
diff --git a/tests/cogs/test_web.py b/tests/cogs/test_web.py
deleted file mode 100644
index 4de2e8b..0000000
--- a/tests/cogs/test_web.py
+++ /dev/null
@@ -1,57 +0,0 @@
1import pytest
2from unittest.mock import AsyncMock, patch, MagicMock
3from cogs.web import Web
4from conftest import MockApplicationContext
5
6
7@pytest.fixture
8def web_cog(bot):
9 cog = Web(bot)
10 return cog
11
12
13@pytest.mark.asyncio
14async def test_web_command_success(web_cog, mock_channel, mock_guild, bot):
15 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
16
17 mock_response = MagicMock()
18 mock_response.status_code = 200
19 mock_response.text = '''
20 <html>
21 <a class="result__a" href="https://example.com">Test Result</a>
22 <a class="result__a" href="https://example.com/2">Test Result 2</a>
23 </html>
24 '''
25
26 with patch('cogs.web.requests.get', return_value=mock_response) as mock_get:
27 with patch.object(ctx, 'respond', new_callable=AsyncMock) as mock_respond:
28 await web_cog.web.callback(web_cog, ctx, query="test query")
29 mock_get.assert_called_once()
30 mock_respond.assert_called_once()
31
32
33@pytest.mark.asyncio
34async def test_web_command_no_results(web_cog, mock_channel, mock_guild, bot):
35 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
36
37 mock_response = MagicMock()
38 mock_response.status_code = 200
39 mock_response.text = '<html><body></body></html>'
40
41 with patch('cogs.web.requests.get', return_value=mock_response):
42 with patch.object(ctx, 'respond', new_callable=AsyncMock) as mock_respond:
43 await web_cog.web.callback(web_cog, ctx, query="test")
44 mock_respond.assert_called_once_with(content="No results found.", ephemeral=True)
45
46
47@pytest.mark.asyncio
48async def test_web_command_http_error(web_cog, mock_channel, mock_guild, bot):
49 ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)
50
51 mock_response = MagicMock()
52 mock_response.status_code = 500
53
54 with patch('cogs.web.requests.get', return_value=mock_response):
55 with patch.object(ctx, 'respond', new_callable=AsyncMock) as mock_respond:
56 await web_cog.web.callback(web_cog, ctx, query="test")
57 mock_respond.assert_called_once_with(content="Error: 500", ephemeral=True)