Skip to content

Commit 54b47a4

Browse files
committed
Autowating for WebElement.clear()
1 parent 4820105 commit 54b47a4

File tree

4 files changed

+76
-6
lines changed

4 files changed

+76
-6
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Welcome to the Selenium + Python Template Project! This repository provides a we
88
- **Scalability**: Easy to extend for larger projects.
99
- **Integration-Ready**: Built-in support for integrating with APIs, CI/CD pipelines, and reporting tools.
1010
- **Cross-Browser Support**: Pre-configured WebDriver factory for managing multiple browsers.
11-
- **Auto-waiting**: `WebDriver.click()` waits for an element to be clickable automatically.
11+
- **Autowaiting**: `WebElement.click()`, `WebElement.send_keys()`, `WebElement.clear()` waits for an element to be enabled/clickable/editable automatically, use `autowait` fixture. Feature inspired by Playwright.
1212

1313
## 🏗️ Project Structure
1414

utils/autowait.html

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,30 @@
66
</head>
77
<body>
88

9+
<h1>Playground to test autowaiting for WebElement</h1>
10+
<h2>click()</h2>
911
<p>
1012
<button id="first" onclick="first_button_on_click()">Enable button</button>
1113
</p>
1214
<p>
1315
<button id="second" disabled onclick="second_button_on_click()">Second button</button>
1416
</p>
1517
<p id="placeholder"></p>
18+
<h2>send_keys()</h2>
1619
<p>
1720
<button id="third" onclick="third_button_on_click()">Enable input</button>
1821
</p>
1922
<p>
2023
<label for="input">Disabled input</label><input id="input" disabled />
2124
</p>
25+
<h2>clear()</h2>
26+
<p>
27+
<button id="fourth" onclick="enable('textarea')">Enable textarea</button>
28+
</p>
29+
<p>
30+
<label for="textarea">Disabled textarea</label><textarea id="textarea" disabled>Some text which must be cleared</textarea>
31+
</p>
32+
2233
<script>
2334
function first_button_on_click() {
2435
setTimeout(() => {
@@ -35,6 +46,12 @@
3546
document.getElementById("input").disabled = false;
3647
}, 1500);
3748
}
49+
50+
function enable(id) {
51+
setTimeout(() => {
52+
document.getElementById(id).disabled = false;
53+
}, 1500);
54+
}
3855
</script>
3956
</body>
4057
</html>

utils/autowait.py

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Monkey-patching WebElement.click to add retry logic for unclickable elements.
1+
# Monkey-patching WebElement methods to add waiting logic for unclickable elements.
22
# This patch is applied globally to all WebElement instances.
33
from selenium.webdriver.remote.webelement import WebElement
44
from selenium.webdriver.support import expected_conditions as EC
@@ -45,7 +45,27 @@ def patched_send_keys(self, *args, **kwargs):
4545
return patched_send_keys
4646

4747

48-
def enable_autowait(timeout: float=10.0) -> None:
48+
def patched_clear_factory(timeout: float):
49+
"""
50+
Args:
51+
timeout (float): Maximum time to wait for the element to become clickable.
52+
"""
53+
54+
def patched_clear(self, *args, **kwargs):
55+
"""
56+
Patches the WebElement's clear method to wait for the element to be clickable.
57+
Args:
58+
self: WebElement object.
59+
"""
60+
driver = self.parent
61+
WebDriverWait(driver, timeout).until(EC.element_to_be_clickable(self))
62+
63+
self._original_clear(*args, **kwargs)
64+
65+
return patched_clear
66+
67+
68+
def enable_autowait(timeout: float = 10.0) -> None:
4969
"""
5070
Enables auto-waiting globally for all WebDriver.click() invokcations
5171
Args:
@@ -54,16 +74,22 @@ def enable_autowait(timeout: float=10.0) -> None:
5474
"""
5575
assert not hasattr(WebElement, "_original_click"), "Autowait already enabled."
5676
assert not hasattr(WebElement, "_original_send_keys"), "Autowait already enabled."
77+
assert not hasattr(WebElement, "_original_clear"), "Autowait already enabled."
5778
WebElement._original_click = WebElement.click
5879
WebElement.click = patched_click_factory(timeout)
5980
WebElement._original_send_keys = WebElement.send_keys
6081
WebElement.send_keys = patched_send_keys_factory(timeout)
82+
WebElement._original_clear = WebElement.clear
83+
WebElement.clear = patched_clear_factory(timeout)
6184

6285

6386
def disable_autowait() -> None:
6487
assert hasattr(WebElement, "_original_click"), "Autowait is not enabled."
6588
assert hasattr(WebElement, "_original_send_keys"), "Autowait is not enabled."
89+
assert hasattr(WebElement, "_original_clear"), "Autowait is not enabled."
6690
WebElement.click = WebElement._original_click
67-
del(WebElement._original_click)
91+
del WebElement._original_click
6892
WebElement.send_keys = WebElement._original_send_keys
69-
del(WebElement._original_send_keys)
93+
del WebElement._original_send_keys
94+
WebElement.clear = WebElement._original_clear
95+
del WebElement._original_clear

utils/test_autowait.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import os
22

33
import pytest
4-
from selenium.common import ElementNotInteractableException
4+
from selenium.common import (
5+
ElementNotInteractableException,
6+
InvalidElementStateException,
7+
)
58
from selenium.webdriver.common.by import By
69
from selenium.webdriver.remote.webdriver import WebDriver
710

@@ -25,6 +28,8 @@ def test_send_keys(driver: WebDriver):
2528
with pytest.raises(ElementNotInteractableException) as exc:
2629
input_el.send_keys("hello")
2730

31+
assert input_el.get_attribute("value") == ""
32+
2833

2934
def test_click_auto_wait(driver: WebDriver, autowait):
3035
driver.get(f"file://{os.path.abspath('utils/autowait.html')}")
@@ -44,3 +49,25 @@ def test_send_keys_auto_wait(driver: WebDriver, autowait):
4449
input_el.send_keys("hello")
4550

4651
assert input_el.get_attribute("value") == "hello"
52+
53+
54+
def test_clear(driver: WebDriver):
55+
driver.get(f"file://{os.path.abspath('utils/autowait.html')}")
56+
57+
fourth_button = driver.find_element(By.ID, "fourth")
58+
textarea_el = driver.find_element(By.ID, "textarea")
59+
fourth_button.click()
60+
with pytest.raises(InvalidElementStateException) as exc:
61+
textarea_el.clear()
62+
assert textarea_el.get_attribute("value") == "Some text which must be cleared"
63+
64+
65+
def test_clear_autowait(driver: WebDriver, autowait):
66+
driver.get(f"file://{os.path.abspath('utils/autowait.html')}")
67+
68+
fourth_button = driver.find_element(By.ID, "fourth")
69+
textarea_el = driver.find_element(By.ID, "textarea")
70+
fourth_button.click()
71+
textarea_el.clear()
72+
73+
assert textarea_el.get_attribute("value") == ""

0 commit comments

Comments
 (0)