Add 7.41e patch notes with a hand-authored reading sidebar.

Ship Climperor Web 0.6.13: latest-patch summary panel, icon/innate fallbacks, and layout/scroll fixes; keep shared ability badges in git.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
voson
2026-07-31 10:06:09 +08:00
co-authored by Cursor
parent a257f96d94
commit 30218790ce
18 changed files with 2169 additions and 63 deletions
+42
View File
@@ -144,6 +144,48 @@ class RefreshDigestTests(unittest.TestCase):
skip_deploy=True,
)
def test_opendota_probe_failure_skips_opendota_daily_fetches(self) -> None:
calls: list[str] = []
def fake_run_script(script: str, *args: str, dry_run: bool = False, soft_fail: bool = False):
calls.append(script)
return True
with (
patch.object(refresh_web, "probe_opendota_available", return_value=False),
patch.object(refresh_web, "run_script", side_effect=fake_run_script),
patch.object(
refresh_web,
"patch_check",
return_value={"has_new": False, "new_versions": []},
),
):
self.assertFalse(refresh_web.run_daily(dry_run=False))
self.assertNotIn("fetch_hero_stats.py", calls)
self.assertNotIn("fetch_hero_matches.py", calls)
self.assertNotIn("fetch_pro_matches.py", calls)
self.assertIn("fetch_leaderboards.py", calls)
self.assertIn("fetch_streamers.py", calls)
def test_critical_empty_by_hero_refuses_deploy(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
data = Path(tmp)
paths = [
data / "hero_stats.json",
data / "stratz_hero_meta.json",
data / "stratz_matchup_tops.json",
]
write_json_atomic(paths[0], {"by_hero": {"axe": {"pick": 1}}})
write_json_atomic(paths[1], {"by_hero": {}})
write_json_atomic(paths[2], {"by_hero": {"axe": {}}})
with patch.object(refresh_web, "CRITICAL_BY_HERO_FILES", tuple(paths)):
with self.assertRaises(RuntimeError) as ctx:
refresh_web.assert_critical_data_ready()
self.assertIn("stratz_hero_meta.json", str(ctx.exception))
write_json_atomic(paths[1], {"by_hero": {"axe": {}}})
with patch.object(refresh_web, "CRITICAL_BY_HERO_FILES", tuple(paths)):
refresh_web.assert_critical_data_ready()
def test_dry_run_skips_cache_restore_and_summary_write(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
summary_path = Path(tmp) / "summary.json"