robo_appian 0.0.4__py3-none-any.whl → 0.0.5__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.

Potentially problematic release.


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

Files changed (41) hide show
  1. robo_appian/__init__.py +9 -9
  2. {robo_appian_source_backup/utils → robo_appian}/components/ButtonUtils.py +1 -1
  3. {robo_appian_source_backup/utils → robo_appian}/components/DateUtils.py +3 -3
  4. robo_appian/components/DropdownUtils.py +136 -0
  5. robo_appian/components/InputUtils.py +107 -0
  6. {robo_appian_source_backup/utils → robo_appian}/components/LabelUtils.py +1 -1
  7. {robo_appian_source_backup/utils → robo_appian}/components/LinkUtils.py +1 -1
  8. robo_appian/components/SearchInputUtils.py +64 -0
  9. {robo_appian_source_backup/utils → robo_appian}/components/TabUtils.py +2 -2
  10. {robo_appian_source_backup/utils → robo_appian}/components/TableUtils.py +8 -1
  11. {robo_appian_source_backup/utils → robo_appian}/controllers/ComponentDriver.py +18 -13
  12. {robo_appian_source_backup/utils/components → robo_appian/utils}/ComponentUtils.py +37 -100
  13. robo_appian/utils/__init__.py +0 -1
  14. {robo_appian-0.0.4.dist-info → robo_appian-0.0.5.dist-info}/METADATA +13 -36
  15. robo_appian-0.0.5.dist-info/RECORD +21 -0
  16. {robo_appian-0.0.4.dist-info → robo_appian-0.0.5.dist-info}/WHEEL +1 -2
  17. robo_appian/utils/components/ButtonUtils.pyc +0 -0
  18. robo_appian/utils/components/ComponentUtils.pyc +0 -0
  19. robo_appian/utils/components/DateUtils.pyc +0 -0
  20. robo_appian/utils/components/DropdownUtils.pyc +0 -0
  21. robo_appian/utils/components/InputUtils.pyc +0 -0
  22. robo_appian/utils/components/LabelUtils.pyc +0 -0
  23. robo_appian/utils/components/LinkUtils.pyc +0 -0
  24. robo_appian/utils/components/TabUtils.pyc +0 -0
  25. robo_appian/utils/components/TableUtils.pyc +0 -0
  26. robo_appian/utils/components/__init__.py +0 -1
  27. robo_appian/utils/controllers/ComponentDriver.pyc +0 -0
  28. robo_appian/utils/controllers/__init__.py +0 -1
  29. robo_appian/utils/exceptions/MyCustomError.pyc +0 -0
  30. robo_appian/utils/exceptions/__init__.py +0 -1
  31. robo_appian-0.0.4.dist-info/RECORD +0 -37
  32. robo_appian-0.0.4.dist-info/top_level.txt +0 -2
  33. robo_appian_source_backup/__init__.py +0 -23
  34. robo_appian_source_backup/utils/components/DropdownUtils.py +0 -141
  35. robo_appian_source_backup/utils/components/InputUtils.py +0 -193
  36. robo_appian_source_backup/utils/exceptions/__init__.py +0 -0
  37. {robo_appian_source_backup/utils → robo_appian/components}/__init__.py +0 -0
  38. {robo_appian_source_backup/utils/components → robo_appian/controllers}/__init__.py +0 -0
  39. {robo_appian_source_backup/utils → robo_appian}/exceptions/MyCustomError.py +0 -0
  40. {robo_appian_source_backup/utils/controllers → robo_appian/exceptions}/__init__.py +0 -0
  41. {robo_appian-0.0.4.dist-info/licenses → robo_appian-0.0.5.dist-info}/LICENSE +0 -0
robo_appian/__init__.py CHANGED
@@ -1,12 +1,12 @@
1
- from robo_appian.utils.components.ButtonUtils import ButtonUtils
2
- from robo_appian.utils.components.ComponentUtils import ComponentUtils
3
- from robo_appian.utils.components.DateUtils import DateUtils
4
- from robo_appian.utils.components.DropdownUtils import DropdownUtils
5
- from robo_appian.utils.components.InputUtils import InputUtils
6
- from robo_appian.utils.components.LabelUtils import LabelUtils
7
- from robo_appian.utils.components.LinkUtils import LinkUtils
8
- from robo_appian.utils.components.TableUtils import TableUtils
9
- from robo_appian.utils.components.TabUtils import TabUtils
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.TableUtils import TableUtils
9
+ from robo_appian.components.TabUtils import TabUtils
10
10
 
11
11
  __version__ = "0.0.2"
12
12
 
@@ -10,7 +10,7 @@ class ButtonUtils:
10
10
  Usage Example:
11
11
 
12
12
  from selenium.webdriver.support.ui import WebDriverWait
13
- from robo_appian.utils.components.ButtonUtils import ButtonUtils
13
+ from robo_appian.components.ButtonUtils import ButtonUtils
14
14
 
15
15
  wait = WebDriverWait(driver, 10)
16
16
  ButtonUtils.click(wait, "Login")
@@ -4,7 +4,7 @@ from selenium.webdriver.support.ui import WebDriverWait
4
4
  from selenium.webdriver.remote.webdriver import WebDriver
5
5
  from selenium.webdriver.remote.webelement import WebElement
6
6
 
7
- from robo_appian.utils.components.InputUtils import InputUtils
7
+ from robo_appian.components.InputUtils import InputUtils
8
8
 
9
9
 
10
10
  class DateUtils:
@@ -14,7 +14,7 @@ class DateUtils:
14
14
  Usage Example:
15
15
 
16
16
  # Set a date value
17
- from robo_appian.utils.components.DateUtils import DateUtils
17
+ from robo_appian.components.DateUtils import DateUtils
18
18
  DateUtils.setDateValue(wait, "Start Date", "01/01/2024")
19
19
 
