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 CHANGED
@@ -1,5 +1,6 @@
1
- from robo_appian.components.ButtonUtils import ButtonUtils
1
+ from robo_appian.utils.RoboUtils import RoboUtils
2
2
  from robo_appian.utils.ComponentUtils import ComponentUtils
3
+ from robo_appian.components.ButtonUtils import ButtonUtils
3
4
  from robo_appian.components.DateUtils import DateUtils
4
5
  from robo_appian.components.DropdownUtils import DropdownUtils
5
6
  from robo_appian.components.InputUtils import InputUtils
@@ -15,6 +16,7 @@ __version__ = ComponentUtils.get_version()
15
16
 
16
17
  __all__ = [
17
18
  "ButtonUtils",
19
+ "RoboUtils",
18
20
  "ComponentUtils",
19
21
  "DateUtils",
20
22
  "DropdownUtils",
@@ -25,5 +27,5 @@ __all__ = [
25
27
  "TableUtils",
26
28
  "TabUtils",
27
29
  "BrowserUtils",
28
- "SearchInputUtils"
30
+ "SearchInputUtils",
29
31
  ]
@@ -1,23 +1,35 @@
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 selenium.webdriver.remote.webelement import WebElement
5
4
  from robo_appian.utils.ComponentUtils import ComponentUtils
6
5
 
7
6
 
8
7
  class ButtonUtils:
9
8
  """
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
9
+ Click buttons, action links, and control components using visible text labels.
10
+
11
+ Find and interact with buttons by their user-visible text. All methods automatically
12
+ handle whitespace variations and work reliably with overlaid or animated elements.
13
+
14
+ All methods follow the wait-first pattern: pass WebDriverWait as the first argument.
15
+
16
+ Examples:
17
+ >>> from robo_appian import ButtonUtils
18
+
19
+ # Click by exact label match
14
20
  ButtonUtils.clickByLabelText(wait, "Submit")
15
- """
21
+ ButtonUtils.clickByLabelText(wait, "Save Changes")
16
22
 
17
- @staticmethod
18
- def __click(wait: WebDriverWait, component: WebElement):
19
- wait.until(EC.element_to_be_clickable(component))
20
- component.click()
23
+ # Click by partial label match (useful for buttons with dynamic text)
24
+ ButtonUtils.clickByPartialLabelText(wait, "Save")
25
+
26
+ # Click by element ID (when labels are unavailable)
27
+ ButtonUtils.clickById(wait, "save_button_123")
28
+
29
+ # Check if button exists before clicking
30
+ if ButtonUtils.isButtonExistsByLabelText(wait, "Delete"):
31
+ ButtonUtils.clickByLabelText(wait, "Delete")
32
+ """
21
33
 
22
34
  @staticmethod
23
35
  def _findByPartialLabelText(wait: WebDriverWait, label: str):
@@ -27,7 +39,6 @@ class ButtonUtils:
27
39
  Parameters:
28
40
  wait: Selenium WebDriverWait instance.
29
41
  label: The label of the button to find.
30
- label: The label of the button to find.
31
42
 
32
43
  Returns:
33
44
  WebElement representing the button.
@@ -36,26 +47,17 @@ class ButtonUtils:
36
47
  component = ButtonUtils._findByPartialLabelText(wait, "Submit")
37
48
  """
38
49
  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
50
+ return ComponentUtils.waitForComponentToBeVisibleByXpath(wait, xpath)
46
51
 
47
52
  @staticmethod
48
53
  def __findByLabelText(wait: WebDriverWait, label: str):
49
54
  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
+ return ComponentUtils.waitForComponentToBeVisibleByXpath(wait, xpath)
55
56
 
56
57
  @staticmethod
57
58
  def clickByPartialLabelText(wait: WebDriverWait, label: str):
58
- """Finds a button by its partial label and clicks it.
59
+ """
60
+ Finds a button by its partial label and clicks it.
59
61
 
60
62
  Parameters:
61
63
  wait: Selenium WebDriverWait instance.
@@ -64,45 +66,73 @@ class ButtonUtils:
64
66
  ButtonUtils.clickByPartialLabelText(wait, "Button Label")
65
67
  """
66
68
  component = ButtonUtils._findByPartialLabelText(wait, label)
67
- ButtonUtils.__click(wait, component)
69
+
70
+ ComponentUtils.click(wait, component)
68
71
 
69
72
  @staticmethod
70
73
  def clickByLabelText(wait: WebDriverWait, label: str):
71
- """Finds a button by its label and clicks it.
74
+ """
75
+ Click a button by its exact label text.
72
76
 
73
- Parameters:
74
- wait: Selenium WebDriverWait instance.
75
- label: The label of the button to click.
76
- Example:
77
- ButtonUtils.clickByLabelText(wait, "Button Label")
77
+ Finds and clicks a button element containing the exact label text, handling whitespace
78
+ and NBSP characters reliably through normalized matching.
79
+
80
+ Args:
81
+ wait: WebDriverWait instance.
82
+ label: Exact button text (e.g., "Submit", "Save", "Cancel").
83
+
84
+ Raises:
85
+ TimeoutException: If button not found or not clickable within timeout.
86
+
87
+ Examples:
88
+ >>> ButtonUtils.clickByLabelText(wait, "Submit")
89
+ >>> ButtonUtils.clickByLabelText(wait, "Save Changes")
90
+ >>> ButtonUtils.clickByLabelText(wait, "Cancel")
78
91
  """
79
92
  component = ButtonUtils.__findByLabelText(wait, label)
80
- ButtonUtils.__click(wait, component)
93
+
94
+ ComponentUtils.click(wait, component)
81
95
 
82
96
  @staticmethod
83
97
  def clickById(wait: WebDriverWait, id: str):
84
- """
85
- Finds and clicks an input button by its HTML id attribute.
98
+ """Click a button by its HTML id attribute.
86
99
 
87
- Parameters:
88
- wait: Selenium WebDriverWait instance.
89
- id: The HTML id of the input button.
100
+ Finds and clicks a button using its HTML id. Use when label-based locators
101
+ are unavailable or unreliable.
90
102
 
91
- Example:
92
- ButtonUtils.clickById(wait, "button_id")
103
+ Args:
104
+ wait: WebDriverWait instance.
105
+ id: The HTML id of the button element.
93
106
 
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
107
+ Raises:
108
+ TimeoutException: If button not found or not clickable within timeout.
101
109
 
102
- ButtonUtils.__click(wait, component)
110
+ Examples:
111
+ >>> ButtonUtils.clickById(wait, "save_button")
112
+ >>> ButtonUtils.clickById(wait, "submit_btn_123")
113
+ """
114
+ component = wait.until(EC.element_to_be_clickable((By.ID, id)))
115
+ ComponentUtils.click(wait, component)
103
116
 
104
117
  @staticmethod
105
118
  def isButtonExistsByLabelText(wait: WebDriverWait, label: str):
119
+ """
120
+ Check if a button exists by exact label match.
121
+
122
+ Searches for a button with the exact label text and returns True if found.
123
+ Does not raise exceptions; returns boolean result.
124
+
125
+ Args:
126
+ wait: WebDriverWait instance.
127
+ label: Exact button label text to match.
128
+
129
+ Returns:
130
+ bool: True if button found, False otherwise.
131
+
132
+ Examples:
133
+ >>> if ButtonUtils.isButtonExistsByLabelText(wait, "Delete"):
134
+ ... ButtonUtils.clickByLabelText(wait, "Delete")
135
+ """
106
136
  xpath = f".//button[./span[normalize-space(.)='{label}']]"
107
137
  try:
108
138
  ComponentUtils.findComponentByXPath(wait, xpath)
@@ -112,6 +142,19 @@ class ButtonUtils:
112
142
 
113
143
  @staticmethod
114
144
  def isButtonExistsByPartialLabelText(wait: WebDriverWait, label: str):
145
+ """
146
+ Check if a button exists by partial label match.
147
+
148
+ Searches for a button containing the partial label text. Returns True if found, False otherwise.
149
+ Does not raise exceptions.
150
+
151
+ Args:
152
+ wait: WebDriverWait instance.
153
+ label: Partial button label text to match.
154
+
155
+ Returns:
156
+ bool: True if button found, False otherwise.
157
+ """
115
158
  xpath = f".//button[./span[contains(translate(normalize-space(.), '\u00a0', ' '), '{label}')]]"
116
159
  try:
117
160
  ComponentUtils.findComponentByXPath(wait, xpath)
@@ -121,17 +164,47 @@ class ButtonUtils:
121
164
 
122
165
  @staticmethod
123
166
  def isButtonExistsByPartialLabelTextAfterLoad(wait: WebDriverWait, label: str):
167
+ """
168
+ Check if a button exists by partial label match after page load.
169
+
170
+ Validates button presence after page reloads or dynamic content loading.
171
+ Returns True if found, False otherwise.
172
+
173
+ Args:
174
+ wait: WebDriverWait instance.
175
+ label: Partial button label text to match.
176
+
177
+ Returns:
178
+ bool: True if button found and visible, False otherwise.
179
+ """
180
+ xpath = f".//button[./span[contains(translate(normalize-space(.), '\u00a0', ' '), '{label}')]]"
124
181
  try:
125
- ButtonUtils._findByPartialLabelText(wait, label)
182
+ ComponentUtils.waitForComponentToBeVisibleByXpath(wait, xpath)
183
+ return True
126
184
  except Exception:
127
185
  return False
128
- return True
129
186
 
130
187
  @staticmethod
131
188
  def waitForButtonToBeVisibleByPartialLabelText(wait: WebDriverWait, label: str):
189
+ """
190
+ Wait for a button to be visible by partial label match.
191
+
192
+ Blocks until a button containing the partial label text becomes visible
193
+ or timeout occurs.
194
+
195
+ Args:
196
+ wait: WebDriverWait instance.
197
+ label: Partial button label text to match.
198
+
199
+ Returns:
200
+ WebElement: The visible button element.
201
+
202
+ Raises:
203
+ TimeoutException: If button not visible within timeout.
204
+
205
+ Examples:
206
+ >>> ButtonUtils.waitForButtonToBeVisibleByPartialLabelText(wait, "Submit")
207
+ >>> ButtonUtils.clickByPartialLabelText(wait, "Submit")
208
+ """
132
209
  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
210
+ return ComponentUtils.waitForComponentToBeVisibleByXpath(wait, xpath)
@@ -3,15 +3,37 @@ from selenium.webdriver.support import expected_conditions as EC
3
3
  from selenium.webdriver.support.ui import WebDriverWait
4
4
 
5
5
  from robo_appian.components.InputUtils import InputUtils
6
+ from robo_appian.utils.ComponentUtils import ComponentUtils
6
7
 
7
8
 
8
9
  class DateUtils:
9
10
  """
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")
11
+ Fill date picker components by label or interact with date input fields.
12
+
13
+ Set dates in Appian date picker components by their associated label. Handles both
14
+ text-based date entry and date picker interaction. Automatically waits for clickability
15
+ and formats dates according to Appian's expected format.
16
+
17
+ All methods follow the wait-first pattern: pass WebDriverWait as the first argument.
18
+
19
+ Examples:
20
+ >>> from robo_appian import DateUtils, ComponentUtils
21
+
22
+ # Set a date value
23
+ DateUtils.setValueByLabelText(wait, "Start Date", "01/15/2024")
24
+ DateUtils.setValueByLabelText(wait, "End Date", "12/31/2024")
25
+
26
+ # Use helper functions for common dates
27
+ DateUtils.setValueByLabelText(wait, "Today", ComponentUtils.today())
28
+ DateUtils.setValueByLabelText(wait, "Yesterday", ComponentUtils.yesterday())
29
+
30
+ # Click to open date picker
31
+ DateUtils.clickByLabelText(wait, "Event Date")
32
+
33
+ Note:
34
+ - Date format is typically MM/DD/YYYY for Appian
35
+ - Waits for clickability before interacting with date fields
36
+ - ComponentUtils.today() returns today's date as MM/DD/YYYY
15
37
  """
16
38
 
17
39
  @staticmethod
@@ -25,25 +47,36 @@ class DateUtils:
25
47
  DateUtils.__findComponent(wait, "Start Date")
26
48
  """
27
49
 
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
- )
50
+ xpath = f'.//div[./div/label[normalize-space(translate(., "\u00a0", " "))="{label}"]]/div/div/div/input'
51
+ component = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
35
52
  return component
