robo_appian 0.0.8__tar.gz → 0.0.10__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 (22) hide show
  1. {robo_appian-0.0.8 → robo_appian-0.0.10}/PKG-INFO +1 -1
  2. {robo_appian-0.0.8 → robo_appian-0.0.10}/pyproject.toml +1 -1
  3. {robo_appian-0.0.8 → robo_appian-0.0.10}/robo_appian/components/ButtonUtils.py +24 -4
  4. {robo_appian-0.0.8 → robo_appian-0.0.10}/robo_appian/components/DateUtils.py +23 -8
  5. {robo_appian-0.0.8 → robo_appian-0.0.10}/robo_appian/components/DropdownUtils.py +59 -18
  6. {robo_appian-0.0.8 → robo_appian-0.0.10}/robo_appian/components/InputUtils.py +28 -13
  7. {robo_appian-0.0.8 → robo_appian-0.0.10}/robo_appian/components/LabelUtils.py +11 -2
  8. {robo_appian-0.0.8 → robo_appian-0.0.10}/robo_appian/components/LinkUtils.py +11 -6
  9. {robo_appian-0.0.8 → robo_appian-0.0.10}/robo_appian/components/SearchInputUtils.py +12 -5
  10. {robo_appian-0.0.8 → robo_appian-0.0.10}/robo_appian/components/TabUtils.py +18 -8
  11. robo_appian-0.0.10/robo_appian/components/TableUtils.py +157 -0
  12. {robo_appian-0.0.8 → robo_appian-0.0.10}/robo_appian/controllers/ComponentDriver.py +4 -4
  13. {robo_appian-0.0.8 → robo_appian-0.0.10}/robo_appian/utils/ComponentUtils.py +1 -1
  14. robo_appian-0.0.8/robo_appian/components/TableUtils.py +0 -194
  15. {robo_appian-0.0.8 → robo_appian-0.0.10}/LICENSE +0 -0
  16. {robo_appian-0.0.8 → robo_appian-0.0.10}/README.md +0 -0
  17. {robo_appian-0.0.8 → robo_appian-0.0.10}/robo_appian/__init__.py +0 -0
  18. {robo_appian-0.0.8 → robo_appian-0.0.10}/robo_appian/components/__init__.py +0 -0
  19. {robo_appian-0.0.8 → robo_appian-0.0.10}/robo_appian/controllers/__init__.py +0 -0
  20. {robo_appian-0.0.8 → robo_appian-0.0.10}/robo_appian/exceptions/MyCustomError.py +0 -0
  21. {robo_appian-0.0.8 → robo_appian-0.0.10}/robo_appian/exceptions/__init__.py +0 -0
  22. {robo_appian-0.0.8 → robo_appian-0.0.10}/robo_appian/utils/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: robo_appian
3
- Version: 0.0.8
3
+ Version: 0.0.10
4
4
  Summary: Automate your Appian code testing with Python. Boost quality, save time.
5
5
  Author: Dinil Mithra
6
6
  Author-email: dinilmithra@mailme@gmail.com
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "robo_appian"
3
- version = "0.0.8"
3
+ version = "0.0.10"
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,7 +1,7 @@
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.webdriver import WebDriver
4
+
5
5
 
6
6
  class ButtonUtils:
7
7
  """
@@ -37,7 +37,16 @@ class ButtonUtils:
37
37
  # This method locates a button that contains a span with the specified label text.
38
38
 
39
39
  xpath = f".//button[./span[contains(translate(normalize-space(.), '\u00a0', ' '), '{label}')]]"
40
- component = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
40
+ try:
41
+ component = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
42
+ except TimeoutError as e:
43
+ raise TimeoutError(
44
+ f"Button with label '{label}' not found or not clickable."
45
+ ) from e
46
+ except Exception as e:
47
+ raise RuntimeError(
48
+ f"Button with label '{label}' not found or not clickable."
49
+ ) from e
41
50
  return component
42
51
 
43
52
  @staticmethod
@@ -54,6 +63,7 @@ class ButtonUtils:
54
63
  """
55
64
  component = ButtonUtils.find(wait, label)
56
65
  component.click()
66
+
57
67
  @staticmethod
58
68
  def clickInputButtonById(wait: WebDriverWait, id: str):
59
69
  """
@@ -67,5 +77,15 @@ class ButtonUtils:
67
77
  ButtonUtils.clickInputButtonById(wait, "button_id")
68
78
 
69
79
  """
70
- component = wait.until(EC.element_to_be_clickable((By.ID, id)))
71
- component.click()
80
+ try:
81
+ component = wait.until(EC.element_to_be_clickable((By.ID, id)))
82
+ except TimeoutError as e:
83
+ raise TimeoutError(
84
+ f"Input button with id '{id}' not found or not clickable."
85
+ ) from e
86
+ except Exception as e:
87
+ raise RuntimeError(
88
+ f"Input button with id '{id}' not found or not clickable."
89
+ ) from e
90
+
91
+ component.click()
@@ -1,7 +1,6 @@
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.webdriver import WebDriver
5
4
  from selenium.webdriver.remote.webelement import WebElement
6
5
 
7
6
  from robo_appian.components.InputUtils import InputUtils
