robo_appian 0.0.20__tar.gz → 0.0.22__tar.gz

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.

Potentially problematic release.


This version of robo_appian might be problematic. Click here for more details.

Files changed (23) hide show
  1. {robo_appian-0.0.20 → robo_appian-0.0.22}/PKG-INFO +4 -2
  2. {robo_appian-0.0.20 → robo_appian-0.0.22}/pyproject.toml +1 -1
  3. {robo_appian-0.0.20 → robo_appian-0.0.22}/robo_appian/components/DropdownUtils.py +97 -20
  4. robo_appian-0.0.22/robo_appian/utils/BrowserUtils.py +52 -0
  5. {robo_appian-0.0.20 → robo_appian-0.0.22}/robo_appian/utils/ComponentUtils.py +12 -1
  6. {robo_appian-0.0.20 → robo_appian-0.0.22}/LICENSE +0 -0
  7. {robo_appian-0.0.20 → robo_appian-0.0.22}/README.md +0 -0
  8. {robo_appian-0.0.20 → robo_appian-0.0.22}/robo_appian/__init__.py +0 -0
  9. {robo_appian-0.0.20 → robo_appian-0.0.22}/robo_appian/components/ButtonUtils.py +0 -0
  10. {robo_appian-0.0.20 → robo_appian-0.0.22}/robo_appian/components/DateUtils.py +0 -0
  11. {robo_appian-0.0.20 → robo_appian-0.0.22}/robo_appian/components/InputUtils.py +0 -0
  12. {robo_appian-0.0.20 → robo_appian-0.0.22}/robo_appian/components/LabelUtils.py +0 -0
  13. {robo_appian-0.0.20 → robo_appian-0.0.22}/robo_appian/components/LinkUtils.py +0 -0
  14. {robo_appian-0.0.20 → robo_appian-0.0.22}/robo_appian/components/SearchDropdownUtils.py +0 -0
  15. {robo_appian-0.0.20 → robo_appian-0.0.22}/robo_appian/components/SearchInputUtils.py +0 -0
  16. {robo_appian-0.0.20 → robo_appian-0.0.22}/robo_appian/components/TabUtils.py +0 -0
  17. {robo_appian-0.0.20 → robo_appian-0.0.22}/robo_appian/components/TableUtils.py +0 -0
  18. {robo_appian-0.0.20 → robo_appian-0.0.22}/robo_appian/components/__init__.py +0 -0
  19. {robo_appian-0.0.20 → robo_appian-0.0.22}/robo_appian/controllers/ComponentDriver.py +0 -0
  20. {robo_appian-0.0.20 → robo_appian-0.0.22}/robo_appian/controllers/__init__.py +0 -0
  21. {robo_appian-0.0.20 → robo_appian-0.0.22}/robo_appian/exceptions/MyCustomError.py +0 -0
  22. {robo_appian-0.0.20 → robo_appian-0.0.22}/robo_appian/exceptions/__init__.py +0 -0
  23. {robo_appian-0.0.20 → robo_appian-0.0.22}/robo_appian/utils/__init__.py +0 -0
@@ -1,7 +1,8 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: robo_appian
3
- Version: 0.0.20
3
+ Version: 0.0.22
4
4
  Summary: Automate your Appian code testing with Python. Boost quality, save time.
5
+ License-File: LICENSE
5
6
  Author: Dinil Mithra
6
7
  Author-email: dinilmithra@mailme@gmail.com
7
8
  Requires-Python: >=3.12,<4.0
@@ -9,6 +10,7 @@ Classifier: Operating System :: OS Independent
9
10
  Classifier: Programming Language :: Python :: 3
10
11
  Classifier: Programming Language :: Python :: 3.12
11
12
  Classifier: Programming Language :: Python :: 3.13
13
+ Classifier: Programming Language :: Python :: 3.14
12
14
  Requires-Dist: numpy
13
15
  Requires-Dist: requests (>=2.25.1,<3.0.0)
14
16
  Requires-Dist: selenium (>=4.34.0)
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "robo_appian"
3
- version = "0.0.20"
3
+ version = "0.0.22"
4
4
  description = "Automate your Appian code testing with Python. Boost quality, save time."
5
5
  authors = ["Dinil Mithra <dinilmithra@mailme@gmail.com>"]
6
6
  readme = "README.md"
@@ -1,3 +1,4 @@
1
+ import time
1
2
  from selenium.webdriver.common.by import By
2
3
  from selenium.webdriver.support import expected_conditions as EC
3
4
  from selenium.webdriver.support.ui import WebDriverWait
@@ -29,7 +30,9 @@ class DropdownUtils:
29
30
  try:
30
31
  component = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
