Steam UI improvements.
This commit is contained in:
65
tests/test_input_event_regressions.py
Normal file
65
tests/test_input_event_regressions.py
Normal file
@@ -0,0 +1,65 @@
|
||||
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 gi.repository import Gdk
|
||||
|
||||
from cthulhu import input_event
|
||||
|
||||
|
||||
class KeyboardEventConsumptionTests(unittest.TestCase):
|
||||
def test_script_consumed_key_without_handler_is_treated_as_consumed(self):
|
||||
testScript = mock.Mock()
|
||||
testScript.app = None
|
||||
testScript.keyBindings.getInputHandler.return_value = None
|
||||
testScript.shouldConsumeKeyboardEvent.return_value = True
|
||||
testScript.learnModePresenter.is_active.return_value = False
|
||||
testScript.presentKeyboardEvent.return_value = False
|
||||
|
||||
keyboardEvent = input_event.KeyboardEvent(
|
||||
True,
|
||||
36,
|
||||
Gdk.KEY_Return,
|
||||
0,
|
||||
"Return",
|
||||
)
|
||||
keyboardEvent.set_script(testScript)
|
||||
keyboardEvent.set_object(None)
|
||||
keyboardEvent.set_window(None)
|
||||
|
||||
with (
|
||||
mock.patch("cthulhu.input_event.cthulhu_state.capturingKeys", False),
|
||||
mock.patch("cthulhu.input_event.cthulhu_state.bypassNextCommand", False),
|
||||
):
|
||||
keyboardEvent._finalize_initialization()
|
||||
self.assertTrue(keyboardEvent._should_consume)
|
||||
self.assertEqual(
|
||||
keyboardEvent._consume_reason,
|
||||
"Script consumed without handler",
|
||||
)
|
||||
|
||||
didConsume, resultReason = keyboardEvent._process()
|
||||
|
||||
self.assertTrue(didConsume)
|
||||
self.assertEqual(resultReason, "Consumed during shouldConsume")
|
||||
testScript.presentationInterrupt.assert_called_once()
|
||||
testScript.presentKeyboardEvent.assert_called_once_with(keyboardEvent)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -70,13 +70,13 @@ class SteamNotificationQueueTests(unittest.TestCase):
|
||||
testScript._presentSteamNotificationTextNow.assert_not_called()
|
||||
self.assertEqual(
|
||||
testScript._steamPendingNotification["text"],
|
||||
"username Playing: Game Title",
|
||||
"username Playing: Borderlands 2",
|
||||
)
|
||||
|
||||
testScript._flushSteamPendingNotification(fromTimer=True)
|
||||
|
||||
testScript._presentSteamNotificationTextNow.assert_called_once_with(
|
||||
"username Playing: Game Title",
|
||||
"username Playing: Borderlands 2",
|
||||
notification,
|
||||
)
|
||||
|
||||
|
||||
161
tests/test_steam_selection_regressions.py
Normal file
161
tests/test_steam_selection_regressions.py
Normal file
@@ -0,0 +1,161 @@
|
||||
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.scripts.apps.steamwebhelper import script as steam_script
|
||||
from cthulhu.scripts.apps.steamwebhelper import script_utilities as steam_script_utilities
|
||||
|
||||
|
||||
class SteamSelectionChangedTests(unittest.TestCase):
|
||||
def test_selection_changed_tolerates_scalar_any_data(self):
|
||||
testScript = steam_script.Script.__new__(steam_script.Script)
|
||||
source = object()
|
||||
event = mock.Mock(source=source, any_data=0)
|
||||
chromiumCalls = []
|
||||
|
||||
def displayedText(obj):
|
||||
if obj is source:
|
||||
return ""
|
||||
raise TypeError("argument self: Expected Atspi.Accessible, but got int")
|
||||
|
||||
def get_name(obj):
|
||||
if obj is source:
|
||||
return "Notifications"
|
||||
raise TypeError("argument self: Expected Atspi.Accessible, but got int")
|
||||
|
||||
testScript.utilities = mock.Mock()
|
||||
testScript.utilities.displayedText.side_effect = displayedText
|
||||
|
||||
def chromiumOnSelectionChanged(self, selectionEvent):
|
||||
chromiumCalls.append((self, selectionEvent))
|
||||
return True
|
||||
|
||||
with (
|
||||
mock.patch.object(steam_script.AXObject, "get_name", side_effect=get_name),
|
||||
mock.patch.object(steam_script.AXObject, "get_description", return_value=""),
|
||||
mock.patch.object(steam_script.AXObject, "get_role_name", return_value="page tab list"),
|
||||
mock.patch.object(steam_script.AXObject, "get_path", return_value=[1, 2, 3]),
|
||||
mock.patch.object(
|
||||
steam_script.Chromium.Script,
|
||||
"onSelectionChanged",
|
||||
new=chromiumOnSelectionChanged,
|
||||
),
|
||||
):
|
||||
self.assertTrue(testScript.onSelectionChanged(event))
|
||||
|
||||
self.assertEqual(chromiumCalls, [(testScript, event)])
|
||||
|
||||
|
||||
class SteamReturnActivationTests(unittest.TestCase):
|
||||
def test_return_activates_focused_steam_button(self):
|
||||
testScript = steam_script.Script.__new__(steam_script.Script)
|
||||
button = object()
|
||||
keyboardEvent = mock.Mock(event_string="Return", modifiers=0)
|
||||
keyboardEvent.is_pressed_key.return_value = True
|
||||
|
||||
testScript.utilities = mock.Mock()
|
||||
testScript.utilities.inDocumentContent.return_value = True
|
||||
testScript.inFocusMode = mock.Mock(return_value=True)
|
||||
testScript.presentMessage = mock.Mock()
|
||||
testScript._presentDelayedMessage = mock.Mock()
|
||||
testScript._restoreFocusAfterClick = mock.Mock()
|
||||
|
||||
def has_action(obj, action_name):
|
||||
return obj is button and action_name == "press"
|
||||
|
||||
with (
|
||||
mock.patch.object(steam_script.cthulhu_state, "locusOfFocus", button),
|
||||
mock.patch.object(steam_script.AXUtilities, "is_entry", return_value=False),
|
||||
mock.patch.object(steam_script.AXUtilities, "is_text", return_value=False),
|
||||
mock.patch.object(steam_script.AXUtilities, "is_password_text", return_value=False),
|
||||
mock.patch.object(steam_script.AXUtilities, "is_combo_box", return_value=False),
|
||||
mock.patch.object(steam_script.AXUtilities, "is_button", return_value=True),
|
||||
mock.patch.object(steam_script.AXUtilities, "is_push_button", return_value=False),
|
||||
mock.patch.object(steam_script.AXUtilities, "is_link", return_value=False),
|
||||
mock.patch.object(steam_script.AXObject, "has_action", side_effect=has_action),
|
||||
mock.patch.object(steam_script.Script, "_performClickableAction", return_value=True) as performAction,
|
||||
):
|
||||
self.assertTrue(testScript.shouldConsumeKeyboardEvent(keyboardEvent, None))
|
||||
|
||||
performAction.assert_called_once_with(button)
|
||||
|
||||
|
||||
class SteamLabelRecoveryTests(unittest.TestCase):
|
||||
def test_displayed_label_recovers_friends_list_tab_text_from_parent_context(self):
|
||||
testScript = mock.Mock(generatorCache={})
|
||||
utilities = steam_script_utilities.Utilities(testScript)
|
||||
button = object()
|
||||
parent = object()
|
||||
textSibling = object()
|
||||
|
||||
utilities.inDocumentContent = mock.Mock(return_value=True)
|
||||
|
||||
def get_attribute(obj, name):
|
||||
if obj is button and name == "class":
|
||||
return "FriendsListTab Active Panel Focusable gpfocus"
|
||||
return None
|
||||
|
||||
def get_name(obj):
|
||||
if obj is textSibling:
|
||||
return "Friends"
|
||||
return ""
|
||||
|
||||
def iter_children(obj, pred=None):
|
||||
children = [textSibling, button]
|
||||
if obj is not parent:
|
||||
children = []
|
||||
if pred is not None:
|
||||
children = [child for child in children if pred(child)]
|
||||
return iter(children)
|
||||
|
||||
with (
|
||||
mock.patch.object(steam_script_utilities.ChromiumUtilities, "displayedLabel", return_value=""),
|
||||
mock.patch.object(steam_script_utilities.AXObject, "get_parent", side_effect=lambda obj: parent if obj is button else None),
|
||||
mock.patch.object(steam_script_utilities.AXObject, "get_attribute", side_effect=get_attribute),
|
||||
mock.patch.object(steam_script_utilities.AXObject, "get_name", side_effect=get_name),
|
||||
mock.patch.object(steam_script_utilities.AXObject, "supports_text", return_value=False),
|
||||
mock.patch.object(steam_script_utilities.AXObject, "iter_children", side_effect=iter_children),
|
||||
mock.patch.object(steam_script_utilities.AXUtilities, "is_button", side_effect=lambda obj: obj is button),
|
||||
mock.patch.object(steam_script_utilities.AXUtilities, "is_push_button", return_value=False),
|
||||
):
|
||||
self.assertEqual(utilities.displayedLabel(button), "Friends")
|
||||
|
||||
def test_displayed_label_maps_add_friend_button_class_to_fallback_name(self):
|
||||
testScript = mock.Mock(generatorCache={})
|
||||
utilities = steam_script_utilities.Utilities(testScript)
|
||||
button = object()
|
||||
|
||||
utilities.inDocumentContent = mock.Mock(return_value=True)
|
||||
|
||||
def get_attribute(obj, name):
|
||||
if obj is button and name == "class":
|
||||
return "friendListButton AddFriendButton Panel Focusable"
|
||||
return None
|
||||
|
||||
with (
|
||||
mock.patch.object(steam_script_utilities.ChromiumUtilities, "displayedLabel", return_value=""),
|
||||
mock.patch.object(steam_script_utilities.AXObject, "get_attribute", side_effect=get_attribute),
|
||||
mock.patch.object(steam_script_utilities.AXObject, "get_name", return_value=""),
|
||||
mock.patch.object(steam_script_utilities.AXUtilities, "is_button", side_effect=lambda obj: obj is button),
|
||||
mock.patch.object(steam_script_utilities.AXUtilities, "is_push_button", return_value=False),
|
||||
):
|
||||
self.assertEqual(utilities.displayedLabel(button), "Add Friend")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -108,5 +108,45 @@ class WebHiddenPopupTests(unittest.TestCase):
|
||||
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()
|
||||
|
||||
Reference in New Issue
Block a user