36
53
 
37
54
  @staticmethod
38
55
  def setValueByLabelText(wait: WebDriverWait, label: str, value: str):
39
56
  """
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")
57
+ Set a date in a date picker component by label.
58
+
59
+ Finds the date input by its associated label, waits for clickability, clears any
60
+ existing date, and enters the new date value.
61
+
62
+ Args:
63
+ wait: WebDriverWait instance.
64
+ label: Exact label text of the date component (e.g., "Start Date").
65
+ value: Date string in MM/DD/YYYY format (e.g., "01/15/2024").
66
+
67
+ Returns:
68
+ WebElement: The date input component (for chaining if needed).
69
+
70
+ Raises:
71
+ ValueError: If label has no 'for' attribute.
72
+ TimeoutException: If date input not found or not clickable within timeout.
73
+
74
+ Examples:
75
+ >>> DateUtils.setValueByLabelText(wait, "Start Date", "01/15/2024")
76
+ >>> DateUtils.setValueByLabelText(wait, "End Date", "12/31/2024")
77
+ >>> # Using helper for today's date
78
+ >>> from robo_appian.utils.ComponentUtils import ComponentUtils
79
+ >>> DateUtils.setValueByLabelText(wait, "Date", ComponentUtils.today())
47
80
  """
48
81
  component = DateUtils.__findComponent(wait, label)
