robo_appian 0.0.27__py3-none-any.whl → 0.0.34__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- robo_appian/__init__.py +4 -2
- robo_appian/components/ButtonUtils.py +127 -54
- robo_appian/components/DateUtils.py +54 -20
- robo_appian/components/DropdownUtils.py +61 -61
- robo_appian/components/InputUtils.py +51 -19
- robo_appian/components/LabelUtils.py +82 -26
- robo_appian/components/LinkUtils.py +58 -23
- robo_appian/components/SearchDropdownUtils.py +101 -47
- robo_appian/components/SearchInputUtils.py +89 -43
- robo_appian/components/TabUtils.py +71 -24
- robo_appian/components/TableUtils.py +68 -44
- robo_appian/controllers/ComponentDriver.py +65 -16
- robo_appian/exceptions/MyCustomError.py +13 -1
- robo_appian/utils/BrowserUtils.py +55 -16
- robo_appian/utils/ComponentUtils.py +102 -56
- robo_appian/utils/RoboUtils.py +64 -0
- {robo_appian-0.0.27.dist-info → robo_appian-0.0.34.dist-info}/METADATA +4 -2
- robo_appian-0.0.34.dist-info/RECORD +20 -0
- robo_appian-0.0.34.dist-info/licenses/LICENSE +201 -0
- robo_appian/components/__init__.py +0 -22
- robo_appian/controllers/__init__.py +0 -0
- robo_appian/exceptions/__init__.py +0 -0
- robo_appian/utils/__init__.py +0 -0
- robo_appian-0.0.27.dist-info/RECORD +0 -23
- robo_appian-0.0.27.dist-info/licenses/LICENSE +0 -21
- {robo_appian-0.0.27.dist-info → robo_appian-0.0.34.dist-info}/WHEEL +0 -0
|
@@ -2,19 +2,38 @@ from robo_appian.utils.ComponentUtils import ComponentUtils
|
|
|
2
2
|
from selenium.webdriver.support import expected_conditions as EC
|
|
3
3
|
from selenium.webdriver.support.ui import WebDriverWait
|
|
4
4
|
from selenium.webdriver.remote.webelement import WebElement
|
|
5
|
+
from selenium.webdriver.common.action_chains import ActionChains
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
class InputUtils:
|
|
8
9
|
"""
|
|
9
|
-
|
|
10
|
-
Usage Example:
|
|
11
|
-
from robo_appian.components.InputUtils import InputUtils
|
|
10
|
+
Fill text inputs, search fields, and other input components using label-driven selectors.
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
This utility handles text inputs by their visible labels, making tests readable and maintainable.
|
|
13
|
+
Automatically waits for clickability, clears existing values, and enters new text.
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
All methods follow the wait-first pattern: pass WebDriverWait as the first argument.
|
|
16
|
+
|
|
17
|
+
Examples:
|
|
18
|
+
>>> from robo_appian import InputUtils
|
|
19
|
+
|
|
20
|
+
# Set value by exact label match
|
|
21
|
+
InputUtils.setValueByLabelText(wait, "Username", "john_doe")
|
|
22
|
+
InputUtils.setValueByLabelText(wait, "Email Address", "john@example.com")
|
|
23
|
+
|
|
24
|
+
# Set value by partial label match (useful for dynamic labels)
|
|
25
|
+
InputUtils.setValueByPartialLabelText(wait, "First", "John")
|
|
26
|
+
|
|
27
|
+
# Set value by element ID
|
|
28
|
+
InputUtils.setValueById(wait, "email_input_123", "john@example.com")
|
|
29
|
+
|
|
30
|
+
# Set value by placeholder text
|
|
31
|
+
InputUtils.setValueByPlaceholderText(wait, "Enter your name", "John Doe")
|
|
32
|
+
|
|
33
|
+
Note:
|
|
34
|
+
- Uses normalize-space and NBSP translation to handle whitespace variations
|
|
35
|
+
- Automatically moves to element, clears it, and enters text via ActionChains
|
|
36
|
+
- Waits for element to be clickable before interacting
|
|
18
37
|
"""
|
|
19
38
|
|
|
20
39
|
@staticmethod
|
|
@@ -38,7 +57,9 @@ class InputUtils:
|
|
|
38
57
|
|
|
39
58
|
input_id = label_component.get_attribute("for")
|
|
40
59
|
if input_id is None:
|
|
41
|
-
raise ValueError(
|
|
60
|
+
raise ValueError(
|
|
61
|
+
f"Label component with text '{label}' does not have a 'for' attribute."
|
|
62
|
+
)
|
|
42
63
|
|
|
43
64
|
component = ComponentUtils.findComponentById(wait, input_id)
|
|
44
65
|
return component
|
|
@@ -61,7 +82,9 @@ class InputUtils:
|
|
|
61
82
|
label_component = ComponentUtils.waitForComponentToBeVisibleByXpath(wait, xpath)
|
|
62
83
|
input_id = label_component.get_attribute("for")
|
|
63
84
|
if input_id is None:
|
|
64
|
-
raise ValueError(
|
|
85
|
+
raise ValueError(
|
|
86
|
+
f"Label component with text '{label}' does not have a 'for' attribute."
|
|
87
|
+
)
|
|
65
88
|
|
|
66
89
|
component = ComponentUtils.findComponentById(wait, input_id)
|
|
67
90
|
return component
|
|
@@ -71,14 +94,17 @@ class InputUtils:
|
|
|
71
94
|
"""
|
|
72
95
|
Sets a value in an input component.
|
|
73
96
|
Parameters:
|
|
97
|
+
wait: Selenium WebDriverWait instance.
|
|
74
98
|
component: The Selenium WebElement for the input component.
|
|
75
99
|
value: The value to set in the input field.
|
|
76
100
|
Returns:
|
|
77
101
|
The Selenium WebElement for the input component after setting the value.
|
|
78
102
|
Example:
|
|
79
|
-
InputUtils._setValueByComponent(component, "test_value")
|
|
103
|
+
InputUtils._setValueByComponent(wait, component, "test_value")
|
|
80
104
|
"""
|
|
81
105
|
wait.until(EC.element_to_be_clickable(component))
|
|
106
|
+
driver = wait._driver
|
|
107
|
+
ActionChains(driver).move_to_element(component).perform()
|
|
82
108
|
component.clear()
|
|
83
109
|
component.send_keys(value)
|
|
84
110
|
return component
|
|
@@ -102,18 +128,24 @@ class InputUtils:
|
|
|
102
128
|
@staticmethod
|
|
103
129
|
def setValueByLabelText(wait: WebDriverWait, label: str, value: str):
|
|
104
130
|
"""
|
|
105
|
-
|
|
131
|
+
Set value in an input field by its exact label text.
|
|
106
132
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
label: The visible text label of the input component.
|
|
110
|
-
value: The value to set in the input field.
|
|
133
|
+
Finds the input by its associated label, waits for clickability, clears any existing
|
|
134
|
+
text, and enters the new value. Most commonly used method for form filling.
|
|
111
135
|
|
|
112
|
-
|
|
113
|
-
|
|
136
|
+
Args:
|
|
137
|
+
wait: WebDriverWait instance (required by all robo_appian utilities).
|
|
138
|
+
label: Exact visible label text. Must match exactly (e.g., "First Name", not "First").
|
|
139
|
+
value: Text to enter into the input field.
|
|
114
140
|
|
|
115
|
-
|
|
116
|
-
|
|
141
|
+
Raises:
|
|
142
|
+
ValueError: If label element has no 'for' attribute linking to input.
|
|
143
|
+
TimeoutException: If label or input not found within wait timeout.
|
|
144
|
+
|
|
145
|
+
Examples:
|
|
146
|
+
>>> InputUtils.setValueByLabelText(wait, "Username", "john_doe")
|
|
147
|
+
>>> InputUtils.setValueByLabelText(wait, "Email", "john@example.com")
|
|
148
|
+
>>> InputUtils.setValueByLabelText(wait, "Address", "123 Main St")
|
|
117
149
|
"""
|
|
118
150
|
component = InputUtils.__findComponentByLabel(wait, label)
|
|
119
151
|
InputUtils._setValueByComponent(wait, component, value)
|
|
@@ -6,50 +6,89 @@ from robo_appian.utils.ComponentUtils import ComponentUtils
|
|
|
6
6
|
|
|
7
7
|
class LabelUtils:
|
|
8
8
|
"""
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
Find and click text labels and headings in Appian UI.
|
|
10
|
+
|
|
11
|
+
Use these utilities to check for the presence of labels, headers, or other text elements
|
|
12
|
+
that don't fit into form component categories. Useful for validation steps that verify
|
|
13
|
+
page content or labels before/after actions.
|
|
14
|
+
|
|
15
|
+
All methods follow the wait-first pattern: pass WebDriverWait as the first argument.
|
|
16
|
+
|
|
17
|
+
Examples:
|
|
18
|
+
>>> from robo_appian import LabelUtils
|
|
19
|
+
>>> LabelUtils.clickByLabelText(wait, "Expand")
|
|
20
|
+
>>> if LabelUtils.isLabelExists(wait, "Success!"):
|
|
21
|
+
... print("Operation completed")
|
|
22
|
+
|
|
23
|
+
Note:
|
|
24
|
+
- Handles NBSP characters automatically via normalize-space
|
|
25
|
+
- Supports existence checks for validation and assertions
|
|
26
|
+
- Useful in test assertions: `assert LabelUtils.isLabelExists(wait, "Pending")`
|
|
15
27
|
"""
|
|
16
28
|
|
|
17
29
|
@staticmethod
|
|
18
30
|
def __findByLabelText(wait: WebDriverWait, label: str):
|
|
19
31
|
"""
|
|
20
|
-
|
|
32
|
+
Find a label element by exact text (internal helper).
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
wait: WebDriverWait instance.
|
|
36
|
+
label: Exact visible text of the label.
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
WebElement: The label element.
|
|
21
40
|
|
|
22
|
-
:
|
|
23
|
-
|
|
24
|
-
:return: WebElement representing the label.
|
|
25
|
-
Example:
|
|
26
|
-
component = LabelUtils._findByLabelText(wait, "Submit")
|
|
41
|
+
Raises:
|
|
42
|
+
TimeoutException: If label not found within timeout.
|
|
27
43
|
"""
|
|
28
44
|
xpath = f'//*[normalize-space(translate(., "\u00a0", " "))="{label}"]'
|
|
29
|
-
|
|
30
|
-
# component = wait.until(EC.visibility_of_element_located((By.XPATH, xpath)))
|
|
31
|
-
component = ComponentUtils.waitForComponentToBeVisibleByXpath(wait, xpath)
|
|
32
|
-
except Exception as e:
|
|
33
|
-
raise Exception(f"Label with text '{label}' not found.") from e
|
|
34
|
-
|
|
45
|
+
component = ComponentUtils.waitForComponentToBeVisibleByXpath(wait, xpath)
|
|
35
46
|
return component
|
|
36
47
|
|
|
37
48
|
@staticmethod
|
|
38
49
|
def clickByLabelText(wait: WebDriverWait, label: str):
|
|
39
50
|
"""
|
|
40
|
-
|
|
51
|
+
Click a label or text element by its exact visible text.
|
|
52
|
+
|
|
53
|
+
Find and click text elements that trigger UI changes (e.g., collapsible headers).
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
wait: WebDriverWait instance.
|
|
57
|
+
label: Exact visible text of the element to click.
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
None
|
|
61
|
+
|
|
62
|
+
Raises:
|
|
63
|
+
TimeoutException: If element not found or not clickable within timeout.
|
|
41
64
|
|
|
42
|
-
:
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
LabelUtils.clickByLabelText(wait, "Submit")
|
|
65
|
+
Examples:
|
|
66
|
+
>>> LabelUtils.clickByLabelText(wait, "Expand")
|
|
67
|
+
>>> LabelUtils.clickByLabelText(wait, "Show Details")
|
|
46
68
|
"""
|
|
47
69
|
component = LabelUtils.__findByLabelText(wait, label)
|
|
48
|
-
|
|
49
|
-
component.click()
|
|
70
|
+
ComponentUtils.click(wait, component)
|
|
50
71
|
|
|
51
72
|
@staticmethod
|
|
52
73
|
def isLabelExists(wait: WebDriverWait, label: str):
|
|
74
|
+
"""
|
|
75
|
+
Check if a label with the exact text exists on the page.
|
|
76
|
+
|
|
77
|
+
Non-blocking check useful in test assertions and conditional logic.
|
|
78
|
+
Returns False if label not found or times out (doesn't raise exception).
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
wait: WebDriverWait instance.
|
|
82
|
+
label: Exact visible text to search for.
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
bool: True if label found and visible, False otherwise.
|
|
86
|
+
|
|
87
|
+
Examples:
|
|
88
|
+
>>> if LabelUtils.isLabelExists(wait, "Error: Invalid input"):
|
|
89
|
+
... print("Validation error displayed")
|
|
90
|
+
>>> assert LabelUtils.isLabelExists(wait, "Success!"), "Success message not found"
|
|
91
|
+
"""
|
|
53
92
|
try:
|
|
54
93
|
LabelUtils.__findByLabelText(wait, label)
|
|
55
94
|
except Exception:
|
|
@@ -58,9 +97,26 @@ class LabelUtils:
|
|
|
58
97
|
|
|
59
98
|
@staticmethod
|
|
60
99
|
def isLabelExistsAfterLoad(wait: WebDriverWait, label: str):
|
|
100
|
+
"""
|
|
101
|
+
Check if a label exists after waiting for visibility (stricter validation).
|
|
102
|
+
|
|
103
|
+
Waits explicitly for the element to become visible, unlike isLabelExists which
|
|
104
|
+
may find invisible elements. Use this when page is still loading.
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
wait: WebDriverWait instance.
|
|
108
|
+
label: Exact visible text to search for.
|
|
109
|
+
|
|
110
|
+
Returns:
|
|
111
|
+
bool: True if label becomes visible within timeout, False otherwise.
|
|
112
|
+
|
|
113
|
+
Examples:
|
|
114
|
+
>>> # Wait for success message to appear after form submission
|
|
115
|
+
>>> if LabelUtils.isLabelExistsAfterLoad(wait, "Saved successfully"):
|
|
116
|
+
... print("Form saved")
|
|
117
|
+
"""
|
|
61
118
|
try:
|
|
62
119
|
xpath = f'.//*[normalize-space(translate(., "\u00a0", " "))="{label}"]'
|
|
63
|
-
wait.until(EC.presence_of_element_located((By.XPATH, xpath)))
|
|
64
120
|
wait.until(EC.visibility_of_element_located((By.XPATH, xpath)))
|
|
65
121
|
except Exception:
|
|
66
122
|
return False
|
|
@@ -1,46 +1,81 @@
|
|
|
1
1
|
from selenium.webdriver.common.by import By
|
|
2
2
|
from selenium.webdriver.support import expected_conditions as EC
|
|
3
3
|
from selenium.webdriver.support.ui import WebDriverWait
|
|
4
|
+
from robo_appian.utils.ComponentUtils import ComponentUtils
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
class LinkUtils:
|
|
7
8
|
"""
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
9
|
+
Click hyperlinks in Appian UI by their visible text.
|
|
10
|
+
|
|
11
|
+
Find and click links using their user-visible text label. Automatically waits for
|
|
12
|
+
clickability and handles hidden/overlay states. Uses ActionChains for reliable clicking
|
|
13
|
+
even when links are covered by animations or tooltips.
|
|
14
|
+
|
|
15
|
+
All methods follow the wait-first pattern: pass WebDriverWait as the first argument.
|
|
16
|
+
|
|
17
|
+
Examples:
|
|
18
|
+
>>> from robo_appian import LinkUtils
|
|
19
|
+
>>> LinkUtils.click(wait, "Learn More")
|
|
20
|
+
>>> LinkUtils.click(wait, "Edit Details")
|
|
21
|
+
>>> link = LinkUtils.find(wait, "View Report")
|
|
22
|
+
|
|
23
|
+
Note:
|
|
24
|
+
- Uses exact text matching for link discovery
|
|
25
|
+
- Excludes hidden links (aria-hidden="true") automatically
|
|
26
|
+
- Returns the link element (WebElement) for advanced use cases
|
|
18
27
|
"""
|
|
19
28
|
|
|
20
29
|
@staticmethod
|
|
21
30
|
def find(wait: WebDriverWait, label: str):
|
|
22
|
-
|
|
31
|
+
"""
|
|
32
|
+
Find a link element by its visible text.
|
|
33
|
+
|
|
34
|
+
Locates the first link that matches the exact text, excluding hidden links.
|
|
35
|
+
Useful when you need to inspect or chain operations on a link.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
wait: WebDriverWait instance.
|
|
39
|
+
label: Exact visible text of the link.
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
WebElement: The link element (for advanced chaining).
|
|
43
|
+
|
|
44
|
+
Raises:
|
|
45
|
+
TimeoutException: If link not found within timeout.
|
|
46
|
+
|
|
47
|
+
Examples:
|
|
48
|
+
>>> link = LinkUtils.find(wait, "Edit")
|
|
49
|
+
>>> link.get_attribute("href") # Get link URL
|
|
50
|
+
"""
|
|
23
51
|
xpath = f'.//a[normalize-space(.)="{label}" and not(ancestor::*[@aria-hidden="true"])]'
|
|
24
|
-
|
|
25
|
-
component = wait.until(EC.presence_of_element_located((By.XPATH, xpath)))
|
|
26
|
-
except Exception as e:
|
|
27
|
-
raise Exception(f"Could not find clickable link with label '{label}': {e}")
|
|
52
|
+
component = wait.until(EC.presence_of_element_located((By.XPATH, xpath)))
|
|
28
53
|
return component
|
|
29
54
|
|
|
30
55
|
@staticmethod
|
|
31
56
|
def click(wait: WebDriverWait, label: str):
|
|
32
57
|
"""
|
|
33
|
-
|
|
58
|
+
Click a link by its exact visible text.
|
|
59
|
+
|
|
60
|
+
Finds the link by exact text match, waits for clickability, and clicks it using
|
|
61
|
+
ActionChains for reliable interaction even with animations or overlays.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
wait: WebDriverWait instance.
|
|
65
|
+
label: Exact visible text of the link to click (e.g., "Edit", "Learn More").
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
WebElement: The link element that was clicked.
|
|
34
69
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
label: The visible text label of the link.
|
|
70
|
+
Raises:
|
|
71
|
+
TimeoutException: If link not found or not clickable within timeout.
|
|
38
72
|
|
|
39
|
-
|
|
40
|
-
LinkUtils.click(wait, "Learn More")
|
|
73
|
+
Examples:
|
|
74
|
+
>>> LinkUtils.click(wait, "Learn More")
|
|
75
|
+
>>> LinkUtils.click(wait, "View Details")
|
|
76
|
+
>>> LinkUtils.click(wait, "Delete")
|
|
41
77
|
"""
|
|
42
78
|
|
|
43
79
|
component = LinkUtils.find(wait, label)
|
|
44
|
-
|
|
45
|
-
component.click()
|
|
80
|
+
ComponentUtils.click(wait, component)
|
|
46
81
|
return component
|
|
@@ -1,91 +1,145 @@
|
|
|
1
|
+
from robo_appian.components.InputUtils import InputUtils
|
|
2
|
+
from robo_appian.utils.ComponentUtils import ComponentUtils
|
|
1
3
|
from selenium.webdriver.support.ui import WebDriverWait
|
|
2
4
|
from selenium.webdriver.support import expected_conditions as EC
|
|
3
5
|
from selenium.webdriver.common.by import By
|
|
4
6
|
from selenium.webdriver.remote.webelement import WebElement
|
|
5
|
-
from robo_appian.components.InputUtils import InputUtils
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
class SearchDropdownUtils:
|
|
9
10
|
"""
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
Select values from search-enabled dropdowns in Appian UI.
|
|
12
|
+
|
|
13
|
+
Search dropdowns allow users to type to filter options, then click to select. These differ
|
|
14
|
+
from standard dropdowns because they include a search/filter input field. Automatically
|
|
15
|
+
types the search term, waits for options to populate, and clicks the matching option.
|
|
16
|
+
|
|
17
|
+
All methods follow the wait-first pattern: pass WebDriverWait as the first argument.
|
|
18
|
+
|
|
19
|
+
Examples:
|
|
20
|
+
>>> from robo_appian import SearchDropdownUtils
|
|
21
|
+
>>> # Select by exact label match
|
|
22
|
+
>>> SearchDropdownUtils.selectSearchDropdownValueByLabelText(wait, "Employee", "John Doe")
|
|
23
|
+
>>> # Select by partial label match
|
|
24
|
+
>>> SearchDropdownUtils.selectSearchDropdownValueByPartialLabelText(wait, "Status", "Approved")
|
|
25
|
+
|
|
26
|
+
Note:
|
|
27
|
+
- Search dropdowns use the combobox ARIA pattern with ID-based suffixes (`_searchInput`, `_list`)
|
|
28
|
+
- Component lookup by label is more reliable than searching by ID directly
|
|
29
|
+
- Automatically waits for dropdown options to appear after typing search term
|
|
15
30
|
"""
|
|
16
31
|
|
|
17
32
|
@staticmethod
|
|
18
|
-
def __selectSearchDropdownValueByDropdownId(
|
|
33
|
+
def __selectSearchDropdownValueByDropdownId(
|
|
34
|
+
wait: WebDriverWait, component_id: str, value: str
|
|
35
|
+
):
|
|
19
36
|
if not component_id:
|
|
20
37
|
raise ValueError("Invalid component_id provided.")
|
|
21
38
|
|
|
22
39
|
input_component_id = str(component_id) + "_searchInput"
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
except Exception as e:
|
|
27
|
-
raise Exception(f"Failed to locate or click input component with ID '{input_component_id}': {e}")
|
|
40
|
+
input_component = wait.until(
|
|
41
|
+
EC.element_to_be_clickable((By.ID, input_component_id))
|
|
42
|
+
)
|
|
28
43
|
InputUtils._setValueByComponent(wait, input_component, value)
|
|
29
44
|
|
|
30
45
|
dropdown_option_id = str(component_id) + "_list"
|
|
31
46
|
|
|
32
47
|
xpath = f'.//ul[@id="{dropdown_option_id}"]/li[./div[normalize-space(.)="{value}"]][1]'
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
except Exception as e:
|
|
36
|
-
raise Exception(f"Failed to locate or click dropdown option with XPath '{xpath}': {e}")
|
|
37
|
-
component.click()
|
|
48
|
+
component = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
|
|
49
|
+
ComponentUtils.click(wait, component)
|
|
38
50
|
|
|
39
51
|
@staticmethod
|
|
40
|
-
def __selectSearchDropdownValueByPartialLabelText(
|
|
52
|
+
def __selectSearchDropdownValueByPartialLabelText(
|
|
53
|
+
wait: WebDriverWait, label: str, value: str
|
|
54
|
+
):
|
|
41
55
|
xpath = f'.//div[./div/span[contains(normalize-space(.), "{label}")]]/div/div/div/div[@role="combobox" and not(@aria-disabled="true")]'
|
|
42
|
-
|
|
43
|
-
combobox = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
|
|
44
|
-
except Exception as e:
|
|
45
|
-
raise Exception(f"Failed to locate or click dropdown component with XPath '{xpath}': {e}")
|
|
56
|
+
combobox = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
|
|
46
57
|
|
|
47
|
-
SearchDropdownUtils._selectSearchDropdownValueByComboboxComponent(
|
|
58
|
+
SearchDropdownUtils._selectSearchDropdownValueByComboboxComponent(
|
|
59
|
+
wait, combobox, value
|
|
60
|
+
)
|
|
48
61
|
|
|
49
62
|
@staticmethod
|
|
50
|
-
def __selectSearchDropdownValueByLabelText(
|
|
51
|
-
|
|
52
|
-
|
|
63
|
+
def __selectSearchDropdownValueByLabelText(
|
|
64
|
+
wait: WebDriverWait, label: str, value: str
|
|
65
|
+
):
|
|
66
|
+
xpath = f'.//div[./div/span[normalize-space(.)="{label}"]]/div/div/div/div[@role="combobox" and not(@aria-disabled="true")]'
|
|
67
|
+
combobox = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
|
|
68
|
+
SearchDropdownUtils._selectSearchDropdownValueByComboboxComponent(
|
|
69
|
+
wait, combobox, value
|
|
53
70
|
)
|
|
54
|
-
try:
|
|
55
|
-
combobox = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
|
|
56
|
-
except Exception as e:
|
|
57
|
-
raise Exception(f"Failed to locate or click dropdown component with XPath '{xpath}': {e}")
|
|
58
|
-
SearchDropdownUtils._selectSearchDropdownValueByComboboxComponent(wait, combobox, value)
|
|
59
71
|
|
|
60
72
|
@staticmethod
|
|
61
|
-
def _selectSearchDropdownValueByComboboxComponent(
|
|
73
|
+
def _selectSearchDropdownValueByComboboxComponent(
|
|
74
|
+
wait: WebDriverWait, combobox: WebElement, value: str
|
|
75
|
+
):
|
|
62
76
|
id = combobox.get_attribute("id")
|
|
63
77
|
if id is not None:
|
|
64
78
|
component_id = id.rsplit("_value", 1)[0]
|
|
65
79
|
else:
|
|
66
80
|
raise Exception("Combobox element does not have an 'id' attribute.")
|
|
67
81
|
|
|
68
|
-
|
|
69
|
-
combobox.click()
|
|
82
|
+
ComponentUtils.click(wait, combobox)
|
|
70
83
|
|
|
71
|
-
SearchDropdownUtils.__selectSearchDropdownValueByDropdownId(
|
|
84
|
+
SearchDropdownUtils.__selectSearchDropdownValueByDropdownId(
|
|
85
|
+
wait, component_id, value
|
|
86
|
+
)
|
|
72
87
|
|
|
73
88
|
@staticmethod
|
|
74
|
-
def selectSearchDropdownValueByLabelText(
|
|
75
|
-
|
|
89
|
+
def selectSearchDropdownValueByLabelText(
|
|
90
|
+
wait: WebDriverWait, dropdown_label: str, value: str
|
|
91
|
+
):
|
|
92
|
+
"""
|
|
93
|
+
Select a value from a search dropdown using exact label match.
|
|
94
|
+
|
|
95
|
+
Types the value into the search field, waits for filtered options to appear,
|
|
96
|
+
then clicks the matching option.
|
|
97
|
+
|
|
76
98
|
Args:
|
|
77
|
-
wait
|
|
78
|
-
dropdown_label
|
|
79
|
-
value
|
|
99
|
+
wait: WebDriverWait instance.
|
|
100
|
+
dropdown_label: Exact visible label text of the dropdown (e.g., "Employee").
|
|
101
|
+
value: Exact text of the option to select (e.g., "John Doe").
|
|
102
|
+
|
|
103
|
+
Returns:
|
|
104
|
+
None
|
|
105
|
+
|
|
106
|
+
Raises:
|
|
107
|
+
TimeoutException: If dropdown or option not found within timeout.
|
|
108
|
+
ValueError: If dropdown ID cannot be extracted from element.
|
|
109
|
+
|
|
110
|
+
Examples:
|
|
111
|
+
>>> SearchDropdownUtils.selectSearchDropdownValueByLabelText(wait, "Employee", "John Doe")
|
|
112
|
+
>>> SearchDropdownUtils.selectSearchDropdownValueByLabelText(wait, "Status", "Approved")
|
|
80
113
|
"""
|
|
81
|
-
SearchDropdownUtils.__selectSearchDropdownValueByLabelText(
|
|
114
|
+
SearchDropdownUtils.__selectSearchDropdownValueByLabelText(
|
|
115
|
+
wait, dropdown_label, value
|
|
116
|
+
)
|
|
82
117
|
|
|
83
118
|
@staticmethod
|
|
84
|
-
def selectSearchDropdownValueByPartialLabelText(
|
|
85
|
-
|
|
119
|
+
def selectSearchDropdownValueByPartialLabelText(
|
|
120
|
+
wait: WebDriverWait, dropdown_label: str, value: str
|
|
121
|
+
):
|
|
122
|
+
"""
|
|
123
|
+
Select a value from a search dropdown using partial label match.
|
|
124
|
+
|
|
125
|
+
Useful when the dropdown label contains dynamic text (e.g., includes a count or suffix).
|
|
126
|
+
Searches for the label using a contains check instead of exact match.
|
|
127
|
+
|
|
86
128
|
Args:
|
|
87
|
-
wait
|
|
88
|
-
dropdown_label
|
|
89
|
-
value
|
|
129
|
+
wait: WebDriverWait instance.
|
|
130
|
+
dropdown_label: Partial visible label text (uses contains matching).
|
|
131
|
+
value: Exact text of the option to select.
|
|
132
|
+
|
|
133
|
+
Returns:
|
|
134
|
+
None
|
|
135
|
+
|
|
136
|
+
Raises:
|
|
137
|
+
TimeoutException: If dropdown or option not found within timeout.
|
|
138
|
+
ValueError: If dropdown ID cannot be extracted from element.
|
|
139
|
+
|
|
140
|
+
Examples:
|
|
141
|
+
>>> SearchDropdownUtils.selectSearchDropdownValueByPartialLabelText(wait, "Employee", "John")
|
|
90
142
|
"""
|
|
91
|
-
SearchDropdownUtils.__selectSearchDropdownValueByPartialLabelText(
|
|
143
|
+
SearchDropdownUtils.__selectSearchDropdownValueByPartialLabelText(
|
|
144
|
+
wait, dropdown_label, value
|
|
145
|
+
)
|