Files
tipibot/tests/test_leaderboards.py
Rene Arumetsa eb7346b851 fix(economy): handle db_error in commands, dedupe cooldowns, single leaderboard scan
Three robustness/perf fixes from the review:

1. db_error UX: economy core returns {"ok": False, "reason": "db_error"} on a
   PocketBase outage, but no handler expected it - deferred commands hung on
   "thinking..." and others showed a misleading "you're broke". Added a shared
   reply_db_error helper (commands/_replies.py) + S.ERR["db_error"], and wired a
   db_error branch into every handler that can receive it (daily/work/beg/crime/
   rob/give/buy/roulette/slots/blackjack/heist/fish/prestige/vanity/consumables/
   request-funding). Also fixed a latent KeyError in vs-bot RPS that read
   res["balance"] without checking res["ok"].

2. Deduped the item->cooldown mapping that was copied in do_daily/do_work/do_beg,
   do_fish_start, _maybe_remind and _restore_reminders. Single source of truth:
   store.ITEM_COOLDOWNS + effective_cooldown(cmd, items).

3. /leaderboard did six full-collection scans (one per tab). Added
   get_all_leaderboards() which scans once and builds all six views in memory.

Tests: effective_cooldown cases, and get_all_leaderboards matches the individual
queries + scans the collection exactly once.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013VbAVsrZuYesea99mPMmPT
2026-09-04 02:26:07 +03:00

50 lines
1.8 KiB
Python

"""Tests for leaderboard queries, incl. the single-scan combined builder."""
from core import economy, pb_client
from conftest import run
def _seed(fake_pb, n: int) -> None:
for i in range(1, n + 1):
run(economy.get_user(1000 + i))
rec = fake_pb.record_for(1000 + i)
rec["balance"] = i * 100
rec["exp"] = i * 50
rec["season_total_exp"] = i * 10
rec["prestige_level"] = i % 3
rec["prestige_points"] = i
rec["total_wagered"] = i * 7
rec["total_fish_caught"] = n - i # inverse order, to catch sort mistakes
class TestGetAllLeaderboards:
def test_matches_individual_queries(self, fake_pb):
_seed(fake_pb, 5)
combined = run(economy.get_all_leaderboards())
assert combined["coins"] == run(economy.get_leaderboard(top_n=None))
assert combined["exp"] == run(economy.get_leaderboard_exp(top_n=None))
assert combined["season"] == run(economy.get_leaderboard_season_exp(top_n=None))
assert combined["prestige"] == run(economy.get_leaderboard_prestige(top_n=None))
assert combined["wagered"] == run(economy.get_leaderboard_wagered(top_n=None))
assert combined["fish"] == run(economy.get_leaderboard_fish(top_n=None))
def test_scans_collection_once(self, fake_pb, monkeypatch):
_seed(fake_pb, 3)
calls = {"n": 0}
real = pb_client.list_all_records
async def counting():
calls["n"] += 1
return await real()
monkeypatch.setattr(pb_client, "list_all_records", counting)
run(economy.get_all_leaderboards())
assert calls["n"] == 1 # not six
def test_fish_sorted_descending(self, fake_pb):
_seed(fake_pb, 4)
fish = run(economy.get_all_leaderboards())["fish"]
counts = [c for _, c in fish]
assert counts == sorted(counts, reverse=True)