Files
cthulhu/tests/test_web_router_regressions.py
2026-04-05 21:32:06 -04:00

154 lines
7.1 KiB
Python

import sys
import unittest
from pathlib import Path
from unittest import mock
import gi
gi.require_version("Gdk", "3.0")
gi.require_version("Gtk", "3.0")
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
soundGeneratorModule = sys.modules.get("cthulhu.sound_generator")
if soundGeneratorModule is not None and not hasattr(soundGeneratorModule, "SoundGenerator"):
class _StubSoundGenerator:
pass
soundGeneratorModule.SoundGenerator = _StubSoundGenerator
from cthulhu import ax_object
from cthulhu import ax_utilities
from cthulhu.scripts.web import script as web_script
from cthulhu.scripts.web import script_utilities
class WebClickableActivationTests(unittest.TestCase):
def test_return_activates_click_ancestor_on_caret_context(self):
testScript = web_script.Script.__new__(web_script.Script)
caretObject = object()
documentObject = object()
testScript.utilities = mock.Mock()
testScript.utilities.inDocumentContent.return_value = True
testScript.utilities.getCaretContext.return_value = (caretObject, 0)
testScript.utilities.isClickableElement.return_value = False
testScript.inFocusMode = mock.Mock(return_value=False)
testScript.presentMessage = mock.Mock()
testScript._presentDelayedMessage = mock.Mock()
testScript._restoreFocusAfterClick = mock.Mock()
def has_action(obj, action_name):
return obj is caretObject and action_name == "click-ancestor"
with (
mock.patch.object(web_script.cthulhu_state, "locusOfFocus", documentObject),
mock.patch.object(ax_utilities.AXUtilities, "is_entry", return_value=False),
mock.patch.object(ax_utilities.AXUtilities, "is_text", return_value=False),
mock.patch.object(ax_utilities.AXUtilities, "is_password_text", return_value=False),
mock.patch.object(ax_utilities.AXUtilities, "is_combo_box", return_value=False),
mock.patch.object(ax_utilities.AXUtilities, "is_button", return_value=False),
mock.patch.object(ax_utilities.AXUtilities, "is_push_button", return_value=False),
mock.patch.object(ax_utilities.AXUtilities, "is_link", return_value=False),
mock.patch.object(ax_object.AXObject, "has_action", side_effect=has_action),
mock.patch.object(ax_object.AXObject, "do_named_action", return_value=True) as doAction,
mock.patch("cthulhu.ax_event_synthesizer.AXEventSynthesizer.click_object") as clickObject,
):
self.assertTrue(testScript._tryClickableActivation(mock.Mock(event_string="Return")))
doAction.assert_called_once_with(caretObject, "click-ancestor")
clickObject.assert_not_called()
testScript._presentDelayedMessage.assert_not_called()
class WebHiddenPopupTests(unittest.TestCase):
def test_hidden_ancestor_marks_descendant_hidden(self):
utilities = script_utilities.Utilities.__new__(script_utilities.Utilities)
child = object()
hiddenParent = object()
utilities.inDocumentContent = mock.Mock(return_value=True)
utilities.objectAttributes = mock.Mock(
side_effect=lambda obj, useCache=False: {
child: {"display": "block"},
hiddenParent: {"display": "none"},
}.get(obj, {})
)
with mock.patch.object(
script_utilities.AXObject,
"get_parent",
side_effect=lambda obj: hiddenParent if obj is child else None,
):
self.assertTrue(utilities.isHidden(child))
def test_focusable_hidden_object_cannot_have_caret_context(self):
utilities = script_utilities.Utilities.__new__(script_utilities.Utilities)
hiddenObject = object()
utilities._canHaveCaretContextDecision = {}
utilities.isZombie = mock.Mock(return_value=False)
utilities.isStaticTextLeaf = mock.Mock(return_value=False)
utilities.isUselessEmptyElement = mock.Mock(return_value=False)
utilities.isOffScreenLabel = mock.Mock(return_value=False)
utilities.isNonNavigablePopup = mock.Mock(return_value=False)
utilities.isUselessImage = mock.Mock(return_value=False)
utilities.isEmptyAnchor = mock.Mock(return_value=False)
utilities.isEmptyToolTip = mock.Mock(return_value=False)
utilities.isParentOfNullChild = mock.Mock(return_value=False)
utilities.isPseudoElement = mock.Mock(return_value=False)
utilities.isFakePlaceholderForEntry = mock.Mock(return_value=False)
utilities.isNonInteractiveDescendantOfControl = mock.Mock(return_value=False)
utilities.isHidden = mock.Mock(return_value=True)
utilities.hasNoSize = mock.Mock(return_value=False)
with (
mock.patch.object(script_utilities.AXObject, "is_dead", return_value=False),
mock.patch.object(script_utilities.AXUtilities, "is_focusable", return_value=True),
):
self.assertFalse(utilities._canHaveCaretContext(hiddenObject))
class WebRemovedChildRegressionTests(unittest.TestCase):
def test_removed_child_recovery_does_not_crash_when_last_key_is_not_up_or_down(self):
utilities = script_utilities.Utilities.__new__(script_utilities.Utilities)
removedChild = object()
locusOfFocus = object()
source = object()
recoveredObject = object()
event = mock.Mock(any_data=removedChild, source=source, detail1=0)
utilities._script = mock.Mock(pointOfReference={"names": {}})
utilities._handleEventForRemovedListBoxChild = mock.Mock(return_value=False)
utilities.isSameObject = mock.Mock(return_value=False)
utilities.searchForCaretContext = mock.Mock(return_value=(recoveredObject, 0))
utilities.setCaretContext = mock.Mock()
manager = mock.Mock()
manager.last_event_was_up.return_value = False
manager.last_event_was_down.return_value = False
def find_ancestor(obj, predicate):
if obj is locusOfFocus and predicate(removedChild):
return removedChild
return None
with (
mock.patch.object(script_utilities.cthulhu_state, "locusOfFocus", locusOfFocus),
mock.patch.object(script_utilities.input_event_manager, "get_manager", return_value=manager),
mock.patch.object(script_utilities.AXObject, "find_ancestor", side_effect=find_ancestor),
mock.patch.object(script_utilities.AXObject, "get_child_count", return_value=0),
mock.patch.object(script_utilities.AXObject, "clear_cache"),
mock.patch.object(script_utilities.AXObject, "is_dead", return_value=False),
mock.patch.object(script_utilities.AXUtilities, "get_focused_object", return_value=None),
mock.patch.object(script_utilities.cthulhu, "setLocusOfFocus") as setLocusOfFocus,
):
self.assertTrue(utilities.handleEventForRemovedChild(event))
setLocusOfFocus.assert_called_once_with(event, recoveredObject, False)
utilities.setCaretContext.assert_called_once_with(recoveredObject, 0)
if __name__ == "__main__":
unittest.main()