Bug fixes in -x, things should read better now.
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
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"
|
||||
/ "85000-has_attribute.py"
|
||||
)
|
||||
spec = importlib.util.spec_from_file_location(
|
||||
"fenrir_has_attribute", module_path
|
||||
)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(module)
|
||||
return module.command()
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_has_attribute_uses_configured_setting_name():
|
||||
settings_manager = Mock()
|
||||
settings_manager.get_setting_as_bool.return_value = False
|
||||
command = _load_command()
|
||||
command.initialize(
|
||||
{
|
||||
"runtime": {
|
||||
"SettingsManager": settings_manager,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
command.run()
|
||||
|
||||
settings_manager.get_setting_as_bool.assert_called_once_with(
|
||||
"general", "has_attributes"
|
||||
)
|
||||
@@ -67,6 +67,21 @@ def test_present_text_allows_sound_only_feedback():
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_present_text_sound_icon_with_interrupt_cancels_speech():
|
||||
output_manager, sound_driver, speech_driver = build_output_manager()
|
||||
|
||||
output_manager.present_text(
|
||||
"end of screen", sound_icon="Accept", interrupt=True
|
||||
)
|
||||
|
||||
speech_driver.cancel.assert_called_once_with()
|
||||
sound_driver.play_sound_file.assert_called_once_with(
|
||||
"/tmp/Accept.wav", True
|
||||
)
|
||||
speech_driver.speak.assert_not_called()
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_play_sound_supports_error_alias():
|
||||
output_manager, sound_driver, _speech_driver = build_output_manager()
|
||||
@@ -227,3 +242,35 @@ def test_key_interrupt_command_uses_nonblocking_interrupt():
|
||||
|
||||
output_manager.interrupt_output_async.assert_called_once_with()
|
||||
output_manager.interrupt_output.assert_not_called()
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_key_interrupt_command_ignores_fenrir_shortcuts():
|
||||
module = load_key_interrupt_module()
|
||||
settings_manager = Mock()
|
||||
settings_manager.get_setting_as_bool.return_value = True
|
||||
settings_manager.get_setting.return_value = ""
|
||||
input_manager = Mock(
|
||||
no_key_pressed=Mock(return_value=False),
|
||||
get_curr_shortcut=Mock(return_value=[1, ["KEY_KP9"]]),
|
||||
get_command_for_shortcut=Mock(return_value="REVIEW_NEXT_LINE"),
|
||||
)
|
||||
output_manager = Mock()
|
||||
env = {
|
||||
"input": {
|
||||
"curr_input": ["KEY_KP9"],
|
||||
"prev_input": [],
|
||||
},
|
||||
"runtime": {
|
||||
"InputManager": input_manager,
|
||||
"OutputManager": output_manager,
|
||||
"ScreenManager": Mock(is_screen_change=Mock(return_value=False)),
|
||||
"SettingsManager": settings_manager,
|
||||
},
|
||||
}
|
||||
command = module.command()
|
||||
command.initialize(env)
|
||||
|
||||
command.run()
|
||||
|
||||
output_manager.interrupt_output_async.assert_not_called()
|
||||
|
||||
@@ -39,6 +39,29 @@ def test_private_sgr_sequence_from_fullscreen_apps_does_not_crash():
|
||||
assert screen["text"].splitlines()[0] == "X "
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_dcs_terminal_queries_do_not_render_as_text():
|
||||
terminal = Terminal(20, 3, DummyProcessInput())
|
||||
|
||||
terminal.feed(b"\x1bP+q6b32\x1b\\X")
|
||||
screen = terminal.get_screen_content()
|
||||
|
||||
assert screen["text"].splitlines()[0] == "X "
|
||||
assert "+q6b32" not in screen["text"]
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_split_dcs_terminal_query_does_not_render_as_text():
|
||||
terminal = Terminal(20, 3, DummyProcessInput())
|
||||
|
||||
terminal.feed(b"\x1bP+q6")
|
||||
terminal.feed(b"b32\x1b\\X")
|
||||
screen = terminal.get_screen_content()
|
||||
|
||||
assert screen["text"].splitlines()[0] == "X "
|
||||
assert "+q6b32" not in screen["text"]
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_optional_float_setting_uses_default_when_missing():
|
||||
settings_manager = type(
|
||||
@@ -79,6 +102,35 @@ def test_pty_stdin_input_interrupts_output_when_all_keys_interrupt_enabled():
|
||||
output_manager.interrupt_output.assert_called_once_with()
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
@pytest.mark.parametrize(
|
||||
"sequence",
|
||||
[
|
||||
b"\x1b[12;40R",
|
||||
b"\x1b[?1;2c",
|
||||
b"\x1b[>85;95;0c",
|
||||
b"\x1b[4;80;24t",
|
||||
b"\x1b]10;rgb:ffff/ffff/ffff\x1b\\",
|
||||
],
|
||||
)
|
||||
def test_pty_terminal_response_stdin_does_not_interrupt_output(sequence):
|
||||
pty_driver = PtyDriver()
|
||||
settings_manager = Mock()
|
||||
settings_manager.get_setting_as_bool.return_value = True
|
||||
settings_manager.get_setting.return_value = ""
|
||||
output_manager = Mock()
|
||||
pty_driver.env = {
|
||||
"runtime": {
|
||||
"SettingsManager": settings_manager,
|
||||
"OutputManager": output_manager,
|
||||
}
|
||||
}
|
||||
|
||||
pty_driver.interrupt_output_on_stdin_input(sequence)
|
||||
|
||||
output_manager.interrupt_output.assert_not_called()
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_pty_stdin_input_interrupt_does_not_block_input_injection():
|
||||
pty_driver = PtyDriver()
|
||||
@@ -160,6 +212,325 @@ def test_pty_plain_stdin_does_not_record_tab_keypress():
|
||||
pty_driver.inject_text_to_screen.assert_called_once_with(b"a")
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_pty_stdin_consumes_fenrir_shortcut_input():
|
||||
pty_driver = PtyDriver()
|
||||
settings_manager = Mock()
|
||||
settings_manager.get_setting_as_bool.return_value = True
|
||||
input_manager = Mock(
|
||||
get_curr_shortcut=Mock(return_value=[1, ["KEY_KP9"]]),
|
||||
get_command_for_shortcut=Mock(return_value="REVIEW_NEXT_LINE"),
|
||||
)
|
||||
output_manager = Mock()
|
||||
pty_driver.env = {
|
||||
"input": {"curr_input": ["KEY_KP9"]},
|
||||
"runtime": {
|
||||
"DebugManager": Mock(write_debug_out=Mock()),
|
||||
"InputManager": input_manager,
|
||||
"OutputManager": output_manager,
|
||||
"SettingsManager": settings_manager,
|
||||
},
|
||||
}
|
||||
pty_driver.inject_text_to_screen = Mock()
|
||||
|
||||
pty_driver.handle_stdin_input(b"\x1b[6~", Mock())
|
||||
|
||||
output_manager.interrupt_output.assert_not_called()
|
||||
pty_driver.inject_text_to_screen.assert_not_called()
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_pty_stdin_consumes_late_fenrir_shortcut_tail_after_release():
|
||||
pty_driver = PtyDriver()
|
||||
settings_manager = Mock()
|
||||
settings_manager.get_setting_as_bool.return_value = True
|
||||
input_manager = Mock(
|
||||
get_curr_shortcut=Mock(return_value=[1, []]),
|
||||
get_command_for_shortcut=Mock(return_value=""),
|
||||
)
|
||||
output_manager = Mock()
|
||||
pty_driver.env = {
|
||||
"input": {"curr_input": []},
|
||||
"runtime": {
|
||||
"DebugManager": Mock(write_debug_out=Mock()),
|
||||
"InputManager": input_manager,
|
||||
"OutputManager": output_manager,
|
||||
"SettingsManager": settings_manager,
|
||||
},
|
||||
}
|
||||
pty_driver.last_fenrir_stdin_command_time = time.monotonic()
|
||||
pty_driver.inject_text_to_screen = Mock()
|
||||
|
||||
pty_driver.handle_stdin_input(b"\x1b[6~", Mock())
|
||||
|
||||
output_manager.interrupt_output.assert_not_called()
|
||||
pty_driver.inject_text_to_screen.assert_not_called()
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_pty_stdin_consumes_split_fenrir_shortcut_tail_after_release():
|
||||
pty_driver = PtyDriver()
|
||||
settings_manager = Mock()
|
||||
settings_manager.get_setting_as_bool.return_value = True
|
||||
input_manager = Mock(
|
||||
get_curr_shortcut=Mock(
|
||||
side_effect=[
|
||||
[1, ["KEY_KP7"]],
|
||||
[1, []],
|
||||
]
|
||||
),
|
||||
get_command_for_shortcut=Mock(
|
||||
side_effect=[
|
||||
"REVIEW_PREV_LINE",
|
||||
"",
|
||||
]
|
||||
),
|
||||
)
|
||||
output_manager = Mock()
|
||||
pty_driver.env = {
|
||||
"input": {"curr_input": ["KEY_KP7"]},
|
||||
"runtime": {
|
||||
"DebugManager": Mock(write_debug_out=Mock()),
|
||||
"InputManager": input_manager,
|
||||
"OutputManager": output_manager,
|
||||
"SettingsManager": settings_manager,
|
||||
},
|
||||
}
|
||||
pty_driver.inject_text_to_screen = Mock()
|
||||
|
||||
pty_driver.handle_stdin_input(b"\x1b", Mock())
|
||||
pty_driver.env["input"]["curr_input"] = []
|
||||
pty_driver.handle_stdin_input(b"[H", Mock())
|
||||
|
||||
output_manager.interrupt_output.assert_not_called()
|
||||
pty_driver.inject_text_to_screen.assert_not_called()
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_pty_stdin_consumes_split_ss3_fenrir_shortcut_tail_after_release():
|
||||
pty_driver = PtyDriver()
|
||||
settings_manager = Mock()
|
||||
settings_manager.get_setting_as_bool.return_value = True
|
||||
input_manager = Mock(
|
||||
get_curr_shortcut=Mock(
|
||||
side_effect=[
|
||||
[1, ["KEY_KP7"]],
|
||||
[1, []],
|
||||
[1, []],
|
||||
]
|
||||
),
|
||||
get_command_for_shortcut=Mock(
|
||||
side_effect=[
|
||||
"REVIEW_PREV_LINE",
|
||||
"",
|
||||
"",
|
||||
]
|
||||
),
|
||||
)
|
||||
output_manager = Mock()
|
||||
pty_driver.env = {
|
||||
"input": {"curr_input": ["KEY_KP7"]},
|
||||
"runtime": {
|
||||
"DebugManager": Mock(write_debug_out=Mock()),
|
||||
"InputManager": input_manager,
|
||||
"OutputManager": output_manager,
|
||||
"SettingsManager": settings_manager,
|
||||
},
|
||||
}
|
||||
pty_driver.inject_text_to_screen = Mock()
|
||||
|
||||
pty_driver.handle_stdin_input(b"\x1b", Mock())
|
||||
pty_driver.env["input"]["curr_input"] = []
|
||||
pty_driver.handle_stdin_input(b"O", Mock())
|
||||
pty_driver.handle_stdin_input(b"w", Mock())
|
||||
|
||||
output_manager.interrupt_output.assert_not_called()
|
||||
pty_driver.inject_text_to_screen.assert_not_called()
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_pty_stdin_does_not_consume_printable_input_after_fenrir_shortcut():
|
||||
pty_driver = PtyDriver()
|
||||
settings_manager = Mock()
|
||||
settings_manager.get_setting_as_bool.return_value = False
|
||||
input_manager = Mock(
|
||||
get_curr_shortcut=Mock(return_value=[1, []]),
|
||||
get_command_for_shortcut=Mock(return_value=""),
|
||||
)
|
||||
output_manager = Mock()
|
||||
pty_driver.env = {
|
||||
"input": {"curr_input": []},
|
||||
"runtime": {
|
||||
"DebugManager": Mock(write_debug_out=Mock()),
|
||||
"InputManager": input_manager,
|
||||
"OutputManager": output_manager,
|
||||
"SettingsManager": settings_manager,
|
||||
},
|
||||
}
|
||||
pty_driver.last_fenrir_stdin_command_time = time.monotonic()
|
||||
pty_driver.inject_text_to_screen = Mock()
|
||||
|
||||
pty_driver.handle_stdin_input(b"a", Mock())
|
||||
|
||||
output_manager.interrupt_output.assert_not_called()
|
||||
pty_driver.inject_text_to_screen.assert_called_once_with(b"a")
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_pty_stdin_does_not_consume_stale_fenrir_shortcut_tail():
|
||||
pty_driver = PtyDriver()
|
||||
settings_manager = Mock()
|
||||
settings_manager.get_setting_as_bool.return_value = False
|
||||
input_manager = Mock(
|
||||
get_curr_shortcut=Mock(return_value=[1, []]),
|
||||
get_command_for_shortcut=Mock(return_value=""),
|
||||
)
|
||||
pty_driver.env = {
|
||||
"input": {"curr_input": []},
|
||||
"runtime": {
|
||||
"DebugManager": Mock(write_debug_out=Mock()),
|
||||
"InputManager": input_manager,
|
||||
"SettingsManager": settings_manager,
|
||||
},
|
||||
}
|
||||
pty_driver.last_fenrir_stdin_command_time = (
|
||||
time.monotonic()
|
||||
- PTYConstants.FENRIR_SHORTCUT_STDIN_TAIL_TIMEOUT
|
||||
- 0.1
|
||||
)
|
||||
pty_driver.inject_text_to_screen = Mock()
|
||||
|
||||
pty_driver.handle_stdin_input(b"\x1b[6~", Mock())
|
||||
|
||||
pty_driver.inject_text_to_screen.assert_called_once_with(b"\x1b[6~")
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_pty_stdin_consumes_late_tail_after_recent_review_command():
|
||||
pty_driver = PtyDriver()
|
||||
settings_manager = Mock()
|
||||
settings_manager.get_setting_as_bool.return_value = True
|
||||
input_manager = Mock(
|
||||
get_curr_shortcut=Mock(return_value=[1, []]),
|
||||
get_command_for_shortcut=Mock(return_value=""),
|
||||
)
|
||||
output_manager = Mock()
|
||||
pty_driver.env = {
|
||||
"input": {"curr_input": []},
|
||||
"commandInfo": {
|
||||
"lastCommand": "REVIEW_NEXT_LINE",
|
||||
"lastCommandSection": "commands",
|
||||
"lastCommandRunTime": time.time(),
|
||||
},
|
||||
"runtime": {
|
||||
"DebugManager": Mock(write_debug_out=Mock()),
|
||||
"InputManager": input_manager,
|
||||
"OutputManager": output_manager,
|
||||
"SettingsManager": settings_manager,
|
||||
},
|
||||
}
|
||||
pty_driver.inject_text_to_screen = Mock()
|
||||
|
||||
pty_driver.handle_stdin_input(b"\x1b[6~", Mock())
|
||||
|
||||
output_manager.interrupt_output.assert_not_called()
|
||||
pty_driver.inject_text_to_screen.assert_not_called()
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
@pytest.mark.parametrize("sequence", [b"[H", b"[1~", b"Ow"])
|
||||
def test_pty_stdin_consumes_split_tail_after_recent_review_command(sequence):
|
||||
pty_driver = PtyDriver()
|
||||
settings_manager = Mock()
|
||||
settings_manager.get_setting_as_bool.return_value = True
|
||||
input_manager = Mock(
|
||||
get_curr_shortcut=Mock(return_value=[1, []]),
|
||||
get_command_for_shortcut=Mock(return_value=""),
|
||||
)
|
||||
output_manager = Mock()
|
||||
pty_driver.env = {
|
||||
"input": {"curr_input": []},
|
||||
"commandInfo": {
|
||||
"lastCommand": "REVIEW_NEXT_LINE",
|
||||
"lastCommandSection": "commands",
|
||||
"lastCommandRunTime": time.time(),
|
||||
},
|
||||
"runtime": {
|
||||
"DebugManager": Mock(write_debug_out=Mock()),
|
||||
"InputManager": input_manager,
|
||||
"OutputManager": output_manager,
|
||||
"SettingsManager": settings_manager,
|
||||
},
|
||||
}
|
||||
pty_driver.inject_text_to_screen = Mock()
|
||||
|
||||
pty_driver.handle_stdin_input(sequence, Mock())
|
||||
|
||||
output_manager.interrupt_output.assert_not_called()
|
||||
pty_driver.inject_text_to_screen.assert_not_called()
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_pty_stdin_consumes_lone_escape_after_recent_review_command():
|
||||
pty_driver = PtyDriver()
|
||||
settings_manager = Mock()
|
||||
settings_manager.get_setting_as_bool.return_value = True
|
||||
input_manager = Mock(
|
||||
get_curr_shortcut=Mock(return_value=[1, []]),
|
||||
get_command_for_shortcut=Mock(return_value=""),
|
||||
)
|
||||
output_manager = Mock()
|
||||
pty_driver.env = {
|
||||
"input": {"curr_input": []},
|
||||
"commandInfo": {
|
||||
"lastCommand": "REVIEW_CURR_LINE",
|
||||
"lastCommandSection": "commands",
|
||||
"lastCommandRunTime": time.time(),
|
||||
},
|
||||
"runtime": {
|
||||
"DebugManager": Mock(write_debug_out=Mock()),
|
||||
"InputManager": input_manager,
|
||||
"OutputManager": output_manager,
|
||||
"SettingsManager": settings_manager,
|
||||
},
|
||||
}
|
||||
pty_driver.inject_text_to_screen = Mock()
|
||||
|
||||
pty_driver.handle_stdin_input(b"\x1b", Mock())
|
||||
|
||||
output_manager.interrupt_output.assert_not_called()
|
||||
pty_driver.inject_text_to_screen.assert_not_called()
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_pty_stdin_does_not_consume_late_tail_after_non_review_command():
|
||||
pty_driver = PtyDriver()
|
||||
settings_manager = Mock()
|
||||
settings_manager.get_setting_as_bool.return_value = False
|
||||
input_manager = Mock(
|
||||
get_curr_shortcut=Mock(return_value=[1, []]),
|
||||
get_command_for_shortcut=Mock(return_value=""),
|
||||
)
|
||||
pty_driver.env = {
|
||||
"input": {"curr_input": []},
|
||||
"commandInfo": {
|
||||
"lastCommand": "CURSOR_POSITION",
|
||||
"lastCommandSection": "commands",
|
||||
"lastCommandRunTime": time.time(),
|
||||
},
|
||||
"runtime": {
|
||||
"DebugManager": Mock(write_debug_out=Mock()),
|
||||
"InputManager": input_manager,
|
||||
"SettingsManager": settings_manager,
|
||||
},
|
||||
}
|
||||
pty_driver.inject_text_to_screen = Mock()
|
||||
|
||||
pty_driver.handle_stdin_input(b"\x1b[6~", Mock())
|
||||
|
||||
pty_driver.inject_text_to_screen.assert_called_once_with(b"\x1b[6~")
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
@pytest.mark.parametrize(
|
||||
("sequence", "key_name"),
|
||||
@@ -281,6 +652,22 @@ def test_pty_stdin_input_leaves_filtered_interrupts_to_key_events():
|
||||
output_manager.interrupt_output.assert_not_called()
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_pty_terminal_attributes_use_fenrir_attribute_shape():
|
||||
terminal = Terminal(10, 2, DummyProcessInput())
|
||||
|
||||
terminal.feed(b"plain\r\n\x1b[7mfocus\x1b[0m")
|
||||
screen_content = terminal.get_screen_content()
|
||||
|
||||
plain_attribute = screen_content["attributes"][0][0]
|
||||
focused_attribute = screen_content["attributes"][1][0]
|
||||
assert len(plain_attribute) == 10
|
||||
assert len(focused_attribute) == 10
|
||||
assert plain_attribute[1] == "default"
|
||||
assert focused_attribute[1] == "reverse"
|
||||
assert focused_attribute[6] is True
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_pty_backspace_with_fenrir_key_synthesizes_shortcut_events():
|
||||
pty_driver = PtyDriver()
|
||||
|
||||
@@ -195,3 +195,27 @@ def test_tui_input_line_typing_is_filtered_from_mixed_repaint_delta():
|
||||
assert "Username" not in env["screen"]["new_delta"]
|
||||
assert "#channel" not in env["screen"]["new_delta"]
|
||||
assert env["screen"]["new_delta_is_typing"] is False
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_pty_prompt_repaint_from_blank_line_keeps_full_prompt():
|
||||
manager, env = _build_screen_manager(
|
||||
" ".ljust(40),
|
||||
{"x": 2, "y": 0},
|
||||
)
|
||||
|
||||
manager.update(
|
||||
{
|
||||
"bytes": b"",
|
||||
"lines": 1,
|
||||
"columns": 40,
|
||||
"textCursor": {"x": 23, "y": 0},
|
||||
"screen": "pty",
|
||||
"text": "[storm@fenrir fenrir] $ ".ljust(40),
|
||||
"attributes": [],
|
||||
},
|
||||
"onScreenUpdate",
|
||||
)
|
||||
|
||||
assert env["screen"]["new_delta"] == "[storm@fenrir fenrir] $"
|
||||
assert env["screen"]["new_delta_is_typing"] is False
|
||||
|
||||
@@ -334,6 +334,7 @@ def test_large_insertion_echo_speaks_pasted_cursor_text():
|
||||
is_delta=Mock(return_value=True),
|
||||
)
|
||||
env = {
|
||||
"commandsIgnore": {"onScreenUpdate": {"INCOMING_IGNORE": False}},
|
||||
"runtime": {
|
||||
"InputManager": input_manager,
|
||||
"OutputManager": output_manager,
|
||||
@@ -357,6 +358,7 @@ def test_large_insertion_echo_speaks_pasted_cursor_text():
|
||||
announce_capital=True,
|
||||
flush=False,
|
||||
)
|
||||
assert env["commandsIgnore"]["onScreenUpdate"]["INCOMING_IGNORE"] is True
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
@@ -377,6 +379,7 @@ def test_large_insertion_echo_defers_recent_tab_to_tab_completion():
|
||||
is_delta=Mock(return_value=True),
|
||||
)
|
||||
env = {
|
||||
"commandsIgnore": {"onScreenUpdate": {"INCOMING_IGNORE": False}},
|
||||
"runtime": {
|
||||
"InputManager": input_manager,
|
||||
"OutputManager": output_manager,
|
||||
@@ -395,3 +398,4 @@ def test_large_insertion_echo_defers_recent_tab_to_tab_completion():
|
||||
command.run()
|
||||
|
||||
output_manager.present_text.assert_not_called()
|
||||
assert env["commandsIgnore"]["onScreenUpdate"]["INCOMING_IGNORE"] is False
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
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
|
||||
Reference in New Issue
Block a user