File indexing completed on 2024-05-12 05:36:59

0001 #!/usr/bin/env python3
0002 
0003 # SPDX-FileCopyrightText: 2022 Harald Sitter <sitter@kde.org>
0004 # SPDX-FileCopyrightText: 2023 Fushan Wen <qydwhotmail@gmail.com>
0005 # SPDX-License-Identifier: MIT
0006 
0007 import os
0008 import shutil
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.common.exceptions import NoSuchElementException
0018 from selenium.webdriver.common.action_chains import ActionChains
0019 from selenium.webdriver.common.keys import Keys
0020 from selenium.webdriver.support.ui import WebDriverWait
0021 
0022 gi.require_version('Gdk', '3.0')
0023 from gi.repository import GLib
0024 
0025 WIDGET_ID: Final = "org.kde.plasma.clipboard"
0026 
0027 
0028 class ClipboardTest(unittest.TestCase):
0029     """
0030     Tests for the clipboard widget
0031     """
0032 
0033     driver: webdriver.Remote
0034 
0035     @classmethod
0036     def setUpClass(cls) -> None:
0037         """
0038         Opens the widget and initialize the webdriver
0039         """
0040         # Create history file to suppress warnings
0041         data_dir: str = GLib.get_user_data_dir()
0042         klipper_folder: Final = os.path.join(data_dir, "klipper")
0043         klipper_data_file: Final = os.path.join(klipper_folder, "history2.lst")
0044         if os.path.exists(klipper_data_file):
0045             shutil.move(klipper_data_file, f"{klipper_data_file}.bak")
0046             cls.addClassCleanup(lambda: shutil.move(f"{klipper_data_file}.bak", klipper_data_file))
0047         elif os.path.exists(klipper_folder):
0048             cls.addClassCleanup(lambda: os.remove(klipper_data_file))
0049         else:
0050             os.mkdir(klipper_folder)
0051             cls.addClassCleanup(lambda: shutil.rmtree(klipper_folder))
0052 
0053         shutil.copy("../klipper/autotests/data/onetextentry.lst", klipper_data_file)
0054 
0055         options = AppiumOptions()
0056         options.set_capability("app", f"plasmawindowed -p org.kde.plasma.nano {WIDGET_ID}")
0057         options.set_capability("environ", {
0058             "QT_FATAL_WARNINGS": "1",
0059             "QT_LOGGING_RULES": "qt.accessibility.atspi.warning=false;kf.plasma.core.warning=false;kf.windowsystem.warning=false;kf.kirigami.platform.warning=false;org.kde.klipper.debug=true",
0060         })
0061         options.set_capability("timeouts", {'implicit': 10000})
0062         cls.driver = webdriver.Remote(command_executor='http://127.0.0.1:4723', options=options)
0063 
0064     def tearDown(self) -> None:
0065         """
0066         Take screenshot when the current test fails
0067         """
0068         if not self._outcome.result.wasSuccessful():
0069             self.driver.get_screenshot_as_file(f"failed_test_shot_{WIDGET_ID}_#{self.id()}.png")
0070 
0071     @classmethod
0072     def tearDownClass(cls) -> None:
0073         """
0074         Make sure to terminate the driver again, lest it dangles.
0075         """
0076         cls.driver.quit()
0077 
0078     def test_0_open(self) -> None:
0079         """
0080         Tests the widget can be opened
0081         """
0082         self.driver.find_element(AppiumBy.NAME, "Fushan Wen")
0083         self.driver.find_element(AppiumBy.NAME, "clipboard")
0084 
0085     def test_1_barcode_1_open_barcode_page(self) -> None:
0086         """
0087         Tests the barcode page can be opened
0088         """
0089         actions = ActionChains(self.driver)
0090         actions.send_keys(Keys.DOWN).perform()
0091         # Wait until the first item is selected
0092         try:
0093             self.driver.find_element(AppiumBy.NAME, "Show QR code")
0094         except NoSuchElementException:
0095             actions.send_keys(Keys.DOWN).perform()  # Try pressing down key again
0096             self.driver.find_element(AppiumBy.NAME, "Show QR code")
0097 
0098         actions.send_keys(Keys.RIGHT).perform()
0099         time.sleep(1)
0100         actions.send_keys(Keys.RIGHT).perform()
0101         time.sleep(1)
0102         actions.send_keys(Keys.SPACE).perform()
0103         self.driver.find_element(AppiumBy.NAME, "QR Code")
0104         self.driver.find_element(AppiumBy.NAME, "Return to Clipboard")
0105         self.driver.find_element(AppiumBy.NAME, "Change the QR code type")
0106 
0107     def test_1_barcode_2_change_barcode_type(self) -> None:
0108         """
0109         Opens the barcode type menu and changes the current barcode type
0110         """
0111         self.driver.find_element(AppiumBy.NAME, "Change the QR code type").click()
0112         menu_item = self.driver.find_element(AppiumBy.NAME, "Aztec")
0113         # Switch to Aztec
0114         actions = ActionChains(self.driver)
0115         for _ in range(3):
0116             actions.send_keys(Keys.DOWN).perform()
0117             time.sleep(1)
0118         actions.send_keys(Keys.SPACE).perform()
0119         WebDriverWait(self.driver, 5).until_not(lambda _: menu_item.is_displayed())
0120         self.driver.find_element(AppiumBy.NAME, "Aztec")  # This is from barcodeItem
0121 
0122     def test_1_barcode_3_go_back_to_list_from_barcode_page(self) -> None:
0123         """
0124         Go back to the list from the barcode page
0125         """
0126         button_item = self.driver.find_element(AppiumBy.NAME, "Return to Clipboard")
0127         self.assertTrue(button_item.is_displayed())
0128         button_item.click()
0129         self.driver.find_element(AppiumBy.NAME, "Fushan Wen")
0130         self.assertFalse(button_item.is_displayed())
0131 
0132     def test_2_list_1_bug475696(self) -> None:
0133         """
0134         Pressing Return on an item should trigger the copy action
0135         @see https://bugs.kde.org/show_bug.cgi?id=475696
0136         """
0137         ActionChains(self.driver).send_keys(Keys.TAB).send_keys(Keys.DOWN).perform()
0138         self.driver.find_element(AppiumBy.NAME, "Show QR code")
0139         ActionChains(self.driver).send_keys(Keys.RETURN).perform()
0140         self.assertEqual(self.driver.get_clipboard_text(), "clipboard")
0141         ActionChains(self.driver).send_keys(Keys.ENTER).perform()
0142         self.assertEqual(self.driver.get_clipboard_text(), "Fushan Wen")
0143         ActionChains(self.driver).send_keys(Keys.SPACE).perform()
0144         self.assertEqual(self.driver.get_clipboard_text(), "clipboard")
0145 
0146     def test_2_list_2_delete(self) -> None:
0147         """
0148         Deletes the top item and tests if the current clipboard changes
0149         @see https://bugs.kde.org/show_bug.cgi?id=475696
0150         """
0151         # Now "clipboard" is the first item
0152         ActionChains(self.driver).send_keys(Keys.UP).perform()
0153         self.driver.find_element(AppiumBy.NAME, "Remove from history").click()
0154         # The first item becomes the current clipboard item
0155         self.assertEqual(self.driver.get_clipboard_text(), "Fushan Wen")
0156 
0157 
0158 if __name__ == '__main__':
0159     unittest.main()