20
20
  """
@@ -75,7 +75,7 @@ class DateUtils:
75
75
  # component = wait.until(EC.element_to_be_clickable((By.XPATH, f".//div/label[text()='{label}']/following-sibling::input")))
76
76
 
77
77
  component = DateUtils.findComponent(wait, label)
78
- InputUtils.setValueUsingComponent(component, value)
78
+ InputUtils._setComponentValue(component, value)
79
79
  return component
80
80
 
81
81
  @staticmethod
@@ -0,0 +1,136 @@
1
+ import stat
2
+ from turtle import st
3
+ from selenium.webdriver.common.by import By
4
+ from selenium.webdriver.support import expected_conditions as EC
5
+ from selenium.webdriver.support.ui import WebDriverWait
6
+ from selenium.webdriver.remote.webdriver import WebDriver
7
+ from selenium.webdriver.remote.webelement import WebElement
8
+
9
+ from robo_appian.components.InputUtils import InputUtils
10
+
11
+
12
+ class DropdownUtils:
13
+ """
14
+ Utility class for interacting with dropdown components in Appian UI.
15
+
16
+ Usage Example:
17
+
18
+ # Select a value from a dropdown
19
+ from robo_appian.components.DropdownUtils import DropdownUtils
20
+ DropdownUtils.selectDropdownValueByLabelText(wait, "Status", "Approved")
21
+
22
+ # Select a value from a search dropdown
23
+ from robo_appian.components.DropdownUtils import DropdownUtils
24
+ DropdownUtils.selectSearchDropdownValueByLabelText(wait, "Category", "Finance")
25
+ """
26
+
27
+ @staticmethod
28
+ def __findDropdownComponentsByXpath(wait: WebDriverWait, xpath: str):
29
+
30
+ try:
31
+ # Wait for at least one element to be present
32
+ wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
33
+
34
+ # Find all matching elements
35
+ driver = wait._driver
36
+ components = driver.find_elements(By.XPATH, xpath)
37
+
38
+ # Filter for clickable and displayed components
39
+ valid_components = []
40
+ for component in components:
41
+ try:
42
+ if component.is_displayed() and component.is_enabled():
43
+ valid_components.append(component)
44
+ except Exception:
45
+ continue
46
+
47
+ if not valid_components:
48
+ raise Exception(
49
+ f'No valid dropdown components with xpath "{xpath}" found.'
50
+ )
51
+
52
+ # Return single component if only one found, list if multiple
53
+ return valid_components
54
+
55
+ except Exception as e:
56
+ raise Exception(
57
+ f'Dropdown component with xpath "{xpath}" not found: {str(e)}'
58
+ )
59
+
60
+ @staticmethod
61
+ def selectDropdownValueByComponent(wait, combobox, value):
62
+ dropdown_id = combobox.get_attribute("aria-controls") # type: ignore[reportUnknownMemberType]
63
+ combobox.click()
64
+
65
+ 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)))
68
+ component.click()
69
+
70
+ @staticmethod
71
+ def __selectDropdownValueByXpath(wait, xpath, value):
72
+ components = DropdownUtils.__findDropdownComponentsByXpath(wait, xpath)
73
+ for combobox in components:
74
+ if combobox.is_displayed() and combobox.is_enabled():
75
+ DropdownUtils.selectDropdownValueByComponent(wait, combobox, value)
76
+
77
+ @staticmethod
78
+ def selectDropdownValueByLabelText(
79
+ wait: WebDriverWait, dropdown_label: str, value: str
80
+ ):
81
+
82
+ xpath = f'.//div[./div/span[normalize-space(text())="{dropdown_label}"]]/div/div/div/div[@role="combobox" and @tabindex="0"]'
83
+ DropdownUtils.__selectDropdownValueByXpath(wait, xpath, value)
84
+
85
+ @staticmethod
86
+ def selectDropdownValueByPartialLabelText(
87
+ wait: WebDriverWait, dropdown_label: str, value: str
88
+ ):
89
+
90
+ xpath = f'.//div[./div/span[contains(normalize-space(text()), "{dropdown_label}")]]/div/div/div/div[@role="combobox" and @tabindex="0"]'
91
+ DropdownUtils.__selectDropdownValueByXpath(wait, xpath, value)
92
+
93
+ @staticmethod
94
+ def __selectSearchDropdownValueByXpath(wait, xpath, value):
95
+
96
+ components = DropdownUtils.__findDropdownComponentsByXpath(wait, xpath)
97
+
98
+ for component in components:
99
+ if component.is_displayed() and component.is_enabled():
100
+ component_id = component.get_attribute("aria-labelledby") # type: ignore[reportUnknownMemberType]
101
+ dropdown_id = component.get_attribute("aria-controls") # type: ignore[reportUnknownMemberType]
102
+ component.click()
103
+
104
+ input_component_id = str(component_id) + "_searchInput"
105
+ input_component = wait.until(
106
+ EC.element_to_be_clickable((By.ID, input_component_id))
107
+ )
108
+ InputUtils._setComponentValue(input_component, value)
109
+
110
+ 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)))
112
+ component.click()
113
+
114
+ @staticmethod
115
+ def selectSearchDropdownValueByLabelText(
116
+ wait: WebDriverWait, dropdown_label: str, value: str
117
+ ):
118
+ xpath = f'.//div[./div/span[normalize-space(text())="{dropdown_label}"]]/div/div/div/div[@role="combobox" and @tabindex="0"]'
119
+ DropdownUtils.__selectSearchDropdownValueByXpath(wait, xpath, value)
120
+
121
+ @staticmethod
122
+ def selectSearchDropdownValueByPartialLabelText(
123
+ wait: WebDriverWait, dropdown_label: str, value: str
124
+ ):
125
+
126
+ xpath = f'.//div[./div/span[contains(normalize-space(text()), "{dropdown_label}")]]/div/div/div/div[@role="combobox" and @tabindex="0"]'
127
+ DropdownUtils.__selectSearchDropdownValueByXpath(wait, xpath, value)
128
+
129
+ @staticmethod
130
+ def selectValueByDropdownWrapperComponent(
131
+ wait: WebDriverWait, component: WebElement, value: str
132
+ ):
133
+ xpath = f'./div/div[@role="combobox" and @tabindex="0"]'
134
+ combobox = component.find_element(By.XPATH, xpath)
135
+ DropdownUtils.selectDropdownValueByComponent(wait, combobox, value)
136
+ return combobox
@@ -0,0 +1,107 @@
1
+ from numpy import size
2
+ from robo_appian.utils.ComponentUtils import ComponentUtils
3
+ from selenium.webdriver.common.by import By
4
+ from selenium.webdriver.common.keys import Keys
5
+ from selenium.webdriver.support import expected_conditions as EC
6
+ from selenium.webdriver.support.ui import WebDriverWait
7
+ from selenium.webdriver.remote.webelement import WebElement
8
+ from typing import List
9
+
10
+
11
+ class InputUtils:
12
+ """
13
+ Utility class for interacting with input components in Appian UI.
14
+
15
+ Usage Example:
16
+
17
+ # Set a value in an input field
18
+ from robo_appian.components.InputUtils import InputUtils
19
+ InputUtils.setValueByLabelText(wait, "Username", "test_user")
20
+
21
+ """
22
+
23
+ @staticmethod
24
+ def setValueAndSubmitUsingComponent(component: WebElement, value: str):
25
+ """
26
+ Sets a value in an input component and submits it using the provided component element.
27
+
28
+ Parameters:
29
+ component: The Selenium WebElement for the input component.
30
+ value: The value to set in the input field.
31
+
32
+ Returns:
33
+ The Selenium WebElement for the input component after setting the value and submitting.
34
+
35
+ Example:
36
+ InputUtils.setValueAndSubmitUsingComponent(component, "test_user")
37
+
38
+ """
39
+ # This method assumes that the component is already found and passed as an argument.
40
+
41
+ if not component.is_displayed():
42
+ raise Exception(
43
+ f"Component with label '{component.text}' is not displayed."
44
+ )
45
+
46
+ component = InputUtils._setComponentValue(component, value)
47
+ component.send_keys(Keys.ENTER)
48
+ return component
49
+
50
+ @staticmethod
51
+ def __findInputComponentsByLabelPath(wait: WebDriverWait, xpath: str):
52
+ label_components = ComponentUtils.findComponentsByXPath(wait, xpath)
53
+ input_components = []
54
+ for label_component in label_components:
55
+ attribute: str = "for"
56
+ component_id = label_component.get_attribute(attribute) # type: ignore[reportUnknownMemberType]
57
+ if component_id:
58
+ component = wait.until(
59
+ EC.element_to_be_clickable((By.ID, component_id))
60
+ )
61
+ input_components.append(component)
62
+ return input_components
63
+
64
+ @staticmethod
65
+ def __findInputComponentsByPartialLabel(wait: WebDriverWait, label: str):
66
+ xpath = f'.//div/label[contains(normalize-space(text()), "{label}")]'
67
+ components = InputUtils.__findInputComponentsByLabelPath(wait, xpath)
68
+ return components
69
+
70
+ @staticmethod
71
+ def __findInputComponentsByLabel(wait: WebDriverWait, label: str):
72
+ xpath = f'.//div/label[normalize-space(text())="{label}"]'
73
+ components = InputUtils.__findInputComponentsByLabelPath(wait, xpath)
74
+ return components
75
+
76
+ @staticmethod
77
+ def _setComponentValue(component: WebElement, value: str):
78
+ component.clear()
79
+ component.send_keys(value)
80
+ return component
81
+
82
+ @staticmethod
83
+ def __setValueByComponents(wait: WebDriverWait, input_components, value: str):
84
+ """
85
+ Sets a value in an input component identified by its label text.
86
+ Parameters:
87
+ wait: Selenium WebDriverWait instance.
88
+ label: The visible text label of the input component.
89
+ value: The value to set in the input field.
90
+ Returns:
91
+ None
92
+ Example:
93
+ InputUtils.setValueByLabelText(wait, "Username", "test_user")
94
+ """
95
+
96
+ for component in input_components:
97
+ InputUtils._setComponentValue(component, value)
98
+
99
+ @staticmethod
100
+ def setValueByPartialLabelText(wait: WebDriverWait, label: str, value: str):
101
+ input_components = InputUtils.__findInputComponentsByPartialLabel(wait, label)
102
+ InputUtils.__setValueByComponents(wait, input_components, value)
103
+
104
+ @staticmethod
105
+ def setValueByLabelText(wait: WebDriverWait, label: str, value: str):
106
+ input_components = InputUtils.__findInputComponentsByLabel(wait, label)
107
+ InputUtils.__setValueByComponents(wait, input_components, value)
@@ -11,7 +11,7 @@ class LabelUtils:
11
11
  Usage Example:
12
12
 
13
13
  # Find a label component
14
- from robo_appian.utils.components.LabelUtils import LabelUtils
14
+ from robo_appian.components.LabelUtils import LabelUtils
15
15
  label_component = LabelUtils.find(wait, "Username")
16
16
 
17
17
  """