@@ -37,11 +36,18 @@ class DateUtils:
37
36
  """
38
37
 
39
38
  xpath = f".//div/label[text()='{label}']"
40
- component: WebElement = wait.until(
41
- EC.element_to_be_clickable((By.XPATH, xpath))
42
- )
43
- if not component:
44
- raise ValueError(f"Could not find date component with label '{label}'.")
39
+ try:
40
+ component: WebElement = wait.until(
41
+ EC.element_to_be_clickable((By.XPATH, xpath))
42
+ )
43
+ except TimeoutError as e:
44
+ raise TimeoutError(
45
+ f"Could not find clickable date component with label '{label}': {e}"
46
+ )
47
+ except Exception as e:
48
+ raise Exception(
49
+ f"Could not find clickable date component with label '{label}': {e}"
50
+ )
45
51
 
46
52
  attribute: str = "for"
47
53
  component_id = component.get_attribute(attribute) # type: ignore[reportUnknownMemberType]
@@ -50,7 +56,16 @@ class DateUtils:
50
56
  f"Could not find component using {attribute} attribute for label '{label}'."
51
57
  )
52
58
 
53
- component = wait.until(EC.element_to_be_clickable((By.ID, component_id)))
59
+ try:
60
+ component = wait.until(EC.element_to_be_clickable((By.ID, component_id)))
61
+ except TimeoutError as e:
62
+ raise TimeoutError(
63
+ f"Could not find clickable date input with id '{component_id}': {e}"
64
+ )
65
+ except Exception as e:
66
+ raise Exception(
67
+ f"Could not find clickable date input with id '{component_id}': {e}"
68
+ )
54
69
  return component
55
70
 
56
71
  @staticmethod
@@ -101,7 +116,7 @@ class DateUtils:
101
116
  # It sets the value of the input element and submits it.
102
117
 
103
118
  component = DateUtils.findComponent(wait, label)
104
- InputUtils.setValueAndSubmitUsingComponent(component, value)
119
+ InputUtils.setValueAndSubmitByComponent(component, value)
105
120
 
106
121
  return component
107
122
 
@@ -1,9 +1,6 @@
1
- import stat
2
- from turtle import st
3
1
  from selenium.webdriver.common.by import By
4
2
  from selenium.webdriver.support import expected_conditions as EC
5
3
  from selenium.webdriver.support.ui import WebDriverWait
6
- from selenium.webdriver.remote.webdriver import WebDriver
7
4
  from selenium.webdriver.remote.webelement import WebElement
8
5
 
9
6
  from robo_appian.components.InputUtils import InputUtils
@@ -26,10 +23,18 @@ class DropdownUtils:
26
23
 
27
24
  @staticmethod
28
25
  def __findDropdownComponentsByXpath(wait: WebDriverWait, xpath: str):
29
-
30
26
  try:
31
27
  # Wait for at least one element to be present
32
- wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
28
+ try:
29
+ wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
30
+ except TimeoutError as e:
31
+ raise TimeoutError(
32
+ f'No clickable dropdown component found for xpath "{xpath}": {str(e)}'
33
+ )
34
+ except Exception as e:
35
+ raise Exception(
36
+ f'No clickable dropdown component found for xpath "{xpath}": {str(e)}'
37
+ )
33
38
 
34
39
  # Find all matching elements
35
40
  driver = wait._driver
@@ -59,12 +64,23 @@ class DropdownUtils:
59
64
 
60
65
  @staticmethod
61
66
  def selectDropdownValueByComponent(wait, combobox, value):
62
- dropdown_id = combobox.get_attribute("aria-controls") # type: ignore[reportUnknownMemberType]
67
+ dropdown_id = combobox.get_attribute("aria-controls")
63
68
  combobox.click()
64
69
 
65
70
  option_xpath = f'.//div/ul[@id="{dropdown_id}"]/li[./div[normalize-space(text())="{value}"]]'
66
- component = wait.until(EC.presence_of_element_located((By.XPATH, option_xpath)))
67
- component = wait.until(EC.element_to_be_clickable((By.XPATH, option_xpath)))
71
+ try:
72
+ component = wait.until(
73
+ EC.presence_of_element_located((By.XPATH, option_xpath))
74
+ )
75
+ component = wait.until(EC.element_to_be_clickable((By.XPATH, option_xpath)))
76
+ except TimeoutError as e:
77
+ raise TimeoutError(
78
+ f'Could not find or click dropdown option "{value}" with xpath "{option_xpath}": {str(e)}'
79
+ )
80
+ except Exception as e:
81
+ raise Exception(
82
+ f'Could not find or click dropdown option "{value}" with xpath "{option_xpath}": {str(e)}'
83
+ )
68
84
  component.click()
69
85
 
70
86
  @staticmethod
@@ -78,7 +94,6 @@ class DropdownUtils:
78
94
  def selectDropdownValueByLabelText(
79
95
  wait: WebDriverWait, dropdown_label: str, value: str
80
96
  ):
81
-
82
97
  xpath = f'.//div[./div/span[normalize-space(text())="{dropdown_label}"]]/div/div/div/div[@role="combobox" and @tabindex="0"]'
83
98
  DropdownUtils.__selectDropdownValueByXpath(wait, xpath, value)
84
99
 
@@ -86,13 +101,11 @@ class DropdownUtils:
86
101
  def selectDropdownValueByPartialLabelText(
87
102
  wait: WebDriverWait, dropdown_label: str, value: str
88
103
  ):
89
-
90
104
  xpath = f'.//div[./div/span[contains(normalize-space(text()), "{dropdown_label}")]]/div/div/div/div[@role="combobox" and @tabindex="0"]'
91
105
  DropdownUtils.__selectDropdownValueByXpath(wait, xpath, value)
92
106
 
93
107
  @staticmethod
94
108
  def __selectSearchDropdownValueByXpath(wait, xpath, value):
95
-
96
109
  components = DropdownUtils.__findDropdownComponentsByXpath(wait, xpath)
97
110
 
98
111
  for component in components:
@@ -102,13 +115,33 @@ class DropdownUtils:
102
115
  component.click()
103
116
 
104
117
  input_component_id = str(component_id) + "_searchInput"
105
- input_component = wait.until(
106
- EC.element_to_be_clickable((By.ID, input_component_id))
107
- )
118
+ try:
119
+ input_component = wait.until(
120
+ EC.element_to_be_clickable((By.ID, input_component_id))
121
+ )
122
+ except TimeoutError as e:
123
+ raise TimeoutError(
124
+ f'Could not find or click search input component with id "{input_component_id}": {str(e)}'
125
+ )
126
+ except Exception as e:
127
+ raise Exception(
128
+ f'Could not find or click search input component with id "{input_component_id}": {str(e)}'
129
+ )
108
130
  InputUtils._setComponentValue(input_component, value)
109
131
 
110
132
  xpath = f'.//ul[@id="{dropdown_id}"]/li[./div[normalize-space(text())="{value}"]][1]'
111
- component = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
133
+ try:
134
+ component = wait.until(
135
+ EC.element_to_be_clickable((By.XPATH, xpath))
136
+ )
137
+ except TimeoutError as e:
138
+ raise TimeoutError(
139
+ f'Could not find or click search dropdown option "{value}" with xpath "{xpath}": {str(e)}'
140
+ )
141
+ except Exception as e:
142
+ raise Exception(
143
+ f'Could not find or click search dropdown option "{value}" with xpath "{xpath}": {str(e)}'
144
+ )
112
145
  component.click()
113
146
 
114
147
  @staticmethod
@@ -122,7 +155,6 @@ class DropdownUtils:
122
155
  def selectSearchDropdownValueByPartialLabelText(
123
156
  wait: WebDriverWait, dropdown_label: str, value: str
124
157
  ):
125
-
126
158
  xpath = f'.//div[./div/span[contains(normalize-space(text()), "{dropdown_label}")]]/div/div/div/div[@role="combobox" and @tabindex="0"]'
127
159
  DropdownUtils.__selectSearchDropdownValueByXpath(wait, xpath, value)
128
160
 
@@ -130,7 +162,16 @@ class DropdownUtils:
130
162
  def selectValueByDropdownWrapperComponent(
131
163
  wait: WebDriverWait, component: WebElement, value: str
132
164
  ):
133
- xpath = f'./div/div[@role="combobox" and @tabindex="0"]'
134
- combobox = component.find_element(By.XPATH, xpath)
165
+ xpath = './div/div[@role="combobox" and @tabindex="0"]'
166
+ try:
167
+ combobox = component.find_element(By.XPATH, xpath)
168
+ except TimeoutError as e:
169
+ raise TimeoutError(
170
+ f'Could not find combobox element with xpath "{xpath}" in the provided component: {str(e)}'
171
+ )
172
+ except Exception as e:
173
+ raise Exception(
174
+ f'Could not find combobox element with xpath "{xpath}" in the provided component: {str(e)}'
175
+ )
135
176
  DropdownUtils.selectDropdownValueByComponent(wait, combobox, value)
136
177
  return combobox
@@ -1,12 +1,9 @@
1
- import stat
2
- from numpy import size
3
1
  from robo_appian.utils.ComponentUtils import ComponentUtils
4
2
  from selenium.webdriver.common.by import By
5
3
  from selenium.webdriver.common.keys import Keys
6
4
  from selenium.webdriver.support import expected_conditions as EC
7
5
  from selenium.webdriver.support.ui import WebDriverWait
8
6
  from selenium.webdriver.remote.webelement import WebElement
9
- from typing import List
10
7
 
11
8
 
12
9
  class InputUtils:
@@ -22,7 +19,7 @@ class InputUtils:
22
19
  """
