aboutsummaryrefslogtreecommitdiffstats
path: root/tests/cogs
diff options
context:
space:
mode:
authorsalmonik <raisersoft@proton.me>2026-04-28 20:05:36 +0200
committersalmonik <raisersoft@proton.me>2026-04-28 20:05:36 +0200
commit5675dfd20b24f1e0eef06b11d9ec41a894d3a5bf (patch)
treecaad1669db6fce506dd0494aeaf2a43f7e291679 /tests/cogs
parentbetter UX for web.py (diff)
downloadsenator-sperma-5675dfd20b24f1e0eef06b11d9ec41a894d3a5bf.tar.gz
senator-sperma-5675dfd20b24f1e0eef06b11d9ec41a894d3a5bf.zip
multitude of changes.
but primarly, use db for all data. Signed-off-by: salmonik <raisersoft@proton.me>
Diffstat (limited to 'tests/cogs')
-rw-r--r--tests/cogs/test_cron.py88
-rw-r--r--tests/cogs/test_uploader.py226
-rw-r--r--tests/cogs/test_vclogs.py31
3 files changed, 277 insertions, 68 deletions
diff --git a/tests/cogs/test_cron.py b/tests/cogs/test_cron.py
index 93031f8..91fcb82 100644
--- a/tests/cogs/test_cron.py
+++ b/tests/cogs/test_cron.py
@@ -1,5 +1,3 @@
1import json
2import os
3import pytest 1import pytest
4from datetime import datetime 2from datetime import datetime
5from unittest.mock import MagicMock, patch 3from unittest.mock import MagicMock, patch
@@ -19,68 +17,48 @@ def mock_bot():
19 17
20def create_cog(mock_bot, tmp_path): 18def create_cog(mock_bot, tmp_path):
21 with patch.object(Cron, "__init__", lambda self, bot: None): 19 with patch.object(Cron, "__init__", lambda self, bot: None):
22 cog = Cron.__new__(Cron) 20 with patch("cogs.cron.init_database"):
23 cog.bot = mock_bot 21 mock_conn = MagicMock()
24 cog.scheduled_tasks = [] 22 mock_cursor = MagicMock()
25 cog.cron_file = str(tmp_path / "cron_jobs.json") 23 mock_cursor.fetchall.return_value = []
26 cog.task = MagicMock() 24 mock_conn.cursor.return_value = mock_cursor
27 return cog 25 mock_conn.close.return_value = None
26
27 with patch("cogs.cron.get_connection", return_value=mock_conn):
28 with patch("cogs.utils.database.get_db_path", return_value=":memory:"):
29 cog = Cron.__new__(Cron)
30 cog.bot = mock_bot
31 cog.scheduled_tasks = []
32 cog.task = MagicMock()
33 return cog
28 34
29 35
30class TestLoadTasks: 36class TestLoadTasks:
31 def test_load_tasks_file_not_exists(self, mock_bot, tmp_path): 37 def test_load_tasks_with_data(self, mock_bot, tmp_path):
32 cog = create_cog(mock_bot, tmp_path) 38 mock_conn = MagicMock()
33 cog.cron_file = str(tmp_path / "nonexistent.json") 39 mock_cursor = MagicMock()
34 cog.load_tasks() 40 mock_cursor.fetchall.return_value = [
35 assert cog.scheduled_tasks == [] 41 (1, "* * * * *", "audio", 123, 1, None, "test message")
36 42 ]
37 def test_load_tasks_empty_file(self, mock_bot, tmp_path): 43 mock_conn.cursor.return_value = mock_cursor
38 cron_file = tmp_path / "empty.json" 44 mock_conn.close.return_value = None
39 cron_file.write_text("")
40 cog = create_cog(mock_bot, tmp_path)
41 cog.cron_file = str(cron_file)
42 cog.load_tasks()
43 assert cog.scheduled_tasks == []
44
45 def test_load_tasks_valid_file(self, mock_bot, tmp_path):
46 cron_file = tmp_path / "valid.json"
47 tasks = [{"id": 1, "cron_expression": "* * * * *", "type": "audio", "channel_id": 123, "active": True}]
48 cron_file.write_text(json.dumps(tasks))
49 cog = create_cog(mock_bot, tmp_path)
50 cog.cron_file = str(cron_file)
51 cog.load_tasks()
52 assert len(cog.scheduled_tasks) == 1
53 assert cog.scheduled_tasks[0]["id"] == 1
54 45
55 def test_load_tasks_io_error(self, mock_bot, tmp_path): 46 with patch("cogs.cron.get_connection", return_value=mock_conn):
56 cog = create_cog(mock_bot, tmp_path) 47 cog = Cron.__new__(Cron)
57 with patch("builtins.open", side_effect=IOError("test error")): 48 cog.bot = mock_bot
49 cog.scheduled_tasks = []
50 cog.task = MagicMock()
58 cog.load_tasks() 51 cog.load_tasks()
59 assert cog.scheduled_tasks == [] 52 assert len(cog.scheduled_tasks) == 1
53 assert cog.scheduled_tasks[0]["id"] == 1
60 54
61 55
62class TestSaveTasks: 56class TestSaveTasks:
63 def test_save_tasks_with_real_file(self, mock_bot, tmp_path): 57 def test_save_tasks(self, mock_bot, tmp_path):
64 cron_file = tmp_path / "cron_jobs.json"
65 cog = create_cog(mock_bot, tmp_path)
66 cog.cron_file = str(cron_file)
67 cog.scheduled_tasks = [{"id": 1, "cron_expression": "* * * * *"}]
68 cog.save_tasks()
69 assert os.path.exists(cron_file)
70 with open(cron_file) as f:
71 loaded = json.load(f)
72 assert len(loaded) == 1
73
74 def test_save_tasks_creates_directory_structure(self, mock_bot, tmp_path):
75 cog = create_cog(mock_bot, tmp_path) 58 cog = create_cog(mock_bot, tmp_path)
76 new_dir = tmp_path / "new_dir" 59 cog.scheduled_tasks = [{"id": 1, "cron_expression": "* * * * *", "type": "audio", "channel_id": 123, "active": True}]
77 cron_file = new_dir / "cron_jobs.json"
78 cog.cron_file = str(cron_file)
79 cog.scheduled_tasks = [{"id": 1}]
80
81 cog.save_tasks() 60 cog.save_tasks()
82 61 assert len(cog.scheduled_tasks) == 1
83 assert os.path.exists(new_dir)
84 62
85 63
86class TestShouldRunTask: 64class TestShouldRunTask:
@@ -163,4 +141,4 @@ class TestTaskTypes:
163 def test_task_type_message_aliases(self, mock_bot, tmp_path): 141 def test_task_type_message_aliases(self, mock_bot, tmp_path):
164 message_types = ("wyślij_wiadomość", "send_message") 142 message_types = ("wyślij_wiadomość", "send_message")
165 for task_type in message_types: 143 for task_type in message_types:
166 assert task_type in ("wyślij_wiadomość", "send_message") 144 assert task_type in ("wyślij_wiadomość", "send_message") \ No newline at end of file
diff --git a/tests/cogs/test_uploader.py b/tests/cogs/test_uploader.py
new file mode 100644
index 0000000..addf87e
--- /dev/null
+++ b/tests/cogs/test_uploader.py
@@ -0,0 +1,226 @@
1import pytest
2from unittest.mock import AsyncMock, patch, MagicMock
3import os
4import discord
5from tests.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
index 2003478..da41482 100644
--- a/tests/cogs/test_vclogs.py
+++ b/tests/cogs/test_vclogs.py
@@ -1,6 +1,5 @@
1import pytest 1import pytest
2from unittest.mock import AsyncMock, patch, MagicMock 2from unittest.mock import AsyncMock, patch, MagicMock
3import json
4from tests.conftest import MockApplicationContext 3from tests.conftest import MockApplicationContext
5 4
6 5
@@ -13,20 +12,26 @@ def test_format_duration():
13 12
14 13
15def test_load_activity_data(): 14def test_load_activity_data():
16 with patch('builtins.open', MagicMock()): 15 with patch("cogs.vclogs.get_connection") as mock_conn:
17 with patch('os.path.exists', return_value=True): 16 mock_cursor = MagicMock()
18 with patch('json.load', return_value={"123": {"active": True}}): 17 mock_conn.return_value.cursor.return_value = mock_cursor
19 from cogs.vclogs import load_activity_data 18 mock_conn.return_value.close.return_value = None
20 data = load_activity_data() 19 mock_cursor.fetchall.return_value = []
21 assert isinstance(data, dict) 20
21 from cogs.vclogs import load_activity_data
22 data = load_activity_data()
23 assert isinstance(data, dict)
22 24
23 25
24def test_save_activity_data(): 26def test_save_activity_data():
25 with patch('builtins.open', MagicMock()) as mock_open: 27 with patch("cogs.vclogs.get_connection") as mock_conn:
26 with patch('json.dump'): 28 mock_cursor = MagicMock()
27 from cogs.vclogs import save_activity_data 29 mock_conn.return_value.cursor.return_value = mock_cursor
28 save_activity_data({"123": {"active": True}}) 30 mock_conn.return_value.commit.return_value = None
29 mock_open.assert_called_once() 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}})
30 35
31 36
32@pytest.fixture 37@pytest.fixture
@@ -80,4 +85,4 @@ async def test_handle_state_change_mute_false(vclogs_cog):
80 85
81 tts_text, channel = await vclogs_cog.handle_state_change(mock_member, mock_channel, 'mute', False, None) 86 tts_text, channel = await vclogs_cog.handle_state_change(mock_member, mock_channel, 'mute', False, None)
82 87
83 assert "zrobił jajecznice" in tts_text 88 assert "zrobił jajecznice" in tts_text \ No newline at end of file