"""Tests for the evolution status command helpers (WP-11). Unit tests for progress bar rendering, entry formatting, tier display names, close-to-tierup filtering, and edge cases. No Discord bot or API calls required — these test pure functions only. """ import pytest from cogs.players_new.evolution import ( render_progress_bar, format_evo_entry, is_close_to_tierup, TIER_NAMES, FORMULA_SHORTHANDS, ) # --------------------------------------------------------------------------- # render_progress_bar # --------------------------------------------------------------------------- class TestRenderProgressBar: def test_80_percent_filled(self): """120/149 should be ~80% filled (8 of 10 chars).""" result = render_progress_bar(120, 149, width=10) assert "[========--]" in result assert "120/149" in result def test_zero_progress(self): """0/37 should be empty bar.""" result = render_progress_bar(0, 37, width=10) assert "[----------]" in result assert "0/37" in result def test_full_progress_not_evolved(self): """Value at threshold shows full bar.""" result = render_progress_bar(149, 149, width=10) assert "[==========]" in result assert "149/149" in result def test_fully_evolved(self): """next_threshold=None means fully evolved.""" result = render_progress_bar(900, None, width=10) assert "FULLY EVOLVED" in result assert "[==========]" in result def test_over_threshold_capped(self): """Value exceeding threshold still caps at 100%.""" result = render_progress_bar(200, 149, width=10) assert "[==========]" in result # --------------------------------------------------------------------------- # format_evo_entry # --------------------------------------------------------------------------- class TestFormatEvoEntry: def test_batter_t1_to_t2(self): """Batter at T1 progressing toward T2.""" state = { "current_tier": 1, "current_value": 120.0, "next_threshold": 149, "fully_evolved": False, "track": {"card_type": "batter"}, } result = format_evo_entry(state) assert "(PA+TB×2)" in result assert "Initiate → Rising" in result def test_pitcher_sp(self): """SP track shows IP+K formula.""" state = { "current_tier": 0, "current_value": 5.0, "next_threshold": 10, "fully_evolved": False, "track": {"card_type": "sp"}, } result = format_evo_entry(state) assert "(IP+K)" in result assert "Unranked → Initiate" in result def test_fully_evolved_entry(self): """Fully evolved card shows T4 — Evolved.""" state = { "current_tier": 4, "current_value": 900.0, "next_threshold": None, "fully_evolved": True, "track": {"card_type": "batter"}, } result = format_evo_entry(state) assert "FULLY EVOLVED" in result assert "Evolved" in result # --------------------------------------------------------------------------- # is_close_to_tierup # --------------------------------------------------------------------------- class TestIsCloseToTierup: def test_at_80_percent(self): """Exactly 80% of threshold counts as close.""" state = {"current_value": 119.2, "next_threshold": 149} assert is_close_to_tierup(state, threshold_pct=0.80) def test_below_80_percent(self): """Below 80% is not close.""" state = {"current_value": 100, "next_threshold": 149} assert not is_close_to_tierup(state, threshold_pct=0.80) def test_fully_evolved_not_close(self): """Fully evolved (no next threshold) is not close.""" state = {"current_value": 900, "next_threshold": None} assert not is_close_to_tierup(state) def test_zero_threshold(self): """Zero threshold edge case returns False.""" state = {"current_value": 0, "next_threshold": 0} assert not is_close_to_tierup(state) # --------------------------------------------------------------------------- # Tier names and formula shorthands # --------------------------------------------------------------------------- class TestConstants: def test_all_tier_names_present(self): """All 5 tiers (0-4) have display names.""" assert len(TIER_NAMES) == 5 for i in range(5): assert i in TIER_NAMES def test_tier_name_values(self): assert TIER_NAMES[0] == "Unranked" assert TIER_NAMES[1] == "Initiate" assert TIER_NAMES[2] == "Rising" assert TIER_NAMES[3] == "Ascendant" assert TIER_NAMES[4] == "Evolved" def test_formula_shorthands(self): assert FORMULA_SHORTHANDS["batter"] == "PA+TB×2" assert FORMULA_SHORTHANDS["sp"] == "IP+K" assert FORMULA_SHORTHANDS["rp"] == "IP+K" # --------------------------------------------------------------------------- # Empty / edge cases # --------------------------------------------------------------------------- class TestEdgeCases: def test_missing_track_defaults(self): """State with missing track info still formats without error.""" state = { "current_tier": 0, "current_value": 0, "next_threshold": 37, "fully_evolved": False, "track": {}, } result = format_evo_entry(state) assert isinstance(result, str) def test_state_with_no_keys(self): """Completely empty state dict doesn't crash.""" state = {} result = format_evo_entry(state) assert isinstance(result, str)