23
20
 
24
21
  @staticmethod
25
- def setValueAndSubmitUsingComponent(component: WebElement, value: str):
22
+ def setValueAndSubmitByComponent(component: WebElement, value: str):
26
23
  """
27
24
  Sets a value in an input component and submits it using the provided component element.
28
25
 
@@ -34,7 +31,7 @@ class InputUtils:
34
31
  The Selenium WebElement for the input component after setting the value and submitting.
35
32
 
36
33
  Example:
37
- InputUtils.setValueAndSubmitUsingComponent(component, "test_user")
34
+ InputUtils.setValueAndSubmitByComponent(component, "test_user")
38
35
 
39
36
  """
40
37
  # This method assumes that the component is already found and passed as an argument.
@@ -49,29 +46,38 @@ class InputUtils:
49
46
  return component
50
47
 
51
48
  @staticmethod
52
- def __findInputComponentsByLabelPath(wait: WebDriverWait, xpath: str):
49
+ def __findInputComponentsByXpath(wait: WebDriverWait, xpath: str):
53
50
  label_components = ComponentUtils.findComponentsByXPath(wait, xpath)
54
51
  input_components = []
55
52
  for label_component in label_components:
56
53
  attribute: str = "for"
57
54
  component_id = label_component.get_attribute(attribute) # type: ignore[reportUnknownMemberType]
