Speech history added, bound to fenrir+control+h.
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
from unittest.mock import Mock
|
||||
|
||||
import pytest
|
||||
|
||||
from fenrirscreenreader.core.eventData import FenrirEventType
|
||||
from fenrirscreenreader.core.fenrirManager import FenrirManager
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_speech_history_plain_key_modal_command_is_dispatched():
|
||||
manager = FenrirManager.__new__(FenrirManager)
|
||||
manager.modifierInput = False
|
||||
manager.singleKeyCommand = False
|
||||
manager.command = ""
|
||||
|
||||
event_manager = Mock(put_to_event_queue=Mock())
|
||||
input_manager = Mock(
|
||||
is_key_press=Mock(return_value=False),
|
||||
no_key_pressed=Mock(return_value=False),
|
||||
get_curr_shortcut=Mock(return_value=str([1, ["KEY_UP"]])),
|
||||
get_command_for_shortcut=Mock(return_value="SPEECH_HISTORY_PREV"),
|
||||
)
|
||||
speech_history_manager = Mock(is_active=Mock(return_value=True))
|
||||
diff_review_manager = Mock(is_active=Mock(return_value=False))
|
||||
|
||||
manager.environment = {
|
||||
"input": {
|
||||
"key_forward": 0,
|
||||
"prev_input": ["KEY_UP"],
|
||||
"curr_input": ["KEY_UP"],
|
||||
},
|
||||
"runtime": {
|
||||
"InputManager": input_manager,
|
||||
"EventManager": event_manager,
|
||||
"DiffReviewManager": diff_review_manager,
|
||||
"SpeechHistoryManager": speech_history_manager,
|
||||
},
|
||||
}
|
||||
|
||||
manager.detect_shortcut_command()
|
||||
|
||||
event_manager.put_to_event_queue.assert_called_once_with(
|
||||
FenrirEventType.execute_command, "SPEECH_HISTORY_PREV"
|
||||
)
|
||||
@@ -164,6 +164,43 @@ def test_speak_text_drops_speech_when_cancel_holds_driver_lock():
|
||||
speech_driver.speak.assert_not_called()
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_present_text_records_speech_history_when_enabled():
|
||||
output_manager, _sound_driver, speech_driver = build_output_manager()
|
||||
speech_history_manager = Mock(add_text=Mock())
|
||||
output_manager.env["runtime"]["SpeechHistoryManager"] = (
|
||||
speech_history_manager
|
||||
)
|
||||
|
||||
output_manager.present_text("hello history", interrupt=False)
|
||||
|
||||
speech_history_manager.add_text.assert_called_once_with("hello history")
|
||||
speech_driver.speak.assert_called_once()
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_present_text_does_not_record_when_speech_disabled():
|
||||
output_manager, _sound_driver, speech_driver = build_output_manager()
|
||||
speech_history_manager = Mock(add_text=Mock())
|
||||
output_manager.env["runtime"]["SpeechHistoryManager"] = (
|
||||
speech_history_manager
|
||||
)
|
||||
|
||||
def _get_setting_as_bool(section, setting):
|
||||
if (section, setting) == ("speech", "enabled"):
|
||||
return False
|
||||
return True
|
||||
|
||||
output_manager.env["runtime"][
|
||||
"SettingsManager"
|
||||
].get_setting_as_bool.side_effect = _get_setting_as_bool
|
||||
|
||||
output_manager.present_text("hello history", interrupt=False)
|
||||
|
||||
speech_history_manager.add_text.assert_not_called()
|
||||
speech_driver.speak.assert_not_called()
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_key_interrupt_command_uses_nonblocking_interrupt():
|
||||
module = load_key_interrupt_module()
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
from unittest.mock import Mock
|
||||
|
||||
import pytest
|
||||
|
||||
from fenrirscreenreader.core.speechHistoryManager import SpeechHistoryManager
|
||||
|
||||
|
||||
def build_speech_history_manager(history_size=3):
|
||||
spoken_messages = []
|
||||
output_manager = Mock()
|
||||
|
||||
def _capture_message(message, **_kwargs):
|
||||
spoken_messages.append(message)
|
||||
|
||||
output_manager.present_text.side_effect = _capture_message
|
||||
settings_manager = Mock()
|
||||
settings_manager.get_setting_as_int.return_value = history_size
|
||||
memory_manager = Mock(add_value_to_first_index=Mock())
|
||||
env = {
|
||||
"runtime": {
|
||||
"OutputManager": output_manager,
|
||||
"SettingsManager": settings_manager,
|
||||
"MemoryManager": memory_manager,
|
||||
},
|
||||
"bindings": {"original": "COMMAND"},
|
||||
"rawBindings": {"original": [1, ["KEY_FENRIR"]]},
|
||||
}
|
||||
manager = SpeechHistoryManager()
|
||||
manager.initialize(env)
|
||||
return manager, env, spoken_messages, memory_manager
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_speech_history_keeps_configured_number_of_items():
|
||||
manager, _env, _spoken_messages, _memory_manager = (
|
||||
build_speech_history_manager(history_size=2)
|
||||
)
|
||||
|
||||
assert manager.add_text("one")
|
||||
assert manager.add_text("two")
|
||||
assert manager.add_text("three")
|
||||
|
||||
assert manager.history == ["three", "two"]
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_speech_history_suppresses_exact_duplicates_until_item_drops():
|
||||
manager, _env, _spoken_messages, _memory_manager = (
|
||||
build_speech_history_manager(history_size=2)
|
||||
)
|
||||
|
||||
assert manager.add_text("hello world")
|
||||
assert not manager.add_text("hello world")
|
||||
assert manager.add_text("other")
|
||||
assert manager.add_text("third")
|
||||
assert manager.add_text("hello world")
|
||||
|
||||
assert manager.history == ["hello world", "third"]
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_speech_history_dedupe_keeps_case_and_suppresses_whitespace_variants():
|
||||
manager, _env, _spoken_messages, _memory_manager = (
|
||||
build_speech_history_manager()
|
||||
)
|
||||
|
||||
assert manager.add_text("hello")
|
||||
assert manager.add_text("Hello")
|
||||
assert not manager.add_text("hello ")
|
||||
assert not manager.add_text("hello ")
|
||||
|
||||
assert manager.history == ["Hello", "hello"]
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_open_empty_history_announces_empty_without_modal_bindings():
|
||||
manager, env, spoken_messages, _memory_manager = (
|
||||
build_speech_history_manager()
|
||||
)
|
||||
|
||||
assert not manager.open_history()
|
||||
|
||||
assert not manager.is_active()
|
||||
assert spoken_messages == ["speech history empty"]
|
||||
assert env["bindings"] == {"original": "COMMAND"}
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_open_history_installs_modal_bindings_and_replay_is_not_recorded():
|
||||
manager, env, spoken_messages, _memory_manager = (
|
||||
build_speech_history_manager()
|
||||
)
|
||||
manager.add_text("first")
|
||||
manager.add_text("second")
|
||||
|
||||
assert manager.open_history()
|
||||
manager.add_text("replayed")
|
||||
|
||||
assert manager.is_active()
|
||||
assert spoken_messages == ["Speech history"]
|
||||
assert manager.curr_index == -1
|
||||
assert manager.history == ["second", "first"]
|
||||
assert "original" not in env["bindings"]
|
||||
assert "original" not in env["rawBindings"]
|
||||
assert env["bindings"][str([1, ["KEY_UP"]])] == "SPEECH_HISTORY_PREV"
|
||||
assert env["bindings"][str([1, ["KEY_ENTER"]])] == "SPEECH_HISTORY_COPY"
|
||||
assert env["bindings"][str([1, ["KEY_ESC"]])] == "SPEECH_HISTORY_CLOSE"
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_navigation_moves_between_newer_and_older_items():
|
||||
manager, _env, spoken_messages, _memory_manager = (
|
||||
build_speech_history_manager()
|
||||
)
|
||||
manager.add_text("oldest")
|
||||
manager.add_text("middle")
|
||||
manager.add_text("newest")
|
||||
manager.open_history()
|
||||
|
||||
manager.prev_entry()
|
||||
manager.prev_entry()
|
||||
manager.prev_entry()
|
||||
manager.next_entry()
|
||||
|
||||
assert spoken_messages[-4:] == ["newest", "middle", "oldest", "middle"]
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_copy_current_adds_clipboard_and_restores_bindings():
|
||||
manager, env, spoken_messages, memory_manager = (
|
||||
build_speech_history_manager()
|
||||
)
|
||||
manager.add_text("first")
|
||||
manager.add_text("second")
|
||||
manager.open_history()
|
||||
manager.prev_entry()
|
||||
manager.prev_entry()
|
||||
|
||||
manager.copy_current_to_clipboard()
|
||||
|
||||
memory_manager.add_value_to_first_index.assert_called_once_with(
|
||||
"clipboardHistory", "first"
|
||||
)
|
||||
assert spoken_messages[-1] == "copied to clipboard"
|
||||
assert not manager.is_active()
|
||||
assert env["bindings"] == {"original": "COMMAND"}
|
||||
assert env["rawBindings"] == {"original": [1, ["KEY_FENRIR"]]}
|
||||
Reference in New Issue
Block a user