@@ -12,7 +12,7 @@ class LinkUtils:
12
12
  Usage Example:
13
13
 
14
14
  # Click a link with a specific label
15
- from robo_appian.utils.components.LinkUtils import LinkUtils
15
+ from robo_appian.components.LinkUtils import LinkUtils
16
16
  LinkUtils.click(wait, "Learn More")
17
17
 
18
18
  """
@@ -0,0 +1,64 @@
1
+ from selenium.webdriver.support.ui import WebDriverWait
2
+ from selenium.webdriver.common.by import By
3
+ from selenium.webdriver.support import expected_conditions as EC
4
+ from robo_appian.components.InputUtils import InputUtils
5
+ from robo_appian.utils.ComponentUtils import ComponentUtils
6
+
7
+
8
+ class SearchInputUtils:
9
+
10
+ @staticmethod
11
+ def __findSearchInputComponentsByLabelPathAndSelectValue(
12
+ wait: WebDriverWait, xpath: str, value: str
13
+ ):
14
+ search_input_components = ComponentUtils.findComponentsByXPath(wait, xpath)
15
+ input_components = []
16
+ for search_input_component in search_input_components:
17
+ attribute: str = "aria-controls"
18
+ dropdown_list_id = search_input_component.get_attribute(attribute)
19
+ if dropdown_list_id:
20
+ InputUtils._setComponentValue(search_input_component, value)
21
+ 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
+ )
25
+ drop_down_item.click()
26
+ else:
27
+ raise ValueError(
28
+ f"Search input component with label '{search_input_component.text}' does not have 'aria-controls' attribute."
29
+ )
30
+
31
+ return input_components
32
+
33
+ @staticmethod
34
+ def __selectSearchInputComponentsByPartialLabelText(
35
+ wait: WebDriverWait, label: str, value: str
36
+ ):
37
+ xpath = f".//div[./div/span[contains(normalize-space(text())='{label}']]/div/div/div/input[@role='combobox']"
38
+ SearchInputUtils.__findSearchInputComponentsByLabelPathAndSelectValue(
39
+ wait, xpath, value
40
+ )
41
+
42
+ @staticmethod
43
+ def __selectSearchInputComponentsByLabelText(
44
+ wait: WebDriverWait, label: str, value: str
45
+ ):
46
+ xpath = (
47
+ f".//div[./div/span[text()='{label}']]/div/div/div/input[@role='combobox']"
48
+ )
49
+ SearchInputUtils.__findSearchInputComponentsByLabelPathAndSelectValue(
50
+ wait, xpath, value
51
+ )
52
+
53
+ @staticmethod
54
+ def selectSearchDropdownByLabelText(wait: WebDriverWait, label: str, value: str):
55
+
56
+ SearchInputUtils.__selectSearchInputComponentsByLabelText(wait, label, value)
57
+
58
+ @staticmethod
59
+ def selectSearchDropdownByPartialLabelText(
60
+ wait: WebDriverWait, label: str, value: str
61
+ ):
62
+ SearchInputUtils.__selectSearchInputComponentsByPartialLabelText(
63
+ wait, label, value
64
+ )
@@ -9,11 +9,11 @@ class TabUtils:
9
9
  Usage Example:
10
10
 
11
11
  # Select a tab by its label
12
- from robo_appian.utils.components.TabUtils import TabUtils
12
+ from robo_appian.components.TabUtils import TabUtils
13
13
  TabUtils.select_tab(wait, "Settings")
14
14
 
15
15
  # Find the currently selected tab by its label
16
- from robo_appian.utils.components.TabUtils import TabUtils
16
+ from robo_appian.components.TabUtils import TabUtils
17
17
  selected_tab = TabUtils.find_selected_tab(wait, "Settings")
18
18
  """
19
19
 
@@ -11,7 +11,7 @@ class TableUtils:
11
11
  Usage Example:
12
12
 
13
13
  # Find a table using a column name
14
- from robo_appian.utils.components.TableUtils import TableUtils
14
+ from robo_appian.components.TableUtils import TableUtils
15
15
  table = TableUtils.findTableUsingColumnName(wait, "Status")
16
16
 
