Skip to content

Commit ea81972

Browse files
hendisantikaclaude
andcommitted
✅ test: update all tests for multi-group support
🔄 Replace get_settings() patches with get_group_config_for_update() and get_group_registry() patches across all test files. 🆕 Add test_group_config.py for GroupConfig, GroupRegistry, JSON loading, and singleton management. 🎯 All 440 tests pass. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent b33e86e commit ea81972

10 files changed

+1095
-574
lines changed

tests/test_anti_spam.py

Lines changed: 51 additions & 53 deletions
Large diffs are not rendered by default.

tests/test_captcha.py

Lines changed: 125 additions & 109 deletions
Large diffs are not rendered by default.

tests/test_captcha_recovery.py

Lines changed: 64 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,27 @@
88
from sqlmodel import Session, text
99

1010
from bot.database.service import get_database, init_database, reset_database
11+
from bot.group_config import GroupConfig, GroupRegistry
1112
from bot.services.captcha_recovery import (
1213
handle_captcha_expiration,
1314
recover_pending_captchas,
1415
)
1516

1617

1718
@pytest.fixture
18-
def mock_settings():
19-
settings = MagicMock()
20-
settings.group_id = -1001234567890
21-
settings.captcha_timeout_seconds = 300
22-
settings.captcha_timeout_timedelta = timedelta(seconds=300)
23-
return settings
19+
def group_config():
20+
return GroupConfig(
21+
group_id=-1001234567890,
22+
warning_topic_id=0,
23+
captcha_timeout_seconds=300,
24+
)
25+
26+
27+
@pytest.fixture
28+
def mock_registry(group_config):
29+
registry = GroupRegistry()
30+
registry.register(group_config)
31+
return registry
2432

2533

