2242 lines
103 KiB
Python
2242 lines
103 KiB
Python
# Unit tests for table_navigator.py methods.
|
|
#
|
|
# Copyright 2025 Igalia, S.L.
|
|
# Author: Joanmarie Diggs <jdiggs@igalia.com>
|
|
#
|
|
# This library is free software; you can redistribute it and/or
|
|
# modify it under the terms of the GNU Lesser General Public
|
|
# License as published by the Free Software Foundation; either
|
|
# version 2.1 of the License, or (at your option) any later version.
|
|
#
|
|
# This library is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
# Lesser General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU Lesser General Public
|
|
# License along with this library; if not, write to the
|
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
|
# Boston MA 02110-1301 USA.
|
|
|
|
# pylint: disable=wrong-import-position
|
|
# pylint: disable=import-outside-toplevel
|
|
# pylint: disable=too-many-public-methods
|
|
# pylint: disable=too-many-statements
|
|
# pylint: disable=protected-access
|
|
# pylint: disable=too-many-arguments
|
|
# pylint: disable=too-many-positional-arguments
|
|
# pylint: disable=too-many-locals
|
|
# pylint: disable=too-many-lines
|
|
|
|
"""Unit tests for table_navigator.py methods."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import TYPE_CHECKING
|
|
|
|
import gi
|
|
import pytest
|
|
|
|
gi.require_version("Atspi", "2.0")
|
|
from gi.repository import Atspi
|
|
|
|
if TYPE_CHECKING:
|
|
from unittest.mock import MagicMock
|
|
|
|
from cthulhu_test_context import CthulhuTestContext
|
|
|
|
|
|
@pytest.mark.unit
|
|
class TestTableNavigator:
|
|
"""Test TableNavigator class methods."""
|
|
|
|
def _setup_dependencies(self, test_context: CthulhuTestContext) -> dict[str, MagicMock]:
|
|
"""Set up dependencies for table_navigator module testing."""
|
|
|
|
additional_modules = [
|
|
"cthulhu.command_manager",
|
|
"cthulhu.guilabels",
|
|
"cthulhu.input_event_manager",
|
|
"cthulhu.cmdnames",
|
|
"cthulhu.messages",
|
|
"cthulhu.object_properties",
|
|
"cthulhu.cthulhu_gui_navlist",
|
|
"cthulhu.cthulhu_i18n",
|
|
"cthulhu.AXHypertext",
|
|
"cthulhu.AXObject",
|
|
"cthulhu.AXTable",
|
|
"cthulhu.AXText",
|
|
"cthulhu.AXUtilities",
|
|
"cthulhu.input_event",
|
|
"cthulhu.braille_presenter",
|
|
"cthulhu.presentation_manager",
|
|
]
|
|
essential_modules = test_context.setup_shared_dependencies(additional_modules)
|
|
|
|
# Set up cmdnames with all required values for structural_navigator
|
|
cmdnames = essential_modules["cthulhu.cmdnames"]
|
|
cmdnames.STRUCTURAL_NAVIGATION_MODE_CYCLE = "cycle_mode"
|
|
cmdnames.BLOCKQUOTE_PREV = "previous_blockquote"
|
|
cmdnames.BLOCKQUOTE_NEXT = "next_blockquote"
|
|
cmdnames.BLOCKQUOTE_LIST = "list_blockquotes"
|
|
cmdnames.BUTTON_PREV = "previous_button"
|
|
cmdnames.BUTTON_NEXT = "next_button"
|
|
cmdnames.BUTTON_LIST = "list_buttons"
|
|
cmdnames.CHECK_BOX_PREV = "previous_checkbox"
|
|
cmdnames.CHECK_BOX_NEXT = "next_checkbox"
|
|
cmdnames.CHECK_BOX_LIST = "list_checkboxes"
|
|
cmdnames.COMBO_BOX_PREV = "previous_combobox"
|
|
cmdnames.COMBO_BOX_NEXT = "next_combobox"
|
|
cmdnames.COMBO_BOX_LIST = "list_comboboxes"
|
|
cmdnames.ENTRY_PREV = "previous_entry"
|
|
cmdnames.ENTRY_NEXT = "next_entry"
|
|
cmdnames.ENTRY_LIST = "list_entries"
|
|
cmdnames.FORM_FIELD_PREV = "previous_form_field"
|
|
cmdnames.FORM_FIELD_NEXT = "next_form_field"
|
|
cmdnames.FORM_FIELD_LIST = "list_form_fields"
|
|
cmdnames.HEADING_PREV = "previous_heading"
|
|
cmdnames.HEADING_NEXT = "next_heading"
|
|
cmdnames.HEADING_LIST = "list_headings"
|
|
cmdnames.HEADING_AT_LEVEL_PREV = "previous_heading_level_%d"
|
|
cmdnames.HEADING_AT_LEVEL_NEXT = "next_heading_level_%d"
|
|
cmdnames.HEADING_AT_LEVEL_LIST = "list_headings_level_%d"
|
|
cmdnames.IFRAME_PREV = "previous_iframe"
|
|
cmdnames.IFRAME_NEXT = "next_iframe"
|
|
cmdnames.IFRAME_LIST = "list_iframes"
|
|
cmdnames.IMAGE_PREV = "previous_image"
|
|
cmdnames.IMAGE_NEXT = "next_image"
|
|
cmdnames.IMAGE_LIST = "list_images"
|
|
cmdnames.LANDMARK_PREV = "previous_landmark"
|
|
cmdnames.LANDMARK_NEXT = "next_landmark"
|
|
cmdnames.LANDMARK_LIST = "list_landmarks"
|
|
cmdnames.LIST_PREV = "previous_list"
|
|
cmdnames.LIST_NEXT = "next_list"
|
|
cmdnames.LIST_LIST = "list_lists"
|
|
cmdnames.LIST_ITEM_PREV = "previous_list_item"
|
|
cmdnames.LIST_ITEM_NEXT = "next_list_item"
|
|
cmdnames.LIST_ITEM_LIST = "list_list_items"
|
|
cmdnames.LIVE_REGION_PREV = "previous_live_region"
|
|
cmdnames.LIVE_REGION_NEXT = "next_live_region"
|
|
cmdnames.LIVE_REGION_LAST = "last_live_region"
|
|
cmdnames.PARAGRAPH_PREV = "previous_paragraph"
|
|
cmdnames.PARAGRAPH_NEXT = "next_paragraph"
|
|
cmdnames.PARAGRAPH_LIST = "list_paragraphs"
|
|
cmdnames.RADIO_BUTTON_PREV = "previous_radio_button"
|
|
cmdnames.RADIO_BUTTON_NEXT = "next_radio_button"
|
|
cmdnames.RADIO_BUTTON_LIST = "list_radio_buttons"
|
|
cmdnames.SEPARATOR_PREV = "previous_separator"
|
|
cmdnames.SEPARATOR_NEXT = "next_separator"
|
|
cmdnames.TABLE_PREV = "previous_table"
|
|
cmdnames.TABLE_NEXT = "next_table"
|
|
cmdnames.TABLE_LIST = "list_tables"
|
|
cmdnames.UNVISITED_LINK_PREV = "previous_unvisited_link"
|
|
cmdnames.UNVISITED_LINK_NEXT = "next_unvisited_link"
|
|
cmdnames.UNVISITED_LINK_LIST = "list_unvisited_links"
|
|
cmdnames.VISITED_LINK_PREV = "previous_visited_link"
|
|
cmdnames.VISITED_LINK_NEXT = "next_visited_link"
|
|
cmdnames.VISITED_LINK_LIST = "list_visited_links"
|
|
cmdnames.LINK_PREV = "previous_link"
|
|
cmdnames.LINK_NEXT = "next_link"
|
|
cmdnames.LINK_LIST = "list_links"
|
|
cmdnames.CLICKABLE_PREV = "previous_clickable"
|
|
cmdnames.CLICKABLE_NEXT = "next_clickable"
|
|
cmdnames.CLICKABLE_LIST = "list_clickables"
|
|
cmdnames.LARGE_OBJECT_PREV = "previous_large_object"
|
|
cmdnames.LARGE_OBJECT_NEXT = "next_large_object"
|
|
cmdnames.LARGE_OBJECT_LIST = "list_large_objects"
|
|
cmdnames.CONTAINER_START = "container_start"
|
|
cmdnames.CONTAINER_END = "container_end"
|
|
|
|
essential_modules["cthulhu.cthulhu_i18n"]._ = lambda x: x
|
|
essential_modules["cthulhu.debug"].print_message = test_context.Mock()
|
|
essential_modules["cthulhu.debug"].LEVEL_INFO = 800
|
|
|
|
controller_mock = test_context.Mock()
|
|
controller_mock.register_decorated_module.return_value = None
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = controller_mock
|
|
|
|
focus_manager_instance = test_context.Mock()
|
|
focus_manager_instance.get_locus_of_focus.return_value = None
|
|
essential_modules["cthulhu.focus_manager"].get_manager.return_value = focus_manager_instance
|
|
|
|
essential_modules["cthulhu.AXObject"].supports_collection.return_value = True
|
|
essential_modules["cthulhu.AXUtilities"].is_heading.return_value = False
|
|
|
|
return essential_modules
|
|
|
|
def test_init(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test TableNavigator.__init__ creates instance with correct default values."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
from cthulhu import command_manager
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
assert navigator._previous_reported_row is None
|
|
assert navigator._previous_reported_col is None
|
|
assert navigator._last_input_event is None
|
|
assert navigator.get_is_enabled() is True
|
|
# D-Bus registration and commands are registered during setup()
|
|
navigator.set_up_commands()
|
|
# Verify commands are registered in CommandManager
|
|
cmd_manager = command_manager.get_manager()
|
|
assert cmd_manager.get_command("table_navigator_toggle_enabled") is not None
|
|
assert cmd_manager.get_command("table_cell_down") is not None
|
|
mock_controller.register_decorated_module.assert_called_with("TableNavigator", navigator)
|
|
|
|
def test_is_enabled_default_true(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test TableNavigator.is_enabled returns True by default."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
assert navigator.get_is_enabled() is True
|
|
|
|
def test_is_enabled_after_disable(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test TableNavigator.get_is_enabled returns False when disabled."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
from cthulhu import gsettings_registry
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
gsettings_registry.get_registry().set_runtime_value("table-navigation", "enabled", False)
|
|
navigator = TableNavigator()
|
|
assert navigator.get_is_enabled() is False
|
|
|
|
def test_last_input_event_was_navigation_command_none(
|
|
self,
|
|
test_context: CthulhuTestContext,
|
|
) -> None:
|
|
"""Test last_input_event_was_navigation_command with None event returns False."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
mock_manager = test_context.Mock()
|
|
essential_modules["cthulhu.input_event_manager"].get_manager.return_value = mock_manager
|
|
mock_manager.last_event_equals_or_is_release_for_event.return_value = False
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
result = navigator.last_input_event_was_navigation_command()
|
|
assert result is False
|
|
mock_manager.last_event_equals_or_is_release_for_event.assert_not_called()
|
|
|
|
def test_last_input_event_was_navigation_command_with_event(
|
|
self,
|
|
test_context: CthulhuTestContext,
|
|
) -> None:
|
|
"""Test last_input_event_was_navigation_command with event returns True when matching."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
mock_manager = test_context.Mock()
|
|
essential_modules["cthulhu.input_event_manager"].get_manager.return_value = mock_manager
|
|
mock_manager.last_event_equals_or_is_release_for_event.return_value = True
|
|
mock_event = test_context.Mock()
|
|
mock_event.as_single_line_string.return_value = "test_event"
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
navigator._last_input_event = mock_event
|
|
result = navigator.last_input_event_was_navigation_command()
|
|
assert result is True
|
|
mock_manager.last_event_equals_or_is_release_for_event.assert_called_once_with(mock_event)
|
|
|
|
@pytest.mark.parametrize(
|
|
"initial_enabled,expected_enabled,expected_message_attr",
|
|
[
|
|
(False, True, "TABLE_NAVIGATION_ENABLED"),
|
|
(True, False, "TABLE_NAVIGATION_DISABLED"),
|
|
],
|
|
)
|
|
def test_toggle_enabled(
|
|
self,
|
|
test_context: CthulhuTestContext,
|
|
initial_enabled: bool,
|
|
expected_enabled: bool,
|
|
expected_message_attr: str,
|
|
) -> None:
|
|
"""Test TableNavigator.toggle_enabled toggles state and presents appropriate message."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
mock_cmd_mgr = test_context.Mock()
|
|
essential_modules["cthulhu.command_manager"].get_manager.return_value = mock_cmd_mgr
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
guilabels_mock = essential_modules["cthulhu.guilabels"]
|
|
guilabels_mock.KB_GROUP_TABLE_NAVIGATION = "Table navigation"
|
|
|
|
navigator = TableNavigator()
|
|
mock_cmd_mgr.is_group_enabled.return_value = initial_enabled
|
|
mock_script = test_context.Mock()
|
|
mock_event = test_context.Mock()
|
|
pres_manager = essential_modules["cthulhu.presentation_manager"].get_manager()
|
|
pres_manager.present_message.reset_mock()
|
|
result = navigator.toggle_enabled(mock_script, mock_event, notify_user=True)
|
|
assert result is True
|
|
expected_message = getattr(essential_modules["cthulhu.messages"], expected_message_attr)
|
|
pres_manager.present_message.assert_called_once_with(expected_message)
|
|
|
|
def test_toggle_enabled_no_notify(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test TableNavigator.toggle_enabled does not present message when notify_user=False."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
mock_cmd_mgr = test_context.Mock()
|
|
essential_modules["cthulhu.command_manager"].get_manager.return_value = mock_cmd_mgr
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
guilabels_mock = essential_modules["cthulhu.guilabels"]
|
|
guilabels_mock.KB_GROUP_TABLE_NAVIGATION = "Table navigation"
|
|
|
|
navigator = TableNavigator()
|
|
mock_cmd_mgr.is_group_enabled.return_value = False
|
|
mock_script = test_context.Mock()
|
|
mock_event = test_context.Mock()
|
|
pres_manager = essential_modules["cthulhu.presentation_manager"].get_manager()
|
|
pres_manager.present_message.reset_mock()
|
|
result = navigator.toggle_enabled(mock_script, mock_event, notify_user=False)
|
|
assert result is True
|
|
pres_manager.present_message.assert_not_called()
|
|
|
|
@pytest.mark.parametrize(
|
|
"is_focusable, has_name, has_children, is_whitespace, expected_result",
|
|
[
|
|
pytest.param(True, False, False, True, False, id="focusable_object"),
|
|
pytest.param(False, True, False, True, False, id="object_with_name"),
|
|
pytest.param(False, False, True, True, False, id="object_with_non_blank_children"),
|
|
pytest.param(False, False, False, False, False, id="object_with_text"),
|
|
pytest.param(False, False, False, True, True, id="blank_object"),
|
|
pytest.param(False, False, True, True, True, id="object_with_only_blank_children"),
|
|
],
|
|
)
|
|
def test_is_blank(
|
|
self,
|
|
test_context,
|
|
is_focusable,
|
|
has_name,
|
|
has_children,
|
|
is_whitespace,
|
|
expected_result,
|
|
) -> None:
|
|
"""Test _is_blank correctly identifies blank objects based on various criteria."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXUtilities.is_focusable",
|
|
return_value=is_focusable,
|
|
)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXObject.get_name",
|
|
return_value="name" if has_name else "",
|
|
)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXObject.get_child_count",
|
|
return_value=1 if has_children else 0,
|
|
)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXUtilities.is_whitespace_or_empty",
|
|
return_value=is_whitespace,
|
|
)
|
|
if has_children:
|
|
mock_child = test_context.Mock()
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXObject.iter_children",
|
|
return_value=[mock_child],
|
|
)
|
|
# For the recursive call on child, configure mock to handle both expected cases
|
|
if expected_result and not is_focusable and not has_name:
|
|
# Child should also be blank - override child-specific mocking
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXUtilities.is_focusable",
|
|
side_effect=lambda obj: False if obj == mock_child else is_focusable,
|
|
)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXObject.get_name",
|
|
side_effect=lambda obj: (
|
|
"" if obj == mock_child else ("name" if has_name else "")
|
|
),
|
|
)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXObject.get_child_count",
|
|
side_effect=lambda obj: 0 if obj == mock_child else (1 if has_children else 0),
|
|
)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXUtilities.is_whitespace_or_empty",
|
|
side_effect=lambda obj: True if obj == mock_child else is_whitespace,
|
|
)
|
|
else:
|
|
# Child should not be blank - make it focusable to stop recursion
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXUtilities.is_focusable",
|
|
side_effect=lambda obj: True if obj == mock_child else is_focusable,
|
|
)
|
|
else:
|
|
test_context.patch("cthulhu.table_navigator.AXObject.iter_children", return_value=[])
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
mock_obj = test_context.Mock(spec=Atspi.Accessible)
|
|
result = navigator._is_blank(mock_obj)
|
|
assert result == expected_result
|
|
|
|
def test_get_current_cell_basic(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test TableNavigator._get_current_cell returns focus manager's locus when it is a cell."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
mock_focus_manager = test_context.Mock()
|
|
mock_focus_manager.get_locus_of_focus.return_value = mock_cell
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.focus_manager.get_manager",
|
|
return_value=mock_focus_manager,
|
|
)
|
|
test_context.patch("cthulhu.table_navigator.AXObject.get_parent", return_value=None)
|
|
|
|
def mock_is_cell_or_header(obj):
|
|
return obj == mock_cell
|
|
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXUtilities.is_table_cell_or_header",
|
|
new=mock_is_cell_or_header,
|
|
)
|
|
test_context.patch("cthulhu.table_navigator.AXUtilities.find_ancestor", return_value=None)
|
|
test_context.patch("cthulhu.table_navigator.debug.print_tokens", return_value=None)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
result = navigator._get_current_cell()
|
|
assert result == mock_cell
|
|
|
|
def test_get_current_cell_nested(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test TableNavigator._get_current_cell returns parent when it is also a table cell."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_focus_manager = test_context.Mock()
|
|
essential_modules["cthulhu.focus_manager"].get_manager.return_value = mock_focus_manager
|
|
mock_inner_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
mock_parent_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
mock_focus_manager.get_locus_of_focus.return_value = mock_inner_cell
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXObject.get_parent",
|
|
side_effect=lambda obj: mock_parent_cell if obj == mock_inner_cell else None,
|
|
)
|
|
|
|
def mock_is_table_cell(obj):
|
|
return obj in [mock_inner_cell, mock_parent_cell]
|
|
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXUtilities.is_table_cell_or_header",
|
|
new=mock_is_table_cell,
|
|
)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
result = navigator._get_current_cell()
|
|
assert result == mock_parent_cell
|
|
|
|
def test_get_cell_coordinates_basic(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test TableNavigator._get_cell_coordinates returns coordinates from AXTable."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXTable.get_cell_coordinates",
|
|
return_value=(2, 3),
|
|
)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
mock_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
result = navigator._get_cell_coordinates(mock_cell)
|
|
assert result == (2, 3)
|
|
|
|
def test_get_cell_coordinates_with_previous(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test _get_cell_coordinates returns previous coordinates when cell matches."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
mock_table = test_context.Mock(spec=Atspi.Accessible)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXTable.get_cell_coordinates",
|
|
return_value=(2, 3),
|
|
)
|
|
test_context.patch("cthulhu.table_navigator.AXUtilities.get_table", return_value=mock_table)
|
|
test_context.patch("cthulhu.table_navigator.AXTable.get_cell_at", return_value=mock_cell)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
navigator._previous_reported_row = 1
|
|
navigator._previous_reported_col = 2
|
|
result = navigator._get_cell_coordinates(mock_cell)
|
|
assert result == (1, 2)
|
|
|
|
@pytest.mark.parametrize(
|
|
"direction, boundary_check, boundary_message, get_next_cell_method",
|
|
[
|
|
pytest.param(
|
|
"left",
|
|
"is_start_of_row",
|
|
"TABLE_ROW_BEGINNING",
|
|
"get_cell_on_left",
|
|
id="move_left",
|
|
),
|
|
pytest.param(
|
|
"right",
|
|
"is_end_of_row",
|
|
"TABLE_ROW_END",
|
|
"get_cell_on_right",
|
|
id="move_right",
|
|
),
|
|
pytest.param(
|
|
"up",
|
|
"is_top_of_column",
|
|
"TABLE_COLUMN_TOP",
|
|
"get_cell_above",
|
|
id="move_up",
|
|
),
|
|
pytest.param(
|
|
"down",
|
|
"is_bottom_of_column",
|
|
"TABLE_COLUMN_BOTTOM",
|
|
"get_cell_below",
|
|
id="move_down",
|
|
),
|
|
],
|
|
)
|
|
def test_move_direction_scenarios(
|
|
self,
|
|
test_context: CthulhuTestContext,
|
|
direction: str,
|
|
boundary_check: str,
|
|
boundary_message: str,
|
|
get_next_cell_method: str,
|
|
) -> None:
|
|
"""Test TableNavigator move methods for various scenarios."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
mock_script = test_context.Mock()
|
|
mock_event = test_context.Mock()
|
|
move_method = getattr(navigator, f"move_{direction}")
|
|
pres_manager = essential_modules["cthulhu.presentation_manager"].get_manager()
|
|
|
|
navigator._get_current_cell = test_context.Mock(return_value=None)
|
|
pres_manager.present_message.reset_mock()
|
|
result = move_method(mock_script, mock_event)
|
|
assert result is True
|
|
pres_manager.present_message.assert_called_with(
|
|
essential_modules["cthulhu.messages"].TABLE_NOT_IN_A,
|
|
)
|
|
assert navigator._last_input_event == mock_event
|
|
|
|
mock_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
test_context.patch(f"cthulhu.table_navigator.AXTable.{boundary_check}", return_value=True)
|
|
navigator._get_current_cell = test_context.Mock(return_value=mock_cell)
|
|
pres_manager.present_message.reset_mock()
|
|
result = move_method(mock_script, mock_event)
|
|
assert result is True
|
|
pres_manager.present_message.assert_called_with(
|
|
getattr(essential_modules["cthulhu.messages"], boundary_message),
|
|
)
|
|
|
|
mock_current_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
mock_next_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
test_context.patch(f"cthulhu.table_navigator.AXTable.{boundary_check}", return_value=False)
|
|
test_context.patch(
|
|
f"cthulhu.table_navigator.AXTable.{get_next_cell_method}",
|
|
return_value=mock_next_cell,
|
|
)
|
|
navigator._get_current_cell = test_context.Mock(return_value=mock_current_cell)
|
|
navigator._get_cell_coordinates = test_context.Mock(return_value=(1, 2))
|
|
mock_present_cell = test_context.Mock()
|
|
navigator._present_cell = mock_present_cell
|
|
mock_script.reset_mock()
|
|
result = move_method(mock_script, mock_event)
|
|
assert result is True
|
|
mock_present_cell.assert_called_once()
|
|
call_args = mock_present_cell.call_args[0]
|
|
assert call_args[0] == mock_script
|
|
assert call_args[1] == mock_next_cell
|
|
assert call_args[4] == mock_current_cell
|
|
assert call_args[5] is True
|
|
|
|
def test_move_left_successful(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test TableNavigator.move_left successfully moves to left cell and presents it."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
mock_current_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
mock_left_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
test_context.patch("cthulhu.table_navigator.AXTable.is_start_of_row", return_value=False)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXTable.get_cell_on_left",
|
|
return_value=mock_left_cell,
|
|
)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
navigator._get_current_cell = test_context.Mock(return_value=mock_current_cell)
|
|
navigator._get_cell_coordinates = test_context.Mock(return_value=(1, 2))
|
|
mock_present_cell = test_context.Mock()
|
|
navigator._present_cell = mock_present_cell
|
|
mock_script = test_context.Mock()
|
|
mock_event = test_context.Mock()
|
|
result = navigator.move_left(mock_script, mock_event)
|
|
assert result is True
|
|
mock_present_cell.assert_called_once_with(
|
|
mock_script,
|
|
mock_left_cell,
|
|
1,
|
|
1,
|
|
mock_current_cell,
|
|
True,
|
|
)
|
|
|
|
def test_move_right_successful(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test TableNavigator.move_right successfully moves to right cell and presents it."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
mock_current_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
mock_right_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
test_context.patch("cthulhu.table_navigator.AXTable.is_end_of_row", return_value=False)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXTable.get_cell_on_right",
|
|
return_value=mock_right_cell,
|
|
)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
navigator._get_current_cell = test_context.Mock(return_value=mock_current_cell)
|
|
navigator._get_cell_coordinates = test_context.Mock(return_value=(1, 2))
|
|
mock_present_cell = test_context.Mock()
|
|
navigator._present_cell = mock_present_cell
|
|
mock_script = test_context.Mock()
|
|
mock_event = test_context.Mock()
|
|
result = navigator.move_right(mock_script, mock_event)
|
|
assert result is True
|
|
mock_present_cell.assert_called_once_with(
|
|
mock_script,
|
|
mock_right_cell,
|
|
1,
|
|
3,
|
|
mock_current_cell,
|
|
True,
|
|
)
|
|
|
|
def test_move_up_not_in_table(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test TableNavigator.move_up presents not in table message when current cell is None."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
navigator._get_current_cell = test_context.Mock(return_value=None)
|
|
mock_script = test_context.Mock()
|
|
mock_event = test_context.Mock()
|
|
pres_manager = essential_modules["cthulhu.presentation_manager"].get_manager()
|
|
pres_manager.present_message.reset_mock()
|
|
result = navigator.move_up(mock_script, mock_event)
|
|
assert result is True
|
|
pres_manager.present_message.assert_called_once_with(
|
|
essential_modules["cthulhu.messages"].TABLE_NOT_IN_A,
|
|
)
|
|
assert navigator._last_input_event == mock_event
|
|
|
|
def test_move_up_at_top_of_column(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test TableNavigator.move_up presents column top message when at top of column."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
mock_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
test_context.patch("cthulhu.table_navigator.AXTable.is_top_of_column", return_value=True)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
navigator._get_current_cell = test_context.Mock(return_value=mock_cell)
|
|
mock_script = test_context.Mock()
|
|
mock_event = test_context.Mock()
|
|
pres_manager = essential_modules["cthulhu.presentation_manager"].get_manager()
|
|
pres_manager.present_message.reset_mock()
|
|
result = navigator.move_up(mock_script, mock_event)
|
|
assert result is True
|
|
pres_manager.present_message.assert_called_once_with(
|
|
essential_modules["cthulhu.messages"].TABLE_COLUMN_TOP,
|
|
)
|
|
|
|
def test_move_up_successful(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test TableNavigator.move_up successfully moves to cell above and presents it."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
mock_current_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
mock_up_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
test_context.patch("cthulhu.table_navigator.AXTable.is_top_of_column", return_value=False)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXTable.get_cell_above",
|
|
return_value=mock_up_cell,
|
|
)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
navigator._get_current_cell = test_context.Mock(return_value=mock_current_cell)
|
|
navigator._get_cell_coordinates = test_context.Mock(return_value=(2, 1))
|
|
mock_present_cell = test_context.Mock()
|
|
navigator._present_cell = mock_present_cell
|
|
mock_script = test_context.Mock()
|
|
mock_event = test_context.Mock()
|
|
result = navigator.move_up(mock_script, mock_event)
|
|
assert result is True
|
|
mock_present_cell.assert_called_once_with(
|
|
mock_script,
|
|
mock_up_cell,
|
|
1,
|
|
1,
|
|
mock_current_cell,
|
|
True,
|
|
)
|
|
|
|
def test_move_down_successful(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test TableNavigator.move_down successfully moves to cell below and presents it."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
mock_current_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
mock_down_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXTable.is_bottom_of_column",
|
|
return_value=False,
|
|
)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXTable.get_cell_below",
|
|
return_value=mock_down_cell,
|
|
)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
navigator._get_current_cell = test_context.Mock(return_value=mock_current_cell)
|
|
navigator._get_cell_coordinates = test_context.Mock(return_value=(1, 1))
|
|
mock_present_cell = test_context.Mock()
|
|
navigator._present_cell = mock_present_cell
|
|
mock_script = test_context.Mock()
|
|
mock_event = test_context.Mock()
|
|
result = navigator.move_down(mock_script, mock_event)
|
|
assert result is True
|
|
mock_present_cell.assert_called_once_with(
|
|
mock_script,
|
|
mock_down_cell,
|
|
2,
|
|
1,
|
|
mock_current_cell,
|
|
True,
|
|
)
|
|
|
|
def test_move_to_first_cell_not_in_table(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test move_to_first_cell presents not in table message when current cell is None."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
navigator._get_current_cell = test_context.Mock(return_value=None)
|
|
mock_script = test_context.Mock()
|
|
mock_event = test_context.Mock()
|
|
pres_manager = essential_modules["cthulhu.presentation_manager"].get_manager()
|
|
pres_manager.present_message.reset_mock()
|
|
result = navigator.move_to_first_cell(mock_script, mock_event)
|
|
assert result is True
|
|
pres_manager.present_message.assert_called_once_with(
|
|
essential_modules["cthulhu.messages"].TABLE_NOT_IN_A,
|
|
)
|
|
|
|
def test_move_to_first_cell_successful(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test move_to_first_cell successfully moves to first cell and presents it."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
mock_current_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
mock_table = test_context.Mock(spec=Atspi.Accessible)
|
|
mock_first_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
test_context.patch("cthulhu.table_navigator.AXUtilities.get_table", return_value=mock_table)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXTable.get_first_cell",
|
|
return_value=mock_first_cell,
|
|
)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
navigator._get_current_cell = test_context.Mock(return_value=mock_current_cell)
|
|
mock_present_cell = test_context.Mock()
|
|
navigator._present_cell = mock_present_cell
|
|
mock_script = test_context.Mock()
|
|
mock_event = test_context.Mock()
|
|
result = navigator.move_to_first_cell(mock_script, mock_event)
|
|
assert result is True
|
|
mock_present_cell.assert_called_once_with(
|
|
mock_script,
|
|
mock_first_cell,
|
|
0,
|
|
0,
|
|
mock_current_cell,
|
|
True,
|
|
)
|
|
|
|
def test_present_cell_not_cell_or_header(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test TableNavigator._present_cell returns early when object is not a cell or header."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXUtilities.is_table_cell_or_header",
|
|
return_value=False,
|
|
)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
mock_script = test_context.Mock()
|
|
mock_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
mock_previous_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
navigator._present_cell(mock_script, mock_cell, 1, 2, mock_previous_cell)
|
|
assert navigator._previous_reported_row != 1
|
|
assert navigator._previous_reported_col != 2
|
|
|
|
def test_present_cell_successful(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test TableNavigator._present_cell sets focus, coordinates, and presents cell."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXUtilities.is_table_cell_or_header",
|
|
return_value=True,
|
|
)
|
|
test_context.patch("cthulhu.table_navigator.AXObject.grab_focus", return_value=None)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXUtilities.get_descendant_supporting_text", return_value=None
|
|
)
|
|
test_context.patch("cthulhu.table_navigator.AXObject.supports_text", return_value=False)
|
|
test_context.patch("cthulhu.table_navigator.AXTable.get_cell_spans", return_value=(1, 1))
|
|
mock_focus_manager = test_context.Mock()
|
|
essential_modules["cthulhu.focus_manager"].get_manager.return_value = mock_focus_manager
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
|
|
from cthulhu import gsettings_registry
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
registry = gsettings_registry.get_registry()
|
|
registry.set_runtime_value("speech", "announce-cell-coordinates", False)
|
|
registry.set_runtime_value("speech", "announce-cell-span", False)
|
|
|
|
navigator = TableNavigator()
|
|
mock_script = test_context.Mock()
|
|
mock_script.utilities.grab_focus_when_setting_caret.return_value = False
|
|
test_context.patch("cthulhu.table_navigator.AXUtilities.is_gui_cell", return_value=False)
|
|
mock_script.present_object = test_context.Mock()
|
|
mock_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
mock_previous_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
navigator._present_cell(mock_script, mock_cell, 1, 2, mock_previous_cell)
|
|
assert navigator._previous_reported_row == 1
|
|
assert navigator._previous_reported_col == 2
|
|
mock_focus_manager.set_locus_of_focus.assert_called()
|
|
mock_script.present_object.assert_called_once_with(
|
|
mock_cell,
|
|
offset=0,
|
|
priorObj=mock_previous_cell,
|
|
interrupt=True,
|
|
)
|
|
|
|
def test_get_navigator(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test table_navigator.get_navigator returns singleton TableNavigator instance."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
from cthulhu import table_navigator
|
|
|
|
navigator1 = table_navigator.get_navigator()
|
|
navigator2 = table_navigator.get_navigator()
|
|
assert navigator1 is navigator2
|
|
assert isinstance(navigator1, table_navigator.TableNavigator)
|
|
|
|
def test_get_current_cell_needs_ancestor_search(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test _get_current_cell when cell is not table cell and needs ancestor search."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_initial_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
mock_ancestor_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
mock_focus_manager = test_context.Mock()
|
|
mock_focus_manager.get_locus_of_focus.return_value = mock_initial_cell
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.focus_manager.get_manager",
|
|
return_value=mock_focus_manager,
|
|
)
|
|
test_context.patch("cthulhu.table_navigator.AXObject.get_parent", return_value=None)
|
|
|
|
def mock_is_cell_or_header(obj):
|
|
return obj == mock_ancestor_cell
|
|
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXUtilities.is_table_cell_or_header",
|
|
new=mock_is_cell_or_header,
|
|
)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXUtilities.find_ancestor",
|
|
return_value=mock_ancestor_cell,
|
|
)
|
|
test_context.patch("cthulhu.table_navigator.debug.print_tokens", return_value=None)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
result = navigator._get_current_cell()
|
|
assert result == mock_ancestor_cell
|
|
|
|
def test_move_left_skip_blank_cells(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test TableNavigator.move_left skipping blank cells when setting is enabled."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
|
|
from cthulhu import gsettings_registry
|
|
|
|
gsettings_registry.get_registry().set_runtime_value(
|
|
"table-navigation",
|
|
"skip-blank-cells",
|
|
True,
|
|
)
|
|
mock_script = test_context.Mock()
|
|
mock_current_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
mock_blank_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
mock_final_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXTable.get_cell_coordinates",
|
|
return_value=(1, 1),
|
|
)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXTable.is_start_of_row",
|
|
side_effect=lambda cell: cell == mock_final_cell,
|
|
)
|
|
cell_sequence = [mock_blank_cell, mock_final_cell]
|
|
call_count = [0]
|
|
|
|
def mock_get_cell_on_left(_cell):
|
|
if call_count[0] < len(cell_sequence):
|
|
result = cell_sequence[call_count[0]]
|
|
call_count[0] += 1
|
|
return result
|
|
return None
|
|
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXTable.get_cell_on_left",
|
|
new=mock_get_cell_on_left,
|
|
)
|
|
|
|
def mock_is_blank(cell):
|
|
return cell == mock_blank_cell
|
|
|
|
test_context.patch("cthulhu.table_navigator.debug.print_tokens", return_value=None)
|
|
test_context.patch("cthulhu.table_navigator.TableNavigator._present_cell", return_value=None)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
navigator._is_blank = mock_is_blank
|
|
result = navigator.move_left(mock_script, mock_current_cell)
|
|
assert result is True
|
|
|
|
def test_move_right_at_end_of_row(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test TableNavigator.move_right when at end of row returns True and notifies user."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_script = test_context.Mock()
|
|
mock_current_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXTable.get_cell_coordinates",
|
|
return_value=(1, 5),
|
|
)
|
|
test_context.patch("cthulhu.table_navigator.AXTable.get_cell_on_right", return_value=None)
|
|
test_context.patch("cthulhu.table_navigator.AXTable.is_end_of_row", return_value=True)
|
|
test_context.patch("cthulhu.table_navigator.debug.print_tokens", return_value=None)
|
|
test_context.patch("cthulhu.table_navigator.TableNavigator._present_cell", return_value=None)
|
|
mock_focus_manager = test_context.Mock()
|
|
mock_focus_manager.get_locus_of_focus.return_value = mock_current_cell
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.focus_manager.get_manager",
|
|
return_value=mock_focus_manager,
|
|
)
|
|
test_context.patch("cthulhu.table_navigator.AXObject.get_parent", return_value=None)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXUtilities.is_table_cell_or_header",
|
|
return_value=True,
|
|
)
|
|
test_context.patch("cthulhu.table_navigator.AXUtilities.find_ancestor", return_value=None)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
pres_manager = essential_modules["cthulhu.presentation_manager"].get_manager()
|
|
pres_manager.present_message.reset_mock()
|
|
result = navigator.move_right(mock_script)
|
|
# move_right returns True even at end of row, but presents a message
|
|
assert result is True
|
|
pres_manager.present_message.assert_called_once()
|
|
|
|
def test_move_to_last_cell_not_in_table(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test move_to_last_cell presents not in table message when current cell is None."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
navigator._get_current_cell = test_context.Mock(return_value=None)
|
|
mock_script = test_context.Mock()
|
|
mock_event = test_context.Mock()
|
|
pres_manager = essential_modules["cthulhu.presentation_manager"].get_manager()
|
|
pres_manager.present_message.reset_mock()
|
|
result = navigator.move_to_last_cell(mock_script, mock_event)
|
|
assert result is True
|
|
pres_manager.present_message.assert_called_once_with(
|
|
essential_modules["cthulhu.messages"].TABLE_NOT_IN_A,
|
|
)
|
|
assert navigator._last_input_event == mock_event
|
|
|
|
def test_move_to_last_cell_successful(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test TableNavigator.move_to_last_cell successfully moves to last cell and presents it."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
mock_current_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
mock_table = test_context.Mock(spec=Atspi.Accessible)
|
|
mock_last_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
test_context.patch("cthulhu.table_navigator.AXUtilities.get_table", return_value=mock_table)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXTable.get_last_cell",
|
|
return_value=mock_last_cell,
|
|
)
|
|
test_context.patch("cthulhu.table_navigator.AXTable.get_row_count", return_value=5)
|
|
test_context.patch("cthulhu.table_navigator.AXTable.get_column_count", return_value=3)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
navigator._get_current_cell = test_context.Mock(return_value=mock_current_cell)
|
|
mock_present_cell = test_context.Mock()
|
|
navigator._present_cell = mock_present_cell
|
|
mock_script = test_context.Mock()
|
|
mock_event = test_context.Mock()
|
|
result = navigator.move_to_last_cell(mock_script, mock_event)
|
|
assert result is True
|
|
mock_present_cell.assert_called_once_with(
|
|
mock_script,
|
|
mock_last_cell,
|
|
5,
|
|
3,
|
|
mock_current_cell,
|
|
True,
|
|
)
|
|
|
|
def test_move_to_top_of_column_not_in_table(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test move_to_top_of_column presents not in table message when current cell is None."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
navigator._get_current_cell = test_context.Mock(return_value=None)
|
|
mock_script = test_context.Mock()
|
|
mock_event = test_context.Mock()
|
|
pres_manager = essential_modules["cthulhu.presentation_manager"].get_manager()
|
|
pres_manager.present_message.reset_mock()
|
|
result = navigator.move_to_top_of_column(mock_script, mock_event)
|
|
assert result is True
|
|
pres_manager.present_message.assert_called_once_with(
|
|
essential_modules["cthulhu.messages"].TABLE_NOT_IN_A,
|
|
)
|
|
|
|
def test_move_to_top_of_column_already_at_top(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test move_to_top_of_column presents column top message when already at top."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
mock_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
test_context.patch("cthulhu.table_navigator.AXTable.is_top_of_column", return_value=True)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
navigator._get_current_cell = test_context.Mock(return_value=mock_cell)
|
|
mock_script = test_context.Mock()
|
|
mock_event = test_context.Mock()
|
|
pres_manager = essential_modules["cthulhu.presentation_manager"].get_manager()
|
|
pres_manager.present_message.reset_mock()
|
|
result = navigator.move_to_top_of_column(mock_script, mock_event)
|
|
assert result is True
|
|
pres_manager.present_message.assert_called_once_with(
|
|
essential_modules["cthulhu.messages"].TABLE_COLUMN_TOP,
|
|
)
|
|
|
|
def test_move_to_top_of_column_successful(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test move_to_top_of_column successfully moves to top of column and presents it."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
mock_current_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
mock_top_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
test_context.patch("cthulhu.table_navigator.AXTable.is_top_of_column", return_value=False)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXTable.get_top_of_column",
|
|
return_value=mock_top_cell,
|
|
)
|
|
|
|
def mock_get_cell_coordinates(cell, prefer_attribute=False): # pylint: disable=unused-argument
|
|
if cell == mock_current_cell:
|
|
return (3, 1)
|
|
if cell == mock_top_cell:
|
|
return (0, 1)
|
|
return (0, 0)
|
|
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXTable.get_cell_coordinates",
|
|
new=mock_get_cell_coordinates,
|
|
)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
navigator._get_current_cell = test_context.Mock(return_value=mock_current_cell)
|
|
mock_present_cell = test_context.Mock()
|
|
navigator._present_cell = mock_present_cell
|
|
mock_script = test_context.Mock()
|
|
mock_event = test_context.Mock()
|
|
result = navigator.move_to_top_of_column(mock_script, mock_event)
|
|
assert result is True
|
|
mock_present_cell.assert_called_once_with(
|
|
mock_script,
|
|
mock_top_cell,
|
|
3,
|
|
1,
|
|
mock_current_cell,
|
|
True,
|
|
)
|
|
|
|
def test_move_to_bottom_of_column_not_in_table(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test move_to_bottom_of_column presents not in table message when current cell is None."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
navigator._get_current_cell = test_context.Mock(return_value=None)
|
|
mock_script = test_context.Mock()
|
|
mock_event = test_context.Mock()
|
|
pres_manager = essential_modules["cthulhu.presentation_manager"].get_manager()
|
|
pres_manager.present_message.reset_mock()
|
|
result = navigator.move_to_bottom_of_column(mock_script, mock_event)
|
|
assert result is True
|
|
pres_manager.present_message.assert_called_once_with(
|
|
essential_modules["cthulhu.messages"].TABLE_NOT_IN_A,
|
|
)
|
|
|
|
def test_move_to_bottom_of_column_already_at_bottom(
|
|
self,
|
|
test_context: CthulhuTestContext,
|
|
) -> None:
|
|
"""Test move_to_bottom_of_column presents column bottom message when already at bottom."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
mock_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXTable.is_bottom_of_column",
|
|
return_value=True,
|
|
)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
navigator._get_current_cell = test_context.Mock(return_value=mock_cell)
|
|
mock_script = test_context.Mock()
|
|
mock_event = test_context.Mock()
|
|
pres_manager = essential_modules["cthulhu.presentation_manager"].get_manager()
|
|
pres_manager.present_message.reset_mock()
|
|
result = navigator.move_to_bottom_of_column(mock_script, mock_event)
|
|
assert result is True
|
|
pres_manager.present_message.assert_called_once_with(
|
|
essential_modules["cthulhu.messages"].TABLE_COLUMN_BOTTOM,
|
|
)
|
|
|
|
def test_move_to_bottom_of_column_successful(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test move_to_bottom_of_column successfully moves to bottom of column and presents it."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
mock_current_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
mock_bottom_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXTable.is_bottom_of_column",
|
|
return_value=False,
|
|
)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXTable.get_bottom_of_column",
|
|
return_value=mock_bottom_cell,
|
|
)
|
|
|
|
def mock_get_cell_coordinates(cell, prefer_attribute=False): # pylint: disable=unused-argument
|
|
if cell == mock_current_cell:
|
|
return (1, 2)
|
|
if cell == mock_bottom_cell:
|
|
return (4, 2)
|
|
return (0, 0)
|
|
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXTable.get_cell_coordinates",
|
|
new=mock_get_cell_coordinates,
|
|
)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
navigator._get_current_cell = test_context.Mock(return_value=mock_current_cell)
|
|
mock_present_cell = test_context.Mock()
|
|
navigator._present_cell = mock_present_cell
|
|
mock_script = test_context.Mock()
|
|
mock_event = test_context.Mock()
|
|
result = navigator.move_to_bottom_of_column(mock_script, mock_event)
|
|
assert result is True
|
|
mock_present_cell.assert_called_once_with(
|
|
mock_script,
|
|
mock_bottom_cell,
|
|
1,
|
|
2,
|
|
mock_current_cell,
|
|
True,
|
|
)
|
|
|
|
def test_move_to_beginning_of_row_not_in_table(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test move_to_beginning_of_row presents not in table message when current cell is None."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
navigator._get_current_cell = test_context.Mock(return_value=None)
|
|
mock_script = test_context.Mock()
|
|
mock_event = test_context.Mock()
|
|
pres_manager = essential_modules["cthulhu.presentation_manager"].get_manager()
|
|
pres_manager.present_message.reset_mock()
|
|
result = navigator.move_to_beginning_of_row(mock_script, mock_event)
|
|
assert result is True
|
|
pres_manager.present_message.assert_called_once_with(
|
|
essential_modules["cthulhu.messages"].TABLE_NOT_IN_A,
|
|
)
|
|
|
|
def test_move_to_beginning_of_row_already_at_start(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test move_to_beginning_of_row presents row beginning message when already at start."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
mock_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
test_context.patch("cthulhu.table_navigator.AXTable.is_start_of_row", return_value=True)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
navigator._get_current_cell = test_context.Mock(return_value=mock_cell)
|
|
mock_script = test_context.Mock()
|
|
mock_event = test_context.Mock()
|
|
pres_manager = essential_modules["cthulhu.presentation_manager"].get_manager()
|
|
pres_manager.present_message.reset_mock()
|
|
result = navigator.move_to_beginning_of_row(mock_script, mock_event)
|
|
assert result is True
|
|
pres_manager.present_message.assert_called_once_with(
|
|
essential_modules["cthulhu.messages"].TABLE_ROW_BEGINNING,
|
|
)
|
|
|
|
def test_move_to_beginning_of_row_successful(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test move_to_beginning_of_row successfully moves to beginning of row and presents it."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
mock_current_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
mock_start_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
test_context.patch("cthulhu.table_navigator.AXTable.is_start_of_row", return_value=False)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXTable.get_start_of_row",
|
|
return_value=mock_start_cell,
|
|
)
|
|
|
|
def mock_get_cell_coordinates(cell, prefer_attribute=False): # pylint: disable=unused-argument
|
|
if cell == mock_start_cell:
|
|
return (2, 0)
|
|
return (2, 3)
|
|
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXTable.get_cell_coordinates",
|
|
new=mock_get_cell_coordinates,
|
|
)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
navigator._get_current_cell = test_context.Mock(return_value=mock_current_cell)
|
|
mock_present_cell = test_context.Mock()
|
|
navigator._present_cell = mock_present_cell
|
|
mock_script = test_context.Mock()
|
|
mock_event = test_context.Mock()
|
|
result = navigator.move_to_beginning_of_row(mock_script, mock_event)
|
|
assert result is True
|
|
mock_present_cell.assert_called_once_with(
|
|
mock_script,
|
|
mock_start_cell,
|
|
2,
|
|
0,
|
|
mock_current_cell,
|
|
True,
|
|
)
|
|
|
|
def test_move_to_end_of_row_not_in_table(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test move_to_end_of_row presents not in table message when current cell is None."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
navigator._get_current_cell = test_context.Mock(return_value=None)
|
|
mock_script = test_context.Mock()
|
|
mock_event = test_context.Mock()
|
|
pres_manager = essential_modules["cthulhu.presentation_manager"].get_manager()
|
|
pres_manager.present_message.reset_mock()
|
|
result = navigator.move_to_end_of_row(mock_script, mock_event)
|
|
assert result is True
|
|
pres_manager.present_message.assert_called_once_with(
|
|
essential_modules["cthulhu.messages"].TABLE_NOT_IN_A,
|
|
)
|
|
|
|
def test_move_to_end_of_row_already_at_end(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test move_to_end_of_row presents row end message when already at end."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
mock_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
test_context.patch("cthulhu.table_navigator.AXTable.is_end_of_row", return_value=True)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
navigator._get_current_cell = test_context.Mock(return_value=mock_cell)
|
|
mock_script = test_context.Mock()
|
|
mock_event = test_context.Mock()
|
|
pres_manager = essential_modules["cthulhu.presentation_manager"].get_manager()
|
|
pres_manager.present_message.reset_mock()
|
|
result = navigator.move_to_end_of_row(mock_script, mock_event)
|
|
assert result is True
|
|
pres_manager.present_message.assert_called_once_with(
|
|
essential_modules["cthulhu.messages"].TABLE_ROW_END,
|
|
)
|
|
|
|
def test_move_to_end_of_row_successful(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test move_to_end_of_row successfully moves to end of row and presents it."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
mock_current_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
mock_end_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
test_context.patch("cthulhu.table_navigator.AXTable.is_end_of_row", return_value=False)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXTable.get_end_of_row",
|
|
return_value=mock_end_cell,
|
|
)
|
|
|
|
def mock_get_cell_coordinates(cell, prefer_attribute=False): # pylint: disable=unused-argument
|
|
if cell == mock_end_cell:
|
|
return (2, 4)
|
|
return (2, 1)
|
|
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXTable.get_cell_coordinates",
|
|
new=mock_get_cell_coordinates,
|
|
)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
navigator._get_current_cell = test_context.Mock(return_value=mock_current_cell)
|
|
mock_present_cell = test_context.Mock()
|
|
navigator._present_cell = mock_present_cell
|
|
mock_script = test_context.Mock()
|
|
mock_event = test_context.Mock()
|
|
result = navigator.move_to_end_of_row(mock_script, mock_event)
|
|
assert result is True
|
|
mock_present_cell.assert_called_once_with(
|
|
mock_script,
|
|
mock_end_cell,
|
|
2,
|
|
4,
|
|
mock_current_cell,
|
|
True,
|
|
)
|
|
|
|
def test_set_dynamic_column_headers_row_not_in_table(
|
|
self,
|
|
test_context: CthulhuTestContext,
|
|
) -> None:
|
|
"""Test set_dynamic_column_headers_row presents not in table message.
|
|
|
|
Test case when current cell is None.
|
|
"""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
navigator._get_current_cell = test_context.Mock(return_value=None)
|
|
mock_script = test_context.Mock()
|
|
mock_event = test_context.Mock()
|
|
pres_manager = essential_modules["cthulhu.presentation_manager"].get_manager()
|
|
pres_manager.present_message.reset_mock()
|
|
result = navigator.set_dynamic_column_headers_row(mock_script, mock_event)
|
|
assert result is True
|
|
pres_manager.present_message.assert_called_once_with(
|
|
essential_modules["cthulhu.messages"].TABLE_NOT_IN_A,
|
|
)
|
|
|
|
def test_set_dynamic_column_headers_row_successful(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test set_dynamic_column_headers_row successfully sets column headers row."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
mock_current_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
mock_table = test_context.Mock(spec=Atspi.Accessible)
|
|
test_context.patch("cthulhu.table_navigator.AXUtilities.get_table", return_value=mock_table)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXTable.get_cell_coordinates",
|
|
return_value=(1, 2),
|
|
)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXUtilities.set_dynamic_column_headers_row",
|
|
return_value=None,
|
|
)
|
|
essential_modules["cthulhu.messages"].DYNAMIC_COLUMN_HEADER_SET = "Column header row set to %d"
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
navigator._get_current_cell = test_context.Mock(return_value=mock_current_cell)
|
|
mock_script = test_context.Mock()
|
|
mock_event = test_context.Mock()
|
|
pres_manager = essential_modules["cthulhu.presentation_manager"].get_manager()
|
|
pres_manager.present_message.reset_mock()
|
|
result = navigator.set_dynamic_column_headers_row(mock_script, mock_event)
|
|
assert result is True
|
|
pres_manager.present_message.assert_called_once_with("Column header row set to 2")
|
|
|
|
def test_clear_dynamic_column_headers_row_not_in_table(
|
|
self,
|
|
test_context: CthulhuTestContext,
|
|
) -> None:
|
|
"""Test clear_dynamic_column_headers_row presents not in table message.
|
|
|
|
Test case when current cell is None.
|
|
"""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
navigator._get_current_cell = test_context.Mock(return_value=None)
|
|
mock_script = test_context.Mock()
|
|
mock_event = test_context.Mock()
|
|
pres_manager = essential_modules["cthulhu.presentation_manager"].get_manager()
|
|
pres_manager.present_message.reset_mock()
|
|
result = navigator.clear_dynamic_column_headers_row(mock_script, mock_event)
|
|
assert result is True
|
|
pres_manager.present_message.assert_called_once_with(
|
|
essential_modules["cthulhu.messages"].TABLE_NOT_IN_A,
|
|
)
|
|
|
|
def test_clear_dynamic_column_headers_row_successful(
|
|
self,
|
|
test_context: CthulhuTestContext,
|
|
) -> None:
|
|
"""Test clear_dynamic_column_headers_row successfully clears column headers row."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
mock_current_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
mock_table = test_context.Mock(spec=Atspi.Accessible)
|
|
mock_focus_manager = test_context.Mock()
|
|
essential_modules["cthulhu.focus_manager"].get_manager.return_value = mock_focus_manager
|
|
mock_focus_manager.get_locus_of_focus.return_value = mock_current_cell
|
|
test_context.patch("cthulhu.table_navigator.AXUtilities.get_table", return_value=mock_table)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXUtilities.clear_dynamic_column_headers_row",
|
|
return_value=None,
|
|
)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
navigator._get_current_cell = test_context.Mock(return_value=mock_current_cell)
|
|
mock_script = test_context.Mock()
|
|
mock_event = test_context.Mock()
|
|
pres_manager = essential_modules["cthulhu.presentation_manager"].get_manager()
|
|
pres_manager.present_message.reset_mock()
|
|
pres_manager.interrupt_presentation.reset_mock()
|
|
result = navigator.clear_dynamic_column_headers_row(mock_script, mock_event)
|
|
assert result is True
|
|
pres_manager.interrupt_presentation.assert_called_once()
|
|
pres_manager.present_message.assert_called_once_with(
|
|
essential_modules["cthulhu.messages"].DYNAMIC_COLUMN_HEADER_CLEARED,
|
|
)
|
|
|
|
def test_set_dynamic_row_headers_column_not_in_table(
|
|
self,
|
|
test_context: CthulhuTestContext,
|
|
) -> None:
|
|
"""Test set_dynamic_row_headers_column presents not in table message.
|
|
|
|
Test case when current cell is None.
|
|
"""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
navigator._get_current_cell = test_context.Mock(return_value=None)
|
|
mock_script = test_context.Mock()
|
|
mock_event = test_context.Mock()
|
|
pres_manager = essential_modules["cthulhu.presentation_manager"].get_manager()
|
|
pres_manager.present_message.reset_mock()
|
|
result = navigator.set_dynamic_row_headers_column(mock_script, mock_event)
|
|
assert result is True
|
|
pres_manager.present_message.assert_called_once_with(
|
|
essential_modules["cthulhu.messages"].TABLE_NOT_IN_A,
|
|
)
|
|
|
|
def test_set_dynamic_row_headers_column_successful(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test set_dynamic_row_headers_column successfully sets row headers column."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
mock_current_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
mock_table = test_context.Mock(spec=Atspi.Accessible)
|
|
test_context.patch("cthulhu.table_navigator.AXUtilities.get_table", return_value=mock_table)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXTable.get_cell_coordinates",
|
|
return_value=(2, 1),
|
|
)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXUtilities.set_dynamic_row_headers_column",
|
|
return_value=None,
|
|
)
|
|
essential_modules["cthulhu.messages"].DYNAMIC_ROW_HEADER_SET = "Row header column set to %s"
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXUtilities.get_column_label",
|
|
create=True,
|
|
return_value="B",
|
|
)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
navigator._get_current_cell = test_context.Mock(return_value=mock_current_cell)
|
|
mock_script = test_context.Mock()
|
|
mock_event = test_context.Mock()
|
|
pres_manager = essential_modules["cthulhu.presentation_manager"].get_manager()
|
|
pres_manager.present_message.reset_mock()
|
|
result = navigator.set_dynamic_row_headers_column(mock_script, mock_event)
|
|
assert result is True
|
|
pres_manager.present_message.assert_called_once_with("Row header column set to B")
|
|
|
|
def test_clear_dynamic_row_headers_column_not_in_table(
|
|
self,
|
|
test_context: CthulhuTestContext,
|
|
) -> None:
|
|
"""Test clear_dynamic_row_headers_column presents not in table message.
|
|
|
|
Test case when current cell is None.
|
|
"""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
navigator._get_current_cell = test_context.Mock(return_value=None)
|
|
mock_script = test_context.Mock()
|
|
mock_event = test_context.Mock()
|
|
pres_manager = essential_modules["cthulhu.presentation_manager"].get_manager()
|
|
pres_manager.present_message.reset_mock()
|
|
result = navigator.clear_dynamic_row_headers_column(mock_script, mock_event)
|
|
assert result is True
|
|
pres_manager.present_message.assert_called_once_with(
|
|
essential_modules["cthulhu.messages"].TABLE_NOT_IN_A,
|
|
)
|
|
|
|
def test_clear_dynamic_row_headers_column_successful(
|
|
self,
|
|
test_context: CthulhuTestContext,
|
|
) -> None:
|
|
"""Test clear_dynamic_row_headers_column successfully clears row headers column."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
mock_current_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
mock_table = test_context.Mock(spec=Atspi.Accessible)
|
|
mock_focus_manager = test_context.Mock()
|
|
essential_modules["cthulhu.focus_manager"].get_manager.return_value = mock_focus_manager
|
|
mock_focus_manager.get_locus_of_focus.return_value = mock_current_cell
|
|
test_context.patch("cthulhu.table_navigator.AXUtilities.get_table", return_value=mock_table)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXUtilities.clear_dynamic_row_headers_column",
|
|
return_value=None,
|
|
)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
navigator._get_current_cell = test_context.Mock(return_value=mock_current_cell)
|
|
mock_script = test_context.Mock()
|
|
mock_event = test_context.Mock()
|
|
pres_manager = essential_modules["cthulhu.presentation_manager"].get_manager()
|
|
pres_manager.present_message.reset_mock()
|
|
pres_manager.interrupt_presentation.reset_mock()
|
|
result = navigator.clear_dynamic_row_headers_column(mock_script, mock_event)
|
|
assert result is True
|
|
pres_manager.interrupt_presentation.assert_called_once()
|
|
pres_manager.present_message.assert_called_once_with(
|
|
essential_modules["cthulhu.messages"].DYNAMIC_ROW_HEADER_CLEARED,
|
|
)
|
|
|
|
def test_get_cell_coordinates_with_different_previous_cell(
|
|
self,
|
|
test_context: CthulhuTestContext,
|
|
) -> None:
|
|
"""Test _get_cell_coordinates returns actual coordinates when previous cell differs."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
mock_table = test_context.Mock(spec=Atspi.Accessible)
|
|
mock_different_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXTable.get_cell_coordinates",
|
|
return_value=(2, 3),
|
|
)
|
|
test_context.patch("cthulhu.table_navigator.AXUtilities.get_table", return_value=mock_table)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXTable.get_cell_at",
|
|
return_value=mock_different_cell,
|
|
)
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
navigator._previous_reported_row = 1
|
|
navigator._previous_reported_col = 2
|
|
result = navigator._get_cell_coordinates(mock_cell)
|
|
assert result == (2, 3)
|
|
|
|
def test_present_cell_with_settings_enabled(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test _present_cell with speakCellCoordinates and speakCellSpan enabled."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXUtilities.is_table_cell_or_header",
|
|
return_value=True,
|
|
)
|
|
test_context.patch("cthulhu.table_navigator.AXObject.grab_focus", return_value=None)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXUtilities.get_descendant_supporting_text", return_value=None
|
|
)
|
|
test_context.patch("cthulhu.table_navigator.AXObject.supports_text", return_value=False)
|
|
test_context.patch("cthulhu.table_navigator.AXTable.get_cell_spans", return_value=(2, 3))
|
|
mock_focus_manager = test_context.Mock()
|
|
essential_modules["cthulhu.focus_manager"].get_manager.return_value = mock_focus_manager
|
|
essential_modules["cthulhu.messages"].TABLE_CELL_COORDINATES = "Row %(row)s, column %(column)s"
|
|
essential_modules["cthulhu.messages"].cell_span.return_value = "spans 2 rows and 3 columns"
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
mock_script = test_context.Mock()
|
|
mock_script.utilities.grab_focus_when_setting_caret.return_value = False
|
|
test_context.patch("cthulhu.table_navigator.AXUtilities.is_gui_cell", return_value=False)
|
|
mock_script.present_object = test_context.Mock()
|
|
mock_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
mock_previous_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
pres_manager = essential_modules["cthulhu.presentation_manager"].get_manager()
|
|
pres_manager.present_message.reset_mock()
|
|
navigator._present_cell(mock_script, mock_cell, 1, 2, mock_previous_cell)
|
|
assert navigator._previous_reported_row == 1
|
|
assert navigator._previous_reported_col == 2
|
|
mock_focus_manager.set_locus_of_focus.assert_called()
|
|
mock_script.present_object.assert_called_once_with(
|
|
mock_cell,
|
|
offset=0,
|
|
priorObj=mock_previous_cell,
|
|
interrupt=True,
|
|
)
|
|
assert pres_manager.present_message.call_count == 2
|
|
|
|
def test_present_cell_with_text_descendant_and_gui_cell(
|
|
self,
|
|
test_context: CthulhuTestContext,
|
|
) -> None:
|
|
"""Test _present_cell when cell has text descendant and is gui cell."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
mock_text_obj = test_context.Mock(spec=Atspi.Accessible)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXUtilities.is_table_cell_or_header",
|
|
return_value=True,
|
|
)
|
|
test_context.patch("cthulhu.table_navigator.AXObject.grab_focus", return_value=None)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXUtilities.get_descendant_supporting_text",
|
|
return_value=mock_text_obj,
|
|
)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXObject.supports_text",
|
|
side_effect=lambda obj: obj == mock_text_obj,
|
|
)
|
|
test_context.patch("cthulhu.table_navigator.AXTable.get_cell_spans", return_value=(1, 1))
|
|
mock_focus_manager = test_context.Mock()
|
|
essential_modules["cthulhu.focus_manager"].get_manager.return_value = mock_focus_manager
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
|
|
from cthulhu import gsettings_registry
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
registry = gsettings_registry.get_registry()
|
|
registry.set_runtime_value("speech", "announce-cell-coordinates", False)
|
|
registry.set_runtime_value("speech", "announce-cell-span", False)
|
|
|
|
navigator = TableNavigator()
|
|
mock_script = test_context.Mock()
|
|
mock_script.utilities.grab_focus_when_setting_caret.return_value = True
|
|
test_context.patch("cthulhu.table_navigator.AXUtilities.is_gui_cell", return_value=True)
|
|
mock_script.utilities.set_caret_position = test_context.Mock()
|
|
mock_script.present_object = test_context.Mock()
|
|
mock_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
mock_previous_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
navigator._present_cell(mock_script, mock_cell, 1, 2, mock_previous_cell)
|
|
mock_focus_manager.set_locus_of_focus.assert_called_with(None, mock_text_obj, False)
|
|
assert navigator._previous_reported_row == 1
|
|
assert navigator._previous_reported_col == 2
|
|
|
|
def test_get_skip_blank_cells(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test TableNavigator.get_skip_blank_cells returns setting value."""
|
|
|
|
self._setup_dependencies(test_context)
|
|
|
|
from cthulhu import gsettings_registry
|
|
from cthulhu.table_navigator import get_navigator
|
|
|
|
gsettings_registry.get_registry().set_runtime_value(
|
|
"table-navigation",
|
|
"skip-blank-cells",
|
|
True,
|
|
)
|
|
nav = get_navigator()
|
|
result = nav.get_skip_blank_cells()
|
|
assert result is True
|
|
|
|
def test_set_skip_blank_cells(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test TableNavigator.set_skip_blank_cells updates setting."""
|
|
|
|
self._setup_dependencies(test_context)
|
|
from cthulhu.table_navigator import get_navigator
|
|
|
|
nav = get_navigator()
|
|
result = nav.set_skip_blank_cells(True)
|
|
assert result is True
|
|
assert nav.get_skip_blank_cells() is True
|
|
|
|
def test_set_skip_blank_cells_no_change(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test TableNavigator.set_skip_blank_cells returns early if value unchanged."""
|
|
|
|
self._setup_dependencies(test_context)
|
|
|
|
from cthulhu import gsettings_registry
|
|
from cthulhu.table_navigator import get_navigator
|
|
|
|
gsettings_registry.get_registry().set_runtime_value(
|
|
"table-navigation",
|
|
"skip-blank-cells",
|
|
True,
|
|
)
|
|
nav = get_navigator()
|
|
result = nav.set_skip_blank_cells(True)
|
|
assert result is True
|
|
|
|
def test_present_cell_emits_region_changed(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test _present_cell emits region_changed with TABLE_NAVIGATOR mode."""
|
|
|
|
essential_modules = self._setup_dependencies(test_context)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXUtilities.is_table_cell_or_header",
|
|
return_value=True,
|
|
)
|
|
test_context.patch("cthulhu.table_navigator.AXObject.grab_focus", return_value=None)
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.AXUtilities.get_descendant_supporting_text", return_value=None
|
|
)
|
|
test_context.patch("cthulhu.table_navigator.AXObject.supports_text", return_value=False)
|
|
test_context.patch("cthulhu.table_navigator.AXTable.get_cell_spans", return_value=(1, 1))
|
|
mock_focus_manager = test_context.Mock()
|
|
essential_modules["cthulhu.focus_manager"].get_manager.return_value = mock_focus_manager
|
|
|
|
from cthulhu import focus_manager, gsettings_registry
|
|
|
|
essential_modules["cthulhu.focus_manager"].TABLE_NAVIGATOR = focus_manager.TABLE_NAVIGATOR
|
|
registry = gsettings_registry.get_registry()
|
|
registry.set_runtime_value("speech", "announce-cell-coordinates", False)
|
|
registry.set_runtime_value("speech", "announce-cell-span", False)
|
|
|
|
mock_controller = test_context.Mock()
|
|
essential_modules["cthulhu.dbus_service"].get_remote_controller.return_value = mock_controller
|
|
mock_keybindings_class = test_context.Mock()
|
|
mock_keybindings_instance = test_context.Mock()
|
|
mock_keybindings_class.return_value = mock_keybindings_instance
|
|
test_context.patch(
|
|
"cthulhu.table_navigator.keybindings.KeyBindings",
|
|
new=mock_keybindings_class,
|
|
)
|
|
from cthulhu.table_navigator import TableNavigator
|
|
|
|
navigator = TableNavigator()
|
|
mock_script = test_context.Mock()
|
|
mock_script.utilities.grab_focus_when_setting_caret.return_value = False
|
|
test_context.patch("cthulhu.table_navigator.AXUtilities.is_gui_cell", return_value=False)
|
|
mock_script.present_object = test_context.Mock()
|
|
mock_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
mock_previous_cell = test_context.Mock(spec=Atspi.Accessible)
|
|
|
|
navigator._present_cell(mock_script, mock_cell, 1, 2, mock_previous_cell)
|
|
|
|
mock_focus_manager.emit_region_changed.assert_called()
|
|
call_kwargs = mock_focus_manager.emit_region_changed.call_args
|
|
assert call_kwargs.kwargs.get("mode") == focus_manager.TABLE_NAVIGATOR
|