import importlib.util from pathlib import Path from unittest.mock import Mock import pytest def _load_command(): module_path = ( Path(__file__).resolve().parents[2] / "src" / "fenrirscreenreader" / "commands" / "onCursorChange" / "65000-present_line_if_cursor_change_vertical.py" ) spec = importlib.util.spec_from_file_location( "fenrir_present_line_if_cursor_change_vertical", module_path ) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) return module.command() def _build_environment(screen_name): settings_manager = Mock() settings_manager.get_setting_as_bool.side_effect = ( lambda section, setting: section == "focus" and setting == "cursor" ) output_manager = Mock() return { "commandsIgnore": {"onScreenUpdate": {"INCOMING_IGNORE": False}}, "screen": { "newTTY": screen_name, "new_cursor": {"x": 0, "y": 1}, "new_content_text": "first line\nsecond line", }, "runtime": { "BarrierManager": Mock(), "CursorManager": Mock(is_cursor_vertical_move=Mock(return_value=True)), "OutputManager": output_manager, "ScreenManager": Mock( is_screen_change=Mock(return_value=False), is_delta=Mock(return_value=True), ), "SettingsManager": settings_manager, }, } @pytest.mark.unit def test_pty_vertical_cursor_move_speaks_line_despite_repaint_delta(): command = _load_command() env = _build_environment("pty") command.initialize(env) command.run() env["runtime"]["OutputManager"].present_text.assert_called_once_with( "second line", interrupt=True, flush=False ) assert env["commandsIgnore"]["onScreenUpdate"]["INCOMING_IGNORE"] is True @pytest.mark.unit def test_non_pty_vertical_cursor_move_still_suppresses_delta(): command = _load_command() env = _build_environment("1") command.initialize(env) command.run() env["runtime"]["OutputManager"].present_text.assert_not_called() assert env["commandsIgnore"]["onScreenUpdate"]["INCOMING_IGNORE"] is False @pytest.mark.unit def test_pty_dialog_button_row_speaks_nearby_question(): command = _load_command() env = _build_environment("pty") env["screen"]["new_cursor"] = {"x": 30, "y": 4} env["screen"]["new_content_text"] = "\n".join( [ "".ljust(80), "".ljust(80), "Do you want to save changes?".center(80), "".ljust(80), "< Yes > < No >".center(80), "".ljust(80), ] ) command.initialize(env) command.run() env["runtime"]["OutputManager"].present_text.assert_called_once_with( "Do you want to save changes?\n< Yes > < No >", interrupt=True, flush=False, ) assert env["commandsIgnore"]["onScreenUpdate"]["INCOMING_IGNORE"] is True @pytest.mark.unit def test_pty_blank_cursor_line_does_not_suppress_nonblank_delta(): command = _load_command() env = _build_environment("pty") env["screen"]["new_cursor"] = {"x": 0, "y": 1} env["screen"]["new_content_text"] = "Birthday soon\n".ljust(80) env["screen"]["new_delta"] = "Birthday soon" command.initialize(env) command.run() env["runtime"]["OutputManager"].present_text.assert_not_called() assert env["commandsIgnore"]["onScreenUpdate"]["INCOMING_IGNORE"] is False