robo_appian 0.0.2__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.

@@ -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.
@@ -0,0 +1,91 @@
1
+ Metadata-Version: 2.3
2
+ Name: robo_appian
3
+ Version: 0.0.2
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
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.12
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
17
+ Description-Content-Type: text/markdown
18
+
19
+ # Robo Appian
20
+
21
+ Python library for automating Appian web UI test cases!
22
+
23
+ # Modules
24
+ ## Components
25
+
26
+ ButtonUtils: Find and click buttons.
27
+ DateUtils: Interact with date fields.
28
+ DropdownUtils: Interact with dropdowns.
29
+ InputUtils: Interact with input fields.
30
+ LabelUtils: Find labels.
31
+ LinkUtils: Click links.
32
+ TableUtils: Interact with tables.
33
+ TabUtils: Interact with tabs.
34
+ ComponentUtils: General utilities for components (input, dropdown, tab, etc).
35
+
36
+ ## Controllers
37
+
38
+ ComponentDriver: High-level interface to execute actions on components.
39
+
40
+ ## Exceptions
41
+
42
+ MyCustomError: Custom exception for specific error conditions.
43
+
44
+ # Usage
45
+
46
+ Import the utilities in your test scripts:
47
+
48
+ from robo_appian import (
49
+ ButtonUtils, ComponentUtils, DateUtils, DropdownUtils, InputUtils,
50
+ LabelUtils, LinkUtils, TableUtils, TabUtils
51
+ )
52
+
53
+ # Example: Set a Date Value
54
+ DateUtils.set_date_value("date_field_id", "2023-10-01")
55
+
56
+ # Example: Click a Button
57
+ ButtonUtils.click_button("submit_button_id")
58
+
59
+ # Example: Select a Dropdown Value
60
+ DropdownUtils.select_value("dropdown_id", "Option 1")
61
+
62
+ # Example: Enter Text in an Input Field
63
+ InputUtils.enter_text("input_field_id", "Sample Text")
64
+
65
+ # Example: Click a Link
66
+ LinkUtils.click_link("link_id")
67
+
68
+ # Example: Click a Tab
69
+ TabUtils.click_tab("tab_id")
70
+
71
+ # Example: Get a Table Cell Value
72
+ TableUtils.get_cell_value("table_id", 1, 2) # Row 1, Column 2
73
+
74
+ # Example: Get a Label Value
75
+ LabelUtils.get_label_value("label_id")
76
+
77
+ # Example: Get a Component Value
78
+ ComponentUtils.get_component_value("component_id")
79
+
80
+ # Example: Use the Component Driver
81
+ from robo_appian.utils.controllers.ComponentDriver import ComponentDriver
82
+ ComponentDriver.execute(wait, "Button", "Click", "Submit", None)
83
+
84
+ ## Dependencies
85
+
86
+ Python >= 3.8
87
+ Uses selenium
88
+
89
+ ## License
90
+
91
+ MIT License. See LICENSE.
@@ -0,0 +1,73 @@
1
+ # Robo Appian
2
+
3
+ Python library for automating Appian web UI test cases!
4
+
5
+ # Modules
6
+ ## Components
7
+
8
+ ButtonUtils: Find and click buttons.
9
+ DateUtils: Interact with date fields.
10
+ DropdownUtils: Interact with dropdowns.
11
+ InputUtils: Interact with input fields.
12
+ LabelUtils: Find labels.
13
+ LinkUtils: Click links.
14
+ TableUtils: Interact with tables.
15
+ TabUtils: Interact with tabs.
16
+ ComponentUtils: General utilities for components (input, dropdown, tab, etc).
17
+
18
+ ## Controllers
19
+
20
+ ComponentDriver: High-level interface to execute actions on components.
21
+
22
+ ## Exceptions
23
+
24
+ MyCustomError: Custom exception for specific error conditions.
25
+
26
+ # Usage
27
+
28
+ Import the utilities in your test scripts:
29
+
30
+ from robo_appian import (
31
+ ButtonUtils, ComponentUtils, DateUtils, DropdownUtils, InputUtils,
32
+ LabelUtils, LinkUtils, TableUtils, TabUtils
33
+ )
34
+
35
+ # Example: Set a Date Value
36
+ DateUtils.set_date_value("date_field_id", "2023-10-01")
37
+
38
+ # Example: Click a Button
39
+ ButtonUtils.click_button("submit_button_id")
40
+
41
+ # Example: Select a Dropdown Value
42
+ DropdownUtils.select_value("dropdown_id", "Option 1")
43
+
44
+ # Example: Enter Text in an Input Field
45
+ InputUtils.enter_text("input_field_id", "Sample Text")
46
+
47
+ # Example: Click a Link
48
+ LinkUtils.click_link("link_id")
49
+
50
+ # Example: Click a Tab
51
+ TabUtils.click_tab("tab_id")
52
+
53
+ # Example: Get a Table Cell Value
54
+ TableUtils.get_cell_value("table_id", 1, 2) # Row 1, Column 2
55
+
56
+ # Example: Get a Label Value
57
+ LabelUtils.get_label_value("label_id")
58
+
59
+ # Example: Get a Component Value
60
+ ComponentUtils.get_component_value("component_id")
61
+
62
+ # Example: Use the Component Driver
63
+ from robo_appian.utils.controllers.ComponentDriver import ComponentDriver
64
+ ComponentDriver.execute(wait, "Button", "Click", "Submit", None)
65
+
66
+ ## Dependencies
67
+
68
+ Python >= 3.8
69
+ Uses selenium
70
+
71
+ ## License
72
+
73
+ MIT License. See LICENSE.
@@ -0,0 +1,22 @@
1
+ [tool.poetry]
2
+ name = "robo_appian"
3
+ version = "0.0.2"
4
+ description = "Automate your Appian code testing with Python. Boost quality, save time."
5
+ authors = ["Dinil Mithra <dinilmithra@mailme@gmail.com>"]
6
+ readme = "README.md"
7
+ homepage = "https://github.com/dinilmithra/robo_appian"
8
+ repository = "https://github.com/dinilmithra/robo_appian.git"
9
+ classifiers = [
10
+ "Programming Language :: Python :: 3",
11
+ "Operating System :: OS Independent",
12
+ ]
13
+
14
+ [tool.poetry.dependencies]
15
+ python = "^3.12"
16
+ requests = "^2.25.1"
17
+ numpy = "*"
18
+ selenium = ">=4.34.0"
19
+
20
+ [build-system]
21
+ requires = ["poetry-core"]
22
+ build-backend = "poetry.core.masonry.api"
@@ -0,0 +1,11 @@
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.1.0"
File without changes
@@ -0,0 +1,72 @@
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
+ class ButtonUtils:
7
+ """
8
+ Utility class for interacting with button elements in Selenium-based Appian UI automation.
9
+
10
+ Usage Example:
11
+
12
+ from selenium.webdriver.support.ui import WebDriverWait
13
+ from robo_appian.utils.components.ButtonUtils import ButtonUtils
14
+
15
+ wait = WebDriverWait(driver, 10)
16
+ ButtonUtils.click(wait, "Login")
17
+
18
+ """
19
+
20
+ @staticmethod
21
+ def find(wait: WebDriverWait, label: str):
22
+ """
23
+ Finds a button element by its label.
24
+
25
+ Parameters:
26
+ wait: Selenium WebDriverWait instance.
27
+ label: The visible text label of the button.
28
+
29
+ Returns:
30
+ The Selenium WebElement for the button.
31
+
32
+ Example:
33
+ ButtonUtils.find(wait, "Submit")
34
+
35
+ """
36
+
37
+ # This method locates a button that contains a span with the specified label text.
38
+
39
+ xpath = f".//button[./span[contains(translate(normalize-space(.), '\u00a0', ' '), '{label}')]]"
40
+ component = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
41
+ return component
42
+
43
+ @staticmethod
44
+ def click(wait: WebDriverWait, label: str):
45
+ """
46
+ Clicks a button identified by its label.
47
+
48
+ Parameters:
49
+ wait: Selenium WebDriverWait instance.
50
+ label: The visible text label of the button.
51
+ Example:
52
+ ButtonUtils.click(wait, "Submit")
53
+
54
+ """
55
+ component = ButtonUtils.find(wait, label)
56
+ component.click()
57
+ @staticmethod
58
+ def clickInputButtonById(wait: WebDriverWait, id: str):
59
+ """
60
+ Finds and clicks an input button by its HTML id attribute.
61
+
62
+ Parameters:
63
+ wait: Selenium WebDriverWait instance.
64
+ id: The HTML id of the input button.
65
+
66
+ Example:
67
+ ButtonUtils.clickInputButtonById(wait, "button_id")
68
+
69
+ """
70
+ component = wait.until(EC.element_to_be_clickable((By.ID, id)))
71
+ component.click()
72
+ component.click()
@@ -0,0 +1,289 @@
1
+ from selenium.common.exceptions import NoSuchElementException
2
+ from selenium.webdriver import ActionChains
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.remote.webdriver import WebDriver
7
+ from selenium.webdriver.support.ui import WebDriverWait
8
+
9
+
10
+ class ComponentUtils:
11
+ """
12
+ Utility class for interacting with various components in Appian UI.
13
+
14
+ """
15
+
16
+ @staticmethod
17
+ def today():
18
+ """
19
+ Returns today's date formatted as MM/DD/YYYY.
20
+ """
21
+
22
+ from datetime import date
23
+
24
+ today = date.today()
25
+ yesterday_formatted = today.strftime("%m/%d/%Y")
26
+ return yesterday_formatted
27
+
28
+ @staticmethod
29
+ def yesterday():
30
+ """
31
+ Returns yesterday's date formatted as MM/DD/YYYY.
32
+ """
33
+
34
+ from datetime import date, timedelta
35
+
36
+ yesterday = date.today() - timedelta(days=1)
37
+ yesterday_formatted = yesterday.strftime("%m/%d/%Y")
38
+ return yesterday_formatted
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
+ @staticmethod
132
+ def findSuccessMessage(wait: WebDriverWait, message: str):
133
+ """
134
+ Finds a success message in the UI by its text.
135
+ Parameters:
136
+ wait: Selenium WebDriverWait instance.
137
+ message: The text of the success message to find.
138
+ Returns:
139
+ The Selenium WebElement for the success message.
140
+ Example:
141
+ ComponentUtils.findSuccessMessage(wait, "Operation completed successfully")
142
+ """
143
+ # This method locates a success message that contains a strong tag with the specified text.
144
+ # The message is normalized to handle any extra spaces.
145
+ # It uses the presence_of_element_located condition to ensure the element is present in the DOM.
146
+
147
+ xpath = f'.//div/div/p/span/strong[normalize-space(text())="{message}"]'
148
+ component = wait.until(EC.presence_of_element_located((By.XPATH, xpath)))
149
+ return component
150
+
151
+ @staticmethod
152
+ def findComponentUsingXpathAndClick(wait: WebDriverWait, xpath: str):
153
+ """
154
+ Finds a component using its XPath and clicks it.
155
+ Parameters:
156
+ wait: Selenium WebDriverWait instance.
157
+ xpath: The XPath of the component to find and click.
158
+ Example:
159
+ ComponentUtils.findComponentUsingXpathAndClick(wait, "//button[@id='submit']")
160
+
161
+ """
162
+ # This method locates a component using the provided XPath and clicks it.
163
+ # It uses the presence_of_element_located condition to ensure the element is present in the DOM.
164
+ # After locating the component, it clicks it to perform the action.
165
+ component = ComponentUtils.findComponentUsingXpath(wait, xpath)
166
+ component.click()
167
+
168
+ @staticmethod
169
+ def findComponentUsingXpath(wait: WebDriverWait, xpath: str):
170
+ """
171
+ Finds a component using its XPath.
172
+ Parameters:
173
+ wait: Selenium WebDriverWait instance.
174
+ xpath: The XPath of the component to find.
175
+ Returns:
176
+ The Selenium WebElement for the component.
177
+ Example:
178
+ ComponentUtils.findComponentUsingXpath(wait, "//button[@id='submit']")
179
+ """
180
+ # This method locates a component using the provided XPath.
181
+ # It uses the presence_of_element_located condition to ensure the element is present in the DOM.
182
+ # The method returns the WebElement for further interaction.
183
+ component = wait.until(EC.presence_of_element_located((By.XPATH, xpath)))
184
+ return component
185
+
186
+ @staticmethod
187
+ def checkComponentExistsByXpath(wait: WebDriverWait, xpath: str):
188
+ """
189
+ Checks if a component exists using its XPath.
190
+ Parameters:
191
+ wait: Selenium WebDriverWait instance.
192
+ xpath: The XPath of the component to check.
193
+ Returns:
194
+ True if the component exists, False otherwise.
195
+ Example:
196
+ ComponentUtils.checkComponentExistsByXpath(wait, "//button[@id='submit']")
197
+ """
198
+ # This method checks if a component exists by attempting to find it using the provided XPath.
199
+ # If the component is found, it returns True; otherwise, it catches the NoSuchElementException and returns False.
200
+ # It uses the presence_of_element_located condition to ensure the element is present in the DOM.
201
+
202
+ status = False
203
+ try:
204
+ ComponentUtils.findComponentUsingXpath(wait, xpath)
205
+ status = True
206
+ except NoSuchElementException:
207
+ pass
208
+
209
+ return status
210
+
211
+ @staticmethod
212
+ def checkComponentExistsById(driver: WebDriver, id: str):
213
+ """
214
+ Checks if a component exists using its ID.
215
+ Parameters:
216
+ driver: Selenium WebDriver instance.
217
+ id: The ID of the component to check.
218
+ Returns:
219
+ True if the component exists, False otherwise.
220
+ Example:
221
+ ComponentUtils.checkComponentExistsById(driver, "submit-button")
222
+ """
223
+ # This method checks if a component exists by attempting to find it using the provided ID.
224
+ # If the component is found, it returns True; otherwise, it catches the NoSuchElementException and returns False.
225
+ # It uses the find_element method to locate the element by its ID.
226
+
227
+ status = False
228
+ try:
229
+ driver.find_element(By.ID, id)
230
+ status = True
231
+ except NoSuchElementException:
232
+ pass
233
+
234
+ return status
235
+
236
+ @staticmethod
237
+ def findCount(wait: WebDriverWait, xpath: str):
238
+ """
239
+ Finds the count of components matching the given XPath.
240
+ Parameters:
241
+ wait: Selenium WebDriverWait instance.
242
+ xpath: The XPath of the components to count.
243
+ Returns:
244
+ The count of components matching the XPath.
245
+ Example:
246
+ count = ComponentUtils.findCount(wait, "//div[@class='item']")
247
+ """
248
+ # This method locates all components matching the provided XPath and returns their count.
249
+ # It uses the presence_of_all_elements_located condition to ensure all elements are present in the DOM.
250
+ # If no elements are found, it catches the NoSuchElementException and returns 0.
251
+
252
+ length = 0
253
+
254
+ try:
255
+ component = wait.until(
256
+ EC.presence_of_all_elements_located((By.XPATH, xpath))
257
+ )
258
+ length = len(component)
259
+ except NoSuchElementException:
260
+ pass
261
+
262
+ return length
263
+
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
+ @staticmethod
274
+ def tab(driver: WebDriver):
275
+ """
276
+ Simulates a TAB key press in the browser.
277
+
278
+ Parameters:
279
+ driver: Selenium WebDriver instance.
280
+ Example:
281
+ ComponentUtils.tab(driver)
282
+ """
283
+ # This method simulates a TAB key press in the browser using ActionChains.
284
+ # It creates an ActionChains instance, sends the TAB key, and performs the action.
285
+ # This is useful for navigating through form fields or components in the UI.
286
+ # It uses the ActionChains class to perform the key press action.
287
+
288
+ actions = ActionChains(driver)
289
+ actions.send_keys(Keys.TAB).perform()