58
55
  if component_id:
59
- component = wait.until(
60
- EC.element_to_be_clickable((By.ID, component_id))
61
- )
62
- input_components.append(component)
56
+ try:
57
+ component = wait.until(
58
+ EC.element_to_be_clickable((By.ID, component_id))
59
+ )
60
+ input_components.append(component)
61
+ except TimeoutError as e:
62
+ raise TimeoutError(
63
+ f"Timeout or error finding input component with id '{component_id}': {e}"
64
+ )
65
+ except Exception as e:
66
+ raise Exception(
67
+ f"Timeout or error finding input component with id '{component_id}': {e}"
68
+ )
63
69
  return input_components
64
70
 
65
71
  @staticmethod
66
72
  def __findInputComponentsByPartialLabel(wait: WebDriverWait, label: str):
67
73
  xpath = f'.//div/label[contains(normalize-space(text()), "{label}")]'
68
- components = InputUtils.__findInputComponentsByLabelPath(wait, xpath)
74
+ components = InputUtils.__findInputComponentsByXpath(wait, xpath)
69
75
  return components
70
76
 
71
77
  @staticmethod
72
78
  def __findInputComponentsByLabel(wait: WebDriverWait, label: str):
73
79
  xpath = f'.//div/label[normalize-space(text())="{label}"]'
74
- components = InputUtils.__findInputComponentsByLabelPath(wait, xpath)
80
+ components = InputUtils.__findInputComponentsByXpath(wait, xpath)
75
81
  return components
76
82
 
77
83
  @staticmethod
@@ -109,6 +115,15 @@ class InputUtils:
109
115
 
110
116
  @staticmethod
111
117
  def setValueById(wait: WebDriverWait, component_id: str, value: str):
112
- component = wait.until(EC.element_to_be_clickable((By.ID, component_id)))
118
+ try:
119
+ component = wait.until(EC.element_to_be_clickable((By.ID, component_id)))
120
+ except TimeoutError as e:
121
+ raise TimeoutError(
122
+ f"Timeout or error finding input component with id '{component_id}': {e}"
123
+ )
124
+ except Exception as e:
125
+ raise Exception(
126
+ f"Timeout or error finding input component with id '{component_id}': {e}"
127
+ )
113
128
  InputUtils._setComponentValue(component, value)
114
129
  return component
@@ -1,7 +1,6 @@
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.webdriver import WebDriver
5
4
 
6
5
 
7
6
  class LabelUtils:
@@ -36,7 +35,17 @@ class LabelUtils:
36
35
  # It uses XPath to find the element that matches the text.
37
36
 
38
37
  xpath = f".//*[normalize-space(text())='{label}']"
39
- component = wait.until(EC.presence_of_element_located((By.XPATH, xpath)))
38
+ try:
39
+ component = wait.until(EC.presence_of_element_located((By.XPATH, xpath)))
40
+ except TimeoutError as e:
41
+ raise TimeoutError(
42
+ f"Label '{label}' not found within the timeout period."
43
+ ) from e
44
+ except Exception as e:
45
+ raise Exception(
46
+ f"Label '{label}' not found within the timeout period."
47
+ ) from e
48
+
40
49
  return component
41
50
 
42
51
  @staticmethod
@@ -1,11 +1,9 @@
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.webdriver import WebDriver
5
4
 
6
5
 
7
6
  class LinkUtils:
8
-
9
7
  """
10
8
  Utility class for interacting with link components in Appian UI.
11
9
 
@@ -16,15 +14,22 @@ class LinkUtils:
16
14
  LinkUtils.click(wait, "Learn More")
17
15
 
18
16
  """
17
+
19
18
  @staticmethod
20
19
  def find(wait: WebDriverWait, label: str):
21
20
  xpath = f'.//a[normalize-space(text())="{label}"]'
22
- component = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
21
+ try:
22
+ component = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
23
+ except TimeoutError as e:
24
+ raise TimeoutError(
25
+ f"Could not find clickable link with label '{label}': {e}"
26
+ )
27
+ except Exception as e:
28
+ raise Exception(f"Could not find clickable link with label '{label}': {e}")
23
29
  return component
24
30
 
25
31
  @staticmethod
26
32
  def click(wait: WebDriverWait, label: str):
27
-
28
33
  """
29
34
  Clicks a link identified by its label.
30
35
 
@@ -35,7 +40,7 @@ class LinkUtils:
35
40
  Example:
36
41
  LinkUtils.click(wait, "Learn More")
37
42
  """
38
-
39
- component = LinkUtils.find(wait. label)
43
+
44
+ component = LinkUtils.find(wait, label)
40
45
  component.click()