2634
@pytest.fixture
@@ -58,7 +66,7 @@ async def test_handle_captcha_expiration_success(
5866

5967
with patch("bot.services.captcha_recovery.BotInfoCache.get_username") as mock_username:
6068
mock_username.return_value = "testbot"
61-
69+
6270
await handle_captcha_expiration(
6371
bot=mock_bot,
6472
user_id=12345,
@@ -106,7 +114,7 @@ async def test_handle_captcha_expiration_message_edit_fails(
106114

107115
with patch("bot.services.captcha_recovery.BotInfoCache.get_username") as mock_username:
108116
mock_username.return_value = "testbot"
109-
117+
110118
await handle_captcha_expiration(
111119
bot=mock_bot,
112120
user_id=12345,
@@ -122,35 +130,35 @@ async def test_handle_captcha_expiration_message_edit_fails(
122130

123131
class TestRecoverPendingCaptchas:
124132
async def test_recover_pending_captchas_no_records(
125-
self, mock_application, mock_settings, temp_db, caplog
133+
self, mock_application, mock_registry, temp_db, caplog
126134
):
127135
caplog.set_level(logging.INFO)
128-
with patch("bot.services.captcha_recovery.get_settings", return_value=mock_settings):
136+
with patch("bot.services.captcha_recovery.get_group_registry", return_value=mock_registry):
129137
await recover_pending_captchas(mock_application)
130138

131139
assert "No pending captcha verifications to recover" in caplog.text
132140
mock_application.job_queue.run_once.assert_not_called()
133141

134142
async def test_recover_pending_captchas_expired_timeout(
135-
self, mock_application, mock_settings, temp_db, caplog
143+
self, mock_application, mock_registry, temp_db, caplog
136144
):
137145
caplog.set_level(logging.INFO)
138146
db = get_database()
139-
147+
140148
# Create a record that expired 100 seconds ago
141149
old_time = datetime.now(UTC) - timedelta(seconds=400)
142150
record = db.add_pending_captcha(
143151
12345, -1001234567890, -1001234567890, 999, "Test User"
144152
)
145-
153+
146154
# Manually update created_at to simulate old record
147155
with Session(db._engine) as session:
148156
stmt = text("UPDATE pending_validations SET created_at = :created_at WHERE id = :id")
149157
session.execute(stmt, {"created_at": old_time, "id": record.id})
150158
session.commit()
151159

152160
with (
153-
patch("bot.services.captcha_recovery.get_settings", return_value=mock_settings),
161+
patch("bot.services.captcha_recovery.get_group_registry", return_value=mock_registry),
154162
patch("bot.services.captcha_recovery.handle_captcha_expiration") as mock_expire,
155163
):
156164
mock_expire.return_value = AsyncMock()
@@ -171,32 +179,32 @@ async def test_recover_pending_captchas_expired_timeout(
171179
assert "Captcha recovery complete" in caplog.text
172180

173181
async def test_recover_pending_captchas_reschedule_timeout(
174-
self, mock_application, mock_settings, temp_db, caplog
182+
self, mock_application, mock_registry, temp_db, caplog
175183
):
176184
caplog.set_level(logging.INFO)
177185
db = get_database()
178-
186+
179187
# Create a record with 150 seconds remaining (150 seconds ago)
180188
recent_time = datetime.now(UTC) - timedelta(seconds=150)
181189
record = db.add_pending_captcha(
182190
12345, -1001234567890, -1001234567890, 999, "Test User"
183191
)
184-
192+
185193
# Manually update created_at
186194
with Session(db._engine) as session:
187195
stmt = text("UPDATE pending_validations SET created_at = :created_at WHERE id = :id")
188196
session.execute(stmt, {"created_at": recent_time, "id": record.id})
189197
session.commit()
190198

191199
with (
192-
patch("bot.services.captcha_recovery.get_settings", return_value=mock_settings),
200+
patch("bot.services.captcha_recovery.get_group_registry", return_value=mock_registry),
193201
patch("bot.services.captcha_recovery.captcha_timeout_callback") as mock_callback,
194202
):
195203
await recover_pending_captchas(mock_application)
196204

197205
mock_application.job_queue.run_once.assert_called_once()
198206
call_args = mock_application.job_queue.run_once.call_args
199-
207+
200208
assert call_args.args[0] == mock_callback
201209
assert 149 <= call_args.kwargs["when"] <= 151 # Allow 1 second tolerance
202210
assert call_args.kwargs["name"] == "captcha_timeout_-1001234567890_12345"
@@ -211,52 +219,52 @@ async def test_recover_pending_captchas_reschedule_timeout(
211219
assert "remaining:" in caplog.text
212220

213221
async def test_recover_pending_captchas_handles_errors(
214-
self, mock_application, mock_settings, temp_db, caplog
222+
self, mock_application, mock_registry, temp_db, caplog
215223
):
216224
caplog.set_level(logging.INFO)
217225
db = get_database()
218-
226+
219227
# Create a record
220228
record = db.add_pending_captcha(
221229
12345, -1001234567890, -1001234567890, 999, "Test User"
222230
)
223231

224232
with (
225-
patch("bot.services.captcha_recovery.get_settings", return_value=mock_settings),
233+
patch("bot.services.captcha_recovery.get_group_registry", return_value=mock_registry),
226234
patch("bot.services.captcha_recovery.handle_captcha_expiration") as mock_expire,
227235
):
228236
mock_expire.side_effect = Exception("Something went wrong")
229-
237+
230238
# Manually update to make it expired
231239
old_time = datetime.now(UTC) - timedelta(seconds=400)
232240
with Session(db._engine) as session:
233241
stmt = text("UPDATE pending_validations SET created_at = :created_at WHERE id = :id")
234242
session.execute(stmt, {"created_at": old_time, "id": record.id})
235243
session.commit()
236-
244+
237245
await recover_pending_captchas(mock_application)
238246

239247
assert "Failed to recover captcha for user 12345: Something went wrong" in caplog.text
240248
assert "Captcha recovery complete" in caplog.text
241249

242250
async def test_recover_pending_captchas_multiple_records(
243-
self, mock_application, mock_settings, temp_db, caplog
251+
self, mock_application, mock_registry, temp_db, caplog
244252
):
245253
caplog.set_level(logging.INFO)
246254
db = get_database()
247-
255+
248256
# Create expired record
249257
old_time = datetime.now(UTC) - timedelta(seconds=400)
250258
record1 = db.add_pending_captcha(
251259
12345, -1001234567890, -1001234567890, 999, "User One"
252260
)
253-
261+
254262
# Create pending record
255263
recent_time = datetime.now(UTC) - timedelta(seconds=150)
256264
record2 = db.add_pending_captcha(
257265
67890, -1001234567890, -1001234567890, 888, "User Two"
258266
)
259-
267+
260268
# Manually update created_at for both
261269
with Session(db._engine) as session:
262270
stmt = text("UPDATE pending_validations SET created_at = :created_at WHERE id = :id")
@@ -265,7 +273,7 @@ async def test_recover_pending_captchas_multiple_records(
265273
session.commit()
266274

267275
with (
268-
patch("bot.services.captcha_recovery.get_settings", return_value=mock_settings),
276+
patch("bot.services.captcha_recovery.get_group_registry", return_value=mock_registry),
269277
patch("bot.services.captcha_recovery.handle_captcha_expiration") as mock_expire,
270278
patch("bot.services.captcha_recovery.captcha_timeout_callback"),
271279
):
@@ -275,7 +283,7 @@ async def test_recover_pending_captchas_multiple_records(
275283
# Should expire the first one
276284
mock_expire.assert_called_once()
277285
assert mock_expire.call_args.kwargs["user_id"] == 12345
278-
286+
279287
# Should reschedule the second one
280288
mock_application.job_queue.run_once.assert_called_once()
281289
call_args = mock_application.job_queue.run_once.call_args
@@ -285,3 +293,29 @@ async def test_recover_pending_captchas_multiple_records(
285293
assert "Expiring captcha for user 12345" in caplog.text
286294
assert "Rescheduling captcha timeout for user 67890" in caplog.text
287295
assert "Captcha recovery complete" in caplog.text
296+
297+
async def test_recover_pending_captchas_skips_unknown_group(
298+
self, mock_application, mock_registry, temp_db, caplog
299+
):
300+
caplog.set_level(logging.WARNING)
301+
db = get_database()
302+
303+
# Create a captcha record for a group NOT in the registry
304+
unknown_group_id = -1009999999999
305+
old_time = datetime.now(UTC) - timedelta(seconds=400)
306+
record = db.add_pending_captcha(
307+
12345, unknown_group_id, unknown_group_id, 999, "Test User"
308+
)
309+
310+
with Session(db._engine) as session:
311+
stmt = text("UPDATE pending_validations SET created_at = :created_at WHERE id = :id")
312+
session.execute(stmt, {"created_at": old_time, "id": record.id})
313+
session.commit()
314+
315+
with patch("bot.services.captcha_recovery.get_group_registry", return_value=mock_registry):
316+
await recover_pending_captchas(mock_application)
317+
318+
# Should skip - no expiration, no reschedule
319+
mock_application.job_queue.run_once.assert_not_called()
320+
321+
assert "group no longer in registry" in caplog.text

0 commit comments

Comments
 (0)