File indexing completed on 2024-05-12 05:35:22

0001 #!/usr/bin/env python3
0002 
0003 # SPDX-FileCopyrightText: 2023 Fushan Wen <qydwhotmail@gmail.com>
0004 # SPDX-License-Identifier: MIT
0005 
0006 import base64
0007 import os
0008 import subprocess
0009 import sys
0010 import tempfile
0011 import time
0012 import unittest
0013 
0014 import cv2 as cv
0015 import gi
0016 
0017 gi.require_version('Gtk', '4.0')
0018 from appium import webdriver
0019 from appium.options.common.base import AppiumOptions
0020 from appium.webdriver.common.appiumby import AppiumBy
0021 from desktoptest import start_kactivitymanagerd, start_kded
0022 from gi.repository import Gtk
0023 from selenium.common.exceptions import TimeoutException
0024 from selenium.webdriver.common.actions.action_builder import ActionBuilder
0025 from selenium.webdriver.common.actions.interaction import POINTER_TOUCH
0026 from selenium.webdriver.common.actions.pointer_input import PointerInput
0027 from selenium.webdriver.support import expected_conditions as EC
0028 from selenium.webdriver.support.ui import WebDriverWait
0029 
0030 
0031 class Bug477220Test(unittest.TestCase):
0032 
0033     driver: webdriver.Remote
0034     kactivitymanagerd: subprocess.Popen | None = None
0035     kded: subprocess.Popen | None = None
0036 
0037     @classmethod
0038     def setUpClass(cls) -> None:
0039         cls.kactivitymanagerd = start_kactivitymanagerd()
0040         cls.kded = start_kded()
0041 
0042         options = AppiumOptions()
0043         options.set_capability("app", "plasmashell -p org.kde.plasma.desktop --no-respawn")
0044         options.set_capability("environ", {
0045             "QT_LOGGING_RULES": "kf.kirigami.platform.warning=false",
0046         })
0047         options.set_capability("timeouts", {'implicit': 30000})
0048         cls.driver = webdriver.Remote(command_executor='http://127.0.0.1:4723', options=options)
0049 
0050     def tearDown(self) -> None:
0051         """
0052         Take screenshot when the current test fails
0053         """
0054         if not self._outcome.result.wasSuccessful():
0055             self.driver.get_screenshot_as_file(f"failed_test_shot_bug476968_#{self.id()}.png")
0056 
0057     @classmethod
0058     def tearDownClass(cls) -> None:
0059         """
0060         Make sure to terminate the driver again, lest it dangles.
0061         """
0062         subprocess.check_output(["kquitapp6", "plasmashell"], stderr=sys.stderr)
0063         if cls.kded:
0064             cls.kded.kill()
0065         if cls.kactivitymanagerd:
0066             cls.kactivitymanagerd.kill()
0067         cls.driver.quit()
0068 
0069     def test_1_bug478958_touch_long_press_on_desktop(self) -> None:
0070         """
0071         Long press on the desktop to enter the edit mode
0072         """
0073         time.sleep(3)
0074         screen_geometry = Gtk.Window().get_display().get_monitors()[0].get_geometry()
0075         long_press_time_ms: int = Gtk.Settings.get_default().get_property("gtk-long-press-time") * 2 + 5000
0076         self.assertGreater(screen_geometry.width, 100)
0077         self.assertGreater(screen_geometry.height, 100)
0078 
0079         # Click "More" to open the desktop context menu
0080         wait = WebDriverWait(self.driver, 5)
0081         success = False
0082         for _ in range(20):
0083             try:
0084                 # Work around "no target window"
0085                 action = ActionBuilder(self.driver, mouse=PointerInput(POINTER_TOUCH, "finger"))
0086                 action.pointer_action.move_to_location(int(screen_geometry.width / 2), int(screen_geometry.height / 2)).click()
0087                 action.perform()
0088                 action = ActionBuilder(self.driver, mouse=PointerInput(POINTER_TOUCH, "finger"))
0089                 action.pointer_action.move_to_location(int(screen_geometry.width / 2), int(screen_geometry.height / 2)).pointer_down().pause(long_press_time_ms / 1000).pointer_up()
0090                 action.perform()
0091                 wait.until(EC.presence_of_element_located((AppiumBy.NAME, "More"))).click()
0092                 success = True
0093                 break
0094             except TimeoutException:
0095                 continue
0096         self.assertTrue(success)
0097 
0098     def test_2_bug477220_open_context_menu(self) -> None:
0099         """
0100         "More" button in the desktop toolbox does not open the context menu
0101         """
0102         time.sleep(3)  # Wait until the menu appears
0103         with tempfile.TemporaryDirectory() as temp_dir:
0104             saved_image_path: str = os.path.join(temp_dir, "desktop.png")
0105             self.assertTrue(self.driver.get_screenshot_as_file(saved_image_path))
0106 
0107             cv_first_image = cv.imread(saved_image_path, cv.IMREAD_COLOR)
0108             first_image = base64.b64encode(cv.imencode('.png', cv_first_image)[1].tobytes()).decode()
0109 
0110         cv_expected_image = cv.imread(os.path.join(os.path.dirname(os.path.abspath(__file__)), "resources", "bug478958_new_file_menu_item_icon.png"), cv.IMREAD_COLOR)
0111         expected_image = base64.b64encode(cv.imencode('.png', cv_expected_image)[1].tobytes()).decode()
0112         self.driver.find_image_occurrence(first_image, expected_image, threshold=1e-7)
0113 
0114         # Click an empty area to close the menu
0115         screen_geometry = Gtk.Window().get_display().get_monitors()[0].get_geometry()
0116         action = ActionBuilder(self.driver, mouse=PointerInput(POINTER_TOUCH, "finger"))
0117         action.pointer_action.move_to_location(int(screen_geometry.width / 2), int(screen_geometry.height / 2)).click()
0118         action.perform()
0119 
0120 
0121 if __name__ == '__main__':
0122     unittest.main()