49
82
  InputUtils._setValueByComponent(wait, component, value)
@@ -60,5 +93,6 @@ class DateUtils:
60
93
  DateUtils.clickByLabelText(wait, "Start Date")
61
94
  """
62
95
  component = DateUtils.__findComponent(wait, label)
63
- component.click()
96
+
97
+ ComponentUtils.click(wait, component)
64
98
  return component
@@ -1,4 +1,5 @@
1
1
  import time
2
+ from robo_appian.utils.ComponentUtils import ComponentUtils
2
3
  from selenium.webdriver.common.by import By
3
4
  from selenium.webdriver.support import expected_conditions as EC
4
5
  from selenium.webdriver.support.ui import WebDriverWait
@@ -8,11 +9,10 @@ from selenium.common.exceptions import NoSuchElementException
8
9
 
9
10
  class DropdownUtils:
10
11
  """
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")
12
+ Utility class for interacting with dropdown components in a web application.
13
+ Provides methods to select values, check statuses, and retrieve options from dropdowns.
14
+ Example:
15
+ DropdownUtils.selectDropdownValueByLabelText(wait, "Dropdown Label", "Option Value")
16
16
  """
17
17
 
18
18
  @staticmethod
@@ -22,26 +22,20 @@ class DropdownUtils:
22
22
  """
