#!/usr/bin/env python3 # SPDX-FileCopyrightText: 2024 Niccolò Venerandi # SPDX-License-Identifier: MIT import functools import os import pathlib import stat import subprocess import sys import time import unittest from typing import Final from appium import webdriver from appium.options.common.base import AppiumOptions from appium.webdriver.common.appiumby import AppiumBy from appium.webdriver.webelement import WebElement from gi.repository import Gio, GLib from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.common.keys import Keys from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import WebDriverWait from desktoptest import start_plasmashell class PanelFocusTest(unittest.TestCase): """ Tests for panel focus """ driver: webdriver.Remote kactivitymanagerd: subprocess.Popen | None = None kded: subprocess.Popen | None = None plasmashell: subprocess.Popen | None = None @classmethod def setUpClass(cls) -> None: """ Initializes the webdriver """ cls.kactivitymanagerd, cls.kded, cls.plasmashell = start_plasmashell() options = AppiumOptions() options.set_capability("app", "Root") options.set_capability("timeouts", {'implicit': 30000}) cls.driver = webdriver.Remote(command_executor='http://127.0.0.1:4723', options=options) def tearDown(self) -> None: """ Take screenshot when the current test fails """ if not self._outcome.result.wasSuccessful(): self.driver.get_screenshot_as_file(f"failed_test_shot_plasmashell_#{self.id()}.png") @classmethod def tearDownClass(cls) -> None: """ Make sure to terminate the driver again, lest it dangles. """ cls.driver.quit() def test_0_peek_at_desktop_not_giving_panel_focus(self) -> None: """ This clicks on the Peek at Desktop element and checks that the panel has not gained keyboard focus by checking for the invisibility of the panel focus indicator. """ el = self.driver.find_element(by=AppiumBy.NAME, value="Peek at Desktop") el.click() WebDriverWait(self.driver, 6).until(EC.visibility_of_element_located((AppiumBy.NAME, "Minimize All Applet Active Indicator"))) WebDriverWait(self.driver, 6).until(EC.invisibility_of_element_located((AppiumBy.NAME, "Panel Focus Indicator"))) el.click() def test_1_setting_focus_shortcut(self) -> None: """ We set a shortcut for the panel, we activate it, and we check that the panel focus indicator is indeed visible. """ # The driver doesn't support sending global keyboard shortcuts session_bus: Gio.DBusConnection = Gio.bus_get_sync(Gio.BusType.SESSION) message = Gio.DBusMessage.new_method_call("org.kde.kglobalaccel", "/component/plasmashell", "org.kde.kglobalaccel.Component", "allShortcutInfos") reply, _ = session_bus.send_message_with_reply_sync(message, Gio.DBusSendMessageFlags.NONE, 1000) shortcut_list = reply.get_body().get_child_value(0) before = set(shortcut_list.get_child_value(i).get_child_value(0).get_string() for i in range(shortcut_list.n_children())) actions = ActionChains(self.driver) actions.context_click(self.driver.find_element(by=AppiumBy.NAME, value="Peek at Desktop")) # Wait for the context menu to appear actions.pause(0.4) actions.send_keys(Keys.ARROW_UP) actions.pause(0.1) actions.send_keys(Keys.ENTER) actions.perform() setter = self.driver.find_element(by=AppiumBy.NAME, value="Focus Shortcut Setter") actions.click(setter) actions.key_down(Keys.ALT) actions.send_keys("a") actions.key_up(Keys.ALT) # Wait for the shortcut input button to set the new shortcut actions.pause(1.5) actions.send_keys(Keys.ESCAPE) actions.perform() actions.pause(0.5) actions.context_click() # Wait for the context menu to appear actions.pause(0.1) actions.send_keys(Keys.ARROW_UP) actions.pause(0.1) actions.send_keys(Keys.ENTER) actions.pause(1) actions.perform() message = Gio.DBusMessage.new_method_call("org.kde.kglobalaccel", "/component/plasmashell", "org.kde.kglobalaccel.Component", "allShortcutInfos") reply, _ = session_bus.send_message_with_reply_sync(message, Gio.DBusSendMessageFlags.NONE, 1000) shortcut_list = reply.get_body().get_child_value(0) after = set(shortcut_list.get_child_value(i).get_child_value(0).get_string() for i in range(shortcut_list.n_children())) difference = after - before self.assertTrue(len(difference) == 1) launcher_shortcut_id = difference.pop() message = Gio.DBusMessage.new_method_call("org.kde.kglobalaccel", "/component/plasmashell", "org.kde.kglobalaccel.Component", "invokeShortcut") message.set_body(GLib.Variant("(s)", [launcher_shortcut_id])) session_bus.send_message_with_reply_sync(message, Gio.DBusSendMessageFlags.NONE, 1000) WebDriverWait(self.driver, 6).until(EC.visibility_of_element_located((AppiumBy.NAME, "Panel Focus Indicator"))) if __name__ == '__main__': assert subprocess.call(["pidof", "plasmashell"]) != 0, "The test requires plasmashell to quit" unittest.main()