31
32
  except Exception as e:
32
- raise Exception(f'Could not find combobox with partial label "{label}" : {str(e)}')
33
+ raise Exception(
34
+ f'Could not find combobox with partial label "{label}" : {str(e)}'
35
+ )
33
36
 
34
37
  return component
35
38
 
@@ -77,11 +80,15 @@ class DropdownUtils:
77
80
  """
78
81
  dropdown_option_id = combobox.get_attribute("aria-controls")
79
82
  if dropdown_option_id is None:
80
- raise Exception('Dropdown component does not have a valid "aria-controls" attribute.')
83
+ raise Exception(
84
+ 'Dropdown component does not have a valid "aria-controls" attribute.'
85
+ )
81
86
  return dropdown_option_id
82
87
 
83
88
  @staticmethod
84
- def __checkDropdownOptionValueExistsByDropdownOptionId(wait: WebDriverWait, dropdown_option_id: str, value: str):
89
+ def __checkDropdownOptionValueExistsByDropdownOptionId(
90
+ wait: WebDriverWait, dropdown_option_id: str, value: str
91
+ ):
85
92
  """
86
93
  Checks if a dropdown option value exists by its option id and value.
87
94
 
@@ -103,10 +110,14 @@ class DropdownUtils:
103
110
  except NoSuchElementException:
104
111
  return False
105
112
  except Exception as e:
106
- raise Exception(f'Could not find dropdown option "{value}" with dropdown option id "{dropdown_option_id}": {str(e)}')
113
+ raise Exception(
114
+ f'Could not find dropdown option "{value}" with dropdown option id "{dropdown_option_id}": {str(e)}'
115
+ )
107
116
 
108
117
  @staticmethod
109
- def __selectDropdownValueByDropdownOptionId(wait: WebDriverWait, dropdown_option_id: str, value: str):
118
+ def __selectDropdownValueByDropdownOptionId(
119
+ wait: WebDriverWait, dropdown_option_id: str, value: str
120
+ ):
110
121
  """
111
122
  Selects a value from a dropdown by its option id and value.
112
123
 
@@ -119,18 +130,26 @@ class DropdownUtils:
119
130
  option_xpath = f'.//div/ul[@id="{dropdown_option_id}"]/li[./div[normalize-space(.)="{value}"]]'
120
131
  try:
121
132
  try:
122
- component = wait.until(EC.presence_of_element_located((By.XPATH, option_xpath)))
123
- component = wait.until(EC.element_to_be_clickable((By.XPATH, option_xpath)))
133
+ component = wait.until(
134
+ EC.presence_of_element_located((By.XPATH, option_xpath))
135
+ )
136
+ component = wait.until(
137
+ EC.element_to_be_clickable((By.XPATH, option_xpath))
138
+ )
139
+ component.click()
124
140
  except Exception as e:
125
141
  raise Exception(
126
142
  f'Could not locate or click dropdown option "{value}" with dropdown option id "{dropdown_option_id}": {str(e)}' # noqa: E501
127
143
  )
128
144
  except Exception as e:
129
- raise Exception(f'Could not find or click dropdown option "{value}" with xpath "{option_xpath}": {str(e)}')
130
- component.click()
145
+ raise Exception(
146
+ f'Could not find or click dropdown option "{value}" with xpath "{option_xpath}": {str(e)}'
147
+ )
131
148
 
132
149
  @staticmethod
133
- def __selectDropdownValueByPartialLabelText(wait: WebDriverWait, label: str, value: str):
150
+ def __selectDropdownValueByPartialLabelText(
151
+ wait: WebDriverWait, label: str, value: str
152
+ ):
134
153
  """
135
154
  Selects a value from a dropdown by its label text.
136
155
 
@@ -141,7 +160,9 @@ class DropdownUtils:
141
160
  combobox = DropdownUtils.__findComboboxByPartialLabelText(wait, label)
142
161
  DropdownUtils.__clickCombobox(wait, combobox)
143
162
  dropdown_option_id = DropdownUtils.__findDropdownOptionId(wait, combobox)
144
- DropdownUtils.__selectDropdownValueByDropdownOptionId(wait, dropdown_option_id, value)
163
+ DropdownUtils.__selectDropdownValueByDropdownOptionId(
164
+ wait, dropdown_option_id, value
165
+ )
145
166
 
146
167
  @staticmethod
147
168
  def __selectDropdownValueByLabelText(wait: WebDriverWait, label: str, value: str):
@@ -155,7 +176,9 @@ class DropdownUtils:
155
176
  combobox = DropdownUtils.__findComboboxByLabelText(wait, label)
156
177
  DropdownUtils.__clickCombobox(wait, combobox)