23
23
  Finds the combobox element by its label text.
24
24
  :param wait: WebDriverWait instance to wait for elements.
25
- :param label: The label of the combobox.
25
+ :param label: The label of the dropdown.
26
26
  :param isPartialText: Whether to use partial text matching for the label.
27
27
  :return: The combobox WebElement.
28
28
  Example:
29
- combobox = DropdownUtils.__findComboboxByLabelText(wait, "Dropdown Label", isPartialText=False)
30
- combobox = DropdownUtils.__findComboboxByLabelText(wait, "Dropdown Label", isPartialText=True)
31
29
  combobox = DropdownUtils.__findComboboxByLabelText(wait, "Dropdown Label")
30
+ combobox = DropdownUtils.__findComboboxByLabelText(wait, "Dropdown Label", isPartialText=True)
32
31
  """
33
32
 
34
33
  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")]'
34
+ xpath = f'//span[contains(normalize-space(.), "{label}")]/ancestor::div[@role="presentation"][1]//div[@role="combobox" and not(@aria-disabled="true")]'
36
35
  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")]'
36
+ xpath = f'//span[text()="{label}"]/ancestor::div[@role="presentation"][1]//div[@role="combobox" and not(@aria-disabled="true")]'
38
37
 
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
38
+ return wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
45
39
 
46
40
  @staticmethod
47
41
  def __clickCombobox(wait: WebDriverWait, combobox: WebElement):
@@ -53,12 +47,11 @@ class DropdownUtils:
53
47
  Example:
54
48
  DropdownUtils.__clickCombobox(wait, combobox)
55
49
  """
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)}")
50
+ component_id = combobox.get_attribute("id")
51
+ if not component_id:
52
+ raise ValueError("Combobox element does not have an 'id' attribute.")
53
+ element = wait.until(EC.element_to_be_clickable((By.ID, component_id)))
54
+ ComponentUtils.click(wait, element)
62
55
 
