2332 lines
89 KiB
Python
2332 lines
89 KiB
Python
# Unit tests for document_presenter.py.
|
|
#
|
|
# Copyright 2026 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=protected-access
|
|
# pylint: disable=import-outside-toplevel
|
|
# pylint: disable=too-many-public-methods
|
|
# pylint: disable=too-many-locals
|
|
|
|
# pylint: disable=too-many-lines
|
|
"""Unit tests for document_presenter.py."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import TYPE_CHECKING
|
|
|
|
import pytest
|
|
|
|
if TYPE_CHECKING:
|
|
from cthulhu_test_context import CthulhuTestContext
|
|
|
|
|
|
@pytest.mark.unit
|
|
class TestDocumentPresenter:
|
|
"""Test DocumentPresenter class."""
|
|
|
|
def _setup_presenter(self, test_context: CthulhuTestContext):
|
|
"""Set up mocks for document_presenter dependencies."""
|
|
|
|
additional_modules = [
|
|
"cthulhu.ax_document",
|
|
"cthulhu.ax_object",
|
|
"cthulhu.ax_table",
|
|
"cthulhu.ax_text",
|
|
"cthulhu.ax_utilities",
|
|
"cthulhu.caret_navigator",
|
|
"cthulhu.focus_manager",
|
|
"cthulhu.guilabels",
|
|
"cthulhu.input_event_manager",
|
|
"cthulhu.live_region_presenter",
|
|
"cthulhu.preferences_grid_base",
|
|
"cthulhu.script_manager",
|
|
"cthulhu.structural_navigator",
|
|
"cthulhu.table_navigator",
|
|
"cthulhu.braille_presenter",
|
|
"cthulhu.presentation_manager",
|
|
]
|
|
essential_modules = test_context.setup_shared_dependencies(additional_modules)
|
|
|
|
# Set up guilabels with required constants
|
|
guilabels = essential_modules["cthulhu.guilabels"]
|
|
guilabels.DOCUMENTS = "Documents"
|
|
guilabels.KB_GROUP_CARET_NAVIGATION = "Caret Navigation"
|
|
guilabels.KB_GROUP_STRUCTURAL_NAVIGATION = "Structural Navigation"
|
|
guilabels.KB_GROUP_TABLE_NAVIGATION = "Table Navigation"
|
|
guilabels.NATIVE_NAVIGATION = "Native Navigation"
|
|
guilabels.AUTOMATIC_FOCUS_MODE = "Automatic focus mode"
|
|
guilabels.CONTENT_LAYOUT_MODE = "Layout mode"
|
|
guilabels.TABLE_SKIP_BLANK_CELLS = "Skip blank cells"
|
|
guilabels.FIND_SPEAK_RESULTS = "Speak find results"
|
|
guilabels.FIND_ONLY_SPEAK_CHANGED_LINES = "Only speak changed lines"
|
|
guilabels.FIND_MINIMUM_MATCH_LENGTH = "Minimum match length"
|
|
guilabels.FIND_OPTIONS = "Find Options"
|
|
guilabels.READ_PAGE_UPON_LOAD = "Read page upon load"
|
|
guilabels.PAGE_SUMMARY_UPON_LOAD = "Page summary upon load"
|
|
guilabels.PAGE_LOAD = "Page Load"
|
|
guilabels.CARET_NAVIGATION_INFO = "Caret navigation info"
|
|
guilabels.STRUCTURAL_NAVIGATION_INFO = "Structural navigation info"
|
|
guilabels.NATIVE_NAVIGATION_INFO = "Native navigation info"
|
|
guilabels.AUTOMATIC_FOCUS_MODE_INFO = "Auto focus mode info"
|
|
|
|
from cthulhu import gsettings_registry
|
|
|
|
registry = gsettings_registry.get_registry()
|
|
registry.clear_runtime_values()
|
|
|
|
# Import and return the module
|
|
from cthulhu import document_presenter
|
|
|
|
return document_presenter, essential_modules
|
|
|
|
def test_get_presenter_returns_singleton(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test get_presenter returns the same instance."""
|
|
|
|
module, _mocks = self._setup_presenter(test_context)
|
|
presenter1 = module.get_presenter()
|
|
presenter2 = module.get_presenter()
|
|
|
|
assert presenter1 is presenter2
|
|
|
|
def test_get_native_nav_triggers_focus_mode_default(
|
|
self,
|
|
test_context: CthulhuTestContext,
|
|
) -> None:
|
|
"""Test get_native_nav_triggers_focus_mode returns default value."""
|
|
|
|
module, _mocks = self._setup_presenter(test_context)
|
|
|
|
presenter = module.get_presenter()
|
|
result = presenter.get_native_nav_triggers_focus_mode()
|
|
|
|
assert result is True
|
|
|
|
def test_set_native_nav_triggers_focus_mode(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test set_native_nav_triggers_focus_mode updates setting."""
|
|
|
|
module, _mocks = self._setup_presenter(test_context)
|
|
|
|
presenter = module.get_presenter()
|
|
result = presenter.set_native_nav_triggers_focus_mode(False)
|
|
|
|
assert result is True
|
|
assert presenter.get_native_nav_triggers_focus_mode() is False
|
|
|
|
def test_set_native_nav_triggers_focus_mode_no_change(
|
|
self,
|
|
test_context: CthulhuTestContext,
|
|
) -> None:
|
|
"""Test set_native_nav_triggers_focus_mode returns True when value unchanged."""
|
|
|
|
module, _mocks = self._setup_presenter(test_context)
|
|
|
|
presenter = module.get_presenter()
|
|
result = presenter.set_native_nav_triggers_focus_mode(True)
|
|
|
|
assert result is True
|
|
|
|
def test_get_say_all_on_load_default(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test get_say_all_on_load returns default value."""
|
|
|
|
module, _mocks = self._setup_presenter(test_context)
|
|
|
|
presenter = module.get_presenter()
|
|
result = presenter.get_say_all_on_load()
|
|
|
|
assert result is True
|
|
|
|
def test_set_say_all_on_load(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test set_say_all_on_load updates setting."""
|
|
|
|
module, _mocks = self._setup_presenter(test_context)
|
|
|
|
presenter = module.get_presenter()
|
|
result = presenter.set_say_all_on_load(False)
|
|
|
|
assert result is True
|
|
assert presenter.get_say_all_on_load() is False
|
|
|
|
def test_set_say_all_on_load_no_change(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test set_say_all_on_load returns True when value unchanged."""
|
|
|
|
module, _mocks = self._setup_presenter(test_context)
|
|
|
|
presenter = module.get_presenter()
|
|
result = presenter.set_say_all_on_load(True)
|
|
|
|
assert result is True
|
|
|
|
def test_get_page_summary_on_load_default(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test get_page_summary_on_load returns default value."""
|
|
|
|
module, _mocks = self._setup_presenter(test_context)
|
|
|
|
presenter = module.get_presenter()
|
|
result = presenter.get_page_summary_on_load()
|
|
|
|
assert result is True
|
|
|
|
def test_set_page_summary_on_load(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test set_page_summary_on_load updates setting."""
|
|
|
|
module, _mocks = self._setup_presenter(test_context)
|
|
|
|
presenter = module.get_presenter()
|
|
result = presenter.set_page_summary_on_load(False)
|
|
|
|
assert result is True
|
|
assert presenter.get_page_summary_on_load() is False
|
|
|
|
def test_set_page_summary_on_load_no_change(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test set_page_summary_on_load returns True when value unchanged."""
|
|
|
|
module, _mocks = self._setup_presenter(test_context)
|
|
|
|
presenter = module.get_presenter()
|
|
result = presenter.set_page_summary_on_load(True)
|
|
|
|
assert result is True
|
|
|
|
def test_get_speak_find_results_true(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test get_speak_find_results returns True when verbosity is not NONE."""
|
|
|
|
module, _mocks = self._setup_presenter(test_context)
|
|
|
|
presenter = module.get_presenter()
|
|
result = presenter.get_speak_find_results()
|
|
|
|
assert result is True
|
|
|
|
def test_get_speak_find_results_false(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test get_speak_find_results returns False when verbosity is NONE."""
|
|
|
|
module, _mocks = self._setup_presenter(test_context)
|
|
from cthulhu import gsettings_registry # pylint: disable=import-outside-toplevel
|
|
|
|
presenter = module.get_presenter()
|
|
gsettings_registry.get_registry().set_runtime_value(
|
|
"document",
|
|
"find-results-verbosity",
|
|
"none",
|
|
)
|
|
result = presenter.get_speak_find_results()
|
|
|
|
assert result is False
|
|
|
|
def test_set_speak_find_results_enable(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test set_speak_find_results enables speech."""
|
|
|
|
module, _mocks = self._setup_presenter(test_context)
|
|
from cthulhu import gsettings_registry # pylint: disable=import-outside-toplevel
|
|
|
|
presenter = module.get_presenter()
|
|
gsettings_registry.get_registry().set_runtime_value(
|
|
"document",
|
|
"find-results-verbosity",
|
|
"none",
|
|
)
|
|
result = presenter.set_speak_find_results(True)
|
|
|
|
assert result is True
|
|
assert presenter.get_speak_find_results() is True
|
|
|
|
def test_set_speak_find_results_disable(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test set_speak_find_results disables speech."""
|
|
|
|
module, _mocks = self._setup_presenter(test_context)
|
|
|
|
presenter = module.get_presenter()
|
|
result = presenter.set_speak_find_results(False)
|
|
|
|
assert result is True
|
|
assert presenter.get_speak_find_results() is False
|
|
|
|
def test_get_only_speak_changed_lines_true(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test get_only_speak_changed_lines returns True when set."""
|
|
|
|
module, _mocks = self._setup_presenter(test_context)
|
|
from cthulhu import gsettings_registry # pylint: disable=import-outside-toplevel
|
|
|
|
presenter = module.get_presenter()
|
|
gsettings_registry.get_registry().set_runtime_value(
|
|
"document",
|
|
"find-results-verbosity",
|
|
"if-line-changed",
|
|
)
|
|
result = presenter.get_only_speak_changed_lines()
|
|
|
|
assert result is True
|
|
|
|
def test_get_only_speak_changed_lines_false(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test get_only_speak_changed_lines returns False when not set."""
|
|
|
|
module, _mocks = self._setup_presenter(test_context)
|
|
|
|
presenter = module.get_presenter()
|
|
result = presenter.get_only_speak_changed_lines()
|
|
|
|
assert result is False
|
|
|
|
def test_set_only_speak_changed_lines_enable(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test set_only_speak_changed_lines enables the option."""
|
|
|
|
module, _mocks = self._setup_presenter(test_context)
|
|
|
|
presenter = module.get_presenter()
|
|
result = presenter.set_only_speak_changed_lines(True)
|
|
|
|
assert result is True
|
|
assert presenter.get_only_speak_changed_lines() is True
|
|
|
|
def test_set_only_speak_changed_lines_disable(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test set_only_speak_changed_lines disables the option."""
|
|
|
|
module, _mocks = self._setup_presenter(test_context)
|
|
from cthulhu import gsettings_registry # pylint: disable=import-outside-toplevel
|
|
|
|
presenter = module.get_presenter()
|
|
gsettings_registry.get_registry().set_runtime_value(
|
|
"document",
|
|
"find-results-verbosity",
|
|
"if-line-changed",
|
|
)
|
|
result = presenter.set_only_speak_changed_lines(False)
|
|
|
|
assert result is True
|
|
assert presenter.get_only_speak_changed_lines() is False
|
|
|
|
def test_get_find_results_minimum_length(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test get_find_results_minimum_length returns current value."""
|
|
|
|
module, _mocks = self._setup_presenter(test_context)
|
|
|
|
presenter = module.get_presenter()
|
|
presenter.set_find_results_minimum_length(5)
|
|
result = presenter.get_find_results_minimum_length()
|
|
|
|
assert result == 5
|
|
|
|
def test_set_find_results_minimum_length(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test set_find_results_minimum_length updates setting."""
|
|
|
|
module, _mocks = self._setup_presenter(test_context)
|
|
|
|
presenter = module.get_presenter()
|
|
presenter.set_find_results_minimum_length(5)
|
|
result = presenter.set_find_results_minimum_length(10)
|
|
|
|
assert result is True
|
|
assert presenter.get_find_results_minimum_length() == 10
|
|
|
|
def test_set_find_results_minimum_length_no_change(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test set_find_results_minimum_length returns True when value unchanged."""
|
|
|
|
module, _mocks = self._setup_presenter(test_context)
|
|
|
|
presenter = module.get_presenter()
|
|
presenter.set_find_results_minimum_length(5)
|
|
result = presenter.set_find_results_minimum_length(5)
|
|
|
|
assert result is True
|
|
|
|
def test_reset_find_announcement_state(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test reset_find_announcement_state resets the internal state."""
|
|
|
|
module, _mocks = self._setup_presenter(test_context)
|
|
presenter = module.get_presenter()
|
|
|
|
# Set the internal state to True
|
|
presenter._made_find_announcement = True
|
|
assert presenter._made_find_announcement is True
|
|
|
|
# Reset and verify
|
|
presenter.reset_find_announcement_state()
|
|
assert presenter._made_find_announcement is False
|
|
|
|
def test_present_find_results_no_active_script(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test present_find_results returns False when no active script."""
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
script_manager = mocks["cthulhu.script_manager"]
|
|
script_manager.get_manager.return_value.get_active_script.return_value = None
|
|
|
|
presenter = module.get_presenter()
|
|
result = presenter.present_find_results(None, 0)
|
|
|
|
assert result is False
|
|
|
|
def test_present_find_results_no_document(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test present_find_results returns False when no document."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
# Set up mock script with utilities
|
|
mock_script = MagicMock()
|
|
mock_script.utilities.get_document_for_object.return_value = None
|
|
script_manager = mocks["cthulhu.script_manager"]
|
|
script_manager.get_manager.return_value.get_active_script.return_value = mock_script
|
|
|
|
presenter = module.get_presenter()
|
|
mock_obj = MagicMock()
|
|
result = presenter.present_find_results(mock_obj, 0)
|
|
|
|
assert result is False
|
|
|
|
def test_present_find_results_selection_too_short(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test present_find_results returns False when selection is too short."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
from cthulhu import gsettings_registry # pylint: disable=import-outside-toplevel
|
|
|
|
gsettings_registry.get_registry().set_runtime_value(
|
|
"document",
|
|
"find-results-minimum-length",
|
|
5,
|
|
)
|
|
|
|
# Set up mock script
|
|
mock_script = MagicMock()
|
|
mock_script.utilities.get_document_for_object.return_value = MagicMock()
|
|
mock_script.utilities.get_caret_context.return_value = (None, 0)
|
|
script_manager = mocks["cthulhu.script_manager"]
|
|
script_manager.get_manager.return_value.get_active_script.return_value = mock_script
|
|
|
|
# Set up AXText mock to return short selection (length 3)
|
|
ax_utilities = mocks["cthulhu.ax_utilities"]
|
|
ax_utilities.AXUtilities.get_selection_start_offset.return_value = 0
|
|
ax_utilities.AXUtilities.get_selection_end_offset.return_value = 3
|
|
|
|
presenter = module.get_presenter()
|
|
mock_obj = MagicMock()
|
|
result = presenter.present_find_results(mock_obj, 0)
|
|
|
|
assert result is False
|
|
|
|
def test_present_find_results_speak_disabled(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test present_find_results returns False when speak is disabled."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
from cthulhu import gsettings_registry # pylint: disable=import-outside-toplevel
|
|
|
|
registry = gsettings_registry.get_registry()
|
|
registry.set_runtime_value("document", "find-results-minimum-length", 3)
|
|
registry.set_runtime_value("document", "find-results-verbosity", "none")
|
|
|
|
# Set up mock script
|
|
mock_script = MagicMock()
|
|
mock_script.utilities.get_document_for_object.return_value = MagicMock()
|
|
mock_script.utilities.get_caret_context.return_value = (None, 0)
|
|
script_manager = mocks["cthulhu.script_manager"]
|
|
script_manager.get_manager.return_value.get_active_script.return_value = mock_script
|
|
|
|
# Set up AXText mock with valid selection length
|
|
ax_utilities = mocks["cthulhu.ax_utilities"]
|
|
ax_utilities.AXUtilities.get_selection_start_offset.return_value = 0
|
|
ax_utilities.AXUtilities.get_selection_end_offset.return_value = 10
|
|
|
|
presenter = module.get_presenter()
|
|
mock_obj = MagicMock()
|
|
result = presenter.present_find_results(mock_obj, 0)
|
|
|
|
assert result is False
|
|
|
|
def test_present_find_results_success(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test present_find_results returns True and presents when conditions are met."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
from cthulhu import gsettings_registry # pylint: disable=import-outside-toplevel
|
|
|
|
gsettings_registry.get_registry().set_runtime_value(
|
|
"document",
|
|
"find-results-minimum-length",
|
|
3,
|
|
)
|
|
|
|
# Set up mock script
|
|
mock_script = MagicMock()
|
|
mock_script.utilities.get_document_for_object.return_value = MagicMock()
|
|
mock_script.utilities.get_caret_context.return_value = (None, 0)
|
|
mock_script.utilities.get_line_contents_at_offset.return_value = ["test content"]
|
|
mock_script.utilities.get_find_results_count.return_value = "1 of 5"
|
|
script_manager = mocks["cthulhu.script_manager"]
|
|
script_manager.get_manager.return_value.get_active_script.return_value = mock_script
|
|
|
|
# Set up AXText mock with valid selection length
|
|
ax_utilities = mocks["cthulhu.ax_utilities"]
|
|
ax_utilities.AXUtilities.get_selection_start_offset.return_value = 0
|
|
ax_utilities.AXUtilities.get_selection_end_offset.return_value = 10
|
|
|
|
presenter = module.get_presenter()
|
|
presenter._made_find_announcement = False
|
|
pres_manager = mocks["cthulhu.presentation_manager"].get_manager()
|
|
pres_manager.speak_contents.reset_mock()
|
|
pres_manager.present_message.reset_mock()
|
|
mock_obj = MagicMock()
|
|
result = presenter.present_find_results(mock_obj, 0)
|
|
|
|
assert result is True
|
|
assert presenter._made_find_announcement is True
|
|
pres_manager.speak_contents.assert_called_once()
|
|
mock_script.update_braille.assert_called_once()
|
|
pres_manager.present_message.assert_called_once_with("1 of 5")
|
|
|
|
def test_present_find_results_skips_same_line_when_only_changed(
|
|
self,
|
|
test_context: CthulhuTestContext,
|
|
) -> None:
|
|
"""Test present_find_results skips when same line and only_speak_changed_lines."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
from cthulhu import gsettings_registry # pylint: disable=import-outside-toplevel
|
|
|
|
registry = gsettings_registry.get_registry()
|
|
registry.set_runtime_value("document", "find-results-minimum-length", 3)
|
|
registry.set_runtime_value("document", "find-results-verbosity", "if-line-changed")
|
|
|
|
# Set up mock script
|
|
mock_script = MagicMock()
|
|
mock_script.utilities.get_document_for_object.return_value = MagicMock()
|
|
mock_script.utilities.get_caret_context.return_value = (MagicMock(), 5)
|
|
script_manager = mocks["cthulhu.script_manager"]
|
|
script_manager.get_manager.return_value.get_active_script.return_value = mock_script
|
|
|
|
# Set up AXText mock with valid selection length
|
|
ax_utilities = mocks["cthulhu.ax_utilities"]
|
|
ax_utilities.AXUtilities.get_selection_start_offset.return_value = 0
|
|
ax_utilities.AXUtilities.get_selection_end_offset.return_value = 10
|
|
ax_text = mocks["cthulhu.ax_text"]
|
|
ax_text.AXText.get_range_rect.return_value = MagicMock()
|
|
|
|
ax_utilities.AXUtilities.rects_are_on_same_line = MagicMock(return_value=True)
|
|
|
|
presenter = module.get_presenter()
|
|
presenter._made_find_announcement = True # Already announced
|
|
pres_manager = mocks["cthulhu.presentation_manager"].get_manager()
|
|
pres_manager.speak_contents.reset_mock()
|
|
mock_obj = MagicMock()
|
|
result = presenter.present_find_results(mock_obj, 5)
|
|
|
|
assert result is False
|
|
pres_manager.speak_contents.assert_not_called()
|
|
|
|
def test_use_focus_mode_no_active_script(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test use_focus_mode returns False when no active script."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
script_manager = mocks["cthulhu.script_manager"]
|
|
script_manager.get_manager.return_value.get_active_script.return_value = None
|
|
|
|
presenter = module.get_presenter()
|
|
result = presenter.use_focus_mode(MagicMock())
|
|
|
|
assert result is False
|
|
|
|
def test_use_focus_mode_sticky_focus_mode(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test use_focus_mode returns True when focus mode is sticky."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
mock_app = MagicMock()
|
|
mock_script = MagicMock()
|
|
mock_script.app = mock_app
|
|
script_manager = mocks["cthulhu.script_manager"]
|
|
script_manager.get_manager.return_value.get_active_script.return_value = mock_script
|
|
|
|
presenter = module.get_presenter()
|
|
presenter._app_states[hash(mock_app)] = module._AppModeState(
|
|
in_focus_mode=True,
|
|
focus_mode_is_sticky=True,
|
|
browse_mode_is_sticky=False,
|
|
)
|
|
|
|
result = presenter.use_focus_mode(MagicMock())
|
|
|
|
assert result is True
|
|
|
|
def test_use_focus_mode_sticky_browse_mode(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test use_focus_mode returns False when browse mode is sticky."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
mock_app = MagicMock()
|
|
mock_script = MagicMock()
|
|
mock_script.app = mock_app
|
|
script_manager = mocks["cthulhu.script_manager"]
|
|
script_manager.get_manager.return_value.get_active_script.return_value = mock_script
|
|
|
|
presenter = module.get_presenter()
|
|
presenter._app_states[hash(mock_app)] = module._AppModeState(
|
|
in_focus_mode=False,
|
|
focus_mode_is_sticky=False,
|
|
browse_mode_is_sticky=True,
|
|
)
|
|
|
|
result = presenter.use_focus_mode(MagicMock())
|
|
|
|
assert result is False
|
|
|
|
def test_use_focus_mode_in_say_all(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test use_focus_mode returns False when in say all."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
mock_app = MagicMock()
|
|
mock_script = MagicMock()
|
|
mock_script.app = mock_app
|
|
script_manager = mocks["cthulhu.script_manager"]
|
|
script_manager.get_manager.return_value.get_active_script.return_value = mock_script
|
|
|
|
focus_manager = mocks["cthulhu.focus_manager"]
|
|
focus_manager.get_manager.return_value.in_say_all.return_value = True
|
|
|
|
presenter = module.get_presenter()
|
|
# No sticky state set (defaults to browse mode)
|
|
result = presenter.use_focus_mode(MagicMock())
|
|
|
|
assert result is False
|
|
|
|
def test_use_focus_mode_struct_nav_prevents(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test use_focus_mode returns False when struct nav prevents it."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
mock_app = MagicMock()
|
|
mock_script = MagicMock()
|
|
mock_script.app = mock_app
|
|
script_manager = mocks["cthulhu.script_manager"]
|
|
script_manager.get_manager.return_value.get_active_script.return_value = mock_script
|
|
|
|
focus_manager = mocks["cthulhu.focus_manager"]
|
|
focus_manager.get_manager.return_value.in_say_all.return_value = False
|
|
|
|
struct_nav = mocks["cthulhu.structural_navigator"]
|
|
struct_nav.get_navigator.return_value.last_command_prevents_focus_mode.return_value = True
|
|
|
|
presenter = module.get_presenter()
|
|
result = presenter.use_focus_mode(MagicMock())
|
|
|
|
assert result is False
|
|
|
|
def test_use_focus_mode_table_nav_prevents(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test use_focus_mode returns False when table nav was last command."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
mock_app = MagicMock()
|
|
mock_script = MagicMock()
|
|
mock_script.app = mock_app
|
|
script_manager = mocks["cthulhu.script_manager"]
|
|
script_manager.get_manager.return_value.get_active_script.return_value = mock_script
|
|
|
|
focus_manager = mocks["cthulhu.focus_manager"]
|
|
focus_manager.get_manager.return_value.in_say_all.return_value = False
|
|
|
|
struct_nav = mocks["cthulhu.structural_navigator"]
|
|
struct_nav.get_navigator.return_value.last_command_prevents_focus_mode.return_value = False
|
|
|
|
table_nav = mocks["cthulhu.table_navigator"]
|
|
nav_mock = table_nav.get_navigator.return_value
|
|
nav_mock.last_input_event_was_navigation_command.return_value = True
|
|
|
|
presenter = module.get_presenter()
|
|
result = presenter.use_focus_mode(MagicMock())
|
|
|
|
assert result is False
|
|
|
|
def test_use_focus_mode_caret_nav_prevents(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test use_focus_mode returns False when caret nav prevents it."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
mock_app = MagicMock()
|
|
mock_script = MagicMock()
|
|
mock_script.app = mock_app
|
|
script_manager = mocks["cthulhu.script_manager"]
|
|
script_manager.get_manager.return_value.get_active_script.return_value = mock_script
|
|
|
|
focus_manager = mocks["cthulhu.focus_manager"]
|
|
focus_manager.get_manager.return_value.in_say_all.return_value = False
|
|
|
|
struct_nav = mocks["cthulhu.structural_navigator"]
|
|
struct_nav.get_navigator.return_value.last_command_prevents_focus_mode.return_value = False
|
|
|
|
table_nav = mocks["cthulhu.table_navigator"]
|
|
nav_mock = table_nav.get_navigator.return_value
|
|
nav_mock.last_input_event_was_navigation_command.return_value = False
|
|
|
|
caret_nav = mocks["cthulhu.caret_navigator"]
|
|
caret_nav.get_navigator.return_value.last_command_prevents_focus_mode.return_value = True
|
|
|
|
ax_object = mocks["cthulhu.ax_object"]
|
|
ax_object.AXObject.is_dead.return_value = False
|
|
|
|
ax_utilities = mocks["cthulhu.ax_utilities"]
|
|
ax_utilities.AXUtilities.find_ancestor_inclusive.return_value = None
|
|
|
|
presenter = module.get_presenter()
|
|
result = presenter.use_focus_mode(MagicMock(), MagicMock())
|
|
|
|
assert result is False
|
|
|
|
def test_use_focus_mode_focus_mode_widget(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test use_focus_mode returns True for focus mode widget."""
|
|
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
mock_app = MagicMock()
|
|
mock_script = MagicMock()
|
|
mock_script.app = mock_app
|
|
script_manager = mocks["cthulhu.script_manager"]
|
|
script_manager.get_manager.return_value.get_active_script.return_value = mock_script
|
|
|
|
focus_manager = mocks["cthulhu.focus_manager"]
|
|
focus_manager.get_manager.return_value.in_say_all.return_value = False
|
|
|
|
struct_nav = mocks["cthulhu.structural_navigator"]
|
|
struct_nav.get_navigator.return_value.last_command_prevents_focus_mode.return_value = False
|
|
|
|
table_nav = mocks["cthulhu.table_navigator"]
|
|
nav_mock = table_nav.get_navigator.return_value
|
|
nav_mock.last_input_event_was_navigation_command.return_value = False
|
|
|
|
caret_nav = mocks["cthulhu.caret_navigator"]
|
|
caret_nav.get_navigator.return_value.last_command_prevents_focus_mode.return_value = False
|
|
|
|
presenter = module.get_presenter()
|
|
with patch.object(presenter, "is_focus_mode_widget", return_value=True):
|
|
result = presenter.use_focus_mode(MagicMock())
|
|
|
|
assert result is True
|
|
|
|
def test_use_focus_mode_entering_web_app(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test use_focus_mode returns True when entering a web application."""
|
|
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
mock_app = MagicMock()
|
|
mock_script = MagicMock()
|
|
mock_script.app = mock_app
|
|
script_manager = mocks["cthulhu.script_manager"]
|
|
script_manager.get_manager.return_value.get_active_script.return_value = mock_script
|
|
|
|
focus_manager = mocks["cthulhu.focus_manager"]
|
|
focus_manager.get_manager.return_value.in_say_all.return_value = False
|
|
|
|
struct_nav = mocks["cthulhu.structural_navigator"]
|
|
struct_nav.get_navigator.return_value.last_command_prevents_focus_mode.return_value = False
|
|
|
|
table_nav = mocks["cthulhu.table_navigator"]
|
|
nav_mock = table_nav.get_navigator.return_value
|
|
nav_mock.last_input_event_was_navigation_command.return_value = False
|
|
|
|
caret_nav = mocks["cthulhu.caret_navigator"]
|
|
caret_nav.get_navigator.return_value.last_command_prevents_focus_mode.return_value = False
|
|
|
|
ax_utilities = mocks["cthulhu.ax_utilities"]
|
|
ax_utilities.AXUtilities.is_link.return_value = False
|
|
ax_utilities.AXUtilities.is_radio_button.return_value = False
|
|
ax_utilities.AXUtilities.is_embedded = MagicMock()
|
|
|
|
# prev_obj not in app, obj in app
|
|
ax_utilities.AXUtilities.find_ancestor.side_effect = [None, MagicMock()]
|
|
|
|
presenter = module.get_presenter()
|
|
with patch.object(presenter, "is_focus_mode_widget", return_value=False):
|
|
result = presenter.use_focus_mode(MagicMock(), MagicMock())
|
|
|
|
assert result is True
|
|
|
|
def test_use_focus_mode_default_false(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test use_focus_mode returns False by default."""
|
|
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
mock_app = MagicMock()
|
|
mock_script = MagicMock()
|
|
mock_script.app = mock_app
|
|
script_manager = mocks["cthulhu.script_manager"]
|
|
script_manager.get_manager.return_value.get_active_script.return_value = mock_script
|
|
|
|
focus_manager = mocks["cthulhu.focus_manager"]
|
|
focus_manager.get_manager.return_value.in_say_all.return_value = False
|
|
|
|
struct_nav = mocks["cthulhu.structural_navigator"]
|
|
struct_nav.get_navigator.return_value.last_command_prevents_focus_mode.return_value = False
|
|
|
|
table_nav = mocks["cthulhu.table_navigator"]
|
|
nav_mock = table_nav.get_navigator.return_value
|
|
nav_mock.last_input_event_was_navigation_command.return_value = False
|
|
|
|
caret_nav = mocks["cthulhu.caret_navigator"]
|
|
caret_nav.get_navigator.return_value.last_command_prevents_focus_mode.return_value = False
|
|
|
|
ax_utilities = mocks["cthulhu.ax_utilities"]
|
|
ax_utilities.AXUtilities.is_link.return_value = False
|
|
ax_utilities.AXUtilities.is_radio_button.return_value = False
|
|
ax_utilities.AXUtilities.is_embedded = MagicMock()
|
|
|
|
ax_utilities.AXUtilities.find_ancestor.return_value = None
|
|
|
|
presenter = module.get_presenter()
|
|
with patch.object(presenter, "is_focus_mode_widget", return_value=False):
|
|
result = presenter.use_focus_mode(MagicMock())
|
|
|
|
assert result is False
|
|
|
|
def test_use_focus_mode_native_nav_no_trigger(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test use_focus_mode returns current mode when native nav doesn't trigger."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
mock_app = MagicMock()
|
|
mock_script = MagicMock()
|
|
mock_script.app = mock_app
|
|
script_manager = mocks["cthulhu.script_manager"]
|
|
script_manager.get_manager.return_value.get_active_script.return_value = mock_script
|
|
|
|
focus_manager = mocks["cthulhu.focus_manager"]
|
|
focus_manager.get_manager.return_value.in_say_all.return_value = False
|
|
|
|
struct_nav = mocks["cthulhu.structural_navigator"]
|
|
struct_nav.get_navigator.return_value.last_command_prevents_focus_mode.return_value = False
|
|
nav_mock = struct_nav.get_navigator.return_value
|
|
nav_mock.last_input_event_was_navigation_command.return_value = False
|
|
|
|
table_nav = mocks["cthulhu.table_navigator"]
|
|
nav_mock = table_nav.get_navigator.return_value
|
|
nav_mock.last_input_event_was_navigation_command.return_value = False
|
|
|
|
caret_nav = mocks["cthulhu.caret_navigator"]
|
|
caret_nav.get_navigator.return_value.last_command_prevents_focus_mode.return_value = False
|
|
nav_mock = caret_nav.get_navigator.return_value
|
|
nav_mock.last_input_event_was_navigation_command.return_value = False
|
|
|
|
presenter = module.get_presenter()
|
|
presenter.set_native_nav_triggers_focus_mode(False)
|
|
presenter._app_states[hash(mock_app)] = module._AppModeState(
|
|
in_focus_mode=True,
|
|
focus_mode_is_sticky=False,
|
|
browse_mode_is_sticky=False,
|
|
)
|
|
|
|
result = presenter.use_focus_mode(MagicMock())
|
|
|
|
assert result is True
|
|
|
|
def test_in_focus_mode_default_false(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test in_focus_mode returns False when no state exists for app."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, _mocks = self._setup_presenter(test_context)
|
|
presenter = module.get_presenter()
|
|
mock_app = MagicMock()
|
|
|
|
result = presenter.in_focus_mode(mock_app)
|
|
|
|
assert result is False
|
|
|
|
def test_in_focus_mode_returns_state(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test in_focus_mode returns stored state."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, _mocks = self._setup_presenter(test_context)
|
|
presenter = module.get_presenter()
|
|
mock_app = MagicMock()
|
|
|
|
presenter._app_states[hash(mock_app)] = module._AppModeState(
|
|
in_focus_mode=True,
|
|
focus_mode_is_sticky=False,
|
|
browse_mode_is_sticky=False,
|
|
)
|
|
|
|
result = presenter.in_focus_mode(mock_app)
|
|
|
|
assert result is True
|
|
|
|
def test_focus_mode_is_sticky_default_false(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test focus_mode_is_sticky returns False by default."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, _mocks = self._setup_presenter(test_context)
|
|
presenter = module.get_presenter()
|
|
mock_app = MagicMock()
|
|
|
|
result = presenter.focus_mode_is_sticky(mock_app)
|
|
|
|
assert result is False
|
|
|
|
def test_focus_mode_is_sticky_returns_state(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test focus_mode_is_sticky returns stored state."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, _mocks = self._setup_presenter(test_context)
|
|
presenter = module.get_presenter()
|
|
mock_app = MagicMock()
|
|
|
|
presenter._app_states[hash(mock_app)] = module._AppModeState(
|
|
in_focus_mode=True,
|
|
focus_mode_is_sticky=True,
|
|
browse_mode_is_sticky=False,
|
|
)
|
|
|
|
result = presenter.focus_mode_is_sticky(mock_app)
|
|
|
|
assert result is True
|
|
|
|
def test_browse_mode_is_sticky_default_false(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test browse_mode_is_sticky returns False by default."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, _mocks = self._setup_presenter(test_context)
|
|
presenter = module.get_presenter()
|
|
mock_app = MagicMock()
|
|
|
|
result = presenter.browse_mode_is_sticky(mock_app)
|
|
|
|
assert result is False
|
|
|
|
def test_browse_mode_is_sticky_returns_state(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test browse_mode_is_sticky returns stored state."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, _mocks = self._setup_presenter(test_context)
|
|
presenter = module.get_presenter()
|
|
mock_app = MagicMock()
|
|
|
|
presenter._app_states[hash(mock_app)] = module._AppModeState(
|
|
in_focus_mode=False,
|
|
focus_mode_is_sticky=False,
|
|
browse_mode_is_sticky=True,
|
|
)
|
|
|
|
result = presenter.browse_mode_is_sticky(mock_app)
|
|
|
|
assert result is True
|
|
|
|
def test_get_state_for_app_sets_mode(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test _get_state_for_app can be used to set mode state."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, _mocks = self._setup_presenter(test_context)
|
|
presenter = module.get_presenter()
|
|
mock_app = MagicMock()
|
|
|
|
state = presenter._get_state_for_app(mock_app)
|
|
state.in_focus_mode = True
|
|
|
|
assert presenter.in_focus_mode(mock_app) is True
|
|
|
|
state = presenter._get_state_for_app(mock_app)
|
|
state.in_focus_mode = False
|
|
|
|
assert presenter.in_focus_mode(mock_app) is False
|
|
|
|
def test_clear_state_for_app(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test clear_state_for_app removes app state."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, _mocks = self._setup_presenter(test_context)
|
|
presenter = module.get_presenter()
|
|
mock_app = MagicMock()
|
|
|
|
presenter._app_states[hash(mock_app)] = module._AppModeState(
|
|
in_focus_mode=False,
|
|
focus_mode_is_sticky=False,
|
|
browse_mode_is_sticky=True,
|
|
)
|
|
|
|
presenter.clear_state_for_app(mock_app)
|
|
|
|
assert presenter.in_focus_mode(mock_app) is False
|
|
assert presenter.focus_mode_is_sticky(mock_app) is False
|
|
|
|
def test_per_app_state_isolation(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test that different apps have isolated mode state."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, _mocks = self._setup_presenter(test_context)
|
|
presenter = module.get_presenter()
|
|
|
|
app1 = MagicMock()
|
|
app2 = MagicMock()
|
|
|
|
presenter._app_states[hash(app1)] = module._AppModeState(
|
|
in_focus_mode=True,
|
|
focus_mode_is_sticky=True,
|
|
browse_mode_is_sticky=False,
|
|
)
|
|
presenter._app_states[hash(app2)] = module._AppModeState(
|
|
in_focus_mode=False,
|
|
focus_mode_is_sticky=False,
|
|
browse_mode_is_sticky=True,
|
|
)
|
|
|
|
assert presenter.in_focus_mode(app1) is True
|
|
assert presenter.focus_mode_is_sticky(app1) is True
|
|
assert presenter.browse_mode_is_sticky(app1) is False
|
|
|
|
assert presenter.in_focus_mode(app2) is False
|
|
assert presenter.focus_mode_is_sticky(app2) is False
|
|
assert presenter.browse_mode_is_sticky(app2) is True
|
|
|
|
def test_set_presentation_mode_not_in_document(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test set_presentation_mode returns False when not in document."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
mock_script = MagicMock()
|
|
mock_script.utilities.in_document_content.return_value = False
|
|
|
|
mocks["cthulhu.messages"] = MagicMock()
|
|
mocks["cthulhu.messages"].DOCUMENT_NOT_IN_A = "Not in document"
|
|
|
|
presenter = module.get_presenter()
|
|
pres_manager = mocks["cthulhu.presentation_manager"].get_manager()
|
|
pres_manager.present_message.reset_mock()
|
|
result = presenter._set_presentation_mode(mock_script, True, obj=MagicMock())
|
|
|
|
assert result is False
|
|
pres_manager.present_message.assert_called_once()
|
|
|
|
def test_set_presentation_mode_same_mode(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test set_presentation_mode returns False when already in requested mode."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, _mocks = self._setup_presenter(test_context)
|
|
|
|
mock_app = MagicMock()
|
|
mock_script = MagicMock()
|
|
mock_script.app = mock_app
|
|
mock_script.utilities.in_document_content.return_value = True
|
|
|
|
presenter = module.get_presenter()
|
|
presenter._app_states[hash(mock_app)] = module._AppModeState(
|
|
in_focus_mode=True,
|
|
focus_mode_is_sticky=False,
|
|
browse_mode_is_sticky=False,
|
|
)
|
|
|
|
result = presenter._set_presentation_mode(mock_script, True, obj=MagicMock())
|
|
|
|
assert result is False
|
|
|
|
def test_set_presentation_mode_to_browse(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test set_presentation_mode switches to browse mode."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
mock_app = MagicMock()
|
|
mock_script = MagicMock()
|
|
mock_script.app = mock_app
|
|
mock_script.utilities.in_document_content.return_value = True
|
|
mock_script.utilities.get_caret_context.return_value = (MagicMock(), 0)
|
|
|
|
struct_nav = mocks["cthulhu.structural_navigator"]
|
|
caret_nav = mocks["cthulhu.caret_navigator"]
|
|
|
|
presenter = module.get_presenter()
|
|
presenter._app_states[hash(mock_app)] = module._AppModeState(
|
|
in_focus_mode=True,
|
|
focus_mode_is_sticky=False,
|
|
browse_mode_is_sticky=False,
|
|
)
|
|
|
|
result = presenter._set_presentation_mode(mock_script, False, obj=MagicMock())
|
|
|
|
assert result is True
|
|
assert presenter.in_focus_mode(mock_app) is False
|
|
struct_nav.get_navigator.return_value.set_mode.assert_called()
|
|
caret_nav.get_navigator.return_value.set_enabled_for_script.assert_called()
|
|
|
|
def test_set_presentation_mode_to_focus(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test set_presentation_mode switches to focus mode."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
mock_app = MagicMock()
|
|
mock_script = MagicMock()
|
|
mock_script.app = mock_app
|
|
mock_script.utilities.in_document_content.return_value = True
|
|
mock_script.utilities.get_caret_context.return_value = (MagicMock(), 0)
|
|
|
|
caret_nav = mocks["cthulhu.caret_navigator"]
|
|
nav_mock = caret_nav.get_navigator.return_value
|
|
nav_mock.last_input_event_was_navigation_command.return_value = False
|
|
struct_nav = mocks["cthulhu.structural_navigator"]
|
|
nav_mock = struct_nav.get_navigator.return_value
|
|
nav_mock.last_input_event_was_navigation_command.return_value = False
|
|
table_nav = mocks["cthulhu.table_navigator"]
|
|
nav_mock = table_nav.get_navigator.return_value
|
|
nav_mock.last_input_event_was_navigation_command.return_value = False
|
|
|
|
presenter = module.get_presenter()
|
|
presenter._app_states[hash(mock_app)] = module._AppModeState(
|
|
in_focus_mode=False,
|
|
focus_mode_is_sticky=False,
|
|
browse_mode_is_sticky=False,
|
|
)
|
|
|
|
result = presenter._set_presentation_mode(mock_script, True, obj=MagicMock())
|
|
|
|
assert result is True
|
|
assert presenter.in_focus_mode(mock_app) is True
|
|
|
|
def test_set_presentation_mode_dead_obj_fallback(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test set_presentation_mode uses locus of focus when obj is dead."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
mock_app = MagicMock()
|
|
mock_script = MagicMock()
|
|
mock_script.app = mock_app
|
|
mock_script.utilities.in_document_content.return_value = True
|
|
mock_script.utilities.get_caret_context.return_value = (MagicMock(), 0)
|
|
|
|
caret_nav = mocks["cthulhu.caret_navigator"]
|
|
nav_mock = caret_nav.get_navigator.return_value
|
|
nav_mock.last_input_event_was_navigation_command.return_value = False
|
|
struct_nav = mocks["cthulhu.structural_navigator"]
|
|
nav_mock = struct_nav.get_navigator.return_value
|
|
nav_mock.last_input_event_was_navigation_command.return_value = False
|
|
table_nav = mocks["cthulhu.table_navigator"]
|
|
nav_mock = table_nav.get_navigator.return_value
|
|
nav_mock.last_input_event_was_navigation_command.return_value = False
|
|
|
|
ax_object = mocks["cthulhu.ax_object"]
|
|
ax_object.AXObject.is_dead.return_value = True
|
|
|
|
presenter = module.get_presenter()
|
|
presenter._app_states[hash(mock_app)] = module._AppModeState(
|
|
in_focus_mode=False,
|
|
focus_mode_is_sticky=False,
|
|
browse_mode_is_sticky=False,
|
|
)
|
|
|
|
dead_obj = MagicMock()
|
|
result = presenter._set_presentation_mode(mock_script, True, obj=dead_obj)
|
|
|
|
assert result is True
|
|
mock_script.utilities.in_document_content.assert_called_with(None)
|
|
|
|
def test_suspend_navigators(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test suspend_navigators suspends all navigators."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
mock_app = MagicMock()
|
|
mock_script = MagicMock()
|
|
mock_script.app = mock_app
|
|
|
|
caret_nav = mocks["cthulhu.caret_navigator"]
|
|
struct_nav = mocks["cthulhu.structural_navigator"]
|
|
|
|
presenter = module.get_presenter()
|
|
result = presenter.suspend_navigators(mock_script, True, "test")
|
|
|
|
assert result is True
|
|
caret_nav.get_navigator.return_value.suspend_commands.assert_called_with(
|
|
mock_script,
|
|
True,
|
|
"test",
|
|
)
|
|
struct_nav.get_navigator.return_value.suspend_commands.assert_called_with(
|
|
mock_script,
|
|
True,
|
|
"test",
|
|
)
|
|
|
|
def test_enable_sticky_focus_mode(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test enable_sticky_focus_mode sets sticky focus mode."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
mock_app = MagicMock()
|
|
mock_script = MagicMock()
|
|
mock_script.app = mock_app
|
|
|
|
presenter = module.get_presenter()
|
|
pres_manager = mocks["cthulhu.presentation_manager"].get_manager()
|
|
pres_manager.present_message.reset_mock()
|
|
result = presenter.enable_sticky_focus_mode(mock_script)
|
|
|
|
assert result is True
|
|
assert presenter.in_focus_mode(mock_app) is True
|
|
assert presenter.focus_mode_is_sticky(mock_app) is True
|
|
assert presenter.browse_mode_is_sticky(mock_app) is False
|
|
pres_manager.present_message.assert_called()
|
|
|
|
def test_enable_sticky_browse_mode(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test enable_sticky_browse_mode sets sticky browse mode."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
mock_app = MagicMock()
|
|
mock_script = MagicMock()
|
|
mock_script.app = mock_app
|
|
|
|
presenter = module.get_presenter()
|
|
pres_manager = mocks["cthulhu.presentation_manager"].get_manager()
|
|
pres_manager.present_message.reset_mock()
|
|
result = presenter.enable_sticky_browse_mode(mock_script)
|
|
|
|
assert result is True
|
|
assert presenter.in_focus_mode(mock_app) is False
|
|
assert presenter.focus_mode_is_sticky(mock_app) is False
|
|
assert presenter.browse_mode_is_sticky(mock_app) is True
|
|
pres_manager.present_message.assert_called()
|
|
|
|
def test_toggle_presentation_mode_not_in_document(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test toggle_presentation_mode when not in document."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
mock_script = MagicMock()
|
|
mock_script.utilities.in_document_content.return_value = False
|
|
|
|
presenter = module.get_presenter()
|
|
pres_manager = mocks["cthulhu.presentation_manager"].get_manager()
|
|
pres_manager.present_message.reset_mock()
|
|
result = presenter.toggle_presentation_mode(mock_script)
|
|
|
|
assert result is True
|
|
pres_manager.present_message.assert_called()
|
|
|
|
def test_toggle_presentation_mode_to_focus(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test toggle_presentation_mode switches to focus mode."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
mock_app = MagicMock()
|
|
mock_script = MagicMock()
|
|
mock_script.app = mock_app
|
|
mock_script.utilities.in_document_content.return_value = True
|
|
mock_script.utilities.get_caret_context.return_value = (MagicMock(), 0)
|
|
|
|
caret_nav = mocks["cthulhu.caret_navigator"]
|
|
nav_mock = caret_nav.get_navigator.return_value
|
|
nav_mock.last_input_event_was_navigation_command.return_value = False
|
|
struct_nav = mocks["cthulhu.structural_navigator"]
|
|
nav_mock = struct_nav.get_navigator.return_value
|
|
nav_mock.last_input_event_was_navigation_command.return_value = False
|
|
table_nav = mocks["cthulhu.table_navigator"]
|
|
nav_mock = table_nav.get_navigator.return_value
|
|
nav_mock.last_input_event_was_navigation_command.return_value = False
|
|
|
|
presenter = module.get_presenter()
|
|
presenter._app_states[hash(mock_app)] = module._AppModeState(
|
|
in_focus_mode=False,
|
|
focus_mode_is_sticky=False,
|
|
browse_mode_is_sticky=False,
|
|
)
|
|
|
|
result = presenter.toggle_presentation_mode(mock_script)
|
|
|
|
assert result is True
|
|
assert presenter.in_focus_mode(mock_app) is True
|
|
|
|
def test_restore_mode_for_script_no_app(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test restore_mode_for_script with no app does nothing."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, _mocks = self._setup_presenter(test_context)
|
|
|
|
mock_script = MagicMock()
|
|
mock_script.app = None
|
|
|
|
presenter = module.get_presenter()
|
|
presenter.restore_mode_for_script(mock_script)
|
|
|
|
def test_restore_mode_for_script_no_state(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test restore_mode_for_script with no existing state does nothing."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, _mocks = self._setup_presenter(test_context)
|
|
|
|
mock_script = MagicMock()
|
|
mock_script.app = MagicMock()
|
|
|
|
presenter = module.get_presenter()
|
|
presenter.restore_mode_for_script(mock_script)
|
|
|
|
def test_restore_mode_for_script_with_state(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test restore_mode_for_script restores navigator suspension state."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
mock_app = MagicMock()
|
|
mock_script = MagicMock()
|
|
mock_script.app = mock_app
|
|
|
|
caret_nav = mocks["cthulhu.caret_navigator"]
|
|
|
|
presenter = module.get_presenter()
|
|
presenter._app_states[hash(mock_app)] = module._AppModeState(
|
|
in_focus_mode=True,
|
|
focus_mode_is_sticky=False,
|
|
browse_mode_is_sticky=False,
|
|
)
|
|
|
|
presenter.restore_mode_for_script(mock_script)
|
|
|
|
caret_nav.get_navigator.return_value.suspend_commands.assert_called()
|
|
|
|
def test_restore_mode_for_script_browse_mode_enables_navigators(
|
|
self,
|
|
test_context: CthulhuTestContext,
|
|
) -> None:
|
|
"""Test restore_mode_for_script re-enables navigators when restoring browse mode."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
mock_app = MagicMock()
|
|
mock_script = MagicMock()
|
|
mock_script.app = mock_app
|
|
|
|
struct_nav = mocks["cthulhu.structural_navigator"]
|
|
caret_nav = mocks["cthulhu.caret_navigator"]
|
|
|
|
presenter = module.get_presenter()
|
|
presenter._app_states[hash(mock_app)] = module._AppModeState(
|
|
in_focus_mode=False,
|
|
focus_mode_is_sticky=False,
|
|
browse_mode_is_sticky=False,
|
|
)
|
|
|
|
presenter.restore_mode_for_script(mock_script)
|
|
|
|
struct_nav.get_navigator.return_value.set_mode.assert_called_once()
|
|
caret_nav.get_navigator.return_value.set_enabled_for_script.assert_called_once_with(
|
|
mock_script,
|
|
True,
|
|
)
|
|
|
|
def test_update_mode_if_needed_not_in_doc(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test update_mode_if_needed when neither in document suspends navigators."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
mock_script = MagicMock()
|
|
mock_script.utilities.get_top_level_document_for_object.return_value = None
|
|
|
|
caret_nav = mocks["cthulhu.caret_navigator"]
|
|
|
|
presenter = module.get_presenter()
|
|
result = presenter.update_mode_if_needed(mock_script, MagicMock(), MagicMock())
|
|
|
|
# When focus is not in a document, navigators should be suspended
|
|
assert result is True
|
|
caret_nav.get_navigator.return_value.suspend_commands.assert_called()
|
|
|
|
def test_update_mode_if_needed_leaving_doc(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test update_mode_if_needed when leaving document."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
mock_app = MagicMock()
|
|
mock_script = MagicMock()
|
|
mock_script.app = mock_app
|
|
mock_doc = MagicMock()
|
|
mock_script.utilities.get_top_level_document_for_object.side_effect = [mock_doc, None]
|
|
|
|
caret_nav = mocks["cthulhu.caret_navigator"]
|
|
|
|
presenter = module.get_presenter()
|
|
old_focus = MagicMock()
|
|
new_focus = MagicMock()
|
|
result = presenter.update_mode_if_needed(mock_script, old_focus, new_focus)
|
|
|
|
assert result is True
|
|
caret_nav.get_navigator.return_value.suspend_commands.assert_called()
|
|
|
|
def test_update_mode_if_needed_sticky_focus(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test update_mode_if_needed with sticky focus mode when entering document."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
mock_app = MagicMock()
|
|
mock_script = MagicMock()
|
|
mock_script.app = mock_app
|
|
mock_doc = MagicMock()
|
|
mock_script.utilities.get_top_level_document_for_object.side_effect = [None, mock_doc]
|
|
|
|
focus_manager = mocks["cthulhu.focus_manager"]
|
|
focus_manager.get_manager.return_value.old_focus_was_dead.return_value = False
|
|
|
|
presenter = module.get_presenter()
|
|
presenter._app_states[hash(mock_app)] = module._AppModeState(
|
|
in_focus_mode=True,
|
|
focus_mode_is_sticky=True,
|
|
browse_mode_is_sticky=False,
|
|
)
|
|
|
|
pres_manager = mocks["cthulhu.presentation_manager"].get_manager()
|
|
pres_manager.present_message.reset_mock()
|
|
result = presenter.update_mode_if_needed(mock_script, MagicMock(), MagicMock())
|
|
|
|
assert result is True
|
|
pres_manager.present_message.assert_called()
|
|
|
|
def test_update_mode_if_needed_sticky_browse(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test update_mode_if_needed with sticky browse mode when entering document."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
mock_app = MagicMock()
|
|
mock_script = MagicMock()
|
|
mock_script.app = mock_app
|
|
mock_doc = MagicMock()
|
|
mock_script.utilities.get_top_level_document_for_object.side_effect = [None, mock_doc]
|
|
|
|
focus_manager = mocks["cthulhu.focus_manager"]
|
|
focus_manager.get_manager.return_value.old_focus_was_dead.return_value = False
|
|
|
|
struct_nav = mocks["cthulhu.structural_navigator"]
|
|
caret_nav = mocks["cthulhu.caret_navigator"]
|
|
|
|
presenter = module.get_presenter()
|
|
presenter._app_states[hash(mock_app)] = module._AppModeState(
|
|
in_focus_mode=False,
|
|
focus_mode_is_sticky=False,
|
|
browse_mode_is_sticky=True,
|
|
)
|
|
|
|
pres_manager = mocks["cthulhu.presentation_manager"].get_manager()
|
|
pres_manager.present_message.reset_mock()
|
|
result = presenter.update_mode_if_needed(mock_script, MagicMock(), MagicMock())
|
|
|
|
assert result is True
|
|
pres_manager.present_message.assert_called()
|
|
struct_nav.get_navigator.return_value.set_mode.assert_called()
|
|
caret_nav.get_navigator.return_value.set_enabled_for_script.assert_called()
|
|
|
|
def test_handle_entering_document_refreshes_commands(
|
|
self,
|
|
test_context: CthulhuTestContext,
|
|
) -> None:
|
|
"""Test entering document refreshes commands even when mode unchanged."""
|
|
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
mock_app = MagicMock()
|
|
mock_script = MagicMock()
|
|
mock_script.app = mock_app
|
|
mock_doc = MagicMock()
|
|
mock_script.utilities.get_top_level_document_for_object.side_effect = [None, mock_doc]
|
|
|
|
caret_nav = mocks["cthulhu.caret_navigator"]
|
|
nav_mock = caret_nav.get_navigator.return_value
|
|
nav_mock.last_input_event_was_navigation_command.return_value = False
|
|
caret_nav.get_navigator.return_value.last_command_prevents_focus_mode.return_value = False
|
|
struct_nav = mocks["cthulhu.structural_navigator"]
|
|
nav_mock = struct_nav.get_navigator.return_value
|
|
nav_mock.last_input_event_was_navigation_command.return_value = False
|
|
struct_nav.get_navigator.return_value.last_command_prevents_focus_mode.return_value = False
|
|
table_nav = mocks["cthulhu.table_navigator"]
|
|
nav_mock = table_nav.get_navigator.return_value
|
|
nav_mock.last_input_event_was_navigation_command.return_value = False
|
|
focus_manager = mocks["cthulhu.focus_manager"]
|
|
focus_manager.get_manager.return_value.in_say_all.return_value = False
|
|
focus_manager.get_manager.return_value.old_focus_was_dead.return_value = False
|
|
|
|
script_manager = mocks["cthulhu.script_manager"]
|
|
script_manager.get_manager.return_value.get_active_script.return_value = mock_script
|
|
|
|
presenter = module.get_presenter()
|
|
# Already in browse mode - entering document should still refresh commands
|
|
presenter._app_states[hash(mock_app)] = module._AppModeState(
|
|
in_focus_mode=False,
|
|
focus_mode_is_sticky=False,
|
|
browse_mode_is_sticky=False,
|
|
)
|
|
|
|
with patch.object(presenter, "is_focus_mode_widget", return_value=False):
|
|
result = presenter.update_mode_if_needed(mock_script, MagicMock(), MagicMock())
|
|
|
|
assert result is True
|
|
# Verify commands were refreshed (suspend_commands called with suspended=False for browse)
|
|
caret_nav.get_navigator.return_value.suspend_commands.assert_called()
|
|
struct_nav.get_navigator.return_value.suspend_commands.assert_called()
|
|
|
|
def test_is_likely_electron_app_true(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test _is_likely_electron_app returns True for Chromium toolkit non-browser."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
ax_object = mocks["cthulhu.ax_object"]
|
|
ax_object.AXObject.get_toolkit_name.return_value = "Chromium"
|
|
ax_object.AXObject.get_name.return_value = "code"
|
|
|
|
mock_app = MagicMock()
|
|
presenter = module.get_presenter()
|
|
result = presenter._is_likely_electron_app(mock_app)
|
|
|
|
assert result is True
|
|
|
|
def test_is_likely_electron_app_false_for_browser(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test _is_likely_electron_app returns False for known browsers."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
ax_object = mocks["cthulhu.ax_object"]
|
|
ax_object.AXObject.get_toolkit_name.return_value = "Chromium"
|
|
ax_object.AXObject.get_name.return_value = "google-chrome"
|
|
|
|
mock_app = MagicMock()
|
|
presenter = module.get_presenter()
|
|
result = presenter._is_likely_electron_app(mock_app)
|
|
|
|
assert result is False
|
|
|
|
def test_is_likely_electron_app_false_for_non_chromium(
|
|
self,
|
|
test_context: CthulhuTestContext,
|
|
) -> None:
|
|
"""Test _is_likely_electron_app returns False for non-Chromium toolkit."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
ax_object = mocks["cthulhu.ax_object"]
|
|
ax_object.AXObject.get_toolkit_name.return_value = "gtk"
|
|
ax_object.AXObject.get_name.return_value = "gedit"
|
|
|
|
mock_app = MagicMock()
|
|
presenter = module.get_presenter()
|
|
result = presenter._is_likely_electron_app(mock_app)
|
|
|
|
assert result is False
|
|
|
|
def test_update_mode_electron_app_sticky_focus(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test update_mode_if_needed enables sticky focus for Electron apps when entering."""
|
|
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
mock_app = MagicMock()
|
|
mock_script = MagicMock()
|
|
mock_script.app = mock_app
|
|
mock_doc = MagicMock()
|
|
mock_script.utilities.get_top_level_document_for_object.side_effect = [None, mock_doc]
|
|
mock_script.utilities.in_document_content.return_value = True
|
|
|
|
focus_manager = mocks["cthulhu.focus_manager"]
|
|
focus_manager.get_manager.return_value.old_focus_was_dead.return_value = False
|
|
|
|
presenter = module.get_presenter()
|
|
|
|
with patch.object(presenter, "_is_likely_electron_app", return_value=True):
|
|
result = presenter.update_mode_if_needed(mock_script, MagicMock(), MagicMock())
|
|
|
|
assert result is True
|
|
assert presenter.in_focus_mode(mock_app) is True
|
|
assert presenter.focus_mode_is_sticky(mock_app) is True
|
|
|
|
def test_is_top_level_web_app_true(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test _is_top_level_web_app returns True for embedded doc with http URI."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
mock_doc = MagicMock()
|
|
mock_script = MagicMock()
|
|
mock_script.utilities.active_document.return_value = mock_doc
|
|
|
|
ax_utilities = mocks["cthulhu.ax_utilities"]
|
|
ax_utilities.AXUtilities.is_embedded.return_value = True
|
|
|
|
ax_document = mocks["cthulhu.ax_document"]
|
|
ax_document.AXDocument.get_uri.return_value = "https://docs.google.com/document"
|
|
|
|
presenter = module.get_presenter()
|
|
|
|
result = presenter._is_top_level_web_app(mock_script, MagicMock())
|
|
|
|
assert result is True
|
|
|
|
def test_is_top_level_web_app_false_no_http(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test _is_top_level_web_app returns False for non-http URI."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
mock_doc = MagicMock()
|
|
mock_script = MagicMock()
|
|
mock_script.utilities.active_document.return_value = mock_doc
|
|
|
|
ax_utilities = mocks["cthulhu.ax_utilities"]
|
|
ax_utilities.AXUtilities.is_embedded.return_value = True
|
|
|
|
ax_document = mocks["cthulhu.ax_document"]
|
|
ax_document.AXDocument.get_uri.return_value = "file:///home/user/doc.html"
|
|
|
|
presenter = module.get_presenter()
|
|
|
|
result = presenter._is_top_level_web_app(mock_script, MagicMock())
|
|
|
|
assert result is False
|
|
|
|
def test_is_top_level_web_app_false_no_document(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test _is_top_level_web_app returns False when no active document."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, _mocks = self._setup_presenter(test_context)
|
|
|
|
mock_script = MagicMock()
|
|
mock_script.utilities.active_document.return_value = None
|
|
|
|
presenter = module.get_presenter()
|
|
|
|
result = presenter._is_top_level_web_app(mock_script, MagicMock())
|
|
|
|
assert result is False
|
|
|
|
def test_is_top_level_web_app_false_not_embedded(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test _is_top_level_web_app returns False when document is not embedded role."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
mock_doc = MagicMock()
|
|
mock_script = MagicMock()
|
|
mock_script.utilities.active_document.return_value = mock_doc
|
|
|
|
ax_utilities = mocks["cthulhu.ax_utilities"]
|
|
ax_utilities.AXUtilities.is_embedded.return_value = False
|
|
|
|
presenter = module.get_presenter()
|
|
|
|
result = presenter._is_top_level_web_app(mock_script, MagicMock())
|
|
|
|
assert result is False
|
|
|
|
def test_update_mode_top_level_web_app_sticky_focus(
|
|
self,
|
|
test_context: CthulhuTestContext,
|
|
) -> None:
|
|
"""Test update_mode_if_needed enables sticky focus for top-level web apps when entering."""
|
|
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
mock_app = MagicMock()
|
|
mock_script = MagicMock()
|
|
mock_script.app = mock_app
|
|
mock_doc = MagicMock()
|
|
mock_script.utilities.get_top_level_document_for_object.side_effect = [None, mock_doc]
|
|
mock_script.utilities.in_document_content.return_value = True
|
|
|
|
focus_manager = mocks["cthulhu.focus_manager"]
|
|
focus_manager.get_manager.return_value.old_focus_was_dead.return_value = False
|
|
|
|
presenter = module.get_presenter()
|
|
|
|
with (
|
|
patch.object(presenter, "_is_likely_electron_app", return_value=False),
|
|
patch.object(presenter, "_is_top_level_web_app", return_value=True),
|
|
):
|
|
result = presenter.update_mode_if_needed(mock_script, MagicMock(), MagicMock())
|
|
|
|
assert result is True
|
|
assert presenter.in_focus_mode(mock_app) is True
|
|
assert presenter.focus_mode_is_sticky(mock_app) is True
|
|
|
|
def test_is_focus_mode_widget_editable(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test is_focus_mode_widget returns True for editable objects."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
ax_utilities = mocks["cthulhu.ax_utilities"]
|
|
ax_utilities.AXUtilities.is_editable.return_value = True
|
|
|
|
mock_script = MagicMock()
|
|
mock_obj = MagicMock()
|
|
|
|
presenter = module.get_presenter()
|
|
result = presenter.is_focus_mode_widget(mock_script, mock_obj)
|
|
|
|
assert result is True
|
|
|
|
def test_is_focus_mode_widget_combo_box(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test is_focus_mode_widget returns True for combo boxes."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
ax_utilities = mocks["cthulhu.ax_utilities"]
|
|
ax_utilities.AXUtilities.is_editable.return_value = False
|
|
ax_utilities.AXUtilities.is_combo_box.return_value = True
|
|
|
|
mock_script = MagicMock()
|
|
mock_obj = MagicMock()
|
|
|
|
presenter = module.get_presenter()
|
|
result = presenter.is_focus_mode_widget(mock_script, mock_obj)
|
|
|
|
assert result is True
|
|
|
|
def test_is_focus_mode_widget_expandable_focusable(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test is_focus_mode_widget returns True for expandable focusable non-links."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
ax_utilities = mocks["cthulhu.ax_utilities"]
|
|
ax_utilities.AXUtilities.is_editable.return_value = False
|
|
ax_utilities.AXUtilities.is_expandable.return_value = True
|
|
ax_utilities.AXUtilities.is_focusable.return_value = True
|
|
ax_utilities.AXUtilities.is_link.return_value = False
|
|
|
|
mock_script = MagicMock()
|
|
mock_obj = MagicMock()
|
|
|
|
presenter = module.get_presenter()
|
|
result = presenter.is_focus_mode_widget(mock_script, mock_obj)
|
|
|
|
assert result is True
|
|
|
|
def test_is_focus_mode_widget_expandable_link_false(
|
|
self,
|
|
test_context: CthulhuTestContext,
|
|
) -> None:
|
|
"""Test is_focus_mode_widget returns False for expandable focusable links."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
import gi
|
|
|
|
gi.require_version("Atspi", "2.0")
|
|
from gi.repository import Atspi
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
ax_utilities = mocks["cthulhu.ax_utilities"]
|
|
ax_utilities.AXUtilities.is_editable.return_value = False
|
|
ax_utilities.AXUtilities.is_expandable.return_value = True
|
|
ax_utilities.AXUtilities.is_focusable.return_value = True
|
|
ax_utilities.AXUtilities.is_link.return_value = True
|
|
ax_utilities.AXUtilities.is_list_box_item.return_value = False
|
|
ax_utilities.AXUtilities.is_button_with_popup.return_value = False
|
|
ax_utilities.AXUtilities.is_grid = MagicMock()
|
|
ax_utilities.AXUtilities.is_menu = MagicMock()
|
|
ax_utilities.AXUtilities.is_tool_bar = MagicMock()
|
|
|
|
ax_object = mocks["cthulhu.ax_object"]
|
|
ax_object.AXObject.get_role.return_value = Atspi.Role.LINK
|
|
ax_utilities.AXUtilities.find_ancestor.return_value = None
|
|
|
|
mock_script = MagicMock()
|
|
mock_script.utilities.is_content_editable_with_embedded_objects.return_value = False
|
|
mock_obj = MagicMock()
|
|
|
|
presenter = module.get_presenter()
|
|
result = presenter.is_focus_mode_widget(mock_script, mock_obj)
|
|
|
|
assert result is False
|
|
|
|
def test_is_focus_mode_widget_always_focus_role(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test is_focus_mode_widget returns True for always-focus-mode roles."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
import gi
|
|
|
|
gi.require_version("Atspi", "2.0")
|
|
from gi.repository import Atspi
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
ax_utilities = mocks["cthulhu.ax_utilities"]
|
|
ax_utilities.AXUtilities.is_editable.return_value = False
|
|
ax_utilities.AXUtilities.is_expandable.return_value = False
|
|
|
|
ax_object = mocks["cthulhu.ax_object"]
|
|
ax_object.AXObject.get_role.return_value = Atspi.Role.SLIDER
|
|
|
|
mock_script = MagicMock()
|
|
mock_obj = MagicMock()
|
|
|
|
presenter = module.get_presenter()
|
|
result = presenter.is_focus_mode_widget(mock_script, mock_obj)
|
|
|
|
assert result is True
|
|
|
|
def test_is_focus_mode_widget_layout_table_false(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test is_focus_mode_widget returns False for layout tables."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
import gi
|
|
|
|
gi.require_version("Atspi", "2.0")
|
|
from gi.repository import Atspi
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
ax_utilities = mocks["cthulhu.ax_utilities"]
|
|
ax_utilities.AXUtilities.is_editable.return_value = False
|
|
ax_utilities.AXUtilities.is_expandable.return_value = False
|
|
|
|
ax_object = mocks["cthulhu.ax_object"]
|
|
ax_object.AXObject.get_role.return_value = Atspi.Role.TABLE_CELL
|
|
|
|
ax_utilities.AXUtilities.get_table.return_value = MagicMock()
|
|
ax_utilities.AXUtilities.is_layout_table.return_value = True
|
|
|
|
mock_script = MagicMock()
|
|
mock_obj = MagicMock()
|
|
|
|
presenter = module.get_presenter()
|
|
result = presenter.is_focus_mode_widget(mock_script, mock_obj)
|
|
|
|
assert result is False
|
|
|
|
def test_is_focus_mode_widget_list_box_item(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test is_focus_mode_widget returns True for list box items."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
import gi
|
|
|
|
gi.require_version("Atspi", "2.0")
|
|
from gi.repository import Atspi
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
ax_utilities = mocks["cthulhu.ax_utilities"]
|
|
ax_utilities.AXUtilities.is_editable.return_value = False
|
|
ax_utilities.AXUtilities.is_expandable.return_value = False
|
|
ax_utilities.AXUtilities.is_list_box_item.return_value = True
|
|
|
|
ax_object = mocks["cthulhu.ax_object"]
|
|
ax_object.AXObject.get_role.return_value = Atspi.Role.LIST_ITEM
|
|
|
|
ax_utilities.AXUtilities.is_layout_table.return_value = False
|
|
|
|
mock_script = MagicMock()
|
|
mock_obj = MagicMock()
|
|
|
|
presenter = module.get_presenter()
|
|
result = presenter.is_focus_mode_widget(mock_script, mock_obj)
|
|
|
|
assert result is True
|
|
|
|
def test_is_focus_mode_widget_button_with_popup(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test is_focus_mode_widget returns True for buttons with popup."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
import gi
|
|
|
|
gi.require_version("Atspi", "2.0")
|
|
from gi.repository import Atspi
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
ax_utilities = mocks["cthulhu.ax_utilities"]
|
|
ax_utilities.AXUtilities.is_editable.return_value = False
|
|
ax_utilities.AXUtilities.is_expandable.return_value = False
|
|
ax_utilities.AXUtilities.is_list_box_item.return_value = False
|
|
ax_utilities.AXUtilities.is_button_with_popup.return_value = True
|
|
|
|
ax_object = mocks["cthulhu.ax_object"]
|
|
ax_object.AXObject.get_role.return_value = Atspi.Role.BUTTON
|
|
|
|
ax_utilities.AXUtilities.is_layout_table.return_value = False
|
|
|
|
mock_script = MagicMock()
|
|
mock_obj = MagicMock()
|
|
|
|
presenter = module.get_presenter()
|
|
result = presenter.is_focus_mode_widget(mock_script, mock_obj)
|
|
|
|
assert result is True
|
|
|
|
def test_is_focus_mode_widget_table_cell_not_layout(
|
|
self,
|
|
test_context: CthulhuTestContext,
|
|
) -> None:
|
|
"""Test is_focus_mode_widget returns True for non-layout table cells."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
import gi
|
|
|
|
gi.require_version("Atspi", "2.0")
|
|
from gi.repository import Atspi
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
ax_utilities = mocks["cthulhu.ax_utilities"]
|
|
ax_utilities.AXUtilities.is_editable.return_value = False
|
|
ax_utilities.AXUtilities.is_expandable.return_value = False
|
|
ax_utilities.AXUtilities.is_list_box_item.return_value = False
|
|
ax_utilities.AXUtilities.is_button_with_popup.return_value = False
|
|
|
|
ax_object = mocks["cthulhu.ax_object"]
|
|
ax_object.AXObject.get_role.return_value = Atspi.Role.TABLE_CELL
|
|
|
|
ax_utilities.AXUtilities.get_table.return_value = MagicMock()
|
|
ax_utilities.AXUtilities.is_layout_table.return_value = False
|
|
|
|
ax_document = mocks["cthulhu.ax_document"]
|
|
ax_document.AXDocument.is_pdf.return_value = False
|
|
|
|
mock_script = MagicMock()
|
|
mock_script.utilities.is_text_block_element.return_value = False
|
|
mock_script.utilities.has_name_and_action_and_no_useful_children.return_value = False
|
|
mock_obj = MagicMock()
|
|
|
|
presenter = module.get_presenter()
|
|
result = presenter.is_focus_mode_widget(mock_script, mock_obj)
|
|
|
|
assert result is True
|
|
|
|
def test_is_focus_mode_widget_grid_descendant(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test is_focus_mode_widget returns True for grid descendants."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
import gi
|
|
|
|
gi.require_version("Atspi", "2.0")
|
|
from gi.repository import Atspi
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
ax_utilities = mocks["cthulhu.ax_utilities"]
|
|
ax_utilities.AXUtilities.is_editable.return_value = False
|
|
ax_utilities.AXUtilities.is_expandable.return_value = False
|
|
ax_utilities.AXUtilities.is_list_box_item.return_value = False
|
|
ax_utilities.AXUtilities.is_button_with_popup.return_value = False
|
|
ax_utilities.AXUtilities.is_grid = MagicMock()
|
|
|
|
ax_object = mocks["cthulhu.ax_object"]
|
|
ax_object.AXObject.get_role.return_value = Atspi.Role.PARAGRAPH
|
|
ax_utilities.AXUtilities.find_ancestor.return_value = MagicMock()
|
|
|
|
ax_utilities.AXUtilities.is_layout_table.return_value = False
|
|
|
|
mock_script = MagicMock()
|
|
mock_script.utilities.is_text_block_element.return_value = True
|
|
mock_obj = MagicMock()
|
|
|
|
presenter = module.get_presenter()
|
|
result = presenter.is_focus_mode_widget(mock_script, mock_obj)
|
|
|
|
assert result is True
|
|
|
|
def test_is_focus_mode_widget_menu_descendant(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test is_focus_mode_widget returns True for menu descendants."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
import gi
|
|
|
|
gi.require_version("Atspi", "2.0")
|
|
from gi.repository import Atspi
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
ax_utilities = mocks["cthulhu.ax_utilities"]
|
|
ax_utilities.AXUtilities.is_editable.return_value = False
|
|
ax_utilities.AXUtilities.is_expandable.return_value = False
|
|
ax_utilities.AXUtilities.is_list_box_item.return_value = False
|
|
ax_utilities.AXUtilities.is_button_with_popup.return_value = False
|
|
ax_utilities.AXUtilities.is_grid = MagicMock()
|
|
ax_utilities.AXUtilities.is_menu = MagicMock()
|
|
|
|
ax_object = mocks["cthulhu.ax_object"]
|
|
ax_object.AXObject.get_role.return_value = Atspi.Role.PARAGRAPH
|
|
ax_utilities.AXUtilities.find_ancestor.side_effect = [None, MagicMock()]
|
|
|
|
ax_utilities.AXUtilities.is_layout_table.return_value = False
|
|
|
|
mock_script = MagicMock()
|
|
mock_script.utilities.is_text_block_element.return_value = True
|
|
mock_obj = MagicMock()
|
|
|
|
presenter = module.get_presenter()
|
|
result = presenter.is_focus_mode_widget(mock_script, mock_obj)
|
|
|
|
assert result is True
|
|
|
|
def test_is_focus_mode_widget_toolbar_descendant(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test is_focus_mode_widget returns True for toolbar descendants."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
import gi
|
|
|
|
gi.require_version("Atspi", "2.0")
|
|
from gi.repository import Atspi
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
ax_utilities = mocks["cthulhu.ax_utilities"]
|
|
ax_utilities.AXUtilities.is_editable.return_value = False
|
|
ax_utilities.AXUtilities.is_expandable.return_value = False
|
|
ax_utilities.AXUtilities.is_list_box_item.return_value = False
|
|
ax_utilities.AXUtilities.is_button_with_popup.return_value = False
|
|
ax_utilities.AXUtilities.is_grid = MagicMock()
|
|
ax_utilities.AXUtilities.is_menu = MagicMock()
|
|
ax_utilities.AXUtilities.is_tool_bar = MagicMock()
|
|
|
|
ax_object = mocks["cthulhu.ax_object"]
|
|
ax_object.AXObject.get_role.return_value = Atspi.Role.PARAGRAPH
|
|
ax_utilities.AXUtilities.find_ancestor.side_effect = [None, None, MagicMock()]
|
|
|
|
ax_utilities.AXUtilities.is_layout_table.return_value = False
|
|
|
|
mock_script = MagicMock()
|
|
mock_script.utilities.is_text_block_element.return_value = True
|
|
mock_obj = MagicMock()
|
|
|
|
presenter = module.get_presenter()
|
|
result = presenter.is_focus_mode_widget(mock_script, mock_obj)
|
|
|
|
assert result is True
|
|
|
|
def test_is_focus_mode_widget_content_editable(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test is_focus_mode_widget returns True for content editable with embedded."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
import gi
|
|
|
|
gi.require_version("Atspi", "2.0")
|
|
from gi.repository import Atspi
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
ax_utilities = mocks["cthulhu.ax_utilities"]
|
|
ax_utilities.AXUtilities.is_editable.return_value = False
|
|
ax_utilities.AXUtilities.is_expandable.return_value = False
|
|
ax_utilities.AXUtilities.is_list_box_item.return_value = False
|
|
ax_utilities.AXUtilities.is_button_with_popup.return_value = False
|
|
ax_utilities.AXUtilities.is_grid = MagicMock()
|
|
ax_utilities.AXUtilities.is_menu = MagicMock()
|
|
ax_utilities.AXUtilities.is_tool_bar = MagicMock()
|
|
|
|
ax_object = mocks["cthulhu.ax_object"]
|
|
ax_object.AXObject.get_role.return_value = Atspi.Role.PARAGRAPH
|
|
ax_utilities.AXUtilities.find_ancestor.return_value = None
|
|
|
|
ax_utilities.AXUtilities.is_layout_table.return_value = False
|
|
|
|
mock_script = MagicMock()
|
|
mock_script.utilities.is_text_block_element.return_value = True
|
|
mock_script.utilities.is_content_editable_with_embedded_objects.return_value = True
|
|
mock_obj = MagicMock()
|
|
|
|
presenter = module.get_presenter()
|
|
result = presenter.is_focus_mode_widget(mock_script, mock_obj)
|
|
|
|
assert result is True
|
|
|
|
def test_is_focus_mode_widget_default_false(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test is_focus_mode_widget returns False by default."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
import gi
|
|
|
|
gi.require_version("Atspi", "2.0")
|
|
from gi.repository import Atspi
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
ax_utilities = mocks["cthulhu.ax_utilities"]
|
|
ax_utilities.AXUtilities.is_editable.return_value = False
|
|
ax_utilities.AXUtilities.is_expandable.return_value = False
|
|
ax_utilities.AXUtilities.is_list_box_item.return_value = False
|
|
ax_utilities.AXUtilities.is_button_with_popup.return_value = False
|
|
ax_utilities.AXUtilities.is_grid = MagicMock()
|
|
ax_utilities.AXUtilities.is_menu = MagicMock()
|
|
ax_utilities.AXUtilities.is_tool_bar = MagicMock()
|
|
|
|
ax_object = mocks["cthulhu.ax_object"]
|
|
ax_object.AXObject.get_role.return_value = Atspi.Role.PARAGRAPH
|
|
ax_utilities.AXUtilities.find_ancestor.return_value = None
|
|
|
|
ax_utilities.AXUtilities.is_layout_table.return_value = False
|
|
|
|
mock_script = MagicMock()
|
|
mock_script.utilities.is_text_block_element.return_value = True
|
|
mock_script.utilities.is_content_editable_with_embedded_objects.return_value = False
|
|
mock_obj = MagicMock()
|
|
|
|
presenter = module.get_presenter()
|
|
result = presenter.is_focus_mode_widget(mock_script, mock_obj)
|
|
|
|
assert result is False
|
|
|
|
def test_is_focus_mode_widget_pdf_table_false(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test is_focus_mode_widget returns False for table cells in PDFs."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
import gi
|
|
|
|
gi.require_version("Atspi", "2.0")
|
|
from gi.repository import Atspi
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
ax_utilities = mocks["cthulhu.ax_utilities"]
|
|
ax_utilities.AXUtilities.is_editable.return_value = False
|
|
ax_utilities.AXUtilities.is_expandable.return_value = False
|
|
ax_utilities.AXUtilities.is_list_box_item.return_value = False
|
|
ax_utilities.AXUtilities.is_button_with_popup.return_value = False
|
|
ax_utilities.AXUtilities.is_grid = MagicMock()
|
|
ax_utilities.AXUtilities.is_menu = MagicMock()
|
|
ax_utilities.AXUtilities.is_tool_bar = MagicMock()
|
|
|
|
ax_object = mocks["cthulhu.ax_object"]
|
|
ax_object.AXObject.get_role.return_value = Atspi.Role.TABLE_CELL
|
|
ax_utilities.AXUtilities.find_ancestor.return_value = None
|
|
|
|
ax_utilities.AXUtilities.get_table.return_value = MagicMock()
|
|
ax_utilities.AXUtilities.is_layout_table.return_value = False
|
|
|
|
ax_document = mocks["cthulhu.ax_document"]
|
|
ax_document.AXDocument.is_pdf.return_value = True
|
|
|
|
mock_script = MagicMock()
|
|
mock_script.utilities.is_text_block_element.return_value = False
|
|
mock_script.utilities.has_name_and_action_and_no_useful_children.return_value = False
|
|
mock_script.utilities.is_content_editable_with_embedded_objects.return_value = False
|
|
mock_obj = MagicMock()
|
|
|
|
presenter = module.get_presenter()
|
|
result = presenter.is_focus_mode_widget(mock_script, mock_obj)
|
|
|
|
assert result is False
|
|
|
|
def test_get_in_focus_mode_no_script(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test get_in_focus_mode returns False when no active script."""
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
script_manager = mocks["cthulhu.script_manager"]
|
|
script_manager.get_manager.return_value.get_active_script.return_value = None
|
|
|
|
presenter = module.get_presenter()
|
|
result = presenter.get_in_focus_mode()
|
|
|
|
assert result is False
|
|
|
|
def test_get_focus_mode_is_sticky_no_script(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test get_focus_mode_is_sticky returns False when no active script."""
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
script_manager = mocks["cthulhu.script_manager"]
|
|
script_manager.get_manager.return_value.get_active_script.return_value = None
|
|
|
|
presenter = module.get_presenter()
|
|
result = presenter.get_focus_mode_is_sticky()
|
|
|
|
assert result is False
|
|
|
|
def test_get_browse_mode_is_sticky_no_script(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test get_browse_mode_is_sticky returns False when no active script."""
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
script_manager = mocks["cthulhu.script_manager"]
|
|
script_manager.get_manager.return_value.get_active_script.return_value = None
|
|
|
|
presenter = module.get_presenter()
|
|
result = presenter.get_browse_mode_is_sticky()
|
|
|
|
assert result is False
|
|
|
|
def test_has_state_for_app(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test has_state_for_app returns correct value."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, _mocks = self._setup_presenter(test_context)
|
|
|
|
mock_app = MagicMock()
|
|
presenter = module.get_presenter()
|
|
|
|
assert presenter.has_state_for_app(mock_app) is False
|
|
|
|
presenter._app_states[hash(mock_app)] = module._AppModeState()
|
|
|
|
assert presenter.has_state_for_app(mock_app) is True
|
|
|
|
def test_update_mode_if_needed_within_doc(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test update_mode_if_needed when moving within document."""
|
|
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
module, mocks = self._setup_presenter(test_context)
|
|
|
|
mock_app = MagicMock()
|
|
mock_script = MagicMock()
|
|
mock_script.app = mock_app
|
|
mock_doc = MagicMock()
|
|
mock_script.utilities.get_top_level_document_for_object.return_value = mock_doc
|
|
mock_script.utilities.in_document_content.return_value = True
|
|
mock_script.utilities.get_caret_context.return_value = (MagicMock(), 0)
|
|
|
|
caret_nav = mocks["cthulhu.caret_navigator"]
|
|
nav_mock = caret_nav.get_navigator.return_value
|
|
nav_mock.last_input_event_was_navigation_command.return_value = False
|
|
caret_nav.get_navigator.return_value.last_command_prevents_focus_mode.return_value = False
|
|
struct_nav = mocks["cthulhu.structural_navigator"]
|
|
nav_mock = struct_nav.get_navigator.return_value
|
|
nav_mock.last_input_event_was_navigation_command.return_value = False
|
|
struct_nav.get_navigator.return_value.last_command_prevents_focus_mode.return_value = False
|
|
table_nav = mocks["cthulhu.table_navigator"]
|
|
nav_mock = table_nav.get_navigator.return_value
|
|
nav_mock.last_input_event_was_navigation_command.return_value = False
|
|
focus_manager = mocks["cthulhu.focus_manager"]
|
|
focus_manager.get_manager.return_value.in_say_all.return_value = False
|
|
|
|
script_manager = mocks["cthulhu.script_manager"]
|
|
script_manager.get_manager.return_value.get_active_script.return_value = mock_script
|
|
|
|
presenter = module.get_presenter()
|
|
presenter._app_states[hash(mock_app)] = module._AppModeState(
|
|
in_focus_mode=False,
|
|
focus_mode_is_sticky=False,
|
|
browse_mode_is_sticky=False,
|
|
)
|
|
|
|
with patch.object(presenter, "is_focus_mode_widget", return_value=False):
|
|
result = presenter.update_mode_if_needed(mock_script, MagicMock(), MagicMock())
|
|
|
|
assert result is True
|
|
|
|
def test_update_mode_if_needed_sticky_within_doc(self, test_context: CthulhuTestContext) -> None:
|
|
"""Test update_mode_if_needed within doc with sticky mode returns False."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
module, _mocks = self._setup_presenter(test_context)
|
|
|
|
mock_app = MagicMock()
|
|
mock_script = MagicMock()
|
|
mock_script.app = mock_app
|
|
mock_doc = MagicMock()
|
|
mock_script.utilities.get_top_level_document_for_object.return_value = mock_doc
|
|
|
|
presenter = module.get_presenter()
|
|
presenter._app_states[hash(mock_app)] = module._AppModeState(
|
|
in_focus_mode=True,
|
|
focus_mode_is_sticky=True,
|
|
browse_mode_is_sticky=False,
|
|
)
|
|
|
|
result = presenter.update_mode_if_needed(mock_script, MagicMock(), MagicMock())
|
|
|
|
assert result is False
|