From 049699fc6c3423fea30fda8c07024925bbf2af0c Mon Sep 17 00:00:00 2001 From: Daniel McCoy Stephenson Date: Sat, 13 Jun 2026 14:40:46 -0600 Subject: [PATCH] Test the pygame UI input primitives via injected events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit showDialogue, timedKeyPress, and promptForText drive pygame event loops and had no coverage — only the resize/font helpers were tested. A regression in their key handling (e.g. backspace or Enter-to-submit) would go unnoticed. Adds tests that inject events through a patched pygame.event.get (with the per-frame flip/clock stubbed): a keypress dismisses showDialogue and resets the prompt, timedKeyPress returns a non-negative reaction, and promptForText accumulates typed characters and honors backspace before Enter submits. Co-Authored-By: Claude Sonnet 4.6 --- tests/ui/test_pygameUserInterface.py | 75 ++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/tests/ui/test_pygameUserInterface.py b/tests/ui/test_pygameUserInterface.py index a59adfa..1db615c 100644 --- a/tests/ui/test_pygameUserInterface.py +++ b/tests/ui/test_pygameUserInterface.py @@ -54,3 +54,78 @@ def test_update_fonts_keeps_fonts_usable_when_tiny(): assert surface.get_width() > 0 and surface.get_height() > 0 finally: ui.cleanup() + + +# --- interactive input primitives (events injected via patched pygame.event.get) --- +import contextlib # noqa: E402 +from types import SimpleNamespace # noqa: E402 +from unittest.mock import patch # noqa: E402 + +import pygame # noqa: E402 + + +def keydown(key=0, unicode=""): + return SimpleNamespace(type=pygame.KEYDOWN, key=key, unicode=unicode) + + +@contextlib.contextmanager +def injected_events(events): + # Feed the given events to the UI's event loop and stub out the per-frame + # display flip / clock so the loop runs without a real frame delay. + with patch("ui.pygameUserInterface.pygame.event.get", return_value=events), patch( + "ui.pygameUserInterface.pygame.display.flip" + ), patch("ui.pygameUserInterface.pygame.time.Clock"): + yield + + +def test_showDialogue_returns_on_keypress(): + ui = makeUI() + try: + ui.currentPrompt.text = "before" + with injected_events([keydown()]): + ui.showDialogue("some text") + assert ui.currentPrompt.text == "What would you like to do?" + finally: + ui.cleanup() + + +def test_timedKeyPress_returns_nonnegative_seconds(): + ui = makeUI() + try: + with injected_events([keydown()]): + reaction = ui.timedKeyPress("React!") + assert isinstance(reaction, float) + assert reaction >= 0.0 + finally: + ui.cleanup() + + +def test_promptForText_collects_typed_characters(): + ui = makeUI() + try: + events = [ + keydown(unicode="h"), + keydown(unicode="i"), + keydown(key=pygame.K_RETURN), + ] + with injected_events(events): + result = ui.promptForText("Name?") + assert result == "hi" + finally: + ui.cleanup() + + +def test_promptForText_handles_backspace(): + ui = makeUI() + try: + events = [ + keydown(unicode="a"), + keydown(unicode="b"), + keydown(key=pygame.K_BACKSPACE), + keydown(key=pygame.K_RETURN), + ] + with injected_events(events): + result = ui.promptForText("Name?") + assert result == "a" + finally: + ui.cleanup()