robo_appian 0.0.2__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.
- robo_appian/__init__.py +11 -0
- robo_appian/utils/__init__.py +0 -0
- robo_appian/utils/components/ButtonUtils.py +72 -0
- robo_appian/utils/components/ComponentUtils.py +289 -0
- robo_appian/utils/components/DateUtils.py +130 -0
- robo_appian/utils/components/DropdownUtils.py +141 -0
- robo_appian/utils/components/InputUtils.py +189 -0
- robo_appian/utils/components/LabelUtils.py +40 -0
- robo_appian/utils/components/LinkUtils.py +41 -0
- robo_appian/utils/components/TabUtils.py +58 -0
- robo_appian/utils/components/TableUtils.py +187 -0
- robo_appian/utils/components/__init__.py +0 -0
- robo_appian/utils/controllers/ComponentDriver.py +91 -0
- robo_appian/utils/controllers/__init__.py +0 -0
- robo_appian/utils/exceptions/MyCustomError.py +6 -0
- robo_appian/utils/exceptions/__init__.py +0 -0
- robo_appian-0.0.2.dist-info/LICENSE +21 -0
- robo_appian-0.0.2.dist-info/METADATA +91 -0
- robo_appian-0.0.2.dist-info/RECORD +20 -0
- robo_appian-0.0.2.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,189 @@
|
|
|
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
|
+
component: WebElement = wait.until(
|
|
42
|
+
EC.element_to_be_clickable((By.XPATH, xpath))
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
attribute: str = "for"
|
|
46
|
+
component_id = component.get_attribute(attribute) # type: ignore[reportUnknownMemberType]
|
|
47
|
+
if not component_id:
|
|
48
|
+
raise ValueError(
|
|
49
|
+
f"Could not find component using {attribute} attribute for label '{label}'."
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
component = wait.until(EC.element_to_be_clickable((By.ID, component_id)))
|
|
53
|
+
return component
|
|
54
|
+
|
|
55
|
+
@staticmethod
|
|
56
|
+
def setValueUsingComponent(component: WebElement, value: str):
|
|
57
|
+
"""
|
|
58
|
+
Sets a value in an input component using the provided component element.
|
|
59
|
+
|
|
60
|
+
Parameters:
|
|
61
|
+
component: The Selenium WebElement for the input component.
|
|
62
|
+
value: The value to set in the input field.
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
The Selenium WebElement for the input component after setting the value.
|
|
66
|
+
|
|
67
|
+
Example:
|
|
68
|
+
InputUtils.setValueUsingComponent(component, "test_user")
|
|
69
|
+
|
|
70
|
+
"""
|
|
71
|
+
# This method assumes that the component is already found and passed as an argument.
|
|
72
|
+
# It clears the existing value and sets the new value in the input field.
|
|
73
|
+
|
|
74
|
+
if not component.is_displayed():
|
|
75
|
+
raise Exception(
|
|
76
|
+
f"Component with label '{component.text}' is not displayed."
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
component.clear()
|
|
80
|
+
component.send_keys(value)
|
|
81
|
+
return component
|
|
82
|
+
|
|
83
|
+
@staticmethod
|
|
84
|
+
def setValueAndSubmitUsingComponent(component: WebElement, value: str):
|
|
85
|
+
"""
|
|
86
|
+
Sets a value in an input component and submits it using the provided component element.
|
|
87
|
+
|
|
88
|
+
Parameters:
|
|
89
|
+
component: The Selenium WebElement for the input component.
|
|
90
|
+
value: The value to set in the input field.
|
|
91
|
+
|
|
92
|
+
Returns:
|
|
93
|
+
The Selenium WebElement for the input component after setting the value and submitting.
|
|
94
|
+
|
|
95
|
+
Example:
|
|
96
|
+
InputUtils.setValueAndSubmitUsingComponent(component, "test_user")
|
|
97
|
+
|
|
98
|
+
"""
|
|
99
|
+
# This method assumes that the component is already found and passed as an argument.
|
|
100
|
+
|
|
101
|
+
if not component.is_displayed():
|
|
102
|
+
raise Exception(
|
|
103
|
+
f"Component with label '{component.text}' is not displayed."
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
component = InputUtils.setValueUsingComponent(component, value)
|
|
107
|
+
component.send_keys(Keys.ENTER)
|
|
108
|
+
return component
|
|
109
|
+
|
|
110
|
+
@staticmethod
|
|
111
|
+
def setInputValue(wait: WebDriverWait, label: str, value: str):
|
|
112
|
+
"""
|
|
113
|
+
Sets a value in an input component identified by its label.
|
|
114
|
+
|
|
115
|
+
Parameters:
|
|
116
|
+
wait: Selenium WebDriverWait instance.
|
|
117
|
+
label: The visible text label of the input component.
|
|
118
|
+
value: The value to set in the input field.
|
|
119
|
+
|
|
120
|
+
Returns:
|
|
121
|
+
The Selenium WebElement for the input component after setting the value.
|
|
122
|
+
|
|
123
|
+
Example:
|
|
124
|
+
InputUtils.setInputValue(wait, "Username", "test_user")
|
|
125
|
+
|
|
126
|
+
"""
|
|
127
|
+
# This method finds the input component by its label and sets the specified value in it.
|
|
128
|
+
# It retrieves the component's ID and uses it to find the actual input element.
|
|
129
|
+
|
|
130
|
+
component = InputUtils.findComponent(wait, label)
|
|
131
|
+
InputUtils.setValueUsingComponent(component, value)
|
|
132
|
+
return component
|
|
133
|
+
|
|
134
|
+
@staticmethod
|
|
135
|
+
def setValueAndSubmit(wait: WebDriverWait, label: str, value: str):
|
|
136
|
+
"""
|
|
137
|
+
Sets a value in an input component identified by its label and submits it.
|
|
138
|
+
|
|
139
|
+
Parameters:
|
|
140
|
+
wait: Selenium WebDriverWait instance.
|
|
141
|
+
label: The visible text label of the input component.
|
|
142
|
+
value: The value to set in the input field.
|
|
143
|
+
|
|
144
|
+
Returns:
|
|
145
|
+
The Selenium WebElement for the input component after setting the value and submitting.
|
|
146
|
+
|
|
147
|
+
Example:
|
|
148
|
+
InputUtils.setValueAndSubmit(wait, "Username", "test_user")
|
|
149
|
+
|
|
150
|
+
"""
|
|
151
|
+
# This method finds the input component by its label, sets the specified value in it,
|
|
152
|
+
# and submits the form by sending an ENTER key.
|
|
153
|
+
|
|
154
|
+
component = InputUtils.findComponent(wait, label)
|
|
155
|
+
component = InputUtils.setValueAndSubmitUsingComponent(component, value)
|
|
156
|
+
return component
|
|
157
|
+
|
|
158
|
+
@staticmethod
|
|
159
|
+
def setSearchInputValue(wait: WebDriverWait, label: str, value: str):
|
|
160
|
+
"""
|
|
161
|
+
Sets a value in a search-enabled input component identified by its label.
|
|
162
|
+
|
|
163
|
+
Parameters:
|
|
164
|
+
wait: Selenium WebDriverWait instance.
|
|
165
|
+
label: The visible text label of the search input component.
|
|
166
|
+
value: The value to set in the search input field.
|
|
167
|
+
|
|
168
|
+
Returns:
|
|
169
|
+
None
|
|
170
|
+
Example:
|
|
171
|
+
InputUtils.setSearchInputValue(wait, "Search", "Appian")
|
|
172
|
+
|
|
173
|
+
"""
|
|
174
|
+
# This method finds the search-enabled input component by its label, retrieves the aria-controls attribute
|
|
175
|
+
# and the component ID, clicks on the input to display the search input,
|
|
176
|
+
# and sets the specified value in the search input field.
|
|
177
|
+
|
|
178
|
+
xpath = (
|
|
179
|
+
f".//div[./div/span[text()='{label}']]/div/div/div/input[@role='combobox']"
|
|
180
|
+
)
|
|
181
|
+
search_input_component = wait.until(
|
|
182
|
+
EC.element_to_be_clickable((By.XPATH, xpath))
|
|
183
|
+
)
|
|
184
|
+
aria_controls = search_input_component.get_attribute("aria-controls") # type: ignore[reportUnknownMemberType]
|
|
185
|
+
InputUtils.setValueUsingComponent(search_input_component, value)
|
|
186
|
+
|
|
187
|
+
xpath = f".//ul[@id='{aria_controls}' and @role='listbox' ]/li[@role='option']/div/div/div/div/div/div/p[text()='{value}'][1]"
|
|
188
|
+
drop_down_item = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
|
|
189
|
+
drop_down_item.click()
|
|
@@ -0,0 +1,40 @@
|
|
|
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 LabelUtils:
|
|
8
|
+
"""
|
|
9
|
+
Utility class for interacting with label components in Appian UI.
|
|
10
|
+
|
|
11
|
+
Usage Example:
|
|
12
|
+
|
|
13
|
+
# Find a label component
|
|
14
|
+
from robo_appian.utils.components.LabelUtils import LabelUtils
|
|
15
|
+
label_component = LabelUtils.find(wait, "Username")
|
|
16
|
+
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
@staticmethod
|
|
20
|
+
def find(wait : WebDriverWait, label: str):
|
|
21
|
+
"""
|
|
22
|
+
Finds a label component by its text.
|
|
23
|
+
|
|
24
|
+
Parameters:
|
|
25
|
+
wait: Selenium WebDriverWait instance.
|
|
26
|
+
label: The visible text label of the component.
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
The Selenium WebElement for the label component.
|
|
30
|
+
|
|
31
|
+
Example:
|
|
32
|
+
LabelUtils.find(wait, "Username")
|
|
33
|
+
|
|
34
|
+
"""
|
|
35
|
+
# This method locates a label component that contains the specified text.
|
|
36
|
+
# It uses XPath to find the element that matches the text.
|
|
37
|
+
|
|
38
|
+
xpath = f".//*[text()='{label}']"
|
|
39
|
+
component = wait.until(EC.presence_of_element_located((By.XPATH, xpath)))
|
|
40
|
+
return component
|
|
@@ -0,0 +1,41 @@
|
|
|
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 LinkUtils:
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
Utility class for interacting with link components in Appian UI.
|
|
11
|
+
|
|
12
|
+
Usage Example:
|
|
13
|
+
|
|
14
|
+
# Click a link with a specific label
|
|
15
|
+
from robo_appian.utils.components.LinkUtils import LinkUtils
|
|
16
|
+
LinkUtils.click(wait, "Learn More")
|
|
17
|
+
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
@staticmethod
|
|
21
|
+
def click(wait: WebDriverWait, label: str):
|
|
22
|
+
|
|
23
|
+
"""
|
|
24
|
+
Clicks a link identified by its label.
|
|
25
|
+
|
|
26
|
+
Parameters:
|
|
27
|
+
wait: Selenium WebDriverWait instance.
|
|
28
|
+
label: The visible text label of the link.
|
|
29
|
+
|
|
30
|
+
Example:
|
|
31
|
+
LinkUtils.click(wait, "Learn More")
|
|
32
|
+
"""
|
|
33
|
+
# This method locates a link that contains a span with the specified label text.
|
|
34
|
+
# It uses XPath to find the element that matches the text and waits until it is clickable.
|
|
35
|
+
# The link component is expected to have a structure where the label is within a span inside a paragraph element.
|
|
36
|
+
|
|
37
|
+
xpath = f'.//p/span[text()="{label}"]'
|
|
38
|
+
# component = wait.until(EC.presence_of_element_located((By.XPATH, xpath)) )
|
|
39
|
+
component = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
|
|
40
|
+
component.click()
|
|
41
|
+
return component
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
from selenium.webdriver.common.by import By
|
|
2
|
+
from selenium.webdriver.support import expected_conditions as EC
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class TabUtils:
|
|
6
|
+
"""
|
|
7
|
+
Utility class for interacting with tab components in Appian UI.
|
|
8
|
+
|
|
9
|
+
Usage Example:
|
|
10
|
+
|
|
11
|
+
# Select a tab by its label
|
|
12
|
+
from robo_appian.utils.components.TabUtils import TabUtils
|
|
13
|
+
TabUtils.select_tab(wait, "Settings")
|
|
14
|
+
|
|
15
|
+
# Find the currently selected tab by its label
|
|
16
|
+
from robo_appian.utils.components.TabUtils import TabUtils
|
|
17
|
+
selected_tab = TabUtils.find_selected_tab(wait, "Settings")
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
@staticmethod
|
|
21
|
+
def find_selected_tab(wait, label):
|
|
22
|
+
"""
|
|
23
|
+
Finds the currently selected tab by its label.
|
|
24
|
+
|
|
25
|
+
Parameters:
|
|
26
|
+
wait: Selenium WebDriverWait instance.
|
|
27
|
+
label: The visible text label of the tab.
|
|
28
|
+
|
|
29
|
+
Returns:
|
|
30
|
+
The Selenium WebElement for the selected tab.
|
|
31
|
+
|
|
32
|
+
Example:
|
|
33
|
+
TabUtils.find_selected_tab(wait, "Settings")
|
|
34
|
+
"""
|
|
35
|
+
# This method locates a tab that is currently selected and contains the specified label.
|
|
36
|
+
|
|
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)))
|
|
39
|
+
return component
|
|
40
|
+
|
|
41
|
+
@staticmethod
|
|
42
|
+
def select_tab(wait, label):
|
|
43
|
+
"""
|
|
44
|
+
Selects a tab by its label.
|
|
45
|
+
|
|
46
|
+
Parameters:
|
|
47
|
+
wait: Selenium WebDriverWait instance.
|
|
48
|
+
label: The visible text label of the tab to select.
|
|
49
|
+
|
|
50
|
+
Example:
|
|
51
|
+
TabUtils.select_tab(wait, "Settings")
|
|
52
|
+
"""
|
|
53
|
+
# This method locates a tab that contains a label with the specified text.
|
|
54
|
+
|
|
55
|
+
xpath = f".//div[@role='link']/div/div/div/div/div[./p/span[text()='{label}']]"
|
|
56
|
+
# 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)))
|
|
58
|
+
component.click()
|
|
@@ -0,0 +1,187 @@
|
|
|
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.utils.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
|
+
class_string = component.get_attribute("class")
|
|
144
|
+
partial_string = "headCell_"
|
|
145
|
+
words = class_string.split()
|
|
146
|
+
selected_word = None
|
|
147
|
+
|
|
148
|
+
for word in words:
|
|
149
|
+
if partial_string in word:
|
|
150
|
+
selected_word = word
|
|
151
|
+
|
|
152
|
+
data = selected_word.split("_")
|
|
153
|
+
return int(data[1])
|
|
154
|
+
|
|
155
|
+
@staticmethod
|
|
156
|
+
def find_component_from_tabele_cell(wait, rowNumber, columnName):
|
|
157
|
+
"""
|
|
158
|
+
Finds a component within a specific table cell based on the row number and column name.
|
|
159
|
+
|
|
160
|
+
Parameters:
|
|
161
|
+
wait: Selenium WebDriverWait instance.
|
|
162
|
+
rowNumber: The row number (0-based index) where the component is located.
|
|
163
|
+
columnName: The name of the column where the component is located.
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
The Selenium WebElement for the component within the specified table cell.
|
|
167
|
+
|
|
168
|
+
Example:
|
|
169
|
+
component = TableUtils.find_component_from_tabele_cell(wait, 2, "Status")
|
|
170
|
+
|
|
171
|
+
"""
|
|
172
|
+
# This method locates a specific component within a table cell based on the provided row number
|
|
173
|
+
# and column name. It constructs an XPath that targets the table cell containing the specified column
|
|
174
|
+
# and row, and then retrieves the component within that cell.
|
|
175
|
+
|
|
176
|
+
tableObject = TableUtils.findTableUsingColumnName(wait, columnName)
|
|
177
|
+
columnNumber = TableUtils.findColumNumberUsingColumnName(
|
|
178
|
+
tableObject, columnName
|
|
179
|
+
)
|
|
180
|
+
# xpath=f'./tbody/tr[@data-dnd-name="row {rowNumber+1}"]/td[not (@data-empty-grid-message)][{columnNumber}]'
|
|
181
|
+
# component = tableObject.find_elements(By.XPATH, xpath)
|
|
182
|
+
rowNumber = rowNumber + 1
|
|
183
|
+
columnNumber = columnNumber + 1
|
|
184
|
+
xpath = f'.//table[./thead/tr/th[@abbr="{columnName}"]]/tbody/tr[@data-dnd-name="row {rowNumber}"]/td[not (@data-empty-grid-message)][{columnNumber}]/*'
|
|
185
|
+
component = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
|
|
186
|
+
# childComponent=component.find_element(By.xpath("./*"))
|
|
187
|
+
return component
|
|
File without changes
|
|
@@ -0,0 +1,91 @@
|
|
|
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
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ComponentDriver:
|
|
11
|
+
"""
|
|
12
|
+
Utility class for interacting with various components in Appian UI.
|
|
13
|
+
Usage Example:
|
|
14
|
+
from robo_appian.utils.controllers.ComponentDriver import ComponentDriver
|
|
15
|
+
# Set a date value
|
|
16
|
+
ComponentDriver.execute(wait, "Date", "Set Value", "Start Date", "01/01/2024")
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
@staticmethod
|
|
20
|
+
def execute(wait : WebDriverWait, type, action, label, value):
|
|
21
|
+
"""
|
|
22
|
+
Executes an action on a specified component type.
|
|
23
|
+
Parameters:
|
|
24
|
+
wait: Selenium WebDriverWait instance.
|
|
25
|
+
type: The type of component (e.g., "Date", "Input Text", "Search Input Text", etc.).
|
|
26
|
+
action: The action to perform on the component (e.g., "Set Value", "Click", "Select").
|
|
27
|
+
label: The visible text label of the component.
|
|
28
|
+
value: The value to set in the component (if applicable).
|
|
29
|
+
Example:
|
|
30
|
+
ComponentDriver.execute(wait, "Date", "Set Value", "Start Date", "01/01/2024")
|
|
31
|
+
"""
|
|
32
|
+
# This method executes an action on a specified component type based on the provided parameters.
|
|
33
|
+
|
|
34
|
+
match type:
|
|
35
|
+
|
|
36
|
+
case "Date":
|
|
37
|
+
match action:
|
|
38
|
+
case "Set Value":
|
|
39
|
+
DateUtils.setDateValue(wait, label, value)
|
|
40
|
+
case _:
|
|
41
|
+
raise ValueError(f"Unsupported action for {type}: {action}")
|
|
42
|
+
case "Input Text":
|
|
43
|
+
match action:
|
|
44
|
+
case "Set Value":
|
|
45
|
+
InputUtils.setInputValue(wait, label, value)
|
|
46
|
+
case _:
|
|
47
|
+
raise ValueError(f"Unsupported action for {type}: {action}")
|
|
48
|
+
case "Search Input Text":
|
|
49
|
+
match action:
|
|
50
|
+
case "Select":
|
|
51
|
+
InputUtils.setSearchInputValue(wait, label, value)
|
|
52
|
+
case _:
|
|
53
|
+
raise ValueError(f"Unsupported action for {type}: {action}")
|
|
54
|
+
case "Label":
|
|
55
|
+
match action:
|
|
56
|
+
case "Find":
|
|
57
|
+
LabelUtils.find(wait, label)
|
|
58
|
+
case _:
|
|
59
|
+
raise ValueError(f"Unsupported action for {type}: {action}")
|
|
60
|
+
case "Link":
|
|
61
|
+
match action:
|
|
62
|
+
case "Click":
|
|
63
|
+
LinkUtils.click(wait, label)
|
|
64
|
+
case _:
|
|
65
|
+
raise ValueError(f"Unsupported action for {type}: {action}")
|
|
66
|
+
case "Drop Down":
|
|
67
|
+
match action:
|
|
68
|
+
case "Select":
|
|
69
|
+
DropdownUtils.selectDropdownValue(wait, label, value)
|
|
70
|
+
case _:
|
|
71
|
+
raise ValueError(f"Unsupported action for {type}: {action}")
|
|
72
|
+
case "Search Drop Down":
|
|
73
|
+
match action:
|
|
74
|
+
case "Select":
|
|
75
|
+
DropdownUtils.selectSearchDropdownValue(wait, label, value)
|
|
76
|
+
case _:
|
|
77
|
+
raise ValueError(f"Unsupported action for {type}: {action}")
|
|
78
|
+
case "Button":
|
|
79
|
+
match action:
|
|
80
|
+
case "Click":
|
|
81
|
+
ComponentUtils.click_button(wait, label)
|
|
82
|
+
case _:
|
|
83
|
+
raise ValueError(f"Unsupported action for {type}: {action}")
|
|
84
|
+
case "Tab":
|
|
85
|
+
match action:
|
|
86
|
+
case "Find":
|
|
87
|
+
TabUtils.find_selected_tab(wait, label)
|
|
88
|
+
case _:
|
|
89
|
+
raise ValueError(f"Unsupported action for {type}: {action}")
|
|
90
|
+
case _:
|
|
91
|
+
raise ValueError(f"Unsupported component type: {type}")
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 dinilmithra
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|