File indexing completed on 2024-05-19 05:37:13
0001 #!/usr/bin/env python3 0002 0003 # SPDX-FileCopyrightText: 2023 Harald Sitter <sitter@kde.org> 0004 # SPDX-FileCopyrightText: 2023 Fushan Wen <qydwhotmail@gmail.com> 0005 # SPDX-License-Identifier: GPL-2.0-or-later 0006 0007 import subprocess 0008 import sys 0009 import time 0010 import unittest 0011 from typing import Final 0012 0013 import gi 0014 from appium import webdriver 0015 from appium.options.common.base import AppiumOptions 0016 from appium.webdriver.common.appiumby import AppiumBy 0017 from selenium.webdriver.support import expected_conditions as EC 0018 from selenium.webdriver.support.ui import WebDriverWait 0019 from appium.webdriver.webdriver import ExtensionBase 0020 from appium.webdriver.webelement import WebElement 0021 0022 gi.require_version('Gdk', '3.0') 0023 from gi.repository import Gdk 0024 0025 WIDGET_ID: Final = "org.kde.plasma.volume" 0026 0027 class SetValueCommand(ExtensionBase): 0028 0029 def method_name(self): 0030 return "set_value" 0031 0032 def set_value(self, element: WebElement, value: str): 0033 """ 0034 Set the value on this element in the application 0035 Args: 0036 value: The value to be set 0037 """ 0038 data = { 0039 "id": element.id, 0040 "text": value, 0041 } 0042 return self.execute(data)["value"] 0043 0044 def add_command(self): 0045 return "post", "/session/$sessionId/appium/element/$id/value" 0046 0047 0048 class AppletTest(unittest.TestCase): 0049 """ 0050 Tests for the widget 0051 """ 0052 0053 driver: webdriver.Remote | None = None 0054 pipewire: subprocess.Popen | None = None 0055 pulseaudio: subprocess.Popen | None = None 0056 0057 @classmethod 0058 def setUpClass(cls) -> None: 0059 """ 0060 Initializes the webdriver 0061 """ 0062 options = AppiumOptions() 0063 options.set_capability("app", f"plasmawindowed -p org.kde.plasma.nano {WIDGET_ID}") 0064 options.set_capability("environ", { 0065 "QT_FATAL_WARNINGS": "1", 0066 "QT_LOGGING_RULES": "qt.accessibility.atspi.warning=false;kf.plasma.core.warning=false;kf.windowsystem.warning=false;kf.kirigami.platform.warning=false", 0067 }) 0068 options.set_capability("timeouts", {'implicit': 30000}) 0069 cls.driver = webdriver.Remote(command_executor='http://127.0.0.1:4723', extensions=[SetValueCommand], options=options) 0070 0071 def tearDown(self) -> None: 0072 """ 0073 Take screenshot when the current test fails 0074 """ 0075 if not self._outcome.result.wasSuccessful(): 0076 self.driver.get_screenshot_as_file(f"failed_test_shot_volume_#{self.id()}.png") 0077 0078 @classmethod 0079 def tearDownClass(cls) -> None: 0080 """ 0081 Make sure to terminate the driver again, lest it dangles. 0082 """ 0083 cls.driver.quit() 0084 if cls.pulseaudio is not None: 0085 cls.pulseaudio.terminate() 0086 if cls.pipewire is not None: 0087 cls.pipewire.terminate() 0088 0089 def test_0_open(self) -> None: 0090 """ 0091 Tests the widget can be opened 0092 """ 0093 self.driver.find_element(AppiumBy.NAME, "No output or input devices found") 0094 0095 def test_1_sink_1_list_device(self) -> None: 0096 """ 0097 Add a null sink and adjust its volume 0098 """ 0099 self.pipewire = subprocess.Popen(["pipewire"], stdout=sys.stderr, stderr=sys.stderr) 0100 time.sleep(1) 0101 self.pulseaudio = subprocess.Popen(["pipewire-pulse"], stdout=sys.stderr, stderr=sys.stderr) 0102 time.sleep(1) 0103 description: Final = "Virtual_Dummy_Output" 0104 subprocess.check_call(["pactl", "load-module", "module-null-sink", "sink_name=DummyOutput", f"sink_properties=node.nick={description}"]) 0105 self.driver.find_element(AppiumBy.NAME, description) 0106 0107 # Raise the maximum volume 0108 self.driver.find_element(AppiumBy.NAME, "Raise maximum volume").click() 0109 slider_element: WebElement = self.driver.find_element(AppiumBy.NAME, f"Adjust volume for {description}") 0110 self.driver.set_value(slider_element, str(int(0x10000 * 1.5))) # PA_VOLUME_NORM * 1.5 0111 slider_element.click() 0112 wait = WebDriverWait(self.driver, 30) 0113 wait.until(EC.presence_of_element_located((AppiumBy.NAME, "150%"))) 0114 time.sleep(1) 0115 0116 self.assertIn("150%", subprocess.check_output(["pactl", "list", "sinks"]).decode(encoding="utf-8")) 0117 0118 0119 if __name__ == '__main__': 0120 unittest.main()