"""Conversation scrollback + push-to-talk hotkey parsing.""" import sys from pathlib import Path import pytest sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) from bolt_pet import history as history_mod from bolt_pet.hotkey import GlobalHotkey, HotkeyError, to_pynput_spec # ── history ───────────────────────────────────────────────────────────────── def test_keeps_entries_in_order(): log = history_mod.ConversationHistory(limit=10) log.add(history_mod.USER, "what's the weather") log.add(history_mod.PET, "sunny and 72") assert [e.text for e in log.entries()] == ["what's the weather", "sunny and 72"] def test_drops_the_oldest_past_the_limit(): log = history_mod.ConversationHistory(limit=2) for i in range(5): log.add(history_mod.PET, f"line {i}") assert [e.text for e in log.entries()] == ["line 3", "line 4"] def test_blank_entries_are_ignored(): log = history_mod.ConversationHistory() assert log.add(history_mod.PET, " ") is None assert len(log) == 0 def test_last_can_filter_by_role(): log = history_mod.ConversationHistory() log.add(history_mod.USER, "hello") log.add(history_mod.PET, "hi there") log.add(history_mod.USER, "still there?") assert log.last().text == "still there?" assert log.last(history_mod.PET).text == "hi there" def test_as_text_is_copyable_transcript(): log = history_mod.ConversationHistory() log.add(history_mod.USER, "ping") log.add(history_mod.PET, "pong") assert log.as_text() == "You: ping\nBolt: pong" def test_timestamps_are_rendered_when_present(): log = history_mod.ConversationHistory() log.add(history_mod.PET, "pong", timestamp=1710000000.0) assert log.as_text(clock=lambda t: "12:00:00") == "[12:00:00] Bolt: pong" def test_clear_empties_the_log(): log = history_mod.ConversationHistory() log.add(history_mod.PET, "pong") log.clear() assert len(log) == 0 # ── hotkey ────────────────────────────────────────────────────────────────── def test_translates_a_readable_spec_to_pynput_syntax(): assert to_pynput_spec("ctrl+alt+space") == "++" assert to_pynput_spec("ctrl+shift+b") == "++b" def test_accepts_the_names_people_actually_type(): assert to_pynput_spec("Control+Option+Space") == "++" assert to_pynput_spec("super+k") == "+k" def test_empty_spec_is_an_error_at_parse_time(): with pytest.raises(HotkeyError): to_pynput_spec("") def test_disabled_hotkey_starts_cleanly_and_reports_nothing(): hotkey = GlobalHotkey("", lambda: None) assert hotkey.start() is None assert hotkey.running is False def test_invalid_hotkey_reports_instead_of_raising(): hotkey = GlobalHotkey("+++", lambda: None) problem = hotkey.start() assert problem and "invalid" in problem assert hotkey.running is False