Skip to content

Commit d0286b0

Browse files
committed
test: add tests for karma pattern, per-user rate limits, and team roles
1 parent 8d96128 commit d0286b0

4 files changed

Lines changed: 242 additions & 1 deletion

File tree

tests/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from sqlmodel.ext.asyncio.session import AsyncSession
55

66
from src.backend.db import Database
7-
from src.backend.models import GuildConfig, KarmaTransaction, KarmaWindow, User # noqa: F401 — register tables
7+
from src.backend.models import GuildConfig, KarmaTransaction, KarmaWindow, User, UserTeamRole # noqa: F401 — register tables
88
from src.backend.tables import KarmaTransactionDB, KarmaWindowDB, UserDB
99

1010

tests/test_karma_pattern.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
"""Tests for the karma regex pattern matching."""
2+
3+
from src.cogs.commands.karma import KARMA_PATTERN
4+
5+
6+
def test_matches_user_plus():
7+
matches = KARMA_PATTERN.findall("<@123456> +++")
8+
assert len(matches) == 1
9+
assert matches[0] == ("123456", "+++")
10+
11+
12+
def test_matches_user_minus():
13+
matches = KARMA_PATTERN.findall("<@123456> ---")
14+
assert len(matches) == 1
15+
assert matches[0] == ("123456", "---")
16+
17+
18+
def test_matches_role_plus():
19+
matches = KARMA_PATTERN.findall("<@&999> +++++")
20+
assert len(matches) == 1
21+
assert matches[0] == ("999", "+++++")
22+
23+
24+
def test_matches_role_minus():
25+
matches = KARMA_PATTERN.findall("<@&999> -----")
26+
assert len(matches) == 1
27+
assert matches[0] == ("999", "-----")
28+
29+
30+
def test_matches_nickname_format():
31+
matches = KARMA_PATTERN.findall("<@!123456> ++")
32+
assert len(matches) == 1
33+
assert matches[0] == ("123456", "++")
34+
35+
36+
def test_no_match_single_plus():
37+
matches = KARMA_PATTERN.findall("<@123456> +")
38+
assert len(matches) == 0
39+
40+
41+
def test_no_match_single_minus():
42+
matches = KARMA_PATTERN.findall("<@123456> -")
43+
assert len(matches) == 0
44+
45+
46+
def test_multiple_mentions():
47+
matches = KARMA_PATTERN.findall("<@111> ++ <@222> +++")
48+
assert len(matches) == 2
49+
assert matches[0] == ("111", "++")
50+
assert matches[1] == ("222", "+++")
51+
52+
53+
def test_mixed_plus_minus():
54+
matches = KARMA_PATTERN.findall("<@111> +++ <@222> ---")
55+
assert len(matches) == 2
56+
assert matches[0] == ("111", "+++")
57+
assert matches[1] == ("222", "---")
58+
59+
60+
def test_no_match_plain_text():
61+
matches = KARMA_PATTERN.findall("hello world")
62+
assert len(matches) == 0

tests/test_karma_rate_limits.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
"""Tests for per-user karma rate limit queries."""
2+
3+
from datetime import datetime, timedelta, timezone
4+
5+
from src.backend.models import User
6+
from src.backend.tables import KarmaTransactionDB, UserDB
7+
8+
9+
async def _seed_users(user_db: UserDB):
10+
await user_db.upsert(User(user_id=1))
11+
await user_db.upsert(User(user_id=2))
12+
await user_db.upsert(User(user_id=3))
13+
14+
15+
async def test_karma_given_to_user_since(
16+
karma_transaction_db: KarmaTransactionDB, user_db: UserDB
17+
):
18+
await _seed_users(user_db)
19+
await karma_transaction_db.log(recipient_id=2, performed_by=1, amount=3)
20+
await karma_transaction_db.log(recipient_id=2, performed_by=1, amount=2)
21+
await karma_transaction_db.log(recipient_id=3, performed_by=1, amount=10)
22+
23+
since = datetime.now(timezone.utc) - timedelta(hours=1)
24+
total = await karma_transaction_db.karma_given_to_user_since(1, 2, since)
25+
assert total == 5
26+
27+
28+
async def test_karma_given_to_user_since_zero(
29+
karma_transaction_db: KarmaTransactionDB,
30+
):
31+
since = datetime.now(timezone.utc) - timedelta(hours=1)
32+
total = await karma_transaction_db.karma_given_to_user_since(1, 2, since)
33+
assert total == 0
34+
35+
36+
async def test_oldest_transaction_to_user(
37+
karma_transaction_db: KarmaTransactionDB, user_db: UserDB
38+
):
39+
await _seed_users(user_db)
40+
await karma_transaction_db.log(recipient_id=2, performed_by=1, amount=3)
41+
await karma_transaction_db.log(recipient_id=2, performed_by=1, amount=2)
42+
43+
since = datetime.now(timezone.utc) - timedelta(hours=1)
44+
oldest = await karma_transaction_db.oldest_transaction_to_user_since(1, 2, since)
45+
assert oldest is not None
46+
47+
48+
async def test_oldest_transaction_to_user_none(
49+
karma_transaction_db: KarmaTransactionDB,
50+
):
51+
since = datetime.now(timezone.utc) - timedelta(hours=1)
52+
oldest = await karma_transaction_db.oldest_transaction_to_user_since(1, 999, since)
53+
assert oldest is None
54+
55+
56+
async def test_negative_karma_tracked(
57+
karma_transaction_db: KarmaTransactionDB, user_db: UserDB
58+
):
59+
"""Negative karma transactions reduce the total given."""
60+
await _seed_users(user_db)
61+
await karma_transaction_db.log(recipient_id=2, performed_by=1, amount=3)
62+
await karma_transaction_db.log(recipient_id=2, performed_by=1, amount=-2)
63+
64+
since = datetime.now(timezone.utc) - timedelta(hours=1)
65+
total = await karma_transaction_db.karma_given_to_user_since(1, 2, since)
66+
assert total == 1
67+
68+
69+
async def test_negative_karma_global(
70+
karma_transaction_db: KarmaTransactionDB, user_db: UserDB
71+
):
72+
"""Global sum accounts for negative transactions."""
73+
await _seed_users(user_db)
74+
await karma_transaction_db.log(recipient_id=2, performed_by=1, amount=5)
75+
await karma_transaction_db.log(recipient_id=3, performed_by=1, amount=-3)
76+
77+
since = datetime.now(timezone.utc) - timedelta(hours=1)
78+
total = await karma_transaction_db.karma_given_since(1, since)
79+
assert total == 2

