"""Run with: uv run python -m unittest discover -s tests -v""" import asyncio import json import os from pathlib import Path import tempfile from types import SimpleNamespace import unittest from unittest.mock import Mock, patch os.environ["SDL_VIDEODRIVER"] = "dummy" os.environ["SDL_AUDIODRIVER"] = "dummy" import pygame from src.game import Game from src.highscore import Highscore class WebCompatibilityTests(unittest.TestCase): def test_loop_yields_and_renders_all_screens(self): async def exercise(state): game = Game() game.player_name = "Test Student" game.state = state if state == "endscreen": game.show_endscreen(won=False) yielded = [] asyncio.get_running_loop().call_soon(yielded.append, True) await game.run(max_frames=2) self.assertTrue(yielded, "Game loop must yield to the browser") with patch.object(Highscore, "load_scores", return_value=[]), patch.object(Highscore, "save_scores"): for state in ("startscreen", "game", "endscreen"): asyncio.run(exercise(state)) def test_highscore_storage(self): pygame.font.init() with tempfile.TemporaryDirectory() as directory: path = str(Path(directory) / "scores.json") scores = Highscore(path) self.assertEqual(scores.load_scores(), []) scores.add_score("Desktop", 5, 12, False) self.assertEqual(Highscore(path).load_scores()[0]["name"], "Desktop") storage = {} window = SimpleNamespace(localStorage=SimpleNamespace( getItem=storage.get, setItem=storage.__setitem__, )) with patch("src.highscore.sys.platform", "emscripten"), patch("src.highscore.window", window, create=True): scores.add_score("Browser", 10, 20, False) Path(path).unlink() # Simulate a fresh browser virtual filesystem. self.assertEqual(Highscore(path).get_top_scores()[0]["name"], "Browser") self.assertEqual(len(json.loads(storage[f"silent-fh:{path}"])), 2) storage[f"silent-fh:{path}"] = "invalid json" self.assertEqual(scores.load_scores(), []) scores.save_scores([]) window.localStorage.getItem = Mock(side_effect=RuntimeError("blocked")) window.localStorage.setItem = Mock(side_effect=RuntimeError("blocked")) scores.add_score("Fallback", 1, 1, False) self.assertEqual(scores.load_scores()[0]["name"], "Fallback") pygame.quit() if __name__ == "__main__": unittest.main()