1
1
from enum import Enum
2
- from typing import Tuple
3
-
4
- from appium .webdriver import WebElement
5
- from selenium .common import ElementNotVisibleException , TimeoutException
2
+ from typing import Tuple , Optional , Literal
6
3
from selenium .webdriver .common .by import By
7
- from selenium .webdriver .support import expected_conditions as ec
4
+ from selenium .webdriver .remote .webelement import WebElement
5
+ from selenium .webdriver .support import expected_conditions as EC
8
6
from selenium .webdriver .support .wait import WebDriverWait
7
+ from selenium .common .exceptions import (
8
+ TimeoutException , ElementNotVisibleException
9
+ )
9
10
11
+ # Type alias for locators
10
12
Locator = Tuple [By , str ]
11
13
12
14
@@ -30,33 +32,77 @@ def __init__(self, driver):
30
32
ignored_exceptions = [ElementNotVisibleException ],
31
33
)
32
34
33
- def wait (
34
- self , locator : Locator , waiter : WebDriverWait = None
35
+ def _get_waiter (self , wait_type : Optional [WaitType ] = None ) -> WebDriverWait :
36
+ """
37
+ Returns the appropriate WebDriverWait object based on the wait_type.
38
+ Defaults to the default wait if no wait_type is provided.
39
+ """
40
+ return {
41
+ WaitType .SHORT : self ._short_wait ,
42
+ WaitType .LONG : self ._long_wait ,
43
+ WaitType .FLUENT : self ._fluent_wait ,
44
+ }.get (wait_type , self ._wait )
45
+
46
+ def wait_for (
47
+ self ,
48
+ locator : Locator ,
49
+ condition : Literal ["clickable" , "visible" , "present" ],
50
+ waiter : Optional [WebDriverWait ] = None ,
35
51
) -> WebElement :
36
- if waiter is None :
37
- waiter = self ._wait
52
+ waiter = waiter or self ._wait
53
+
54
+ conditions = {
55
+ "clickable" : EC .element_to_be_clickable (* locator ),
56
+ "visible" : EC .visibility_of_element_located (* locator ),
57
+ "present" : EC .presence_of_element_located (* locator ),
58
+ }
59
+
60
+ if condition not in conditions :
61
+ raise ValueError (f"Unknown condition: { condition } " )
62
+
38
63
try :
39
- return waiter .until (ec . presence_of_element_located ( locator ) )
40
- except TimeoutException :
64
+ return waiter .until (conditions [ condition ] )
65
+ except TimeoutException as e :
41
66
raise TimeoutException (
42
- f"Element { locator } not found after { waiter ._timeout } seconds"
43
- )
44
-
45
- def find (self , locator : Locator ):
46
- self .driver .find_element (* locator )
67
+ f"Condition '{ condition } ' failed for element { locator } "
68
+ f"after { waiter ._timeout } seconds"
69
+ ) from e
47
70
48
- def click (self , locator : Locator ):
49
- element = self .wait (locator )
71
+ def click (
72
+ self ,
73
+ locator : Locator ,
74
+ condition : Literal ["clickable" , "visible" , "present" ] = "clickable" ,
75
+ wait_type : Optional [WaitType ] = None ,
76
+ ):
77
+ """
78
+ Click on an element.
79
+ """
80
+ waiter = self ._get_waiter (wait_type )
81
+ element = self .wait_for (locator , condition = condition , waiter = waiter )
50
82
element .click ()
51
83
52
- def set (self , locator : Locator , text : str ):
53
- element = self .wait (locator )
84
+ def set (
85
+ self , locator : Locator , text : str , wait_type : Optional [WaitType ] = None
86
+ ):
87
+ """
88
+ Set text in an input field.
89
+ """
90
+ waiter = self ._get_waiter (wait_type )
91
+ element = self .wait_for (locator , condition = "visible" , waiter = waiter )
54
92
element .clear ()
55
93
element .send_keys (text )
56
94
57
- def get_text (self , locator : Locator ):
58
- element = self .wait (locator )
59
- return element .text
95
+ def get_text (
96
+ self , locator : Locator , wait_type : Optional [WaitType ] = None
97
+ ) -> str :
98
+ """
99
+ Get the text of an element.
100
+ """
101
+ waiter = self ._get_waiter (wait_type )
102
+ return self .wait_for (locator , condition = "present" , waiter = waiter ).text
60
103
61
- def get_title (self ):
104
+ def get_title (self ) -> str :
105
+ """
106
+ Get the page title.
107
+ """
62
108
return self .driver .title
0 commit comments