17
17
  """
@@ -140,6 +140,10 @@ class TableUtils:
140
140
 
141
141
  xpath = f'./thead/tr/th[@scope="col" and @abbr="{columnName}"]'
142
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
+
143
147
  class_string = component.get_attribute("class")
144
148
  partial_string = "headCell_"
145
149
  words = class_string.split()
@@ -149,6 +153,9 @@ class TableUtils:
149
153
  if partial_string in word:
150
154
  selected_word = word
151
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
+
152
159
  data = selected_word.split("_")
153
160
  return int(data[1])
154
161
 
@@ -1,10 +1,13 @@
1
- from robo_appian.utils.components.ComponentUtils import ComponentUtils
2
- from robo_appian.utils.components.DateUtils import DateUtils
3
- from robo_appian.utils.components.DropdownUtils import DropdownUtils
4
- from robo_appian.utils.components.InputUtils import InputUtils
5
- from robo_appian.utils.components.LabelUtils import LabelUtils
6
- from robo_appian.utils.components.LinkUtils import LinkUtils
7
- from robo_appian.utils.components.TabUtils import TabUtils
1
+ from robo_appian.components.ButtonUtils import ButtonUtils
2
+ from selenium.webdriver.support.ui import WebDriverWait
3
+ from robo_appian.utils.ComponentUtils import ComponentUtils
4
+ from robo_appian.components.DateUtils import DateUtils
5
+ from robo_appian.components.DropdownUtils import DropdownUtils
6
+ from robo_appian.components.InputUtils import InputUtils
7
+ from robo_appian.components.LabelUtils import LabelUtils
8
+ from robo_appian.components.LinkUtils import LinkUtils
9
+ from robo_appian.components.TabUtils import TabUtils
10
+ from robo_appian.components.SearchInputUtils import SearchInputUtils
8
11
 
9
12
 
10
13
  class ComponentDriver:
@@ -17,7 +20,7 @@ class ComponentDriver:
17
20
  """
18
21
 
19
22
  @staticmethod
20
- def execute(wait : WebDriverWait, type, action, label, value):
23
+ def execute(wait: WebDriverWait, type, action, label, value):
21
24
  """
22
25
  Executes an action on a specified component type.
23
26
  Parameters:
@@ -42,13 +45,15 @@ class ComponentDriver:
42
45
  case "Input Text":
43
46
  match action:
44
47
  case "Set Value":
45
- InputUtils.setInputValue(wait, label, value)
48
+ InputUtils.setValueByLabelText(wait, label, value)
46
49
  case _:
47
50
  raise ValueError(f"Unsupported action for {type}: {action}")
48
51
  case "Search Input Text":
49
52
  match action:
50
53
  case "Select":
51
- InputUtils.setSearchInputValue(wait, label, value)
54
+ SearchInputUtils.selectSearchDropdownByLabelText(
55
+ wait, label, value
56
+ )
52
57
  case _:
53
58
  raise ValueError(f"Unsupported action for {type}: {action}")
54
59
  case "Label":
@@ -66,19 +71,19 @@ class ComponentDriver:
66
71
  case "Drop Down":
67
72
  match action:
68
73
  case "Select":
69
- DropdownUtils.selectDropdownValue(wait, label, value)
74
+ DropdownUtils.selectDropdownValueByLabelText(wait, label, value)
70
75
  case _:
71
76
  raise ValueError(f"Unsupported action for {type}: {action}")
72
77
  case "Search Drop Down":
73
78
  match action:
74
79
  case "Select":
75
- DropdownUtils.selectSearchDropdownValue(wait, label, value)
80
+ DropdownUtils.selectSearchDropdownValueByLabelText(wait, label, value)
76
81
  case _:
77
82
  raise ValueError(f"Unsupported action for {type}: {action}")
78
83
  case "Button":
79
84
  match action:
80
85
  case "Click":
81
- ComponentUtils.click_button(wait, label)
86
+ ButtonUtils.click(wait, label)
82
87
  case _:
83
88
  raise ValueError(f"Unsupported action for {type}: {action}")
84
89
  case "Tab":
@@ -37,97 +37,6 @@ class ComponentUtils:
37
37
  yesterday_formatted = yesterday.strftime("%m/%d/%Y")
38
38
  return yesterday_formatted
39
39
 
40
- # @staticmethod
41
- # def find_dropdown_id(wait, dropdown_label):
42
- # label_class_name = "FieldLayout---field_label"
43
- # xpath = f'.//div/span[normalize-space(text())="{dropdown_label}" and @class="{label_class_name}"]'
44
- # span_element = wait.until(EC.presence_of_element_located((By.XPATH, xpath)))
45
- # span_element_id = span_element.get_attribute('id')
46
- # return span_element_id
47
-
48
- # @staticmethod
49
- # def find_input_id(wait, label_text):
50
- # label_class_name = "FieldLayout---field_label"
51
- # xpath = f'.//div/div/label[@class="{label_class_name}" and contains(normalize-space(text()), "{label_text}")]'
52
- # label_element = wait.until(EC.presence_of_element_located((By.XPATH, xpath)))
53
- # input_element_id = label_element.get_attribute('for')
54
- # return input_element_id
55
-
56
- # @staticmethod
57
- # def set_input_value(wait, label_text, value):
58
- # input_element_id = ComponentUtils.find_input_id(wait, label_text)
59
- # input_element = ComponentUtils.set_input_value_using_id(wait, input_element_id, value)
60
- # return input_element
61
-
62
- # @staticmethod
63
- # def set_input_value_using_id(wait, input_element_id, value):
64
- # input_element = wait.until(EC.presence_of_element_located((By.ID, input_element_id)))
65
- # input_element = wait.until(EC.element_to_be_clickable((By.ID, input_element_id)))
66
- # input_element.clear()
67
- # input_element.send_keys(value)
68
- # input_element.send_keys(Keys.RETURN)
69
- # return input_element
70
-
71
- # @staticmethod
72
- # def select_search_dropdown_value(wait, label, value):
73
- # span_element_id = ComponentUtils.find_dropdown_id(wait, label)
74
- # xpath = f'.//div[@id="{span_element_id}_value"]'
75
- # combobox = wait.until(EC.presence_of_element_located((By.XPATH, xpath)))
76
- # disabled = combobox.get_attribute("aria-disabled")
77
- # if disabled == "true":
78
- # return
79
- # aria_controls = combobox.get_attribute("aria-controls")
80
- # combobox = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
81
- # combobox.click()
82
-
83
- # input_element_id = span_element_id + "_searchInput"
84
- # ComponentUtils.set_input_value_using_id(wait, input_element_id, value)
85
-
86
- # xpath = f'.//ul[@id="{aria_controls}"]/li[./div[normalize-space(text())="{value}"]]'
87
- # component = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
88
- # component.click()
89
-
90
- # @staticmethod
91
- # def selectDropdownValue(wait, combobox, value):
92
-
93
- # aria_controls = combobox.get_attribute("aria-controls")
94
- # combobox.click()
95
-
96
- # xpath = f'.//div/ul[@id="{aria_controls}"]/li[./div[normalize-space(text())="{value}"]]'
97
- # component = wait.until(EC.presence_of_element_located((By.XPATH, xpath)))
98
- # component = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
99
- # component.click()
100
-
101
- # @staticmethod
102
- # def select_dropdown_value(wait, label, value):
103
- # span_element_id = ComponentUtils.find_dropdown_id(wait, label)
104
-
105
- # xpath = f'.//div[@id="{span_element_id}_value"]'
106
- # combobox = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
107
- # disabled = combobox.get_attribute("aria-disabled")
108
- # if disabled == "true":
109
- # return
110
-
111
- # combobox = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
112
- # ComponentUtils.selectDropdownValue(wait, combobox, value)
113
-
114
- # @staticmethod
115
- # def findButton(wait, button_text):
116
- # xpath = f'.//button[.//span/span[contains(normalize-space(text()), "{button_text}")]]'
117
- # component = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
118
- # return component
119
-
120
- # @staticmethod
121
- # def click_button(wait, button_text):
122
- # component = ComponentUtils.findButton(wait, button_text)
123
- # component.click()
124
-
125
- # @staticmethod
126
- # def select_tab(wait, tab_label_text):
127
- # xpath = f'.//div[@role="presentation"]/div/div/p[./span[normalize-space(text())="{tab_label_text}"]]'
128
- # component = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
129
- # component.click()
130
-
131
40
  @staticmethod
132
41
  def findSuccessMessage(wait: WebDriverWait, message: str):
133
42
  """
