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()