Updated tests.
This commit is contained in:
@@ -11,7 +11,7 @@ gi.require_version("Atspi", "2.0")
|
|||||||
from gi.repository import Atspi
|
from gi.repository import Atspi
|
||||||
|
|
||||||
from cthulhu import cthulhu_state
|
from cthulhu import cthulhu_state
|
||||||
from cthulhu.ax_utilities_event import AXUtilitiesEvent
|
from cthulhu.ax_utilities_event import AXUtilitiesEvent, TextEventReason
|
||||||
from cthulhu.scripts import default
|
from cthulhu.scripts import default
|
||||||
from cthulhu.scripts.toolkits.Chromium import script as chromium_script
|
from cthulhu.scripts.toolkits.Chromium import script as chromium_script
|
||||||
from cthulhu.scripts.toolkits.Gecko import script as gecko_script
|
from cthulhu.scripts.toolkits.Gecko import script as gecko_script
|
||||||
@@ -187,6 +187,222 @@ class ChromiumTabFocusSequenceTests(unittest.TestCase):
|
|||||||
self._assert_tab_caret_focused_sequence_presents_once(radio)
|
self._assert_tab_caret_focused_sequence_presents_once(radio)
|
||||||
|
|
||||||
|
|
||||||
|
class FocusedChangeInteractionSequenceTests(unittest.TestCase):
|
||||||
|
"""Ordered ownership contracts around focused-change events."""
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _make_script(
|
||||||
|
document: object,
|
||||||
|
caretContext: FakeAccessible,
|
||||||
|
) -> chromium_script.Script:
|
||||||
|
testScript = chromium_script.Script.__new__(chromium_script.Script)
|
||||||
|
testScript._lastCommandWasCaretNav = False
|
||||||
|
testScript._lastCommandWasStructNav = False
|
||||||
|
testScript._lastCommandWasMouseButton = False
|
||||||
|
testScript._browseModeIsSticky = False
|
||||||
|
testScript._clearSyntheticWebSelection = mock.Mock()
|
||||||
|
testScript.refreshKeyGrabs = mock.Mock()
|
||||||
|
testScript.utilities = mock.Mock()
|
||||||
|
testScript.utilities.isDocument.return_value = False
|
||||||
|
testScript.utilities.isStaticTextLeaf.return_value = False
|
||||||
|
testScript.utilities.isRedundantAutocompleteEvent.return_value = False
|
||||||
|
testScript.utilities.isZombie.return_value = False
|
||||||
|
testScript.utilities.getTopLevelDocumentForObject.return_value = document
|
||||||
|
testScript.utilities.getDocumentForObject.return_value = document
|
||||||
|
testScript.utilities.getCaretContext.return_value = (caretContext, 0)
|
||||||
|
testScript.utilities.lastInputEventWasCaretNavWithSelection.return_value = False
|
||||||
|
testScript.utilities.lastInputEventWasCharNav.return_value = False
|
||||||
|
testScript.utilities.inFindContainer.return_value = False
|
||||||
|
testScript.utilities.eventIsFromLocusOfFocusDocument.return_value = True
|
||||||
|
testScript.utilities.isWebAppDescendant.return_value = False
|
||||||
|
testScript.utilities.handleEventFromContextReplicant.return_value = False
|
||||||
|
testScript.utilities.lastInputEventWasPageNav.return_value = False
|
||||||
|
testScript.utilities.isAnchor.return_value = False
|
||||||
|
testScript.utilities.isLink.return_value = False
|
||||||
|
testScript.utilities.isChildOfCurrentFragment.return_value = False
|
||||||
|
testScript.utilities.documentFragment.return_value = ""
|
||||||
|
return testScript
|
||||||
|
|
||||||
|
def _assert_navigation_command_owns_caret_and_focus_pair(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
caretNavigation: bool,
|
||||||
|
structuralNavigation: bool,
|
||||||
|
) -> None:
|
||||||
|
document = object()
|
||||||
|
target = FakeAccessible(Atspi.Role.PARAGRAPH)
|
||||||
|
testScript = self._make_script(document, target)
|
||||||
|
testScript._lastCommandWasCaretNav = caretNavigation
|
||||||
|
testScript._lastCommandWasStructNav = structuralNavigation
|
||||||
|
events = [
|
||||||
|
FakeEvent("object:text-caret-moved", target, detail1=4),
|
||||||
|
FakeEvent("object:state-changed:focused", target, detail1=1),
|
||||||
|
]
|
||||||
|
presentations = ["navigation-command"]
|
||||||
|
|
||||||
|
with (
|
||||||
|
mock.patch.object(cthulhu_state, "locusOfFocus", target),
|
||||||
|
mock.patch.object(
|
||||||
|
AXUtilitiesEvent,
|
||||||
|
"get_text_event_reason",
|
||||||
|
return_value=TextEventReason.NAVIGATION_BY_CHARACTER,
|
||||||
|
),
|
||||||
|
mock.patch.object(web_script.AXUtilities, "is_editable", return_value=False),
|
||||||
|
mock.patch.object(web_script.AXUtilities, "is_dialog_or_alert", return_value=False),
|
||||||
|
mock.patch.object(web_script.AXUtilities, "is_focusable", return_value=True),
|
||||||
|
mock.patch.object(web_script.AXUtilities, "is_focused", return_value=True),
|
||||||
|
mock.patch.object(web_script.AXUtilities, "is_document", return_value=False),
|
||||||
|
mock.patch.object(
|
||||||
|
default.Script,
|
||||||
|
"onCaretMoved",
|
||||||
|
side_effect=lambda _script, _event: presentations.append("caret-event"),
|
||||||
|
) as defaultCaretHandler,
|
||||||
|
mock.patch.object(
|
||||||
|
default.Script,
|
||||||
|
"onFocusedChanged",
|
||||||
|
side_effect=lambda _script, _event: presentations.append("focus-event"),
|
||||||
|
) as defaultFocusHandler,
|
||||||
|
):
|
||||||
|
WebEventSequence(testScript).run(events)
|
||||||
|
|
||||||
|
self.assertEqual(presentations, ["navigation-command"])
|
||||||
|
defaultCaretHandler.assert_not_called()
|
||||||
|
defaultFocusHandler.assert_not_called()
|
||||||
|
|
||||||
|
def test_caret_navigation_owns_following_caret_and_focus_events(self) -> None:
|
||||||
|
self._assert_navigation_command_owns_caret_and_focus_pair(
|
||||||
|
caretNavigation=True,
|
||||||
|
structuralNavigation=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_structural_navigation_owns_following_caret_and_focus_events(self) -> None:
|
||||||
|
self._assert_navigation_command_owns_caret_and_focus_pair(
|
||||||
|
caretNavigation=False,
|
||||||
|
structuralNavigation=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_tab_clears_navigation_ownership_and_real_focus_still_presents(self) -> None:
|
||||||
|
document = object()
|
||||||
|
oldTarget = FakeAccessible(Atspi.Role.PARAGRAPH)
|
||||||
|
newTarget = FakeAccessible(Atspi.Role.ENTRY, editable=True)
|
||||||
|
testScript = self._make_script(document, oldTarget)
|
||||||
|
testScript._lastCommandWasCaretNav = True
|
||||||
|
ignoredFocus = FakeEvent(
|
||||||
|
"object:state-changed:focused",
|
||||||
|
oldTarget,
|
||||||
|
detail1=1,
|
||||||
|
)
|
||||||
|
realFocus = FakeEvent(
|
||||||
|
"object:state-changed:focused",
|
||||||
|
newTarget,
|
||||||
|
detail1=1,
|
||||||
|
)
|
||||||
|
tabEvent = mock.Mock(event_string="Tab")
|
||||||
|
tabEvent.is_modifier_key.return_value = False
|
||||||
|
presentations: list[FakeAccessible] = []
|
||||||
|
|
||||||
|
with (
|
||||||
|
mock.patch.object(cthulhu_state, "locusOfFocus", oldTarget),
|
||||||
|
mock.patch.object(
|
||||||
|
web_script.AXUtilities,
|
||||||
|
"is_editable",
|
||||||
|
side_effect=lambda obj: obj.editable,
|
||||||
|
),
|
||||||
|
mock.patch.object(web_script.AXUtilities, "is_dialog_or_alert", return_value=False),
|
||||||
|
mock.patch.object(web_script.AXUtilities, "is_focusable", return_value=True),
|
||||||
|
mock.patch.object(web_script.AXUtilities, "is_focused", return_value=True),
|
||||||
|
mock.patch.object(web_script.AXUtilities, "is_document", return_value=False),
|
||||||
|
mock.patch.object(default.Script, "shouldConsumeKeyboardEvent", return_value=False),
|
||||||
|
mock.patch.object(
|
||||||
|
default.Script,
|
||||||
|
"onFocusedChanged",
|
||||||
|
side_effect=lambda _script, event: presentations.append(event.source),
|
||||||
|
) as defaultFocusHandler,
|
||||||
|
):
|
||||||
|
WebEventSequence(testScript).run([ignoredFocus])
|
||||||
|
web_script.Script.shouldConsumeKeyboardEvent(testScript, tabEvent, None)
|
||||||
|
WebEventSequence(testScript).run([realFocus])
|
||||||
|
|
||||||
|
self.assertEqual(presentations, [newTarget])
|
||||||
|
self.assertFalse(testScript._lastCommandWasCaretNav)
|
||||||
|
self.assertFalse(testScript._lastCommandWasStructNav)
|
||||||
|
defaultFocusHandler.assert_called_once_with(testScript, realFocus)
|
||||||
|
|
||||||
|
def _assert_document_focus_uses_recovered_context_once(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
pageNavigation: bool,
|
||||||
|
documentFragment: str,
|
||||||
|
) -> None:
|
||||||
|
document = FakeAccessible(Atspi.Role.DOCUMENT_WEB)
|
||||||
|
oldFocus = FakeAccessible(Atspi.Role.FRAME)
|
||||||
|
context = FakeAccessible(Atspi.Role.LINK)
|
||||||
|
testScript = self._make_script(document, context)
|
||||||
|
testScript.utilities.getDocumentForObject.side_effect = (
|
||||||
|
lambda obj: document if obj is document else None
|
||||||
|
)
|
||||||
|
testScript.utilities.getCaretContext.return_value = (None, -1)
|
||||||
|
testScript.utilities.searchForCaretContext.return_value = (context, 6)
|
||||||
|
testScript.utilities.lastInputEventWasPageNav.return_value = pageNavigation
|
||||||
|
testScript.utilities.isLink.side_effect = lambda obj: obj is context
|
||||||
|
testScript.utilities.documentFragment.return_value = documentFragment
|
||||||
|
event = FakeEvent("object:state-changed:focused", document, detail1=1)
|
||||||
|
presentations: list[FakeAccessible] = []
|
||||||
|
|
||||||
|
def set_focus(
|
||||||
|
_event: FakeEvent,
|
||||||
|
obj: FakeAccessible,
|
||||||
|
notifyScript: bool = True,
|
||||||
|
) -> None:
|
||||||
|
if notifyScript:
|
||||||
|
presentations.append(obj)
|
||||||
|
|
||||||
|
with (
|
||||||
|
mock.patch.object(cthulhu_state, "locusOfFocus", oldFocus),
|
||||||
|
mock.patch.object(web_script.AXUtilities, "is_editable", return_value=False),
|
||||||
|
mock.patch.object(web_script.AXUtilities, "is_dialog_or_alert", return_value=False),
|
||||||
|
mock.patch.object(web_script.AXUtilities, "is_focusable", return_value=True),
|
||||||
|
mock.patch.object(
|
||||||
|
web_script.AXUtilities,
|
||||||
|
"is_focused",
|
||||||
|
side_effect=lambda obj: obj is document,
|
||||||
|
),
|
||||||
|
mock.patch.object(
|
||||||
|
web_script.AXUtilities,
|
||||||
|
"is_document",
|
||||||
|
side_effect=lambda obj: obj is document,
|
||||||
|
),
|
||||||
|
mock.patch.object(web_script.AXObject, "clear_cache"),
|
||||||
|
mock.patch.object(web_script.cthulhu, "setLocusOfFocus", side_effect=set_focus) as setFocus,
|
||||||
|
mock.patch.object(default.Script, "onFocusedChanged") as defaultFocusHandler,
|
||||||
|
):
|
||||||
|
WebEventSequence(testScript).run([event])
|
||||||
|
|
||||||
|
self.assertEqual(presentations, [context])
|
||||||
|
self.assertEqual(
|
||||||
|
setFocus.call_args_list,
|
||||||
|
[mock.call(event, context, False), mock.call(event, context)],
|
||||||
|
)
|
||||||
|
testScript.utilities.setCaretContext.assert_has_calls(
|
||||||
|
[mock.call(context, 6), mock.call(context, 6)]
|
||||||
|
if pageNavigation
|
||||||
|
else [mock.call(context, 6)]
|
||||||
|
)
|
||||||
|
defaultFocusHandler.assert_not_called()
|
||||||
|
|
||||||
|
def test_page_navigation_focus_uses_recovered_caret_context_once(self) -> None:
|
||||||
|
self._assert_document_focus_uses_recovered_context_once(
|
||||||
|
pageNavigation=True,
|
||||||
|
documentFragment="",
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_page_fragment_focus_uses_recovered_caret_context_once(self) -> None:
|
||||||
|
self._assert_document_focus_uses_recovered_context_once(
|
||||||
|
pageNavigation=False,
|
||||||
|
documentFragment="#details",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ChromiumNativeContainerSequenceTests(unittest.TestCase):
|
class ChromiumNativeContainerSequenceTests(unittest.TestCase):
|
||||||
"""Current routing contracts for native containers in Chromium content."""
|
"""Current routing contracts for native containers in Chromium content."""
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user