summaryrefslogtreecommitdiffstats
path: root/tests/auto/wasm/selenium/qwasmwindow.py
diff options
context:
space:
mode:
authorEven Oscar Andersen <even.oscar.andersen@qt.io>2025-08-28 10:49:30 +0200
committerEven Oscar Andersen <even.oscar.andersen@qt.io>2025-09-16 20:02:45 +0200
commit1fb345a25a50d931b46a1c5308dd13c2d7d44df6 (patch)
treed94f84b75cc08d543786fd3018fae5e406bd2fd6 /tests/auto/wasm/selenium/qwasmwindow.py
parenta8566b75cabdff66c694b2936880a3c1a1a93f18 (diff)
wasm: a11y - Add selenium text tests
Also add support for jspi. Fixes: QTBUG-139785 Fixes: QTBUG-129735 Change-Id: Ifd251fd0cd738d2c089084f4fd6d65dd0a7e91e5 Reviewed-by: Piotr Wierciński <piotr.wiercinski@qt.io>
Diffstat (limited to 'tests/auto/wasm/selenium/qwasmwindow.py')
-rw-r--r--tests/auto/wasm/selenium/qwasmwindow.py270
1 files changed, 248 insertions, 22 deletions
diff --git a/tests/auto/wasm/selenium/qwasmwindow.py b/tests/auto/wasm/selenium/qwasmwindow.py
index 6f78d54a10c..5d3748fab92 100644
--- a/tests/auto/wasm/selenium/qwasmwindow.py
+++ b/tests/auto/wasm/selenium/qwasmwindow.py
@@ -3,6 +3,7 @@
from selenium.webdriver import Chrome
from selenium.webdriver.chrome.service import Service as ChromeService
+from selenium.webdriver.chrome.options import Options as ChromeOptions
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.actions.action_builder import ActionBuilder
from selenium.webdriver.common.actions.pointer_actions import PointerActions
@@ -19,9 +20,20 @@ from enum import Enum, auto
class WidgetTestCase(unittest.TestCase):
def setUp(self):
- chromedriver_path = os.getenv('CHROMEDRIVER_PATH')
+ chromedriver_path = os.getenv('WASM_CHROMEDRIVER_PATH_JSPI')
+ chromedriver_args = ""
+
+ if chromedriver_path:
+ chromedriver_args = os.getenv('WASM_CHROMEDRIVER_PATH_JSPI_ARGS')
+ else:
+ chromedriver_path = os.getenv('CHROMEDRIVER_PATH')
+
if chromedriver_path:
- self._driver = Chrome(service=ChromeService(executable_path=chromedriver_path))
+ options = ChromeOptions()
+ args = chromedriver_args.split()
+ for arg in args:
+ options.add_argument(arg)
+ self._driver = Chrome(service=ChromeService(executable_path=chromedriver_path), options=options)
else:
self._driver = Chrome()
self._driver.maximize_window()
@@ -33,6 +45,197 @@ class WidgetTestCase(unittest.TestCase):
self.addTypeEqualityFunc(Color, assert_colors_equal)
self.addTypeEqualityFunc(Rect, assert_rects_equal)
+ def test_zz_a11y_buttons(self):
+ screen = Screen(self._driver, ScreenPosition.FIXED,
+ x=0, y=0, width=600, height=600)
+
+ w0 = Widget(self._driver, "w0", 2)
+ w0.show()
+
+ checkboxa1 = screen.find_element(By.ID, f'CheckBoxA1');
+ checkboxa2 = screen.find_element(By.ID, f'CheckBoxA2');
+ radiobuttonb1 = screen.find_element(By.ID, f'RadioB1');
+ radiobuttonb2 = screen.find_element(By.ID, f'RadioB2');
+ pushbuttonc1 = screen.find_element(By.ID, f'PushC1');
+ pushbuttonc2 = screen.find_element(By.ID, f'PushC2');
+
+ checkboxa1DB = screen.find_element(By.ID, checkboxa1.get_attribute("aria-describedby"));
+ checkboxa2DB = screen.find_element(By.ID, checkboxa2.get_attribute("aria-describedby"));
+ radiobuttonb1DB = screen.find_element(By.ID, radiobuttonb1.get_attribute("aria-describedby"));
+ radiobuttonb2DB = screen.find_element(By.ID, radiobuttonb2.get_attribute("aria-describedby"));
+ pushbuttonc1DB = screen.find_element(By.ID, pushbuttonc1.get_attribute("aria-describedby"));
+ pushbuttonc2DB = screen.find_element(By.ID, pushbuttonc2.get_attribute("aria-describedby"));
+
+ self.assertEqual(checkboxa1DB.get_attribute("innerHTML"), "CheckBoxA1 - Description");
+ self.assertEqual(checkboxa2DB.get_attribute("innerHTML"), "CheckBoxA2 - Description");
+ self.assertEqual(radiobuttonb1DB.get_attribute("innerHTML"), "RadioB1 - Description");
+ self.assertEqual(radiobuttonb2DB.get_attribute("innerHTML"), "RadioB2 - Description");
+ self.assertEqual(pushbuttonc1DB.get_attribute("innerHTML"), "PushC1 - Description");
+ self.assertEqual(pushbuttonc2DB.get_attribute("innerHTML"), "PushC2 - Description");
+
+ self.assertEqual(checkboxa1.get_attribute("checked"), None);
+ self.assertEqual(checkboxa2.get_attribute("checked"), None);
+ self.assertEqual(checkboxa1.get_attribute("type"), "checkbox");
+ self.assertEqual(checkboxa2.get_attribute("type"), "checkbox");
+ self.assertEqual(checkboxa1.get_attribute("aria-label"), "CheckBoxA1");
+ self.assertEqual(checkboxa2.get_attribute("aria-label"), "CheckBoxA2");
+
+ self.assertEqual(radiobuttonb1.get_attribute("checked"), None);
+ self.assertEqual(radiobuttonb2.get_attribute("checked"), None);
+ self.assertEqual(radiobuttonb1.get_attribute("type"), "radio");
+ self.assertEqual(radiobuttonb2.get_attribute("type"), "radio");
+ self.assertEqual(radiobuttonb1.get_attribute("aria-label"), "RadioB1");
+ self.assertEqual(radiobuttonb2.get_attribute("aria-label"), "RadioB2");
+
+ self.assertEqual(pushbuttonc1.get_attribute("checked"), None);
+ self.assertEqual(pushbuttonc2.get_attribute("checked"), None);
+ self.assertEqual(pushbuttonc1.get_attribute("type"), "submit");
+ self.assertEqual(pushbuttonc2.get_attribute("type"), "submit");
+ self.assertEqual(pushbuttonc1.get_attribute("aria-label"), "PushC1");
+ self.assertEqual(pushbuttonc2.get_attribute("aria-label"), "PushC2");
+
+ # Check focus
+ screen.focus(checkboxa1);
+ self.assertTrue(screen.has_focus(checkboxa1));
+ checkboxa1.send_keys("\t");
+ self.assertTrue(screen.has_focus(checkboxa2));
+ checkboxa2.send_keys("\t");
+ self.assertTrue(screen.has_focus(radiobuttonb1));
+ radiobuttonb1.send_keys("\t");
+ self.assertTrue(screen.has_focus(radiobuttonb2));
+ radiobuttonb2.send_keys("\t");
+ self.assertTrue(screen.has_focus(pushbuttonc1));
+ pushbuttonc1.send_keys("\t");
+ self.assertTrue(screen.has_focus(pushbuttonc2));
+
+ screen.focus(checkboxa1);
+
+ # Check behavior checkboxes
+ screen.click(checkboxa1);
+ self.assertEqual(checkboxa1.get_dom_attribute("checked"), "true");
+ self.assertEqual(checkboxa2.get_dom_attribute("checked"), None);
+
+ screen.click(checkboxa2);
+ self.assertEqual(checkboxa1.get_dom_attribute("checked"), "true");
+ self.assertEqual(checkboxa2.get_dom_attribute("checked"), "true");
+
+ screen.click(checkboxa1);
+ self.assertEqual(checkboxa1.get_dom_attribute("checked"), None);
+ self.assertEqual(checkboxa2.get_dom_attribute("checked"), "true");
+
+ screen.click(checkboxa2);
+ self.assertEqual(checkboxa1.get_dom_attribute("checked"), None);
+ self.assertEqual(checkboxa2.get_dom_attribute("checked"), None);
+
+ # Check behavior radiobuttons
+ screen.click(radiobuttonb1);
+ self.assertEqual(radiobuttonb1.get_dom_attribute("checked"), "true");
+ self.assertEqual(radiobuttonb2.get_dom_attribute("checked"), None);
+
+ screen.click(radiobuttonb2);
+ self.assertEqual(radiobuttonb1.get_dom_attribute("checked"), None);
+ self.assertEqual(radiobuttonb2.get_dom_attribute("checked"), "true");
+
+ screen.click(radiobuttonb1);
+ self.assertEqual(radiobuttonb1.get_dom_attribute("checked"), "true");
+ self.assertEqual(radiobuttonb2.get_dom_attribute("checked"), None);
+
+ screen.click(radiobuttonb2);
+ self.assertEqual(radiobuttonb1.get_dom_attribute("checked"), None);
+ self.assertEqual(radiobuttonb2.get_dom_attribute("checked"), "true");
+
+ # Check behaviour push buttons
+ screen.click(pushbuttonc1);
+ screen.click(pushbuttonc2);
+ self.assertEqual(pushbuttonc1.get_attribute("aria-label"), "PushC1 - Clicked");
+ self.assertEqual(pushbuttonc2.get_attribute("aria-label"), "PushC2 - Clicked");
+
+ def test_zz_a11y_text(self):
+ screen = Screen(self._driver, ScreenPosition.FIXED,
+ x=0, y=0, width=600, height=600)
+
+ w0 = Widget(self._driver, "w0", 3)
+ w0.show()
+
+ lineedita1 = screen.find_element(By.ID, f'LineEditA1');
+ lineedita2 = screen.find_element(By.ID, f'LineEditA2');
+ lineedita3 = screen.find_element(By.ID, f'LineEditA3');
+ lineedita4 = screen.find_element(By.ID, f'LineEditA4');
+ lineedita5 = screen.find_element(By.ID, f'LineEditA5');
+
+ texteditb1 = screen.find_element(By.ID, f'TextEditB1');
+ texteditb2 = screen.find_element(By.ID, f'TextEditB2');
+ plaintexteditc1 = screen.find_element(By.ID, f'PlainTextEditC1');
+ plaintexteditc2 = screen.find_element(By.ID, f'PlainTextEditC2');
+ labeld1 = screen.find_element(By.ID, f'LabelD1');
+
+ lineedita1DB = screen.find_element(By.ID, lineedita1.get_attribute("aria-describedby"));
+ lineedita2DB = screen.find_element(By.ID, lineedita2.get_attribute("aria-describedby"));
+ lineedita3DB = screen.find_element(By.ID, lineedita3.get_attribute("aria-describedby"));
+ lineedita4DB = screen.find_element(By.ID, lineedita4.get_attribute("aria-describedby"));
+ lineedita5DB = screen.find_element(By.ID, lineedita5.get_attribute("aria-describedby"));
+
+ texteditb1DB = screen.find_element(By.ID, texteditb1.get_attribute("aria-describedby"));
+ texteditb2DB = screen.find_element(By.ID, texteditb2.get_attribute("aria-describedby"));
+ plaintexteditc1DB = screen.find_element(By.ID, plaintexteditc1.get_attribute("aria-describedby"));
+ plaintexteditc2DB = screen.find_element(By.ID, plaintexteditc2.get_attribute("aria-describedby"));
+ labeld1DB = screen.find_element(By.ID, labeld1.get_attribute("aria-describedby"));
+
+ self.assertEqual(lineedita1DB.get_attribute("innerHTML"), "LineEditA1 - Description");
+ self.assertEqual(lineedita2DB.get_attribute("innerHTML"), "LineEditA2 - Description");
+ self.assertEqual(lineedita3DB.get_attribute("innerHTML"), "LineEditA3 - Description");
+ self.assertEqual(lineedita4DB.get_attribute("innerHTML"), "LineEditA4 - Description");
+ self.assertEqual(lineedita5DB.get_attribute("innerHTML"), "LineEditA5 - Description");
+ self.assertEqual(texteditb1DB.get_attribute("innerHTML"), "TextEditB1 - Description");
+ self.assertEqual(texteditb2DB.get_attribute("innerHTML"), "TextEditB2 - Description");
+ self.assertEqual(plaintexteditc1DB.get_attribute("innerHTML"), "PlainTextEditC1 - Description");
+ self.assertEqual(plaintexteditc2DB.get_attribute("innerHTML"), "PlainTextEditC2 - Description");
+ self.assertEqual(labeld1DB.get_attribute("innerHTML"), "LabelD1 - Description");
+
+ self.assertEqual(lineedita1.get_attribute("value"), "LineEditA1 - Text");
+ self.assertEqual(lineedita2.get_attribute("value"), "LineEditA2 - Text");
+ self.assertEqual(lineedita3.get_attribute("value"), "●●●●●●●●●●●●●●●●●");
+ self.assertEqual(lineedita4.get_attribute("value"), "");
+ self.assertEqual(lineedita5.get_attribute("value"), "●●●●●●●●●●●●●●●●●");
+ self.assertEqual(texteditb1.get_attribute("value"), "TextEditB1 - Text");
+ self.assertEqual(texteditb2.get_attribute("value"), "TextEditB2 - Text");
+ self.assertEqual(plaintexteditc1.get_attribute("value"), "PlainTextEditC1 - Text");
+ self.assertEqual(plaintexteditc2.get_attribute("value"), "PlainTextEditC2 - Text");
+ self.assertEqual(labeld1.get_attribute("innerHTML"), "LabelD1 - Text");
+
+ self.assertEqual(lineedita1.get_attribute("type"), "text");
+ self.assertEqual(lineedita2.get_attribute("type"), "text");
+ self.assertEqual(lineedita3.get_attribute("type"), "password");
+ self.assertEqual(lineedita4.get_attribute("type"), "password");
+ self.assertEqual(lineedita5.get_attribute("type"), "password");
+ self.assertEqual(texteditb1.get_attribute("type"), "text");
+ self.assertEqual(texteditb2.get_attribute("type"), "text");
+ self.assertEqual(plaintexteditc1.get_attribute("type"), "text");
+ self.assertEqual(plaintexteditc2.get_attribute("type"), "text");
+ self.assertEqual(labeld1.get_attribute("type"), None);
+
+ self.assertEqual(lineedita1.get_attribute("readonly"), None);
+ self.assertEqual(lineedita2.get_attribute("readonly"), "true");
+ self.assertEqual(lineedita3.get_attribute("readonly"), None);
+ self.assertEqual(lineedita4.get_attribute("readonly"), None);
+ self.assertEqual(lineedita5.get_attribute("readonly"), None);
+ self.assertEqual(texteditb1.get_attribute("readonly"), None);
+ self.assertEqual(texteditb2.get_attribute("readonly"), "true");
+ self.assertEqual(plaintexteditc1.get_attribute("readonly"), None);
+ self.assertEqual(plaintexteditc2.get_attribute("readonly"), "true");
+ self.assertEqual(labeld1.get_attribute("readonly"), None);
+
+ self.assertEqual(lineedita1.get_dom_attribute("aria-label"), None);
+ self.assertEqual(lineedita2.get_dom_attribute("aria-label"), None);
+ self.assertEqual(lineedita3.get_dom_attribute("aria-label"), None);
+ self.assertEqual(lineedita4.get_dom_attribute("aria-label"), None);
+ self.assertEqual(lineedita5.get_dom_attribute("aria-label"), None);
+ self.assertEqual(texteditb1.get_dom_attribute("aria-label"), None);
+ self.assertEqual(texteditb2.get_dom_attribute("aria-label"), None);
+ self.assertEqual(plaintexteditc1.get_dom_attribute("aria-label"), None);
+ self.assertEqual(plaintexteditc2.get_dom_attribute("aria-label"), None);
+ self.assertEqual(labeld1.get_dom_attribute("aria-label"), None);
+
#
# This is a manual test
# The reason is that the color readback works
@@ -44,7 +247,7 @@ class WidgetTestCase(unittest.TestCase):
w0 = Widget(self._driver, "w0", 1)
w0.show()
- #time.sleep(3600)
+
color = w0.color_at(100, 150)
self.assertEqual(color.r, 255)
self.assertEqual(color.g, 255)
@@ -63,7 +266,6 @@ class WidgetTestCase(unittest.TestCase):
# Wait for tooltip to disappear
#
time.sleep(60)
- #time.sleep(3600)
self.assertEqual(w0.hasFocus(), True)
w1 = Widget(self._driver, "w1")
@@ -233,41 +435,41 @@ class WidgetTestCase(unittest.TestCase):
def test_multitouch_window_move(self):
screen = Screen(self._driver, ScreenPosition.FIXED,
- x=0, y=0, width=800, height=800)
+ x=0, y=0, width=600, height=600)
windows = [Window(screen, rect=Rect(x=50, y=50, width=100, height=100), title='First'),
- Window(screen, rect=Rect(x=400, y=400, width=100, height=100), title='Second'),
- Window(screen, rect=Rect(x=50, y=400, width=100, height=100), title='Third')]
+ Window(screen, rect=Rect(x=250, y=250, width=100, height=100), title='Second'),
+ Window(screen, rect=Rect(x=50, y=250, width=100, height=100), title='Third')]
self.assertEqual(windows[0].rect, Rect(x=50, y=50, width=100, height=100))
- self.assertEqual(windows[1].rect, Rect(x=400, y=400, width=100, height=100))
- self.assertEqual(windows[2].rect, Rect(x=50, y=400, width=100, height=100))
+ self.assertEqual(windows[1].rect, Rect(x=250, y=250, width=100, height=100))
+ self.assertEqual(windows[2].rect, Rect(x=50, y=250, width=100, height=100))
actions = [TouchDragAction(origin=windows[0].at(Handle.TOP_WINDOW_BAR), direction=DOWN(20) + RIGHT(20)),
TouchDragAction(origin=windows[1].at(Handle.TOP_WINDOW_BAR), direction=DOWN(20) + LEFT(20)),
TouchDragAction(origin=windows[2].at(Handle.TOP_WINDOW_BAR), direction=UP(20) + RIGHT(20))]
perform_touch_drag_actions(actions)
self.assertEqual(windows[0].rect, Rect(x=70, y=70, width=100, height=100))
- self.assertEqual(windows[1].rect, Rect(x=380, y=420, width=100, height=100))
- self.assertEqual(windows[2].rect, Rect(x=70, y=380, width=100, height=100))
+ self.assertEqual(windows[1].rect, Rect(x=230, y=270, width=100, height=100))
+ self.assertEqual(windows[2].rect, Rect(x=70, y=230, width=100, height=100))
def test_multitouch_window_resize(self):
screen = Screen(self._driver, ScreenPosition.FIXED,
- x=0, y=0, width=800, height=800)
- windows = [Window(screen, rect=Rect(x=50, y=50, width=150, height=150), title='First'),
- Window(screen, rect=Rect(x=400, y=400, width=150, height=150), title='Second'),
- Window(screen, rect=Rect(x=50, y=400, width=150, height=150), title='Third')]
+ x=0, y=0, width=600, height=600)
+ windows = [Window(screen, rect=Rect(x=50, y=50, width=100, height=100), title='First'),
+ Window(screen, rect=Rect(x=200, y=200, width=100, height=100), title='Second'),
+ Window(screen, rect=Rect(x=50, y=200, width=100, height=100), title='Third')]
- self.assertEqual(windows[0].rect, Rect(x=50, y=50, width=150, height=150))
- self.assertEqual(windows[1].rect, Rect(x=400, y=400, width=150, height=150))
- self.assertEqual(windows[2].rect, Rect(x=50, y=400, width=150, height=150))
+ self.assertEqual(windows[0].rect, Rect(x=50, y=50, width=100, height=100))
+ self.assertEqual(windows[1].rect, Rect(x=200, y=200, width=100, height=100))
+ self.assertEqual(windows[2].rect, Rect(x=50, y=200, width=100, height=100))
actions = [TouchDragAction(origin=windows[0].at(Handle.TOP_LEFT), direction=DOWN(20) + RIGHT(20)),
TouchDragAction(origin=windows[1].at(Handle.TOP), direction=DOWN(20) + LEFT(20)),
TouchDragAction(origin=windows[2].at(Handle.BOTTOM_RIGHT), direction=UP(20) + RIGHT(20))]
perform_touch_drag_actions(actions)
- self.assertEqual(windows[0].rect, Rect(x=70, y=70, width=130, height=130))
- self.assertEqual(windows[1].rect, Rect(x=400, y=420, width=150, height=130))
- self.assertEqual(windows[2].rect, Rect(x=50, y=400, width=170, height=130))
+ self.assertEqual(windows[0].rect, Rect(x=70, y=70, width=80, height=80))
+ self.assertEqual(windows[1].rect, Rect(x=200, y=220, width=100, height=80))
+ self.assertEqual(windows[2].rect, Rect(x=50, y=200, width=120, height=80))
def test_newly_created_window_gets_keyboard_focus(self):
screen = Screen(self._driver, ScreenPosition.FIXED,
@@ -455,7 +657,7 @@ class WidgetTestCase(unittest.TestCase):
x=0, y=0, width=800, height=800)
bottom = Window(parent=screen, rect=Rect(x=800, y=800, width=300, height=300), title='root')
- bottom.close()
+ # Do not close bottom here, it will terminate the application
w1 = Window(parent=screen, rect=Rect(x=50, y=50, width=300, height=300), title='w1')
w2 = Window(parent=screen, rect=Rect(x=50, y=50, width=300, height=300), title='w2')
@@ -673,6 +875,16 @@ class Screen:
shadow_container = self.element.find_element(By.CSS_SELECTOR, f'#qt-shadow-container')
return shadow_container.shadow_root.find_element(method, query)
+ def click(self, element):
+ ActionChains(self.driver).move_to_element(
+ element).click().perform()
+
+ def focus(self, element):
+ self.driver.execute_script("arguments[0].focus();", element);
+
+ def has_focus(self, element):
+ return self.driver.execute_script("return document.activeElement = arguments[0];", element);
+
def clearWidgets(driver):
driver.execute_script(
f'''
@@ -698,6 +910,20 @@ class Widget:
'''
)
+ if isNative == 2:
+ self.driver.execute_script(
+ f'''
+ instance.createNativeA11yButtonWidgets('{self.name}');
+ '''
+ )
+
+ if isNative == 3:
+ self.driver.execute_script(
+ f'''
+ instance.createNativeA11yTextWidgets('{self.name}');
+ '''
+ )
+
if isNative == 1:
information = self.__window_information()
self.screen = Screen(self.driver, screen_name=information['screen']['name'])