41
46
  return component
@@ -6,7 +6,6 @@ from robo_appian.utils.ComponentUtils import ComponentUtils
6
6
 
7
7
 
8
8
  class SearchInputUtils:
9
-
10
9
  @staticmethod
11
10
  def __findSearchInputComponentsByLabelPathAndSelectValue(
12
11
  wait: WebDriverWait, xpath: str, value: str
@@ -19,9 +18,18 @@ class SearchInputUtils:
19
18
  if dropdown_list_id:
20
19
  InputUtils._setComponentValue(search_input_component, value)
21
20
  xpath = f".//ul[@id='{dropdown_list_id}' and @role='listbox' ]/li[@role='option']/div/div/div/div/div/div/p[text()='{value}'][1]"
22
- drop_down_item = wait.until(
23
- EC.element_to_be_clickable((By.XPATH, xpath))
24
- )
21
+ try:
22
+ drop_down_item = wait.until(
23
+ EC.element_to_be_clickable((By.XPATH, xpath))
24
+ )
25
+ except TimeoutError as e:
26
+ raise TimeoutError(
27
+ f"Dropdown item with value '{value}' not found for component '{search_input_component.text}'."
28
+ ) from e
29
+ except Exception as e:
30
+ raise RuntimeError(
31
+ f"Dropdown item with value '{value}' not found for component '{search_input_component.text}'."
32
+ ) from e
25
33
  drop_down_item.click()
26
34
  else:
27
35
  raise ValueError(
@@ -52,7 +60,6 @@ class SearchInputUtils:
52
60
 
53
61
  @staticmethod
54
62
  def selectSearchDropdownByLabelText(wait: WebDriverWait, label: str, value: str):
55
-
56
63
  SearchInputUtils.__selectSearchInputComponentsByLabelText(wait, label, value)
57
64
 
58
65
  @staticmethod
@@ -10,15 +10,15 @@ class TabUtils:
10
10
 
11
11
  # Select a tab by its label
12
12
  from robo_appian.components.TabUtils import TabUtils
13
- TabUtils.select_tab(wait, "Settings")
13
+ TabUtils.selectInactiveTab(wait, "Settings")
14
14
 
15
15
  # Find the currently selected tab by its label
16
16
  from robo_appian.components.TabUtils import TabUtils
17
- selected_tab = TabUtils.find_selected_tab(wait, "Settings")
17
+ selected_tab = TabUtils.findSelectedTab(wait, "Settings")
18
18
  """
19
19
 
20
20
  @staticmethod
21
- def find_selected_tab(wait, label):
21
+ def findSelectedTab(wait, label):
22
22
  """
23
23
  Finds the currently selected tab by its label.
24
24
 
@@ -30,16 +30,21 @@ class TabUtils:
30
30
  The Selenium WebElement for the selected tab.
31
31
 
32
32
  Example:
33
- TabUtils.find_selected_tab(wait, "Settings")
33
+ TabUtils.findSelectedTab(wait, "Settings")
34
34
  """
35
35
  # This method locates a tab that is currently selected and contains the specified label.
36
36
 
37
37
  xpath = f".//div[./div[./div/div/div/div/div/p/strong[normalize-space(text())='{label}']]/span[text()='Selected Tab.']]/div[@role='link']"
38
- component = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
38
+ try:
39
+ component = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
40
+ except TimeoutError as e:
41
+ raise TimeoutError(f"Could not find selected tab with label '{label}': {e}")
42
+ except Exception as e:
43
+ raise RuntimeError(f"Could not find selected tab with label '{label}': {e}")
39
44
  return component
40
45
 
41
46
  @staticmethod
42
- def select_tab(wait, label):
47
+ def selectInactiveTab(wait, label):
43
48
  """
44
49
  Selects a tab by its label.
45
50
 
@@ -48,11 +53,16 @@ class TabUtils:
48
53
  label: The visible text label of the tab to select.
49
54
 
50
55
  Example:
51
- TabUtils.select_tab(wait, "Settings")
56
+ TabUtils.selectInactiveTab(wait, "Settings")
52
57
  """
53
58
  # This method locates a tab that contains a label with the specified text.
54
59
 
55
60
  xpath = f".//div[@role='link']/div/div/div/div/div[./p/span[text()='{label}']]"
56
61
  # xpath=f".//div[./div[./div/div/div/div/div/p/strong[normalize-space(text())='{label}']]/span[text()='Selected Tab.']]/div[@role='link']"
57
- component = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
62
+ try:
63
+ component = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
64
+ except TimeoutError as e:
65
+ raise TimeoutError(f"Could not find tab with label '{label}': {e}")
66
+ except Exception as e:
67
+ raise RuntimeError(f"Could not find tab with label '{label}': {e}")
58
68
  component.click()
@@ -0,0 +1,157 @@
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
+
6
+ class TableUtils:
7
+ """
8
+ Utility class for interacting with table components in Appian UI.
9
+
10
+ Usage Example:
11
+
12
+ # Find a table using a column name
13
+ from robo_appian.components.TableUtils import TableUtils
14
+ table = TableUtils.findTableByColumnName(wait, "Status")
15
+
16
+ """
17
+
18
+ @staticmethod
19
+ def findTableByColumnName(wait: WebDriverWait, columnName: str):
20
+ """
21
+ Finds a table component that contains a column with the specified name.
22
+
23
+ Parameters:
24
+ wait: Selenium WebDriverWait instance.
25
+ columnName: The name of the column to search for in the table.
26
+
27
+ Returns:
28
+ The Selenium WebElement for the table component.
29
+
30
+ Example:
31
+ table = TableUtils.findTableByColumnName(wait, "Status")
32
+
33
+ """
34
+ # This method locates a table that contains a header cell with the specified column name.
35
+ # It uses XPath to find the table element that has a header cell with the specified 'columnName'.
36
+ # The 'abbr' attribute is used to match the column name, which is a common practice in Appian UI tables.
37
+
38
+ # xpath = f".//table[./thead/tr/th[@abbr='{columnName}']]"
39
+ xpath = f'.//table[./thead/tr/th[@abbr="{columnName}"]]'
40
+ try:
41
+ component = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
42
+ except TimeoutError as e:
43
+ raise TimeoutError(
44
+ f"Could not find table with column name '{columnName}': {e}"
45
+ )
46
+ except Exception as e:
47
+ raise RuntimeError(
48
+ f"Could not find table with column name '{columnName}': {e}"
49
+ )
50
+ return component
51
+
52
+ @staticmethod
53
+ def rowCount(tableObject):
54
+ """
55
+ Returns the number of rows in a table, excluding empty grid messages.
56
+
57
+ Parameters:
58
+ tableObject: The Selenium WebElement representing the table.
59
+
60
+ Returns:
61
+ The number of rows in the table.
62
+
63
+ Example:
64
+ count = TableUtils.rowCount(table)
65
+
66
+ """
67
+ # This method counts the number of rows in a table by finding all the table row elements
68
+ # that do not have the 'data-empty-grid-message' attribute.
69
+
70
+ xpath = "./tbody/tr[./td[not (@data-empty-grid-message)]]"
71
+ rows = tableObject.find_elements(By.XPATH, xpath)
72
+ return len(rows)
73
+
74
+ @staticmethod
75
+ def findColumNumberByColumnName(tableObject, columnName):
76
+ """
77
+ Finds the column number in a table based on the column name.
78
+
79
+ Parameters:
80
+ tableObject: The Selenium WebElement representing the table.
81
+ columnName: The name of the column to find.
82
+
83
+ Returns:
84
+ The index of the column (0-based).
85
+
86
+ Example:
87
+ column_number = TableUtils.findColumNumberByColumnName(table, "Status")
88
+
89
+ """
90
+ # This method locates the column header cell with the specified column name
91
+ # and extracts the column index from its class attribute.
92
+
93
+ xpath = f'./thead/tr/th[@scope="col" and @abbr="{columnName}"]'
94
+ component = tableObject.find_element(By.XPATH, xpath)
95
+
96
+ if component is None:
97
+ raise ValueError(
98
+ f"Could not find a column with abbr '{columnName}' in the table header."
99
+ )
100
+
101
+ class_string = component.get_attribute("class")
102
+ partial_string = "headCell_"
103
+ words = class_string.split()
104
+ selected_word = None
105
+
106
+ for word in words:
107
+ if partial_string in word:
108
+ selected_word = word
109
+
110
+ if selected_word is None:
111
+ raise ValueError(
112
+ f"Could not find a class containing '{partial_string}' in the column header for '{columnName}'."
113
+ )
114
+
115
+ data = selected_word.split("_")
116
+ return int(data[1])
117
+
118
+ @staticmethod
119
+ def findComponentFromTableCell(wait, rowNumber, columnName):
120
+ """
121
+ Finds a component within a specific table cell based on the row number and column name.
122
+
123
+ Parameters:
124
+ wait: Selenium WebDriverWait instance.
125
+ rowNumber: The row number (0-based index) where the component is located.
126
+ columnName: The name of the column where the component is located.
127
+
128
+ Returns:
129
+ The Selenium WebElement for the component within the specified table cell.
130
+
131
+ Example:
132
+ component = TableUtils.findComponentFromTableCell(wait, 2, "Status")
133
+
134
+ """
135
+ # This method locates a specific component within a table cell based on the provided row number
136
+ # and column name. It constructs an XPath that targets the table cell containing the specified column
137
+ # and row, and then retrieves the component within that cell.
138
+
139
+ tableObject = TableUtils.findTableByColumnName(wait, columnName)
140
+ columnNumber = TableUtils.findColumNumberByColumnName(tableObject, columnName)
141
+ # xpath=f'./tbody/tr[@data-dnd-name="row {rowNumber+1}"]/td[not (@data-empty-grid-message)][{columnNumber}]'
142
+ # component = tableObject.find_elements(By.XPATH, xpath)
143
+ rowNumber = rowNumber + 1
144
+ columnNumber = columnNumber + 1
145
+ xpath = f'.//table[./thead/tr/th[@abbr="{columnName}"]]/tbody/tr[@data-dnd-name="row {rowNumber}"]/td[not (@data-empty-grid-message)][{columnNumber}]/*'
146
+ try:
147
+ component = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
148
+ except TimeoutError as e:
149
+ raise TimeoutError(
150
+ f"Could not find component in cell at row {rowNumber}, column '{columnName}': {e}"
151
+ )
152
+ except Exception as e:
153
+ raise RuntimeError(
154
+ f"Could not find component in cell at row {rowNumber}, column '{columnName}': {e}"
155
+ )
156
+ # childComponent=component.find_element(By.xpath("./*"))
157
+ return component
@@ -1,6 +1,5 @@
1
1
  from robo_appian.components.ButtonUtils import ButtonUtils
2
2
  from selenium.webdriver.support.ui import WebDriverWait
3
- from robo_appian.utils.ComponentUtils import ComponentUtils
4
3
  from robo_appian.components.DateUtils import DateUtils
5
4
  from robo_appian.components.DropdownUtils import DropdownUtils
6
5
  from robo_appian.components.InputUtils import InputUtils
@@ -35,7 +34,6 @@ class ComponentDriver:
35
34
  # This method executes an action on a specified component type based on the provided parameters.
36
35
 
37
36
  match type:
38
-
39
37
  case "Date":
40
38
  match action:
41
39
  case "Set Value":
@@ -77,7 +75,9 @@ class ComponentDriver:
77
75
  case "Search Drop Down":
78
76
  match action:
79
77
  case "Select":
80
- DropdownUtils.selectSearchDropdownValueByLabelText(wait, label, value)
78
+ DropdownUtils.selectSearchDropdownValueByLabelText(
79
+ wait, label, value
80
+ )
81
81
  case _:
82
82
  raise ValueError(f"Unsupported action for {type}: {action}")
83
83
  case "Button":
@@ -89,7 +89,7 @@ class ComponentDriver:
89
89
  case "Tab":
90
90
  match action:
91
91
  case "Find":
92
- TabUtils.find_selected_tab(wait, label)
92
+ TabUtils.findSelectedTab(wait, label)
93
93
  case _:
94
94
  raise ValueError(f"Unsupported action for {type}: {action}")
95
95
  case _:
@@ -203,7 +203,7 @@ class ComponentUtils:
203
203
  Raises:
204
204
  Exception: If no components are found.
205
205
  """
206
-
206
+
207
207
  # Wait for at least one element to be present
208
208
  wait.until(EC.presence_of_element_located((By.XPATH, xpath)))
209
209
 
@@ -1,194 +0,0 @@
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.webdriver import WebDriver
5
-
6
-
7
- class TableUtils:
8
- """
9
- Utility class for interacting with table components in Appian UI.
10
-
11
- Usage Example:
12
-
13
- # Find a table using a column name
14
- from robo_appian.components.TableUtils import TableUtils
15
- table = TableUtils.findTableUsingColumnName(wait, "Status")
16
-
17
- """
18
-
19
- @staticmethod
20
- def findTableUsingColumnName(wait: WebDriverWait, columnName: str):
21
- """
22
- Finds a table component that contains a column with the specified name.
23
-
24
- Parameters:
25
- wait: Selenium WebDriverWait instance.
26
- columnName: The name of the column to search for in the table.
27
-
28
- Returns:
29
- The Selenium WebElement for the table component.
30
-
31
- Example:
32
- table = TableUtils.findTableUsingColumnName(wait, "Status")
33
-
34
- """
35
- # This method locates a table that contains a header cell with the specified column name.
36
- # It uses XPath to find the table element that has a header cell with the specified 'columnName'.
37
- # The 'abbr' attribute is used to match the column name, which is a common practice in Appian UI tables.
38
-
39
- # xpath = f".//table[./thead/tr/th[@abbr='{columnName}']]"
40
- xpath = f'.//table[./thead/tr/th[@abbr="{columnName}"]]'
41
- component = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
42
- return component
43
-
44
- @staticmethod
45
- def clickOnLinkUsingHoverText(wait, columnName, rowNumber, hoverText):
46
- """
47
- Clicks on a link in a table cell identified by its column name, row number, and the hover text of the link.
48
-
49
- Parameters:
50
- wait: Selenium WebDriverWait instance.
51
- columnName: The name of the column where the link is located.
52
- rowNumber: The row number (0-based index) where the link is located.
53
- hoverText: The text that appears when hovering over the link.
54
-
55
- Example:
56
- TableUtils.clickOnLinkUsingHoverText(wait, "Status", 2, "View Details")
57
-
58
- """
59
-
60
- # This method locates a link within a specific table cell based on the column name and row number.
61
- # It constructs an XPath that targets the table cell containing the link with the specified hover text.
62
- # The XPath first identifies the table by the column name, then finds the specific row and cell,
63
- # and finally looks for the link with the specified hover text.
64
-
65
- xpath = f".//table[./thead/tr/th[@abbr='{columnName}']]/tbody/tr[@data-dnd-name='row {rowNumber + 1}']/td[not (@data-empty-grid-message)]/div/p/a[./span[text()='{hoverText}']]"
66
- # xpath=f".//table[./thead/tr/th/div[text()='{columnName}']][1]/tbody/tr[@data-dnd-name='row {rowNumber}']/td/div/p/a[./span[text()='{hoverText}']]"
67
- component = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
68
- component.click()
69
-
70
- @staticmethod
71
- def clickOnButtonUsingHoverText(wait, columnName, rowNumber, hoverText):
72
- """
73
- Clicks on a button in a table cell identified by its column name, row number, and the hover text of the button.
74
-
75
- Parameters:
76
- wait: Selenium WebDriverWait instance.
77
- columnName: The name of the column where the button is located.
78
- rowNumber: The row number (0-based index) where the button is located.
79
- hoverText: The text that appears when hovering over the button.
80
-
81
- Example:
82
- TableUtils.clickOnButtonUsingHoverText(wait, "Actions", 2, "Delete")
83
-
84
- """
85
- # This method locates a button within a specific table cell based on the column name and row number.
86
- # It constructs an XPath that targets the table cell containing the button with the specified hover text.
87
- # The XPath first identifies the table by the column name, then finds the specific row and cell,
88
- # and finally looks for the button with the specified hover text.
89
-
90
- # TODO rowNumber = rowNumber + 1 # Adjusting for 1-based index in XPath
91
-
92
- xpath = f".//table[./thead/tr/th[@abbr='{columnName}']]/tbody/tr[@data-dnd-name='row {rowNumber}']/td[not (@data-empty-grid-message)]"
93
- component = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
94
- component.click()
95
-
96
- xpath = f".//table[./thead/tr/th[@abbr='{columnName}']]/tbody/tr[@data-dnd-name='row {rowNumber}']/td[not (@data-empty-grid-message)]/div/div/button[./span[text()='{hoverText}']]"
97
- component = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
98
- component.click()
99
-
100
- @staticmethod
101
- def rowCount(tableObject):
102
- """
103
- Returns the number of rows in a table, excluding empty grid messages.
104
-
105
- Parameters:
106
- tableObject: The Selenium WebElement representing the table.
107
-
108
- Returns:
109
- The number of rows in the table.
110
-
111
- Example:
112
- count = TableUtils.rowCount(table)
113
-
114
- """
115
- # This method counts the number of rows in a table by finding all the table row elements
116
- # that do not have the 'data-empty-grid-message' attribute.
117
-
118
- xpath = "./tbody/tr[./td[not (@data-empty-grid-message)]]"
119
- rows = tableObject.find_elements(By.XPATH, xpath)
120
- return len(rows)
121
-
122
- @staticmethod
123
- def findColumNumberUsingColumnName(tableObject, columnName):
124
- """
125
- Finds the column number in a table based on the column name.
126
-
127
- Parameters:
128
- tableObject: The Selenium WebElement representing the table.
129
- columnName: The name of the column to find.
130
-
131
- Returns:
132
- The index of the column (0-based).
133
-
134
- Example:
135
- column_number = TableUtils.findColumNumberUsingColumnName(table, "Status")
136
-
137
- """
138
- # This method locates the column header cell with the specified column name
139
- # and extracts the column index from its class attribute.
140
-
141
- xpath = f'./thead/tr/th[@scope="col" and @abbr="{columnName}"]'
142
- component = tableObject.find_element(By.XPATH, xpath)
143
-
144
- if component is None:
145
- raise ValueError(f"Could not find a column with abbr '{columnName}' in the table header.")
146
-
147
- class_string = component.get_attribute("class")
148
- partial_string = "headCell_"
149
- words = class_string.split()
150
- selected_word = None
151
-
152
- for word in words:
153
- if partial_string in word:
154
- selected_word = word
155
-
156
- if selected_word is None:
157
- raise ValueError(f"Could not find a class containing '{partial_string}' in the column header for '{columnName}'.")
158
-
159
- data = selected_word.split("_")
160
- return int(data[1])
161
-
162
- @staticmethod
163
- def find_component_from_tabele_cell(wait, rowNumber, columnName):
164
- """
165
- Finds a component within a specific table cell based on the row number and column name.
166
-
167
- Parameters:
168
- wait: Selenium WebDriverWait instance.
169
- rowNumber: The row number (0-based index) where the component is located.
170
- columnName: The name of the column where the component is located.
171
-
172
- Returns:
173
- The Selenium WebElement for the component within the specified table cell.
174
-
175
- Example:
176
- component = TableUtils.find_component_from_tabele_cell(wait, 2, "Status")
177
-
178
- """
179
- # This method locates a specific component within a table cell based on the provided row number
180
- # and column name. It constructs an XPath that targets the table cell containing the specified column
181
- # and row, and then retrieves the component within that cell.
182
-
183
- tableObject = TableUtils.findTableUsingColumnName(wait, columnName)
184
- columnNumber = TableUtils.findColumNumberUsingColumnName(
185
- tableObject, columnName
186
- )
187
- # xpath=f'./tbody/tr[@data-dnd-name="row {rowNumber+1}"]/td[not (@data-empty-grid-message)][{columnNumber}]'
188
- # component = tableObject.find_elements(By.XPATH, xpath)
189
- rowNumber = rowNumber + 1
190
- columnNumber = columnNumber + 1
191
- xpath = f'.//table[./thead/tr/th[@abbr="{columnName}"]]/tbody/tr[@data-dnd-name="row {rowNumber}"]/td[not (@data-empty-grid-message)][{columnNumber}]/*'
192
- component = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
193
- # childComponent=component.find_element(By.xpath("./*"))
194
- return component
File without changes
File without changes