[neon/snap-packaging/kwrite-snap] /: Add appium-test file to be used with selenium-at-spi script

Benjamin Port null at kde.org
Sat Mar 15 20:30:49 GMT 2025


Git commit ebfefdfbd7c400c03a503c683262a587c793ebfb by Benjamin Port.
Committed on 15/03/2025 at 20:30.
Pushed by bport into branch 'master'.

Add appium-test file to be used with selenium-at-spi script

A  +1    -0    appium-test
A  +203  -0    kwritetest.py

https://invent.kde.org/neon/snap-packaging/kwrite-snap/-/commit/ebfefdfbd7c400c03a503c683262a587c793ebfb

diff --git a/appium-test b/appium-test
new file mode 100644
index 0000000..83b6f95
--- /dev/null
+++ b/appium-test
@@ -0,0 +1 @@
+kwrite_24.12.2_amd64.snap kwrite kwritetest.py
diff --git a/kwritetest.py b/kwritetest.py
new file mode 100644
index 0000000..f31b2cc
--- /dev/null
+++ b/kwritetest.py
@@ -0,0 +1,203 @@
+#!/usr/bin/env python3
+
+# SPDX-License-Identifier: MIT
+# SPDX-FileCopyrightText: 2024 Antoine Herlicq <antoine.herlicq at enioka.com>
+
+from pathlib import Path
+import tempfile
+import time
+import unittest
+
+from appium import webdriver
+from appium.options.common.base import AppiumOptions
+from appium.webdriver.common.appiumby import AppiumBy
+from selenium.webdriver import ActionChains, Keys
+from selenium.webdriver.support.ui import WebDriverWait
+from selenium.webdriver.support import expected_conditions as EC
+from selenium.common.exceptions import NoSuchElementException
+
+
+class SimpleTextEditorTests(unittest.TestCase):
+    text_area_id = "KTextEditor::ViewPrivate.KateViewInternal"
+
+    def find_element_by_class_name(self, type, name):
+        return self.driver.find_element(by=AppiumBy.CLASS_NAME, value=f"[{type} | {name}]")
+
+    def find_element_by_name(self, element):
+        return self.driver.find_element(by=AppiumBy.NAME, value=element)
+
+    def find_element_by_accessibility_id(self, element):
+        return self.driver.find_element(by=AppiumBy.ACCESSIBILITY_ID, value=element)
+
+    def find_text_area(self):
+        return self.find_element_by_accessibility_id(self.text_area_id)
+
+    def find_main_window(self):
+        return self.find_element_by_accessibility_id("KateCentralWidget")
+
+    def new_file_button(self):
+        return self.find_element_by_name("New File")
+
+    def write_text(self, area_to_write, text):
+        actions = ActionChains(self.driver)
+        actions.move_to_element(area_to_write)
+        actions.click()
+        actions.send_keys(text)
+        actions.perform()
+
+    def write_text_slow(self, area_to_write, text):
+        actions = ActionChains(self.driver)
+        actions.move_to_element(area_to_write)
+        actions.click().perform
+        for l in text:
+            actions = ActionChains(self.driver)
+            actions.send_keys(l).perform()
+
+
+    def wait_for_text(self, text):
+        self.wait.until(EC.text_to_be_present_in_element((AppiumBy.ACCESSIBILITY_ID, self.text_area_id), text))
+
+    def setUp(self):
+        options = AppiumOptions()
+        options.set_capability("app", "org.kde.kwrite.desktop")
+
+        max_attempts = 3
+        attempts = 0
+        while attempts < max_attempts:
+            try:
+                self.driver = webdriver.Remote(command_executor='http://127.0.0.1:4723', options=options)
+                break
+            except Exception as e:
+                attempts += 1
+                time.sleep(1)
+        self.driver.implicitly_wait = 10
+        self.wait = WebDriverWait(self.driver, 10)
+
+    def tearDown(self):
+        max_attempts = 3
+        attempts = 0
+        while attempts < max_attempts:
+            try:
+                self.driver.quit()
+                break
+            except Exception as e:
+                attempts += 1
+                time.sleep(1)
+
+    def test_a_app_installed(self):
+        self.assertTrue(self.driver.is_app_installed("kwrite"))
+
+    def test_b_app_runs(self):
+        self.assertTrue(self.new_file_button().is_displayed())
+        self.find_element_by_name("New File").click()
+        self.assertTrue(self.find_element_by_class_name("frame", "Untitled "))
+
+    def test_c_writing_text(self):
+        self.new_file_button().click()
+        main = self.find_main_window()
+        self.write_text(main, "Hello, World!")
+        self.wait_for_text("Hello, World!")
+        text_area = self.find_text_area()
+        self.assertEqual(text_area.text, "Hello, World!")
+
+    def test_d_undo_redo_buttons(self):
+        self.new_file_button().click()
+        main = self.find_main_window()
+        self.write_text(main, "Hello," + Keys.ENTER + "World!")
+        self.wait_for_text("Hello,\nWorld!")
+        text_area = self.find_text_area()
+        self.assertEqual(text_area.text, "Hello,\nWorld!")
+        self.find_element_by_name("Undo").click()
+        self.assertEqual(text_area.text, "Hello,\n")
+        self.find_element_by_name("Redo").click()
+        self.assertEqual(text_area.text, "Hello,\nWorld!")
+
+    def test_e_new_tab(self):
+        self.new_file_button().click()
+        main = self.find_main_window()
+        self.write_text(main, "Hello, World!")
+        self.wait_for_text("Hello, World!")
+        text_area = self.find_text_area()
+        self.assertEqual(text_area.text, "Hello, World!")
+        self.find_element_by_name("New").click()
+        self.assertFalse(text_area.is_displayed())
+
+        self.write_text(main, "Bye, Moon!")
+        self.wait_for_text("Bye, Moon!")
+        text_area2 = self.find_text_area()
+        self.assertEqual(text_area2.text, "Bye, Moon!")
+
+        text_area2 = self.find_text_area()
+        self.find_element_by_class_name("page tab", "Untitled").click()
+        self.assertTrue(text_area.is_displayed())
+        self.assertFalse(text_area2.is_displayed())
+
+        self.find_element_by_class_name("menu item", "File").click()
+        self.find_element_by_class_name("menu item", "Close").click()
+        self.driver.find_element(by="description", value="Discard changes").click()
+        self.wait.until(EC.visibility_of_element_located((AppiumBy.ACCESSIBILITY_ID, self.text_area_id)))
+
+        self.assertFalse(text_area.is_displayed())
+        self.assertTrue(text_area2.is_displayed())
+
+    def test_f_find_and_replace(self):
+        self.new_file_button().click()
+        main = self.find_main_window()
+        self.write_text(main, "Hello, World!")
+        self.wait_for_text("Hello, World!")
+        text_area = self.find_text_area()
+        self.assertEqual(text_area.text, "Hello, World!")
+
+        self.find_element_by_class_name("menu item", "Edit").click()
+        self.find_element_by_accessibility_id("edit.edit_replace").click()
+
+        find_input = self.find_element_by_class_name("combo box", "Find:")
+        self.write_text(find_input, "Hello" + Keys.TAB + "Good Morning")
+        self.wait.until(EC.text_to_be_present_in_element((AppiumBy.ACCESSIBILITY_ID, "PowerSearchBar.replacement"), "Good Morning"))
+
+        self.find_element_by_class_name("button", "Replace All").click()
+        self.wait_for_text("Good Morning, World!")
+        self.assertEqual(text_area.text, "Good Morning, World!")
+
+    def test_g_save_file(self):
+        with tempfile.TemporaryDirectory(dir=Path.home(), prefix="appium-test") as temp_dir:
+            file_path = Path.home() / temp_dir / "test_file"
+            self.new_file_button().click()
+            main = self.find_main_window()
+            self.write_text(main, "Hello, World!")
+            self.wait.until(EC.text_to_be_present_in_element((AppiumBy.ACCESSIBILITY_ID, self.text_area_id), "Hello, World!"))
+            text_area = self.find_text_area()
+            self.assertEqual(text_area.text, "Hello, World!")
+
+            self.find_element_by_class_name("button", "Save As…").click()
+
+            save_dialog = self.find_element_by_class_name("dialog", "Save File")
+            name_area_save = self.find_element_by_class_name("text", "")
+            self.write_text_slow(name_area_save, str(file_path))
+            save_dialog.find_element(by=AppiumBy.NAME, value="Save").click()
+
+            # Wait for the file to be written
+            wait_start = time.time()
+            while time.time() - wait_start < 3 and not file_path.is_file():
+                time.sleep(1)
+            if not file_path.is_file():
+                raise AssertionError("File was not saved")
+
+            self.find_element_by_name("New").click()
+            self.find_element_by_class_name("page tab", "test_file").click()
+            self.find_element_by_class_name("menu item", "File").click()
+            self.find_element_by_class_name("menu item", "Close").click()
+            # Issue with the previous action "Close" that does not close the menu.
+            self.find_element_by_class_name("menu item", "File").click()
+            # We click again on "File" to close it.
+            self.find_element_by_class_name("menu item", "File").click()
+
+            self.find_element_by_class_name("menu item", "Open…").click()
+            name_area_open = self.find_element_by_class_name("text", "")
+            self.write_text_slow(name_area_open, str(file_path))
+            self.find_element_by_class_name("button", "Open").click()
+            text_area = self.find_text_area()
+            self.assertEqual(text_area.text, "Hello, World!\n")  # There's an extra line when we open a file
+
+if __name__ == '__main__':
+    unittest.main()


More information about the Neon-commits mailing list