robo_appian 0.0.27__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 +29 -0
- robo_appian/components/ButtonUtils.py +137 -0
- robo_appian/components/DateUtils.py +64 -0
- robo_appian/components/DropdownUtils.py +388 -0
- robo_appian/components/InputUtils.py +161 -0
- robo_appian/components/LabelUtils.py +67 -0
- robo_appian/components/LinkUtils.py +46 -0
- robo_appian/components/SearchDropdownUtils.py +91 -0
- robo_appian/components/SearchInputUtils.py +63 -0
- robo_appian/components/TabUtils.py +60 -0
- robo_appian/components/TableUtils.py +149 -0
- robo_appian/components/__init__.py +22 -0
- robo_appian/controllers/ComponentDriver.py +93 -0
- robo_appian/controllers/__init__.py +0 -0
- robo_appian/exceptions/MyCustomError.py +6 -0
- robo_appian/exceptions/__init__.py +0 -0
- robo_appian/utils/BrowserUtils.py +52 -0
- robo_appian/utils/ComponentUtils.py +292 -0
- robo_appian/utils/__init__.py +0 -0
- robo_appian-0.0.27.dist-info/METADATA +68 -0
- robo_appian-0.0.27.dist-info/RECORD +23 -0
- robo_appian-0.0.27.dist-info/WHEEL +4 -0
- robo_appian-0.0.27.dist-info/licenses/LICENSE +21 -0
robo_appian/__init__.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from robo_appian.components.ButtonUtils import ButtonUtils
|
|
2
|
+
from robo_appian.utils.ComponentUtils import ComponentUtils
|
|
3
|
+
from robo_appian.components.DateUtils import DateUtils
|
|
4
|
+
from robo_appian.components.DropdownUtils import DropdownUtils
|
|
5
|
+
from robo_appian.components.InputUtils import InputUtils
|
|
6
|
+
from robo_appian.components.LabelUtils import LabelUtils
|
|
7
|
+
from robo_appian.components.LinkUtils import LinkUtils
|
|
8
|
+
from robo_appian.components.SearchDropdownUtils import SearchDropdownUtils
|
|
9
|
+
from robo_appian.components.TableUtils import TableUtils
|
|
10
|
+
from robo_appian.components.TabUtils import TabUtils
|
|
11
|
+
from robo_appian.utils.BrowserUtils import BrowserUtils
|
|
12
|
+
from robo_appian.components.SearchInputUtils import SearchInputUtils
|
|
13
|
+
|
|
14
|
+
__version__ = ComponentUtils.get_version()
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
"ButtonUtils",
|
|
18
|
+
"ComponentUtils",
|
|
19
|
+
"DateUtils",
|
|
20
|
+
"DropdownUtils",
|
|
21
|
+
"InputUtils",
|
|
22
|
+
"LabelUtils",
|
|
23
|
+
"LinkUtils",
|
|
24
|
+
"SearchDropdownUtils",
|
|
25
|
+
"TableUtils",
|
|
26
|
+
"TabUtils",
|
|
27
|
+
"BrowserUtils",
|
|
28
|
+
"SearchInputUtils"
|
|
29
|
+
]
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
from selenium.webdriver.common.by import By
|
|
2
|
+
from selenium.webdriver.support import expected_conditions as EC
|
|
3
|
+
from selenium.webdriver.support.ui import WebDriverWait
|
|
4
|
+
from selenium.webdriver.remote.webelement import WebElement
|
|
5
|
+
from robo_appian.utils.ComponentUtils import ComponentUtils
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ButtonUtils:
|
|
9
|
+
"""
|
|
10
|
+
Utility class for interacting with button components in Appian UI.
|
|
11
|
+
Usage Example:
|
|
12
|
+
# Click a button by its label
|
|
13
|
+
from robo_appian.components.ButtonUtils import ButtonUtils
|
|
14
|
+
ButtonUtils.clickByLabelText(wait, "Submit")
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
@staticmethod
|
|
18
|
+
def __click(wait: WebDriverWait, component: WebElement):
|
|
19
|
+
wait.until(EC.element_to_be_clickable(component))
|
|
20
|
+
component.click()
|
|
21
|
+
|
|
22
|
+
@staticmethod
|
|
23
|
+
def _findByPartialLabelText(wait: WebDriverWait, label: str):
|
|
24
|
+
"""
|
|
25
|
+
Finds a button by its label.
|
|
26
|
+
|
|
27
|
+
Parameters:
|
|
28
|
+
wait: Selenium WebDriverWait instance.
|
|
29
|
+
label: The label of the button to find.
|
|
30
|
+
label: The label of the button to find.
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
WebElement representing the button.
|
|
34
|
+
|
|
35
|
+
Example:
|
|
36
|
+
component = ButtonUtils._findByPartialLabelText(wait, "Submit")
|
|
37
|
+
"""
|
|
38
|
+
xpath = f"//button[./span[contains(translate(normalize-space(.), '\u00a0', ' '), '{label}')]]"
|
|
39
|
+
try:
|
|
40
|
+
component = ComponentUtils.waitForComponentToBeVisibleByXpath(wait, xpath)
|
|
41
|
+
except Exception as e:
|
|
42
|
+
raise Exception(
|
|
43
|
+
f"Button with label '{label}' not found or not clickable."
|
|
44
|
+
) from e
|
|
45
|
+
return component
|
|
46
|
+
|
|
47
|
+
@staticmethod
|
|
48
|
+
def __findByLabelText(wait: WebDriverWait, label: str):
|
|
49
|
+
xpath = f".//button[./span[normalize-space(.)='{label}']]"
|
|
50
|
+
try:
|
|
51
|
+
component = ComponentUtils.waitForComponentToBeVisibleByXpath(wait, xpath)
|
|
52
|
+
except Exception as e:
|
|
53
|
+
raise Exception(f"Button with label '{label}' not found.") from e
|
|
54
|
+
return component
|
|
55
|
+
|
|
56
|
+
@staticmethod
|
|
57
|
+
def clickByPartialLabelText(wait: WebDriverWait, label: str):
|
|
58
|
+
"""Finds a button by its partial label and clicks it.
|
|
59
|
+
|
|
60
|
+
Parameters:
|
|
61
|
+
wait: Selenium WebDriverWait instance.
|
|
62
|
+
label: The partial label of the button to click.
|
|
63
|
+
Example:
|
|
64
|
+
ButtonUtils.clickByPartialLabelText(wait, "Button Label")
|
|
65
|
+
"""
|
|
66
|
+
component = ButtonUtils._findByPartialLabelText(wait, label)
|
|
67
|
+
ButtonUtils.__click(wait, component)
|
|
68
|
+
|
|
69
|
+
@staticmethod
|
|
70
|
+
def clickByLabelText(wait: WebDriverWait, label: str):
|
|
71
|
+
"""Finds a button by its label and clicks it.
|
|
72
|
+
|
|
73
|
+
Parameters:
|
|
74
|
+
wait: Selenium WebDriverWait instance.
|
|
75
|
+
label: The label of the button to click.
|
|
76
|
+
Example:
|
|
77
|
+
ButtonUtils.clickByLabelText(wait, "Button Label")
|
|
78
|
+
"""
|
|
79
|
+
component = ButtonUtils.__findByLabelText(wait, label)
|
|
80
|
+
ButtonUtils.__click(wait, component)
|
|
81
|
+
|
|
82
|
+
@staticmethod
|
|
83
|
+
def clickById(wait: WebDriverWait, id: str):
|
|
84
|
+
"""
|
|
85
|
+
Finds and clicks an input button by its HTML id attribute.
|
|
86
|
+
|
|
87
|
+
Parameters:
|
|
88
|
+
wait: Selenium WebDriverWait instance.
|
|
89
|
+
id: The HTML id of the input button.
|
|
90
|
+
|
|
91
|
+
Example:
|
|
92
|
+
ButtonUtils.clickById(wait, "button_id")
|
|
93
|
+
|
|
94
|
+
"""
|
|
95
|
+
try:
|
|
96
|
+
component = wait.until(EC.element_to_be_clickable((By.ID, id)))
|
|
97
|
+
except Exception as e:
|
|
98
|
+
raise Exception(
|
|
99
|
+
f"Input button with id '{id}' not found or not clickable."
|
|
100
|
+
) from e
|
|
101
|
+
|
|
102
|
+
ButtonUtils.__click(wait, component)
|
|
103
|
+
|
|
104
|
+
@staticmethod
|
|
105
|
+
def isButtonExistsByLabelText(wait: WebDriverWait, label: str):
|
|
106
|
+
xpath = f".//button[./span[normalize-space(.)='{label}']]"
|
|
107
|
+
try:
|
|
108
|
+
ComponentUtils.findComponentByXPath(wait, xpath)
|
|
109
|
+
except Exception:
|
|
110
|
+
return False
|
|
111
|
+
return True
|
|
112
|
+
|
|
113
|
+
@staticmethod
|
|
114
|
+
def isButtonExistsByPartialLabelText(wait: WebDriverWait, label: str):
|
|
115
|
+
xpath = f".//button[./span[contains(translate(normalize-space(.), '\u00a0', ' '), '{label}')]]"
|
|
116
|
+
try:
|
|
117
|
+
ComponentUtils.findComponentByXPath(wait, xpath)
|
|
118
|
+
except Exception:
|
|
119
|
+
return False
|
|
120
|
+
return True
|
|
121
|
+
|
|
122
|
+
@staticmethod
|
|
123
|
+
def isButtonExistsByPartialLabelTextAfterLoad(wait: WebDriverWait, label: str):
|
|
124
|
+
try:
|
|
125
|
+
ButtonUtils._findByPartialLabelText(wait, label)
|
|
126
|
+
except Exception:
|
|
127
|
+
return False
|
|
128
|
+
return True
|
|
129
|
+
|
|
130
|
+
@staticmethod
|
|
131
|
+
def waitForButtonToBeVisibleByPartialLabelText(wait: WebDriverWait, label: str):
|
|
132
|
+
xpath = f".//button[./span[contains(translate(normalize-space(.), '\u00a0', ' '), '{label}')]]"
|
|
133
|
+
try:
|
|
134
|
+
component = ComponentUtils.waitForComponentToBeVisibleByXpath(wait, xpath)
|
|
135
|
+
except Exception as e:
|
|
136
|
+
raise Exception(f"Button with partial label '{label}' not visible.") from e
|
|
137
|
+
return component
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
from selenium.webdriver.common.by import By
|
|
2
|
+
from selenium.webdriver.support import expected_conditions as EC
|
|
3
|
+
from selenium.webdriver.support.ui import WebDriverWait
|
|
4
|
+
|
|
5
|
+
from robo_appian.components.InputUtils import InputUtils
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class DateUtils:
|
|
9
|
+
"""
|
|
10
|
+
Utility class for interacting with date components in Appian UI.
|
|
11
|
+
Usage Example:
|
|
12
|
+
# Set a date value in a date component
|
|
13
|
+
from robo_appian.components.DateUtils import DateUtils
|
|
14
|
+
DateUtils.setValueByLabelText(wait, "Start Date", "2023-10-01")
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
@staticmethod
|
|
18
|
+
def __findComponent(wait: WebDriverWait, label: str):
|
|
19
|
+
"""
|
|
20
|
+
Finds a date component by its label.
|
|
21
|
+
:param wait: WebDriverWait instance to wait for elements.
|
|
22
|
+
:param label: The label of the date component.
|
|
23
|
+
:return: The WebElement representing the date component.
|
|
24
|
+
Example:
|
|
25
|
+
DateUtils.__findComponent(wait, "Start Date")
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
xpath = f'.//div[./div/label[text()="{label}"]]/div/div/div/input'
|
|
29
|
+
try:
|
|
30
|
+
component = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
|
|
31
|
+
except Exception as e:
|
|
32
|
+
raise Exception(
|
|
33
|
+
f"Could not find clickable date component with label '{label}': {e}"
|
|
34
|
+
)
|
|
35
|
+
return component
|
|
36
|
+
|
|
37
|
+
@staticmethod
|
|
38
|
+
def setValueByLabelText(wait: WebDriverWait, label: str, value: str):
|
|
39
|
+
"""
|
|
40
|
+
Sets the value of a date component.
|
|
41
|
+
:param wait: WebDriverWait instance to wait for elements.
|
|
42
|
+
:param label: The label of the date component.
|
|
43
|
+
:param value: The value to set in the date component.
|
|
44
|
+
:return: The WebElement representing the date component.
|
|
45
|
+
Example:
|
|
46
|
+
DateUtils.setValueByLabelText(wait, "Start Date", "2023-10-01")
|
|
47
|
+
"""
|
|
48
|
+
component = DateUtils.__findComponent(wait, label)
|
|
49
|
+
InputUtils._setValueByComponent(wait, component, value)
|
|
50
|
+
return component
|
|
51
|
+
|
|
52
|
+
@staticmethod
|
|
53
|
+
def clickByLabelText(wait: WebDriverWait, label: str):
|
|
54
|
+
"""
|
|
55
|
+
Clicks on the date component to open the date picker.
|
|
56
|
+
:param wait: WebDriverWait instance to wait for elements.
|
|
57
|
+
:param label: The label of the date component.
|
|
58
|
+
:return: The WebElement representing the date component.
|
|
59
|
+
Example:
|
|
60
|
+
DateUtils.clickByLabelText(wait, "Start Date")
|
|
61
|
+
"""
|
|
62
|
+
component = DateUtils.__findComponent(wait, label)
|
|
63
|
+
component.click()
|
|
64
|
+
return component
|
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
import time
|
|
2
|
+
from selenium.webdriver.common.by import By
|
|
3
|
+
from selenium.webdriver.support import expected_conditions as EC
|
|
4
|
+
from selenium.webdriver.support.ui import WebDriverWait
|
|
5
|
+
from selenium.webdriver.remote.webelement import WebElement
|
|
6
|
+
from selenium.common.exceptions import NoSuchElementException
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class DropdownUtils:
|
|
10
|
+
"""
|
|
11
|
+
Utility class for interacting with dropdown components in Appian UI.
|
|
12
|
+
Usage Example:
|
|
13
|
+
# Select a value from a dropdown
|
|
14
|
+
from robo_appian.components.DropdownUtils import DropdownUtils
|
|
15
|
+
DropdownUtils.selectDropdownValueByLabelText(wait, "Status", "Approved")
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
@staticmethod
|
|
19
|
+
def __findComboboxByLabelText(
|
|
20
|
+
wait: WebDriverWait, label: str, isPartialText: bool = False
|
|
21
|
+
):
|
|
22
|
+
"""
|
|
23
|
+
Finds the combobox element by its label text.
|
|
24
|
+
:param wait: WebDriverWait instance to wait for elements.
|
|
25
|
+
:param label: The label of the combobox.
|
|
26
|
+
:param isPartialText: Whether to use partial text matching for the label.
|
|
27
|
+
:return: The combobox WebElement.
|
|
28
|
+
Example:
|
|
29
|
+
combobox = DropdownUtils.__findComboboxByLabelText(wait, "Dropdown Label", isPartialText=False)
|
|
30
|
+
combobox = DropdownUtils.__findComboboxByLabelText(wait, "Dropdown Label", isPartialText=True)
|
|
31
|
+
combobox = DropdownUtils.__findComboboxByLabelText(wait, "Dropdown Label")
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
if isPartialText:
|
|
35
|
+
xpath = f'//span[contains(normalize-space(.), "{label}")]/ancestor::div[@role="presentation"][1]//div[@aria-labelledby=//span[contains(normalize-space(.), "{label}")]/@id and @role="combobox" and not(@aria-disabled="true")]'
|
|
36
|
+
else:
|
|
37
|
+
xpath = f'//span[normalize-space(.)="{label}"]/ancestor::div[@role="presentation"][1]//div[@aria-labelledby=//span[normalize-space(.)="{label}"]/@id and @role="combobox" and not(@aria-disabled="true")]'
|
|
38
|
+
|
|
39
|
+
try:
|
|
40
|
+
component = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
|
|
41
|
+
except Exception as e:
|
|
42
|
+
raise Exception(f'Could not find combobox with label "{label}" : {str(e)}')
|
|
43
|
+
|
|
44
|
+
return component
|
|
45
|
+
|
|
46
|
+
@staticmethod
|
|
47
|
+
def __clickCombobox(wait: WebDriverWait, combobox: WebElement):
|
|
48
|
+
"""
|
|
49
|
+
Clicks the combobox to open the dropdown options.
|
|
50
|
+
|
|
51
|
+
:param wait: WebDriverWait instance to wait for elements.
|
|
52
|
+
:param combobox: The combobox WebElement.
|
|
53
|
+
Example:
|
|
54
|
+
DropdownUtils.__clickCombobox(wait, combobox)
|
|
55
|
+
"""
|
|
56
|
+
try:
|
|
57
|
+
wait.until(EC.element_to_be_clickable(combobox))
|
|
58
|
+
combobox.click()
|
|
59
|
+
|
|
60
|
+
except Exception as e:
|
|
61
|
+
raise Exception(f"Could not click combobox: {str(e)}")
|
|
62
|
+
|
|
63
|
+
@staticmethod
|
|
64
|
+
def __findDropdownOptionId(combobox: WebElement):
|
|
65
|
+
"""
|
|
66
|
+
Finds the dropdown option id from the combobox.
|
|
67
|
+
|
|
68
|
+
:param wait: WebDriverWait instance to wait for elements.
|
|
69
|
+
:param combobox: The combobox WebElement.
|
|
70
|
+
:return: The id of the dropdown options list.
|
|
71
|
+
Example:
|
|
72
|
+
dropdown_option_id = DropdownUtils.__findDropdownOptionId(wait, combobox)
|
|
73
|
+
"""
|
|
74
|
+
dropdown_option_id = combobox.get_attribute("aria-controls")
|
|
75
|
+
if dropdown_option_id is None:
|
|
76
|
+
raise Exception(
|
|
77
|
+
'Dropdown component does not have a valid "aria-controls" attribute.'
|
|
78
|
+
)
|
|
79
|
+
return dropdown_option_id
|
|
80
|
+
|
|
81
|
+
@staticmethod
|
|
82
|
+
def __checkDropdownOptionValueExistsByDropdownOptionId(
|
|
83
|
+
wait: WebDriverWait, dropdown_option_id: str, value: str
|
|
84
|
+
):
|
|
85
|
+
"""
|
|
86
|
+
Checks if a dropdown option value exists by its option id and value.
|
|
87
|
+
|
|
88
|
+
:param wait: WebDriverWait instance to wait for elements.
|
|
89
|
+
:param dropdown_option_id: The id of the dropdown options list.
|
|
90
|
+
:param value: The value to check in the dropdown.
|
|
91
|
+
Example:
|
|
92
|
+
exists = DropdownUtils.checkDropdownOptionValueExistsByDropdownOptionId(wait, "dropdown_option_id", "Option Value")
|
|
93
|
+
if exists:
|
|
94
|
+
print("The value exists in the dropdown.")
|
|
95
|
+
else:
|
|
96
|
+
print("The value does not exist in the dropdown.")
|
|
97
|
+
"""
|
|
98
|
+
|
|
99
|
+
xpath = f'.//div/ul[@id="{dropdown_option_id}"]/li[./div[normalize-space(.)="{value}"]]'
|
|
100
|
+
try:
|
|
101
|
+
wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
|
|
102
|
+
return True
|
|
103
|
+
except NoSuchElementException:
|
|
104
|
+
return False
|
|
105
|
+
except Exception as e:
|
|
106
|
+
raise Exception(
|
|
107
|
+
f'Could not find dropdown option "{value}" with dropdown option id "{dropdown_option_id}": {str(e)}'
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
@staticmethod
|
|
111
|
+
def __selectDropdownValueByDropdownOptionId(
|
|
112
|
+
wait: WebDriverWait, dropdown_option_id: str, value: str
|
|
113
|
+
):
|
|
114
|
+
"""
|
|
115
|
+
Selects a value from a dropdown by its option id and value.
|
|
116
|
+
|
|
117
|
+
:param wait: WebDriverWait instance to wait for elements.
|
|
118
|
+
:param dropdown_option_id: The id of the dropdown options list.
|
|
119
|
+
:param value: The value to select from the dropdown.
|
|
120
|
+
Example:
|
|
121
|
+
DropdownUtils.selectDropdownValueByDropdownOptionId(wait, "dropdown_option_id", "Option Value")
|
|
122
|
+
"""
|
|
123
|
+
option_xpath = f'.//div/ul[@id="{dropdown_option_id}"]/li[./div[normalize-space(.)="{value}"]]'
|
|
124
|
+
try:
|
|
125
|
+
try:
|
|
126
|
+
component = wait.until(
|
|
127
|
+
EC.presence_of_element_located((By.XPATH, option_xpath))
|
|
128
|
+
)
|
|
129
|
+
component = wait.until(
|
|
130
|
+
EC.element_to_be_clickable((By.XPATH, option_xpath))
|
|
131
|
+
)
|
|
132
|
+
component.click()
|
|
133
|
+
except Exception as e:
|
|
134
|
+
raise Exception(
|
|
135
|
+
f'Could not locate or click dropdown option "{value}" with dropdown option id "{dropdown_option_id}": {str(e)}' # noqa: E501
|
|
136
|
+
)
|
|
137
|
+
except Exception as e:
|
|
138
|
+
raise Exception(
|
|
139
|
+
f'Could not find or click dropdown option "{value}" with xpath "{option_xpath}": {str(e)}'
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
@staticmethod
|
|
143
|
+
def __selectDropdownValueByPartialLabelText(
|
|
144
|
+
wait: WebDriverWait, label: str, value: str
|
|
145
|
+
):
|
|
146
|
+
"""
|
|
147
|
+
Selects a value from a dropdown by its label text.
|
|
148
|
+
|
|
149
|
+
:param wait: WebDriverWait instance to wait for elements.
|
|
150
|
+
:param label: The label of the dropdown.
|
|
151
|
+
:param value: The value to select from the dropdown.
|
|
152
|
+
"""
|
|
153
|
+
combobox = DropdownUtils.__findComboboxByLabelText(wait, label, True)
|
|
154
|
+
DropdownUtils.__clickCombobox(wait, combobox)
|
|
155
|
+
dropdown_option_id = DropdownUtils.__findDropdownOptionId(combobox)
|
|
156
|
+
DropdownUtils.__selectDropdownValueByDropdownOptionId(
|
|
157
|
+
wait, dropdown_option_id, value
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
@staticmethod
|
|
161
|
+
def __selectDropdownValueByLabelText(wait: WebDriverWait, label: str, value: str):
|
|
162
|
+
"""
|
|
163
|
+
Selects a value from a dropdown by its label text.
|
|
164
|
+
|
|
165
|
+
:param wait: WebDriverWait instance to wait for elements.
|
|
166
|
+
:param label: The label of the dropdown.
|
|
167
|
+
:param value: The value to select from the dropdown.
|
|
168
|
+
"""
|
|
169
|
+
combobox = DropdownUtils.__findComboboxByLabelText(wait, label)
|
|
170
|
+
DropdownUtils.__clickCombobox(wait, combobox)
|
|
171
|
+
dropdown_option_id = DropdownUtils.__findDropdownOptionId(combobox)
|
|
172
|
+
DropdownUtils.__selectDropdownValueByDropdownOptionId(
|
|
173
|
+
wait, dropdown_option_id, value
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
@staticmethod
|
|
177
|
+
def checkReadOnlyStatusByLabelText(wait: WebDriverWait, label: str):
|
|
178
|
+
"""
|
|
179
|
+
Checks if a dropdown is read-only by its label text.
|
|
180
|
+
|
|
181
|
+
:param wait: WebDriverWait instance to wait for elements.
|
|
182
|
+
:param label: The label of the dropdown.
|
|
183
|
+
:return: True if the dropdown is read-only, False otherwise.
|
|
184
|
+
Example:
|
|
185
|
+
is_read_only = DropdownUtils.checkReadOnlyStatusByLabelText(wait, "Dropdown Label")
|
|
186
|
+
if is_read_only:
|
|
187
|
+
print("The dropdown is read-only.")
|
|
188
|
+
else:
|
|
189
|
+
print("The dropdown is editable.")
|
|
190
|
+
"""
|
|
191
|
+
# xpath = f'.//div[./div/span[normalize-space(.)="{label}"]]/div/div/p[text()]'
|
|
192
|
+
xpath = f'//span[normalize-space(.)="{label}"]/ancestor::div[@role="presentation"][1]//div[@aria-labelledby=//span[normalize-space(.)="{label}"]/@id and not(@role="combobox")]'
|
|
193
|
+
try:
|
|
194
|
+
wait._driver.find_element(By.XPATH, xpath)
|
|
195
|
+
return True
|
|
196
|
+
except NoSuchElementException:
|
|
197
|
+
return False
|
|
198
|
+
except Exception:
|
|
199
|
+
raise Exception(f'Error checking read-only status for label "{label}"')
|
|
200
|
+
|
|
201
|
+
@staticmethod
|
|
202
|
+
def checkEditableStatusByLabelText(wait: WebDriverWait, label: str):
|
|
203
|
+
"""
|
|
204
|
+
Checks if a dropdown is editable (not disabled) by its label text.
|
|
205
|
+
|
|
206
|
+
:param wait: WebDriverWait instance to wait for elements.
|
|
207
|
+
:param label: The label of the dropdown.
|
|
208
|
+
:return: True if the dropdown is editable, False if disabled.
|
|
209
|
+
Example:
|
|
210
|
+
is_editable = DropdownUtils.checkEditableStatusByLabelText(wait, "Dropdown Label")
|
|
211
|
+
if is_editable:
|
|
212
|
+
print("The dropdown is editable.")
|
|
213
|
+
else:
|
|
214
|
+
print("The dropdown is disabled.")
|
|
215
|
+
"""
|
|
216
|
+
xpath = f'//span[text()="{label}"]/ancestor::div[@role="presentation"][1]//div[@aria-labelledby=//span[normalize-space(.)="{label}"]/@id and @role="combobox" and not(@aria-disabled="true")]'
|
|
217
|
+
try:
|
|
218
|
+
wait._driver.find_element(By.XPATH, xpath)
|
|
219
|
+
return True # If disabled element is found, dropdown is not editable
|
|
220
|
+
except NoSuchElementException:
|
|
221
|
+
return False # If disabled element is not found, dropdown is editable
|
|
222
|
+
except Exception:
|
|
223
|
+
raise Exception(f'Error checking editable status for label "{label}"')
|
|
224
|
+
|
|
225
|
+
@staticmethod
|
|
226
|
+
def waitForDropdownToBeEnabled(
|
|
227
|
+
wait: WebDriverWait, label: str, wait_interval: float = 0.5, timeout: int = 2
|
|
228
|
+
):
|
|
229
|
+
elapsed_time = 0
|
|
230
|
+
status = False
|
|
231
|
+
|
|
232
|
+
while elapsed_time < timeout:
|
|
233
|
+
status = DropdownUtils.checkEditableStatusByLabelText(wait, label)
|
|
234
|
+
if status:
|
|
235
|
+
return True
|
|
236
|
+
time.sleep(wait_interval)
|
|
237
|
+
elapsed_time += wait_interval
|
|
238
|
+
return False
|
|
239
|
+
|
|
240
|
+
@staticmethod
|
|
241
|
+
def selectDropdownValueByComboboxComponent(
|
|
242
|
+
wait: WebDriverWait, combobox: WebElement, value: str
|
|
243
|
+
):
|
|
244
|
+
"""
|
|
245
|
+
Selects a value from a dropdown using the combobox component.
|
|
246
|
+
|
|
247
|
+
:param wait: WebDriverWait instance to wait for elements.
|
|
248
|
+
:param combobox: The combobox WebElement.
|
|
249
|
+
:param value: The value to select from the dropdown.
|
|
250
|
+
Example:
|
|
251
|
+
DropdownUtils.selectDropdownValueByComboboxComponent(wait, combobox, "Option Value")
|
|
252
|
+
"""
|
|
253
|
+
dropdown_option_id = DropdownUtils.__findDropdownOptionId(combobox)
|
|
254
|
+
DropdownUtils.__clickCombobox(wait, combobox)
|
|
255
|
+
DropdownUtils.__selectDropdownValueByDropdownOptionId(
|
|
256
|
+
wait, dropdown_option_id, value
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
@staticmethod
|
|
260
|
+
def selectDropdownValueByLabelText(
|
|
261
|
+
wait: WebDriverWait, dropdown_label: str, value: str
|
|
262
|
+
):
|
|
263
|
+
"""
|
|
264
|
+
Selects a value from a dropdown by its label text.
|
|
265
|
+
|
|
266
|
+
:param wait: WebDriverWait instance to wait for elements.
|
|
267
|
+
:param dropdown_label: The label of the dropdown.
|
|
268
|
+
:param value: The value to select from the dropdown.
|
|
269
|
+
Example:
|
|
270
|
+
DropdownUtils.selectDropdownValueByLabelText(wait, "Dropdown Label", "Option Value")
|
|
271
|
+
"""
|
|
272
|
+
DropdownUtils.__selectDropdownValueByLabelText(wait, dropdown_label, value)
|
|
273
|
+
|
|
274
|
+
@staticmethod
|
|
275
|
+
def selectDropdownValueByPartialLabelText(
|
|
276
|
+
wait: WebDriverWait, dropdown_label: str, value: str
|
|
277
|
+
):
|
|
278
|
+
"""
|
|
279
|
+
Selects a value from a dropdown by its partial label text.
|
|
280
|
+
|
|
281
|
+
:param wait: WebDriverWait instance to wait for elements.
|
|
282
|
+
:param dropdown_label: The partial label of the dropdown.
|
|
283
|
+
:param value: The value to select from the dropdown.
|
|
284
|
+
Example:
|
|
285
|
+
DropdownUtils.selectDropdownValueByPartialLabelText(wait, "Dropdown Label", "Option Value")
|
|
286
|
+
"""
|
|
287
|
+
DropdownUtils.__selectDropdownValueByPartialLabelText(
|
|
288
|
+
wait, dropdown_label, value
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
@staticmethod
|
|
292
|
+
def checkDropdownOptionValueExists(
|
|
293
|
+
wait: WebDriverWait, dropdown_label: str, value: str
|
|
294
|
+
):
|
|
295
|
+
"""
|
|
296
|
+
Checks if a dropdown option value exists by its label text.
|
|
297
|
+
|
|
298
|
+
:param wait: WebDriverWait instance to wait for elements.
|
|
299
|
+
:param dropdown_label: The label of the dropdown.
|
|
300
|
+
:param value: The value to check in the dropdown.
|
|
301
|
+
:return: True if the value exists, False otherwise.
|
|
302
|
+
Example:
|
|
303
|
+
exists = DropdownUtils.checkDropdownOptionValueExists(wait, "Dropdown Label", "Option Value")
|
|
304
|
+
if exists:
|
|
305
|
+
print("The value exists in the dropdown.")
|
|
306
|
+
else:
|
|
307
|
+
print("The value does not exist in the dropdown.")
|
|
308
|
+
"""
|
|
309
|
+
combobox = DropdownUtils.__findComboboxByLabelText(wait, dropdown_label)
|
|
310
|
+
DropdownUtils.__clickCombobox(wait, combobox)
|
|
311
|
+
dropdown_option_id = DropdownUtils.__findDropdownOptionId(combobox)
|
|
312
|
+
return DropdownUtils.__checkDropdownOptionValueExistsByDropdownOptionId(
|
|
313
|
+
wait, dropdown_option_id, value
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
@staticmethod
|
|
317
|
+
def getDropdownOptionValues(wait: WebDriverWait, dropdown_label: str) -> list[str]:
|
|
318
|
+
"""
|
|
319
|
+
Gets all option values from a dropdown by its label text.
|
|
320
|
+
|
|
321
|
+
:param wait: WebDriverWait instance to wait for elements.
|
|
322
|
+
:param dropdown_label: The label of the dropdown.
|
|
323
|
+
:return: A list of all option values in the dropdown.
|
|
324
|
+
Example:
|
|
325
|
+
values = DropdownUtils.getDropdownOptionValues(wait, "Dropdown Label")
|
|
326
|
+
"""
|
|
327
|
+
combobox = DropdownUtils.__findComboboxByLabelText(wait, dropdown_label)
|
|
328
|
+
DropdownUtils.__clickCombobox(wait, combobox)
|
|
329
|
+
dropdown_option_id = DropdownUtils.__findDropdownOptionId(combobox)
|
|
330
|
+
|
|
331
|
+
# Get all option elements
|
|
332
|
+
xpath = f'//ul[@id="{dropdown_option_id}"]//li[@role="option"]/div'
|
|
333
|
+
try:
|
|
334
|
+
option_elements = wait.until(
|
|
335
|
+
EC.presence_of_all_elements_located((By.XPATH, xpath))
|
|
336
|
+
)
|
|
337
|
+
# Extract text immediately to avoid stale element reference
|
|
338
|
+
option_texts = []
|
|
339
|
+
for element in option_elements:
|
|
340
|
+
try:
|
|
341
|
+
text = element.text.strip()
|
|
342
|
+
if text:
|
|
343
|
+
option_texts.append(text)
|
|
344
|
+
except Exception:
|
|
345
|
+
# If element becomes stale, try to re-find it
|
|
346
|
+
continue
|
|
347
|
+
|
|
348
|
+
# If we got no texts due to stale elements, try one more time
|
|
349
|
+
if not option_texts:
|
|
350
|
+
option_elements = wait._driver.find_elements(By.XPATH, xpath)
|
|
351
|
+
for element in option_elements:
|
|
352
|
+
try:
|
|
353
|
+
text = element.text.strip()
|
|
354
|
+
if text:
|
|
355
|
+
option_texts.append(text)
|
|
356
|
+
except Exception:
|
|
357
|
+
continue
|
|
358
|
+
|
|
359
|
+
DropdownUtils.__clickCombobox(wait, combobox)
|
|
360
|
+
return option_texts
|
|
361
|
+
except Exception as e:
|
|
362
|
+
raise Exception(
|
|
363
|
+
f'Could not get dropdown option values for label "{dropdown_label}": {str(e)}'
|
|
364
|
+
)
|
|
365
|
+
|
|
366
|
+
@staticmethod
|
|
367
|
+
def waitForDropdownValuesToBeChanged(
|
|
368
|
+
wait: WebDriverWait,
|
|
369
|
+
dropdown_label: str,
|
|
370
|
+
initial_values: list[str],
|
|
371
|
+
poll_frequency: float = 0.5,
|
|
372
|
+
timeout: int = 2,
|
|
373
|
+
):
|
|
374
|
+
|
|
375
|
+
elapsed_time = 0
|
|
376
|
+
poll_frequency = 0.5
|
|
377
|
+
timeout = 4 # seconds
|
|
378
|
+
while elapsed_time < timeout:
|
|
379
|
+
|
|
380
|
+
current_values: list[str] = DropdownUtils.getDropdownOptionValues(
|
|
381
|
+
wait, dropdown_label
|
|
382
|
+
)
|
|
383
|
+
|
|
384
|
+
# Compare job series values before and after position job title selection
|
|
385
|
+
if initial_values != current_values:
|
|
386
|
+
break
|
|
387
|
+
time.sleep(poll_frequency)
|
|
388
|
+
elapsed_time += poll_frequency
|