tests/test_user_team_role_db.py

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
"""Tests for UserTeamRoleDB."""
2+
3+
from datetime import datetime, timezone
4+
5+
from src.backend.models import KarmaWindow, User
6+
from src.backend.tables.db_user_team_role import UserTeamRoleDB
7+
from src.backend.tables import UserDB, KarmaWindowDB
8+
9+
10+
FIXED_WINDOW = datetime(2026, 1, 1, tzinfo=timezone.utc)
11+
12+
13+
async def test_sync_member_roles(test_db):
14+
db = UserTeamRoleDB(db=test_db)
15+
await db.sync_member_roles(guild_id=1, user_id=100, current_team_role_ids=[10, 20])
16+
17+
r1 = await db.get(1, 100, 10)
18+
r2 = await db.get(1, 100, 20)
19+
assert r1 is not None
20+
assert r2 is not None
21+
22+
23+
async def test_sync_replaces_old_roles(test_db):
24+
db = UserTeamRoleDB(db=test_db)
25+
await db.sync_member_roles(guild_id=1, user_id=100, current_team_role_ids=[10, 20])
26+
await db.sync_member_roles(guild_id=1, user_id=100, current_team_role_ids=[30])
27+
28+
assert await db.get(1, 100, 10) is None
29+
assert await db.get(1, 100, 20) is None
30+
assert await db.get(1, 100, 30) is not None
31+
32+
33+
async def test_sync_empty_clears_all(test_db):
34+
db = UserTeamRoleDB(db=test_db)
35+
await db.sync_member_roles(guild_id=1, user_id=100, current_team_role_ids=[10])
36+
await db.sync_member_roles(guild_id=1, user_id=100, current_team_role_ids=[])
37+
38+
assert await db.get(1, 100, 10) is None
39+
40+
41+
async def test_get_team_karma(test_db):
42+
user_db = UserDB(db=test_db)
43+
team_db = UserTeamRoleDB(db=test_db)
44+
window_db = KarmaWindowDB(db=test_db)
45+
46+
# Create users and windows
47+
await user_db.upsert(User(user_id=100))
48+
await user_db.upsert(User(user_id=200))
49+
await window_db.upsert(KarmaWindow(user_id=100, karma=10, karma_start_dt=FIXED_WINDOW))
50+
await window_db.upsert(KarmaWindow(user_id=200, karma=20, karma_start_dt=FIXED_WINDOW))
51+
52+
# Assign team roles
53+
await team_db.sync_member_roles(guild_id=1, user_id=100, current_team_role_ids=[50])
54+
await team_db.sync_member_roles(guild_id=1, user_id=200, current_team_role_ids=[50])
55+
56+
results = await team_db.get_team_karma(guild_id=1, window_start=FIXED_WINDOW)
57+
assert len(results) == 1
58+
role_id, total = results[0]
59+
assert role_id == 50
60+
assert total == 30
61+
62+
63+
async def test_get_team_karma_multiple_teams(test_db):
64+
user_db = UserDB(db=test_db)
65+
team_db = UserTeamRoleDB(db=test_db)
66+
window_db = KarmaWindowDB(db=test_db)
67+
68+
await user_db.upsert(User(user_id=100))
69+
await window_db.upsert(KarmaWindow(user_id=100, karma=10, karma_start_dt=FIXED_WINDOW))
70+
71+
# User in two teams — their karma counts for both
72+
await team_db.sync_member_roles(guild_id=1, user_id=100, current_team_role_ids=[50, 60])
73+
74+
results = await team_db.get_team_karma(guild_id=1, window_start=FIXED_WINDOW)
75+
assert len(results) == 2
76+
totals = {role_id: total for role_id, total in results}
77+
assert totals[50] == 10
78+
assert totals[60] == 10
79+
80+
81+
async def test_get_team_karma_empty(test_db):
82+
team_db = UserTeamRoleDB(db=test_db)
83+
results = await team_db.get_team_karma(guild_id=1, window_start=FIXED_WINDOW)
84+
assert results == []
85+
86+
87+
async def test_get_team_karma_scoped_by_guild(test_db):
88+
user_db = UserDB(db=test_db)
89+
team_db = UserTeamRoleDB(db=test_db)
90+
window_db = KarmaWindowDB(db=test_db)
91+
92+
await user_db.upsert(User(user_id=100))
93+
await window_db.upsert(KarmaWindow(user_id=100, karma=10, karma_start_dt=FIXED_WINDOW))
94+
95+
# Assign to team in guild 1 only
96+
await team_db.sync_member_roles(guild_id=1, user_id=100, current_team_role_ids=[50])
97+
98+
# Query guild 2 should return nothing
99+
results = await team_db.get_team_karma(guild_id=2, window_start=FIXED_WINDOW)
100+
assert results == []

0 commit comments

Comments
 (0)