157
178
  dropdown_option_id = DropdownUtils.__findDropdownOptionId(wait, combobox)
158
- DropdownUtils.__selectDropdownValueByDropdownOptionId(wait, dropdown_option_id, value)
179
+ DropdownUtils.__selectDropdownValueByDropdownOptionId(
180
+ wait, dropdown_option_id, value
181
+ )
159
182
 
160
183
  @staticmethod
161
184
  def checkReadOnlyStatusByLabelText(wait: WebDriverWait, label: str):
@@ -172,7 +195,8 @@ class DropdownUtils:
172
195
  else:
173
196
  print("The dropdown is editable.")
174
197
  """
175
- xpath = f'.//div[./div/span[normalize-space(.)="{label}"]]/div/div/p[text()]'
198
+ # xpath = f'.//div[./div/span[normalize-space(.)="{label}"]]/div/div/p[text()]'
199
+ xpath = f'//span[normalize-space(.)="{label}"]/ancestor::div[@role="presentation"]//div[@aria-labelledby=//span[normalize-space(.)="{label}"]/@id and not(@role="combobox")]'
176
200
  try:
177
201
  wait._driver.find_element(By.XPATH, xpath)
178
202
  return True
@@ -182,7 +206,48 @@ class DropdownUtils:
182
206
  raise Exception(f'Error checking read-only status for label "{label}"')
183
207
 
184
208
  @staticmethod
185
- def selectDropdownValueByComboboxComponent(wait: WebDriverWait, combobox: WebElement, value: str):
209
+ def checkEditableStatusByLabelText(wait: WebDriverWait, label: str):
210
+ """
211
+ Checks if a dropdown is editable (not disabled) by its label text.
212
+
213
+ :param wait: WebDriverWait instance to wait for elements.
214
+ :param label: The label of the dropdown.
215
+ :return: True if the dropdown is editable, False if disabled.
216
+ Example:
217
+ is_editable = DropdownUtils.checkEditableStatusByLabelText(wait, "Dropdown Label")
218
+ if is_editable:
219
+ print("The dropdown is editable.")
220
+ else:
221
+ print("The dropdown is disabled.")
222
+ """
223
+ xpath = f'//span[text()="{label}"]/ancestor::div[@role="presentation"]//div[@aria-labelledby=//span[normalize-space(.)="{label}"]/@id and @role="combobox" and not(@aria-disabled="true")]'
224
+ try:
225
+ wait._driver.find_element(By.XPATH, xpath)
226
+ return True # If disabled element is found, dropdown is not editable
227
+ except NoSuchElementException:
228
+ return False # If disabled element is not found, dropdown is editable
229
+ except Exception:
230
+ raise Exception(f'Error checking editable status for label "{label}"')
231
+
232
+ @staticmethod
233
+ def waitForDropdownToBeEnabled(
234
+ wait: WebDriverWait, label: str, wait_interval: float = 0.5, timeout: int = 2
235
+ ):
236
+ elapsed_time = 0
237
+ status = False
238
+
239
+ while elapsed_time < timeout:
240
+ status = DropdownUtils.checkEditableStatusByLabelText(wait, label)
241
+ if status:
242
+ return True
243
+ time.sleep(wait_interval)
244
+ elapsed_time += wait_interval
245
+ return False
246
+
247
+ @staticmethod
248
+ def selectDropdownValueByComboboxComponent(
249
+ wait: WebDriverWait, combobox: WebElement, value: str
250
+ ):
186
251
  """
187
252
  Selects a value from a dropdown using the combobox component.
188
253
 
@@ -194,10 +259,14 @@ class DropdownUtils:
194
259
  """
195
260
  dropdown_option_id = DropdownUtils.__findDropdownOptionId(wait, combobox)
196
261
  DropdownUtils.__clickCombobox(wait, combobox)
197
- DropdownUtils.__selectDropdownValueByDropdownOptionId(wait, dropdown_option_id, value)
262
+ DropdownUtils.__selectDropdownValueByDropdownOptionId(
263
+ wait, dropdown_option_id, value
264
+ )
198
265
 
199
266
  @staticmethod
200
- def selectDropdownValueByLabelText(wait: WebDriverWait, dropdown_label: str, value: str):
267
+ def selectDropdownValueByLabelText(
268
+ wait: WebDriverWait, dropdown_label: str, value: str
269
+ ):
201
270
  """
202
271
  Selects a value from a dropdown by its label text.
203
272
 
@@ -210,7 +279,9 @@ class DropdownUtils:
210
279
  DropdownUtils.__selectDropdownValueByLabelText(wait, dropdown_label, value)
211
280
 
