Path: blob/trunk/py/test/selenium/webdriver/common/bidi_input_tests.py
1865 views
# Licensed to the Software Freedom Conservancy (SFC) under one1# or more contributor license agreements. See the NOTICE file2# distributed with this work for additional information3# regarding copyright ownership. The SFC licenses this file4# to you under the Apache License, Version 2.0 (the5# "License"); you may not use this file except in compliance6# with the License. You may obtain a copy of the License at7#8# http://www.apache.org/licenses/LICENSE-2.09#10# Unless required by applicable law or agreed to in writing,11# software distributed under the License is distributed on an12# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY13# KIND, either express or implied. See the License for the14# specific language governing permissions and limitations15# under the License.1617import os18import tempfile19import time2021import pytest2223from selenium.webdriver.common.bidi.input import (24ElementOrigin,25FileDialogInfo,26KeyDownAction,27KeySourceActions,28KeyUpAction,29Origin,30PauseAction,31PointerCommonProperties,32PointerDownAction,33PointerMoveAction,34PointerParameters,35PointerSourceActions,36PointerType,37PointerUpAction,38WheelScrollAction,39WheelSourceActions,40)41from selenium.webdriver.common.by import By42from selenium.webdriver.support.ui import WebDriverWait434445def test_input_initialized(driver):46"""Test that the input module is initialized properly."""47assert driver.input is not None484950def test_basic_key_input(driver, pages):51"""Test basic keyboard input using BiDi."""52pages.load("single_text_input.html")5354input_element = driver.find_element(By.ID, "textInput")5556# Create keyboard actions to type "hello"57key_actions = KeySourceActions(58id="keyboard",59actions=[60KeyDownAction(value="h"),61KeyUpAction(value="h"),62KeyDownAction(value="e"),63KeyUpAction(value="e"),64KeyDownAction(value="l"),65KeyUpAction(value="l"),66KeyDownAction(value="l"),67KeyUpAction(value="l"),68KeyDownAction(value="o"),69KeyUpAction(value="o"),70],71)7273driver.input.perform_actions(driver.current_window_handle, [key_actions])7475WebDriverWait(driver, 5).until(lambda d: input_element.get_attribute("value") == "hello")76assert input_element.get_attribute("value") == "hello"777879def test_key_input_with_pause(driver, pages):80"""Test keyboard input with pause actions."""81pages.load("single_text_input.html")8283input_element = driver.find_element(By.ID, "textInput")8485# Create keyboard actions with pauses86key_actions = KeySourceActions(87id="keyboard",88actions=[89KeyDownAction(value="a"),90KeyUpAction(value="a"),91PauseAction(duration=100),92KeyDownAction(value="b"),93KeyUpAction(value="b"),94],95)9697driver.input.perform_actions(driver.current_window_handle, [key_actions])9899WebDriverWait(driver, 5).until(lambda d: input_element.get_attribute("value") == "ab")100assert input_element.get_attribute("value") == "ab"101102103def test_pointer_click(driver, pages):104"""Test basic pointer click using BiDi."""105pages.load("javascriptPage.html")106107button = driver.find_element(By.ID, "clickField")108109# Get button location110location = button.location111size = button.size112x = location["x"] + size["width"] // 2113y = location["y"] + size["height"] // 2114115# Create pointer actions for a click116pointer_actions = PointerSourceActions(117id="mouse",118parameters=PointerParameters(pointer_type=PointerType.MOUSE),119actions=[120PointerMoveAction(x=x, y=y),121PointerDownAction(button=0),122PointerUpAction(button=0),123],124)125126driver.input.perform_actions(driver.current_window_handle, [pointer_actions])127128WebDriverWait(driver, 5).until(lambda d: button.get_attribute("value") == "Clicked")129assert button.get_attribute("value") == "Clicked"130131132def test_pointer_move_with_element_origin(driver, pages):133"""Test pointer move with element origin."""134pages.load("javascriptPage.html")135136button = driver.find_element(By.ID, "clickField")137138# Get element reference for BiDi139element_id = button.id140element_ref = {"sharedId": element_id}141element_origin = ElementOrigin(element_ref)142143# Create pointer actions with element origin144pointer_actions = PointerSourceActions(145id="mouse",146parameters=PointerParameters(pointer_type=PointerType.MOUSE),147actions=[148PointerMoveAction(x=0, y=0, origin=element_origin),149PointerDownAction(button=0),150PointerUpAction(button=0),151],152)153154driver.input.perform_actions(driver.current_window_handle, [pointer_actions])155156WebDriverWait(driver, 5).until(lambda d: button.get_attribute("value") == "Clicked")157assert button.get_attribute("value") == "Clicked"158159160def test_pointer_with_common_properties(driver, pages):161"""Test pointer actions with common properties."""162pages.load("javascriptPage.html")163164button = driver.find_element(By.ID, "clickField")165location = button.location166size = button.size167x = location["x"] + size["width"] // 2168y = location["y"] + size["height"] // 2169170# Create pointer properties171properties = PointerCommonProperties(172width=2, height=2, pressure=0.5, tangential_pressure=0.0, twist=45, altitude_angle=0.5, azimuth_angle=1.0173)174175pointer_actions = PointerSourceActions(176id="mouse",177parameters=PointerParameters(pointer_type=PointerType.MOUSE),178actions=[179PointerMoveAction(x=x, y=y, properties=properties),180PointerDownAction(button=0, properties=properties),181PointerUpAction(button=0),182],183)184185driver.input.perform_actions(driver.current_window_handle, [pointer_actions])186187WebDriverWait(driver, 5).until(lambda d: button.get_attribute("value") == "Clicked")188assert button.get_attribute("value") == "Clicked"189190191def test_wheel_scroll(driver, pages):192"""Test wheel scroll actions."""193# page that can be scrolled194pages.load("scroll3.html")195196# Scroll down197wheel_actions = WheelSourceActions(198id="wheel", actions=[WheelScrollAction(x=100, y=100, delta_x=0, delta_y=100, origin=Origin.VIEWPORT)]199)200201driver.input.perform_actions(driver.current_window_handle, [wheel_actions])202203# Verify the page scrolled by checking scroll position204scroll_y = driver.execute_script("return window.pageYOffset;")205assert scroll_y == 100206207208def test_combined_input_actions(driver, pages):209"""Test combining multiple input sources."""210pages.load("single_text_input.html")211212input_element = driver.find_element(By.ID, "textInput")213214# First click on the input field, then type215location = input_element.location216size = input_element.size217x = location["x"] + size["width"] // 2218y = location["y"] + size["height"] // 2219220# Pointer actions to click221pointer_actions = PointerSourceActions(222id="mouse",223parameters=PointerParameters(pointer_type=PointerType.MOUSE),224actions=[225PauseAction(duration=0), # Sync with keyboard226PointerMoveAction(x=x, y=y),227PointerDownAction(button=0),228PointerUpAction(button=0),229],230)231232# Keyboard actions to type233key_actions = KeySourceActions(234id="keyboard",235actions=[236PauseAction(duration=0), # Sync with pointer237# write "test"238KeyDownAction(value="t"),239KeyUpAction(value="t"),240KeyDownAction(value="e"),241KeyUpAction(value="e"),242KeyDownAction(value="s"),243KeyUpAction(value="s"),244KeyDownAction(value="t"),245KeyUpAction(value="t"),246],247)248249driver.input.perform_actions(driver.current_window_handle, [pointer_actions, key_actions])250251WebDriverWait(driver, 5).until(lambda d: input_element.get_attribute("value") == "test")252assert input_element.get_attribute("value") == "test"253254255def test_set_files(driver, pages):256"""Test setting files on file input element."""257pages.load("formPage.html")258259upload_element = driver.find_element(By.ID, "upload")260assert upload_element.get_attribute("value") == ""261262# Create a temporary file263with tempfile.NamedTemporaryFile(mode="w", suffix=".txt", delete=False) as temp_file:264temp_file.write("test content")265temp_file_path = temp_file.name266267try:268# Get element reference for BiDi269element_id = upload_element.id270element_ref = {"sharedId": element_id}271272# Set files using BiDi273driver.input.set_files(driver.current_window_handle, element_ref, [temp_file_path])274275# Verify file was set276value = upload_element.get_attribute("value")277assert os.path.basename(temp_file_path) in value278279finally:280# Clean up temp file281if os.path.exists(temp_file_path):282os.unlink(temp_file_path)283284285def test_set_multiple_files(driver):286"""Test setting multiple files on a file input element with 'multiple' attribute using BiDi."""287driver.get("data:text/html,<input id=upload type=file multiple />")288289upload_element = driver.find_element(By.ID, "upload")290291# Create temporary files292temp_files = []293for i in range(2):294temp_file = tempfile.NamedTemporaryFile(mode="w", suffix=".txt", delete=False)295temp_file.write(f"test content {i}")296temp_files.append(temp_file.name)297temp_file.close()298299try:300# Get element reference for BiDi301element_id = upload_element.id302element_ref = {"sharedId": element_id}303304driver.input.set_files(driver.current_window_handle, element_ref, temp_files)305306value = upload_element.get_attribute("value")307assert value != ""308309finally:310# Clean up temp files311for temp_file_path in temp_files:312if os.path.exists(temp_file_path):313os.unlink(temp_file_path)314315316def test_release_actions(driver, pages):317"""Test releasing input actions."""318pages.load("single_text_input.html")319320input_element = driver.find_element(By.ID, "textInput")321322# Perform some actions first323key_actions = KeySourceActions(324id="keyboard",325actions=[326KeyDownAction(value="a"),327# Note: not releasing the key328],329)330331driver.input.perform_actions(driver.current_window_handle, [key_actions])332333# Now release all actions334driver.input.release_actions(driver.current_window_handle)335336# The key should be released now, so typing more should work normally337key_actions2 = KeySourceActions(338id="keyboard",339actions=[340KeyDownAction(value="b"),341KeyUpAction(value="b"),342],343)344345driver.input.perform_actions(driver.current_window_handle, [key_actions2])346347# Should be able to type normally348WebDriverWait(driver, 5).until(lambda d: "b" in input_element.get_attribute("value"))349350351@pytest.mark.parametrize("multiple", [True, False])352@pytest.mark.xfail_firefox(reason="File dialog handling not implemented in Firefox yet")353def test_file_dialog_event_handler_multiple(driver, multiple):354"""Test file dialog event handler with multiple as true and false."""355file_dialog_events = []356357def file_dialog_handler(file_dialog_info):358file_dialog_events.append(file_dialog_info)359360# Test event handler registration361handler_id = driver.input.add_file_dialog_handler(file_dialog_handler)362assert handler_id is not None363364driver.get(f"data:text/html,<input id=upload type=file {'multiple' if multiple else ''} />")365366# Use script.evaluate to trigger the file dialog with user activation367driver.script._evaluate(368expression="document.getElementById('upload').click()",369target={"context": driver.current_window_handle},370await_promise=False,371user_activation=True,372)373374# Wait for the file dialog event to be triggered375WebDriverWait(driver, 5).until(lambda d: len(file_dialog_events) > 0)376377assert len(file_dialog_events) > 0378file_dialog_info = file_dialog_events[0]379assert isinstance(file_dialog_info, FileDialogInfo)380assert file_dialog_info.context == driver.current_window_handle381# Check if multiple attribute is set correctly (True, False)382assert file_dialog_info.multiple is multiple383384driver.input.remove_file_dialog_handler(handler_id)385386387@pytest.mark.xfail_firefox(reason="File dialog handling not implemented in Firefox yet")388def test_file_dialog_event_handler_unsubscribe(driver):389"""Test file dialog event handler unsubscribe."""390file_dialog_events = []391392def file_dialog_handler(file_dialog_info):393file_dialog_events.append(file_dialog_info)394395# Register the handler396handler_id = driver.input.add_file_dialog_handler(file_dialog_handler)397assert handler_id is not None398399# Unsubscribe the handler400driver.input.remove_file_dialog_handler(handler_id)401402driver.get("data:text/html,<input id=upload type=file />")403404# Trigger the file dialog405driver.script._evaluate(406expression="document.getElementById('upload').click()",407target={"context": driver.current_window_handle},408await_promise=False,409user_activation=True,410)411412# Wait to ensure no events are captured413time.sleep(1)414assert len(file_dialog_events) == 0415416417