@@ -261,15 +170,6 @@ class ComponentUtils:
261
170
 
262
171
  return length
263
172
 
264
- # @staticmethod
265
- # def findComponent(wait, label):
266
- # xpath = f".//div/label[text()='{label}']"
267
- # component = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
268
- # component_id = component.get_attribute("for")
269
-
270
- # component = wait.until(EC.element_to_be_clickable((By.ID, component_id)))
271
- # return component
272
-
273
173
  @staticmethod
274
174
  def tab(driver: WebDriver):
275
175
  """
@@ -287,3 +187,40 @@ class ComponentUtils:
287
187
 
288
188
  actions = ActionChains(driver)
289
189
  actions.send_keys(Keys.TAB).perform()
190
+
191
+ @staticmethod
192
+ def findComponentsByXPath(wait: WebDriverWait, xpath: str):
193
+ """
194
+ Finds multiple components that match the same XPath.
195
+
196
+ Parameters:
197
+ wait: Selenium WebDriverWait instance.
198
+ xpath: The XPath expression to find components.
199
+
200
+ Returns:
201
+ List of WebElement objects that match the XPath.
202
+
203
+ Raises:
204
+ Exception: If no components are found.
205
+ """
206
+
207
+ # Wait for at least one element to be present
208
+ wait.until(EC.presence_of_element_located((By.XPATH, xpath)))
209
+
210
+ # Find all matching elements
211
+ driver = wait._driver
212
+ components = driver.find_elements(By.XPATH, xpath)
213
+
214
+ # Filter for clickable and displayed components
215
+ valid_components = []
216
+ for component in components:
217
+ try:
218
+ if component.is_displayed() and component.is_enabled():
219
+ valid_components.append(component)
220
+ except Exception:
221
+ continue
222
+
223
+ if len(valid_components) > 0:
224
+ return valid_components
225
+
226
+ raise Exception(f"No valid components found for XPath: {xpath}")
@@ -1 +0,0 @@
1
- # Bytecode package
@@ -1,43 +1,20 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.3
2
2
  Name: robo_appian
3
- Version: 0.0.4
4
- Summary: Selenium-based automation utilities for Appian applications
5
- Home-page: https://github.com/yourusername/robo_appian
6
- Author: Your Name
7
- Author-email: your.email@example.com
8
- Project-URL: Bug Reports, https://github.com/yourusername/robo_appian/issues
9
- Project-URL: Source, https://github.com/yourusername/robo_appian
10
- Project-URL: Documentation, https://robo-appian.readthedocs.io/
11
- Keywords: selenium,automation,testing,appian,ui
12
- Classifier: Development Status :: 4 - Beta
13
- Classifier: Intended Audience :: Developers
14
- Classifier: Topic :: Software Development :: Testing
15
- Classifier: Topic :: Software Development :: Quality Assurance
16
- Classifier: License :: OSI Approved :: MIT License
3
+ Version: 0.0.5
4
+ Summary: Automate your Appian code testing with Python. Boost quality, save time.
5
+ Author: Dinil Mithra
6
+ Author-email: dinilmithra@mailme@gmail.com
7
+ Requires-Python: >=3.12,<4.0
8
+ Classifier: Operating System :: OS Independent
17
9
  Classifier: Programming Language :: Python :: 3
18
- Classifier: Programming Language :: Python :: 3.8
19
- Classifier: Programming Language :: Python :: 3.9
20
- Classifier: Programming Language :: Python :: 3.10
21
- Classifier: Programming Language :: Python :: 3.11
22
10
  Classifier: Programming Language :: Python :: 3.12
23
- Requires-Python: >=3.8
11
+ Classifier: Programming Language :: Python :: 3.13
12
+ Requires-Dist: numpy
13
+ Requires-Dist: requests (>=2.25.1,<3.0.0)
14
+ Requires-Dist: selenium (>=4.34.0)
15
+ Project-URL: Homepage, https://github.com/dinilmithra/robo_appian
16
+ Project-URL: Repository, https://github.com/dinilmithra/robo_appian.git
24
17
  Description-Content-Type: text/markdown
25
- License-File: LICENSE
26
- Requires-Dist: selenium>=4.34.0
27
- Requires-Dist: requests>=2.25.0
28
- Requires-Dist: numpy>=1.21.0
29
- Dynamic: author
30
- Dynamic: author-email
31
- Dynamic: classifier
32
- Dynamic: description
33
- Dynamic: description-content-type
34
- Dynamic: home-page
35
- Dynamic: keywords
36
- Dynamic: license-file
37
- Dynamic: project-url
38
- Dynamic: requires-dist
39
- Dynamic: requires-python
40
- Dynamic: summary
41
18
 
42
19
  # Robo Appian
43
20
 
@@ -0,0 +1,21 @@
1
+ robo_appian/__init__.py,sha256=6u9n2W7P1IKSSr5IPGsg7LhVR1o1uYv424mXDjJLgb0,720
2
+ robo_appian/components/ButtonUtils.py,sha256=1bBWsnr51idniVs2rHqOpPNPR6g-AGYjCwx2YWyYy4o,2198
3
+ robo_appian/components/DateUtils.py,sha256=mmvyYVgp0thiIQ2uaUiEV-aXwsyCp2d1W8hKR6j_E4M,4599
4
+ robo_appian/components/DropdownUtils.py,sha256=5p6Twef2dYf8Zta_SP3sIcWbaZqVI-yeMNOywHHitHw,5720
5
+ robo_appian/components/InputUtils.py,sha256=BFvNwFoNy3enAspKr0uTxfJrdVye3FuGiZz3QuNf-e8,4125
6
+ robo_appian/components/LabelUtils.py,sha256=qajWEHEpFcBf5sSrkLA6Q0qX_FiHcZjOZeY_P8qXt1o,1224
7
+ robo_appian/components/LinkUtils.py,sha256=0wE2Pr-6X5g3oLrKNSSo0Zo-fcZo5WQXdQTw4Z2dvI8,1414
8
+ robo_appian/components/SearchInputUtils.py,sha256=WbPrsDVWnagtz1Vkj0gftf6jfTYivODEeqz2E12oXUc,2576
9
+ robo_appian/components/TabUtils.py,sha256=A3Zeu5Lg7JcD_c_xCtIm7Xkjm53VTLtBhzFGLyY0FoA,2058
10
+ robo_appian/components/TableUtils.py,sha256=CeYYmFdOD0F78UkkVXlRmrZatPr94oSVCHyGf_fgfuw,8583
11
+ robo_appian/components/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
+ robo_appian/controllers/ComponentDriver.py,sha256=faeC_T06aT9XbDnUPqGwpG5ng7wULPmZigyU8TXLCu4,4354
13
+ robo_appian/controllers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ robo_appian/exceptions/MyCustomError.py,sha256=DVAkytXNNQNjqyTyCjk6FFd6fr3AsBe57Y19erDSqVs,222
15
+ robo_appian/exceptions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
+ robo_appian/utils/ComponentUtils.py,sha256=uq1y6_DxH3O-m7vCvtdVE5640Wx8Je8ydA7pbKDrKVw,8398
17
+ robo_appian/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
+ robo_appian-0.0.5.dist-info/LICENSE,sha256=g-xR4dRa9_4iFkMoJmED-wE-J5hoxbk3105Knhfpjm0,1068
19
+ robo_appian-0.0.5.dist-info/METADATA,sha256=xbaYUrn9O378n6Hr2u_LjslomPmdu1tDk322mRo-mJk,4104
20
+ robo_appian-0.0.5.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
21
+ robo_appian-0.0.5.dist-info/RECORD,,
@@ -1,5 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: poetry-core 2.1.3
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
-
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -1 +0,0 @@
1
- # Bytecode package
@@ -1 +0,0 @@
1
- # Bytecode package
@@ -1 +0,0 @@
1
- # Bytecode package
@@ -1,37 +0,0 @@
1
- robo_appian/__init__.py,sha256=AiMpl0fcPrlwMyUH0ZRzVYAlv4WY6e225XQCMuJa0Zk,779
2
- robo_appian/utils/__init__.py,sha256=GqOJu-ZZRLzA9Nby6uXo82hxkSOPW_ZxBtMCn0xgoB8,19
3
- robo_appian/utils/components/ButtonUtils.pyc,sha256=J90p3zU4Q7vgklQZvLk7-4v-kosISmnyGYcFeoTiOdg,1919
4
- robo_appian/utils/components/ComponentUtils.pyc,sha256=Uw3oEqCJ_8rgZpfs0hBqYJkwiaCcdJxpWtbdVSAwUiw,4579
5
- robo_appian/utils/components/DateUtils.pyc,sha256=O8q1YI8elSEJJaa_rw7msop9GVSTBRF7BGFp_pD64O8,2852
6
- robo_appian/utils/components/DropdownUtils.pyc,sha256=nWNngNDP52jPNw27EkbN9GSAIf_4YeCcfNcprCr4t-A,4334
7
- robo_appian/utils/components/InputUtils.pyc,sha256=tj7K8cbzwKxktSEW7-yRcwaPVlIdQGNToJIcdfigHmg,4530
8
- robo_appian/utils/components/LabelUtils.pyc,sha256=EBWhbr1xHRttUjG2o3YGmDMpc36g0RcHCk3ZbyAjvks,1086
9
- robo_appian/utils/components/LinkUtils.pyc,sha256=ojrwAHobkXBLFRTOUC5KnDhNPjSFymcfXd_Ug33ICJM,1133
10
- robo_appian/utils/components/TabUtils.pyc,sha256=cWs1KGtMkb6pkfXDsVvp6oHXVMRiKwTEoqWMF99lohI,1494
11
- robo_appian/utils/components/TableUtils.pyc,sha256=2nyaYzsOcYuspRf-Hg8-8ZB0yJ8qlN1dCLqkB2ulpmY,4532
12
- robo_appian/utils/components/__init__.py,sha256=GqOJu-ZZRLzA9Nby6uXo82hxkSOPW_ZxBtMCn0xgoB8,19
13
- robo_appian/utils/controllers/ComponentDriver.pyc,sha256=VdV-KUlG6REm6OSJ4uDlMEcE6opRbgDIJexI7jCD-ks,2983
14
- robo_appian/utils/controllers/__init__.py,sha256=GqOJu-ZZRLzA9Nby6uXo82hxkSOPW_ZxBtMCn0xgoB8,19
15
- robo_appian/utils/exceptions/MyCustomError.pyc,sha256=duaUZ7I3lL9L5-LOKBUkLyRuGAUIVjoX5oWsDzCodlM,672
16
- robo_appian/utils/exceptions/__init__.py,sha256=GqOJu-ZZRLzA9Nby6uXo82hxkSOPW_ZxBtMCn0xgoB8,19
17
- robo_appian-0.0.4.dist-info/licenses/LICENSE,sha256=g-xR4dRa9_4iFkMoJmED-wE-J5hoxbk3105Knhfpjm0,1068
18
- robo_appian_source_backup/__init__.py,sha256=AiMpl0fcPrlwMyUH0ZRzVYAlv4WY6e225XQCMuJa0Zk,779
19
- robo_appian_source_backup/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
- robo_appian_source_backup/utils/components/ButtonUtils.py,sha256=Go_F2yJbGHho06notteHU3kXAdpA9EvXw1zm4zp260s,2204
21
- robo_appian_source_backup/utils/components/ComponentUtils.py,sha256=-6CSRa2mBCPt9BrKXXO1cP6IsZ6Tle1X3rlfoJZlpjc,11779
22
- robo_appian_source_backup/utils/components/DateUtils.py,sha256=r-4XnuGwA_cSHjWQub7-qoQQ29eBsG14uumXZkXpcDI,4615
23
- robo_appian_source_backup/utils/components/DropdownUtils.py,sha256=rIqkkJYYJnWsOOppMa-tHeQx9WGQYeNpBSJxnulFUH8,6369
24
- robo_appian_source_backup/utils/components/InputUtils.py,sha256=tuyzWDhxXdHqJ3XGS8O1TA22CaNSLEDpKFWf0QSlsQA,7278
25
- robo_appian_source_backup/utils/components/LabelUtils.py,sha256=5ovTy9OY-QtLS8UoBXeqi4MQDvlPqVWDnp7SIcXWkJw,1230
26
- robo_appian_source_backup/utils/components/LinkUtils.py,sha256=T7dJ5xSXp436VXhczWrQHC13L5wXTXxxgAvBdyKuYM4,1420
27
- robo_appian_source_backup/utils/components/TabUtils.py,sha256=_KsImdeVITxmotphaqVARwhOhAvs4CLWHlx9wr-qZTk,2070
28
- robo_appian_source_backup/utils/components/TableUtils.py,sha256=W-5fpjRStCmSLlryeHvBiOH83qCXNHgeVukMS3iAs6o,8276
29
- robo_appian_source_backup/utils/components/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
- robo_appian_source_backup/utils/controllers/ComponentDriver.py,sha256=Lzhlf7W85FjZn_0j9eybrgC8wSCzUEvsAbgbGNvTMLY,4128
31
- robo_appian_source_backup/utils/controllers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
- robo_appian_source_backup/utils/exceptions/MyCustomError.py,sha256=DVAkytXNNQNjqyTyCjk6FFd6fr3AsBe57Y19erDSqVs,222
33
- robo_appian_source_backup/utils/exceptions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
- robo_appian-0.0.4.dist-info/METADATA,sha256=LpZLjkHL-r978F_hEzlh-oHQ2HaOUpV0-RGJVZ_ZdQw,4880
35
- robo_appian-0.0.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
36
- robo_appian-0.0.4.dist-info/top_level.txt,sha256=UuP4kHKT_rk8Cj08kDZHMv-SMu-c1gouluxYURCUgtk,38
37
- robo_appian-0.0.4.dist-info/RECORD,,
@@ -1,2 +0,0 @@
1
- robo_appian
2
- robo_appian_source_backup
@@ -1,23 +0,0 @@
1
- from robo_appian.utils.components.ButtonUtils import ButtonUtils
2
- from robo_appian.utils.components.ComponentUtils import ComponentUtils
3
- from robo_appian.utils.components.DateUtils import DateUtils
4
- from robo_appian.utils.components.DropdownUtils import DropdownUtils
5
- from robo_appian.utils.components.InputUtils import InputUtils
6
- from robo_appian.utils.components.LabelUtils import LabelUtils
7
- from robo_appian.utils.components.LinkUtils import LinkUtils
8
- from robo_appian.utils.components.TableUtils import TableUtils
9
- from robo_appian.utils.components.TabUtils import TabUtils
10
-
11
- __version__ = "0.0.2"
12
-
13
- __all__ = [
14
- "ButtonUtils",
15
- "ComponentUtils",
16
- "DateUtils",
17
- "DropdownUtils",
18
- "InputUtils",
19
- "LabelUtils",
20
- "LinkUtils",
21
- "TableUtils",
22
- "TabUtils"
23
- ]
@@ -1,141 +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
- from selenium.webdriver.remote.webelement import WebElement
6
-
7
- from robo_appian.utils.components.InputUtils import InputUtils
8
-
9
-
10
- class DropdownUtils:
11
- """
12
- Utility class for interacting with dropdown components in Appian UI.
13
-
14
- Usage Example:
15
-
16
- # Select a value from a dropdown
17
- from robo_appian.utils.components.DropdownUtils import DropdownUtils
18
- DropdownUtils.selectDropdownValue(wait, "Status", "Approved")
19
-
20
- # Select a value from a search dropdown
21
- from robo_appian.utils.components.DropdownUtils import DropdownUtils
22
- DropdownUtils.selectSearchDropdownValue(wait, "Category", "Finance")
23
- """
24
-
25
- @staticmethod
26
- def findDropdownEnabled(wait: WebDriverWait, dropdown_label: str):
27
- """
28
- Finds a dropdown component that is enabled and has the specified label.
29
-
30
- Parameters:
31
- wait: Selenium WebDriverWait instance.
32
- dropdown_label: The visible text label of the dropdown component.
33
-
34
- Returns:
35
- The Selenium WebElement for the dropdown component.
36
-
37
- Example:
38
- DropdownUtils.findDropdownEnabled(wait, "Status")
39
-
40
- """
41
- # This method locates a dropdown component that contains a label with the specified text.
42
- # It then retrieves the component's ID and uses it to find the actual dropdown element.
43
- # The dropdown is identified by its role as a combobox and tabindex attribute.
44
- # The XPath searches for a div that contains a span with the specified label text.
45
- # It ensures that the dropdown is clickable and ready for interaction.
46
- # The dropdown component is expected to have a structure where the label is within a span inside a div.
47
-
48
- # xpath = f'.//div[./div/span[normalize-space(text())="{dropdown_label}"]]/div/div/div/div[@role="combobox" and @tabindex="0"]'
49
- # V0.0.4
50
- xpath = f'.//div[./div/span[contains(normalize-space(text()), "{dropdown_label}")]]/div/div/div/div[@role="combobox" and @tabindex="0"][0]'
51
- component = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
52
- return component
53
-
54
- @staticmethod
55
- def selectValueUsingComponent(
56
- wait: WebDriverWait, combobox: WebElement, value: str
57
- ) -> None:
58
- """
59
- Selects a value from a dropdown component using the provided combobox element.
60
-
61
- Parameters:
62
- wait: Selenium WebDriverWait instance.
63
- combobox: The Selenium WebElement for the combobox.
64
- value: The value to select from the dropdown.
65
-
66
- Example:
67
- DropdownUtils.selectValueUsingComponent(wait, combobox, "Approved")
68
-
69
- """
70
- # This method assumes that the combobox is already found and passed as an argument.
71
- # It retrieves the aria-controls attribute to find the dropdown list and selects the specified value.
72
-
73
- if not combobox:
74
- raise ValueError(f"Dropdown component object is not valid.")
75
-
76
- component: WebElement = combobox.find_element(By.XPATH, "./div/div") # type: ignore[reportUnknownMemberType]
77
- aria_controls = component.get_attribute("aria-controls") # type: ignore[reportUnknownMemberType]
78
- component.click()
79
-
80
- xpath = f'.//div/ul[@id="{aria_controls}"]/li[./div[normalize-space(text())="{value}"]]'
81
- # component = wait.until(EC.presence_of_element_located((By.XPATH, xpath)))
82
- component = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
83
- component.click()
84
-
85
- @staticmethod
86
- def selectDropdownValue(wait: WebDriverWait, label: str, value: str) -> None:
87
- """
88
- Selects a value from a dropdown component identified by its label.
89
-
90
- Parameters:
91
- wait: Selenium WebDriverWait instance.
92
- label: The visible text label of the dropdown component.
93
- value: The value to select from the dropdown.
94
-
95
- Example:
96
- DropdownUtils.selectDropdownValue(wait, "Status", "Approved")
97
-
98
- """
99
- # This method finds the dropdown component by its label, retrieves the aria-controls attribute,
100
- # and then clicks on the dropdown to display the options.
101
-
102
- combobox = DropdownUtils.findDropdownEnabled(wait, label)
103
- aria_controls = combobox.get_attribute("aria-controls") # type: ignore[reportUnknownMemberType]
104
- combobox.click()
105
-
106
- xpath = f'.//div/ul[@id="{aria_controls}"]/li[./div[normalize-space(text())="{value}"]]'
107
- component = wait.until(EC.presence_of_element_located((By.XPATH, xpath)))
108
- component = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
109
- component.click()
110
-
111
- @staticmethod
112
- def selectSearchDropdownValue(wait: WebDriverWait, dropdown_label: str, value: str):
113
- """
114
- Selects a value from a search-enabled dropdown component identified by its label.
115
-
116
- Parameters:
117
- wait: Selenium WebDriverWait instance.
118
- dropdown_label: The visible text label of the search dropdown component.
119
- value: The value to select from the dropdown.
120
-
121
- Example:
122
- DropdownUtils.selectSearchDropdownValue(wait, "Category", "Finance")
123
-
124
- """
125
- # This method finds the search-enabled dropdown component by its label, retrieves the aria-controls attribute
126
- # and the component ID, clicks on the dropdown to display the search input,
127
-
128
- component = DropdownUtils.findDropdownEnabled(wait, dropdown_label)
129
- component_id = component.get_attribute("aria-labelledby") # type: ignore[reportUnknownMemberType]
130
- aria_controls = component.get_attribute("aria-controls") # type: ignore[reportUnknownMemberType]
131
- component.click()
132
-
133
- input_component_id = str(component_id) + "_searchInput"
134
- input_component = wait.until(
135
- EC.element_to_be_clickable((By.ID, input_component_id))
136
- )
137
- InputUtils.setValueUsingComponent(input_component, value)
138
-
139
- xpath = f'.//ul[@id="{aria_controls}"]/li[./div[normalize-space(text())="{value}"]][1]'
140
- component = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
141
- component.click()
@@ -1,193 +0,0 @@
1
- from selenium.webdriver.common.by import By
2
- from selenium.webdriver.common.keys import Keys
3
- from selenium.webdriver.support import expected_conditions as EC
4
- from selenium.webdriver.support.ui import WebDriverWait
5
- from selenium.webdriver.remote.webdriver import WebDriver
6
- from selenium.webdriver.remote.webelement import WebElement
7
-
8
-
9
- class InputUtils:
10
- """
11
- Utility class for interacting with input components in Appian UI.
12
-
13
- Usage Example:
14
-
15
- # Set a value in an input field
16
- from robo_appian.utils.components.InputUtils import InputUtils
17
- InputUtils.setInputValue(wait, "Username", "test_user")
18
-
19
- """
20
-
21
- @staticmethod
22
- def findComponent(wait: WebDriverWait, label: str):
23
- """
24
- Finds an input component by its label.
25
-
26
- Parameters:
27
- wait: Selenium WebDriverWait instance.
28
- label: The visible text label of the input component.
29
-
30
- Returns:
31
- The Selenium WebElement for the input component.
32
-
33
- Example:
34
- InputUtils.findComponent(wait, "Username")
35
-
36
- """
37
- # This method locates an input component that contains a label with the specified text.
38
- # It then retrieves the component's ID and uses it to find the actual input element.
39
-
40
- # xpath = f".//div/label[text()='{label}']"
41
- # V0.0.4
42
- xpath = f".//div/label[contains(normalize-space(text()), '{label}')]"
43
- component: WebElement = wait.until(
44
- EC.element_to_be_clickable((By.XPATH, xpath))
45
- )
46
-
47
- attribute: str = "for"
48
- component_id = component.get_attribute(attribute) # type: ignore[reportUnknownMemberType]
49
- if not component_id:
50
- raise ValueError(
51
- f"Could not find component using {attribute} attribute for label '{label}'."
52
- )
53
-
54
- component = wait.until(EC.element_to_be_clickable((By.ID, component_id)))
55
- return component
56
-
57
- @staticmethod
58
- def setValueUsingComponent(component: WebElement, value: str):
59
- """
60
- Sets a value in an input component using the provided component element.
61
-
62
- Parameters:
63
- component: The Selenium WebElement for the input component.
64
- value: The value to set in the input field.
65
-
66
- Returns:
67
- The Selenium WebElement for the input component after setting the value.
68
-
69
- Example:
70
- InputUtils.setValueUsingComponent(component, "test_user")
71
-
72
- """
73
- # This method assumes that the component is already found and passed as an argument.
74
- # It clears the existing value and sets the new value in the input field.
75
-
76
- if not component.is_displayed():
77
- raise Exception(
78
- f"Component with label '{component.text}' is not displayed."
79
- )
80
-
81
- component.clear()
82
- component.send_keys(value)
83
- return component
84
-
85
- @staticmethod
86
- def setValueAndSubmitUsingComponent(component: WebElement, value: str):
87
- """
88
- Sets a value in an input component and submits it using the provided component element.
89
-
90
- Parameters:
91
- component: The Selenium WebElement for the input component.
92
- value: The value to set in the input field.
93
-
94
- Returns:
95
- The Selenium WebElement for the input component after setting the value and submitting.
96
-
97
- Example:
98
- InputUtils.setValueAndSubmitUsingComponent(component, "test_user")
99
-
100
- """
101
- # This method assumes that the component is already found and passed as an argument.
102
-
103
- if not component.is_displayed():
104
- raise Exception(
105
- f"Component with label '{component.text}' is not displayed."
106
- )
107
-
108
- component = InputUtils.setValueUsingComponent(component, value)
109
- component.send_keys(Keys.ENTER)
110
- return component
111
-
112
- @staticmethod
113
- def setInputValue(wait: WebDriverWait, label: str, value: str):
114
- """
115
- Sets a value in an input component identified by its label.
116
-
117
- Parameters:
118
- wait: Selenium WebDriverWait instance.
119
- label: The visible text label of the input component.
120
- value: The value to set in the input field.
121
-
122
- Returns:
123
- The Selenium WebElement for the input component after setting the value.
124
-
125
- Example:
126
- InputUtils.setInputValue(wait, "Username", "test_user")
127
-
128
- """
129
- # This method finds the input component by its label and sets the specified value in it.
130
- # It retrieves the component's ID and uses it to find the actual input element.
131
-
132
- component = InputUtils.findComponent(wait, label)
133
- InputUtils.setValueUsingComponent(component, value)
134
- return component
135
-
136
- @staticmethod
137
- def setValueAndSubmit(wait: WebDriverWait, label: str, value: str):
138
- """
139
- Sets a value in an input component identified by its label and submits it.
140
-
141
- Parameters:
142
- wait: Selenium WebDriverWait instance.
143
- label: The visible text label of the input component.
144
- value: The value to set in the input field.
145
-
146
- Returns:
147
- The Selenium WebElement for the input component after setting the value and submitting.
148
-
149
- Example:
150
- InputUtils.setValueAndSubmit(wait, "Username", "test_user")
151
-
152
- """
153
- # This method finds the input component by its label, sets the specified value in it,
154
- # and submits the form by sending an ENTER key.
155
-
156
- component = InputUtils.findComponent(wait, label)
157
- component = InputUtils.setValueAndSubmitUsingComponent(component, value)
158
- return component
159
-
160
- @staticmethod
161
- def setSearchInputValue(wait: WebDriverWait, label: str, value: str):
162
- """
163
- Sets a value in a search-enabled input component identified by its label.
164
-
165
- Parameters:
166
- wait: Selenium WebDriverWait instance.
167
- label: The visible text label of the search input component.
168
- value: The value to set in the search input field.
169
-
170
- Returns:
171
- None
172
- Example:
173
- InputUtils.setSearchInputValue(wait, "Search", "Appian")
174
-
175
- """
176
- # This method finds the search-enabled input component by its label, retrieves the aria-controls attribute
177
- # and the component ID, clicks on the input to display the search input,
178
- # and sets the specified value in the search input field.
179
-
180
- # xpath = (
181
- # f".//div[./div/span[text()='{label}']]/div/div/div/input[@role='combobox']"
182
- # )
183
- # V0.0.4
184
- xpath = f".//div[./div/span[contains(normalize-space(text())='{label}']]/div/div/div/input[@role='combobox']"
185
- search_input_component = wait.until(
186
- EC.element_to_be_clickable((By.XPATH, xpath))
187
- )
188
- aria_controls = search_input_component.get_attribute("aria-controls") # type: ignore[reportUnknownMemberType]
189
- InputUtils.setValueUsingComponent(search_input_component, value)
190
-
191
- xpath = f".//ul[@id='{aria_controls}' and @role='listbox' ]/li[@role='option']/div/div/div/div/div/div/p[text()='{value}'][1]"
192
- drop_down_item = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
193
- drop_down_item.click()
File without changes