212
281
  @staticmethod
213
- def selectDropdownValueByPartialLabelText(wait: WebDriverWait, dropdown_label: str, value: str):
282
+ def selectDropdownValueByPartialLabelText(
283
+ wait: WebDriverWait, dropdown_label: str, value: str
284
+ ):
214
285
  """
215
286
  Selects a value from a dropdown by its partial label text.
216
287
 
@@ -220,10 +291,14 @@ class DropdownUtils:
220
291
  Example:
221
292
  DropdownUtils.selectDropdownValueByPartialLabelText(wait, "Dropdown Label", "Option Value")
222
293
  """
223
- DropdownUtils.__selectDropdownValueByPartialLabelText(wait, dropdown_label, value)
294
+ DropdownUtils.__selectDropdownValueByPartialLabelText(
295
+ wait, dropdown_label, value
296
+ )
224
297
 
225
298
  @staticmethod
226
- def checkDropdownOptionValueExists(wait: WebDriverWait, dropdown_label: str, value: str):
299
+ def checkDropdownOptionValueExists(
300
+ wait: WebDriverWait, dropdown_label: str, value: str
301
+ ):
227
302
  """
228
303
  Checks if a dropdown option value exists by its label text.
229
304
 
@@ -241,4 +316,6 @@ class DropdownUtils:
241
316
  combobox = DropdownUtils.__findComboboxByLabelText(wait, dropdown_label)
242
317
  DropdownUtils.__clickCombobox(wait, combobox)
243
318
  dropdown_option_id = DropdownUtils.__findDropdownOptionId(wait, combobox)
244
- return DropdownUtils.__checkDropdownOptionValueExistsByDropdownOptionId(wait, dropdown_option_id, value)
319
+ return DropdownUtils.__checkDropdownOptionValueExistsByDropdownOptionId(
320
+ wait, dropdown_option_id, value
321
+ )
@@ -0,0 +1,52 @@
1
+ from selenium.webdriver.support.ui import WebDriverWait
2
+
3
+
4
+ class BrowserUtils:
5
+ @staticmethod
6
+ def switch_to_Tab(wait: WebDriverWait, tab_number):
7
+ """
8
+ Switches to the specified browser tab.
9
+
10
+ :param wait: WebDriverWait instance
11
+ :param tab_number: The index of the tab to switch to
12
+ :return: None
13
+ Example usage:
14
+ BrowserUtils.switch_to_Tab(wait, 1)
15
+ """
16
+
17
+ # Switch to the specified browser tab
18
+ handler = wait._driver.window_handles[tab_number]
19
+ wait._driver.switch_to.window(handler)
20
+
21
+ @staticmethod
22
+ def switch_to_next_tab(wait: WebDriverWait):
23
+ """
24
+ Switches to the next browser tab.
25
+
26
+ :param wait: WebDriverWait instance
27
+ :return: None
28
+ Example usage:
29
+ BrowserUtils.switch_to_next_tab(wait)
30
+ """
31
+ current_tab_index = wait._driver.window_handles.index(
32
+ wait._driver.current_window_handle
33
+ )
34
+ next_tab_index = (current_tab_index + 1) % len(wait._driver.window_handles)
35
+ BrowserUtils.switch_to_Tab(wait, next_tab_index)
36
+
37
+ @staticmethod
38
+ def close_current_tab_and_switch_back(wait: WebDriverWait):
39
+ """
40
+ Closes the current browser tab and switches back to the original tab.
41
+
42
+ :param wait: WebDriverWait instance
43
+ :return: None
44
+ Example usage:
45
+ BrowserUtils.close_current_tab_and_switch_back(wait)
46
+ """
47
+ current_tab_index = wait._driver.window_handles.index(
48
+ wait._driver.current_window_handle
49
+ )
50
+ wait._driver.close()
51
+ original_tab_index = (current_tab_index - 1) % len(wait._driver.window_handles)
52
+ BrowserUtils.switch_to_Tab(wait, original_tab_index)
@@ -238,4 +238,15 @@ class ComponentUtils:
238
238
  try:
239
239
  wait.until(EC.staleness_of(component))
240
240
  except Exception:
241
- raise Exception("Component did not become invisible (stale) within the timeout period.")
241
+ raise Exception("Component did not become invisible (stale) within the timeout period.")
242
+
243
+ @staticmethod
244
+ def isComponentPresentByXpath(wait: WebDriverWait, xpath: str):
245
+ status = False
246
+ try:
247
+ wait.until(EC.presence_of_element_located((By.XPATH, xpath)))
248
+ status = True
249
+ except NoSuchElementException:
250
+ pass
251
+
252
+ return status
File without changes
File without changes