63
56
  @staticmethod
64
57
  def __findDropdownOptionId(combobox: WebElement):
@@ -103,9 +96,7 @@ class DropdownUtils:
103
96
  except NoSuchElementException:
104
97
  return False
105
98
  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
- )
99
+ raise
109
100
 
110
101
  @staticmethod
111
102
  def __selectDropdownValueByDropdownOptionId(
@@ -113,31 +104,15 @@ class DropdownUtils:
113
104
  ):
114
105
  """
115
106
  Selects a value from a dropdown by its option id and value.
116
-
117
107
  :param wait: WebDriverWait instance to wait for elements.
118
108
  :param dropdown_option_id: The id of the dropdown options list.
119
109
  :param value: The value to select from the dropdown.
120
110
  Example:
121
- DropdownUtils.selectDropdownValueByDropdownOptionId(wait, "dropdown_option_id", "Option Value")
111
+ DropdownUtils.__selectDropdownValueByDropdownOptionId(wait, "dropdown_option_id", "Option Value")
122
112
  """
123
113
  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
- )
114
+ component = wait.until(EC.element_to_be_clickable((By.XPATH, option_xpath)))
115
+ component.click()
141
116
 
142
117
  @staticmethod
143
118
  def __selectDropdownValueByPartialLabelText(
@@ -176,27 +151,26 @@ class DropdownUtils:
176
151
  @staticmethod
177
152
  def checkReadOnlyStatusByLabelText(wait: WebDriverWait, label: str):
178
153
  """
179
- Checks if a dropdown is read-only by its label text.
180
-
154
+ Checks if a dropdown is read-only (disabled) by its label text.
181
155
  :param wait: WebDriverWait instance to wait for elements.
182
156
  :param label: The label of the dropdown.
183
- :return: True if the dropdown is read-only, False otherwise.
157
+ :return: True if the dropdown is read-only, False if editable.
184
158
  Example:
185
- is_read_only = DropdownUtils.checkReadOnlyStatusByLabelText(wait, "Dropdown Label")
186
- if is_read_only:
159
+ is_readonly = DropdownUtils.checkReadOnlyStatusByLabelText(wait, "Dropdown Label")
160
+ if is_readonly:
187
161
  print("The dropdown is read-only.")
188
162
  else:
189
163
  print("The dropdown is editable.")
190
164
  """
191
- # xpath = f'.//div[./div/span[normalize-space(.)="{label}"]]/div/div/p[text()]'
165
+ # xpath = f'.//div[./div/span[normalize-space(.)="{label}"]]/div/div/p[normalize-space(translate(., "\u00a0", " "))]'
192
166
  xpath = f'//span[normalize-space(.)="{label}"]/ancestor::div[@role="presentation"][1]//div[@aria-labelledby=//span[normalize-space(.)="{label}"]/@id and not(@role="combobox")]'
193
167
  try:
194
168
  wait._driver.find_element(By.XPATH, xpath)
195
169
  return True
196
170
  except NoSuchElementException:
197
171
  return False
198
- except Exception:
199
- raise Exception(f'Error checking read-only status for label "{label}"')
172
+ except Exception as e:
173
+ raise
200
174
 
201
175
  @staticmethod
202
176
  def checkEditableStatusByLabelText(wait: WebDriverWait, label: str):
@@ -213,21 +187,34 @@ class DropdownUtils:
213
187
  else:
214
188
  print("The dropdown is disabled.")
215
189
  """
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")]'
190
+ xpath = f'//span[normalize-space(translate(., "\u00a0", " "))="{label}"]/ancestor::div[@role="presentation"][1]//div[@aria-labelledby=//span[normalize-space(.)="{label}"]/@id and @role="combobox" and not(@aria-disabled="true")]'
217
191
  try:
218
192
  wait._driver.find_element(By.XPATH, xpath)
219
193
  return True # If disabled element is found, dropdown is not editable
220
194
  except NoSuchElementException:
221
195
  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}"')
196
+ except Exception as e:
197
+ raise
224
198
 
225
199
  @staticmethod
226
200
  def waitForDropdownToBeEnabled(
227
201
  wait: WebDriverWait, label: str, wait_interval: float = 0.5, timeout: int = 2
228
202
  ):
203
+ """
204
+ Waits for a dropdown to become enabled (editable) by its label text.
205
+ :param wait: WebDriverWait instance to wait for elements.
206
+ :param label: The label of the dropdown.
207
+ :param wait_interval: The interval (in seconds) to wait between checks.
208
+ :param timeout: The maximum time (in seconds) to wait for the dropdown to become enabled.
209
+ :return: True if the dropdown becomes enabled within the timeout, False otherwise.
210
+ Example:
211
+ is_enabled = DropdownUtils.waitForDropdownToBeEnabled(wait, "Dropdown Label")
212
+ if is_enabled:
213
+ print("The dropdown is enabled.")
214
+ else:
215
+ print("The dropdown is still disabled.")
216
+ """
229
217
  elapsed_time = 0
230
- status = False
231
218
 
232
219
  while elapsed_time < timeout:
233
220
  status = DropdownUtils.checkEditableStatusByLabelText(wait, label)
@@ -359,9 +346,7 @@ class DropdownUtils:
359
346
  DropdownUtils.__clickCombobox(wait, combobox)
360
347
  return option_texts
361
348
  except Exception as e:
362
- raise Exception(
363
- f'Could not get dropdown option values for label "{dropdown_label}": {str(e)}'
364
- )
349
+ raise
365
350
 
366
351
  @staticmethod
367
352
  def waitForDropdownValuesToBeChanged(
@@ -371,10 +356,25 @@ class DropdownUtils:
371
356
  poll_frequency: float = 0.5,
372
357
  timeout: int = 2,
373
358
  ):
359
+ """
360
+ Waits for the values of a dropdown to change from the initial values.
361
+
362
+ :param wait: WebDriverWait instance to wait for elements.
363
+ :param dropdown_label: The label of the dropdown.
364
+ :param initial_values: The initial values of the dropdown.
365
+ :param poll_frequency: The interval (in seconds) to wait between checks.
366
+ :param timeout: The maximum time (in seconds) to wait for the dropdown values to change.
367
+ :return: True if the dropdown values change within the timeout, False otherwise.
368
+ Example:
369
+ initial_values = DropdownUtils.getDropdownOptionValues(wait, "Dropdown Label")
370
+ is_changed = DropdownUtils.waitForDropdownValuesToBeChanged(wait, "Dropdown Label", initial_values)
371
+ if is_changed:
372
+ print("The dropdown values have changed.")
373
+ else:
374
+ print("The dropdown values have not changed within the timeout.")
375
+ """
374
376
 
375
377
  elapsed_time = 0
376
- poll_frequency = 0.5
377
- timeout = 4 # seconds
378
378
  while elapsed_time < timeout:
379
379
 
380
380
  current_values: list[str] = DropdownUtils.getDropdownOptionValues(