Players get a fast TTL-backed homepage (local profile / Cloudflare D1) with dense UI polish; login unlocks /home without blocking on every OpenDota refresh. Co-authored-by: Cursor <cursoragent@cursor.com>
96 lines
3.0 KiB
Python
96 lines
3.0 KiB
Python
"""Unit tests for player homepage aggregates."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
PC = Path(__file__).resolve().parents[1]
|
|
sys.path.insert(0, str(PC))
|
|
|
|
from player_stats import ( # noqa: E402
|
|
aggregate_from_rows,
|
|
career_from_opendota,
|
|
kda,
|
|
merge_availability,
|
|
should_keep_old_career,
|
|
top_heroes_from_opendota,
|
|
winrate,
|
|
)
|
|
|
|
|
|
class PlayerStatsTests(unittest.TestCase):
|
|
def test_kda_zero_deaths(self):
|
|
self.assertEqual(kda(5, 0, 5), 10.0)
|
|
|
|
def test_winrate_empty(self):
|
|
self.assertIsNone(winrate(0, 0))
|
|
self.assertEqual(winrate(1, 1), 50.0)
|
|
|
|
def test_aggregate_recent(self):
|
|
rows = [
|
|
{"won": True, "kills": 10, "deaths": 2, "assists": 8, "gpm": 500, "hero_id": 1},
|
|
{"won": False, "kills": 0, "deaths": 10, "assists": 2, "gpm": 300, "hero_id": 2},
|
|
]
|
|
out = aggregate_from_rows(rows, limit=20)
|
|
self.assertEqual(out["sample"], 2)
|
|
self.assertEqual(out["wins"], 1)
|
|
self.assertEqual(out["winrate"], 50.0)
|
|
self.assertEqual(out["avg_gpm"], 400)
|
|
|
|
def test_career_empty_private(self):
|
|
self.assertIsNone(career_from_opendota({"win": 0, "lose": 0}, []))
|
|
|
|
def test_career_populated(self):
|
|
career = career_from_opendota(
|
|
{"win": 10, "lose": 10},
|
|
[
|
|
{"field": "kills", "n": 20, "sum": 100},
|
|
{"field": "deaths", "n": 20, "sum": 50},
|
|
{"field": "assists", "n": 20, "sum": 150},
|
|
{"field": "gold_per_min", "n": 20, "sum": 8000},
|
|
],
|
|
)
|
|
self.assertEqual(career["games"], 20)
|
|
self.assertEqual(career["kda"], 5.0)
|
|
self.assertEqual(career["avg_gpm"], 400)
|
|
|
|
def test_keep_old_career_on_empty(self):
|
|
old = {"games": 100, "wins": 50, "losses": 50}
|
|
self.assertEqual(should_keep_old_career(old, None), old)
|
|
new = {"games": 101, "wins": 51, "losses": 50}
|
|
self.assertEqual(should_keep_old_career(old, new), new)
|
|
|
|
def test_top_heroes(self):
|
|
heroes = top_heroes_from_opendota(
|
|
[
|
|
{"hero_id": 1, "games": 5, "win": 3, "last_played": 100},
|
|
{"hero_id": 2, "games": 10, "win": 4, "last_played": 90},
|
|
],
|
|
hero_lookup={1: {"key": "antimage", "name_loc": "敌法"}, 2: {"key": "axe", "name_loc": "斧王"}},
|
|
limit=1,
|
|
)
|
|
self.assertEqual(len(heroes), 1)
|
|
self.assertEqual(heroes[0]["hero_key"], "axe")
|
|
|
|
def test_availability_syncing(self):
|
|
avail = merge_availability(
|
|
opendota_recent_n=0,
|
|
career=None,
|
|
steam_history_status=1,
|
|
fetched_at="t",
|
|
)
|
|
self.assertEqual(avail["status"], "syncing")
|
|
private = merge_availability(
|
|
opendota_recent_n=0,
|
|
career=None,
|
|
steam_history_status=15,
|
|
fetched_at="t",
|
|
)
|
|
self.assertEqual(private["status"], "private")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|