Actions#
❓What Are Actions?#
Actions are the glue that holds everything together. An action method will chain together UI Interactions from the Page to complete full tasks.
Each Action class uses CommonActions which itself uses UI Interactions from the BasePage.
Since these are “Common” actions, they will not cover specific use cases for your application but are handy time-savers and allow you to avoid writing some WebDriver based functionality.
🌍 Real-world Analogy (Click to expand)
Imagine a warehouse.
On the factory floor, there are several workers. Each worker can perform a very specific motion:
stack a box
label a box
move a box
scan a barcode
They don’t decide when to do these things or why. They just do the motion they’ve been trained to do — nothing more.
Now imagine the floor manager.
🧑💼 The Floor Manager = Actions
The floor manager stands in the middle of the warehouse holding a clipboard full of instructions.
He receives a workflow from upper management:
Build five stacks of boxes
Label each stack
Move them to dispatch
The manager doesn’t question the order, the priority, or whether the job needs to be done today or tomorrow.
He simply:
Looks at the workflow he was given
Breaks it down into small steps
Sends workers off to perform each step in the correct sequence
The manager never performs the physical work himself. He simply orchestrates the workers in a predictable, repeatable way.
No decisions. No branching. No “if admin then…” logic. Just run the workflow exactly as defined.
🧠 And who gives the manager his instructions?
That would be the CEO.
🧓 CEO = Steps
The CEO decides:
which workflow should run
when it should run
under what conditions
who the workflow applies to
what data goes into it
He hands the list of workflows to the floor manager and expects them carried out accurately.
The CEO never talks directly to the workers and never performs warehouse tasks. He stays high-level and outcome-focused.
🎬 Actions Responsibilities#
What it should do#
Chain UI Interactions from the Page together to create workflows
Handle multiple arguments such as username & password
Linear work-flow only
What it should not do#
Contain any branching logic
No decisions about when or how the action is called should be included in the actions page
🎨 Creating a New Actions Class#
To initialise a new Actions class, you can use the ArgoBEAST CLI:
argobeast create actions <name>
This generates the basic scaffolding for a new Actions class.
The class will assume the existence of the respective PageClass and import it automatically.
NOTE: If you have not initialised the page, the import will fail
Example#
Below is a simple ActionClass for a login screen. Notice how there is no “if admin…else” logic, just a simple workflow calling the Page UI Interactions.
from argo_beast.common_actions.common_actions import CommonActions
from pages.login_page import LoginPage
class LoginActions(CommonActions):
PageClass = LoginPage
def __init__(self, page):
super().__init__(page)
def step_go_to_page(context):
return self.page.get_header()
def log_in(self,username,password):
self.page.enter_username(username)
self.page.enter_password(password)
self.page.click_submit()
Working With ActionsClass#
Each ActionsClass uses the CommonActions - This is a collection of common UI interaction patterns to save you time repeating logic.
Available Common Actions (Click to Expand)
- class argo_beast.common_actions.common_actions.CommonActions(page: BasePage)#
Bases:
object- click_element_containing_text(locator: tuple, text: str)#
Click the first element matching the locator that contains the text
- Parameters:
locator – Locator tuple
text – Text to search for
- Returns:
True if clicked, False otherwise
- click_element_with_text(locator, text)#
Click the first element matching the locator with exact text
- Parameters:
locator – Locator tuple
text – Exact text to match
- Returns:
True if clicked, False otherwise
- find_in_list(elements: list, text: str, partial: bool = False)#
Find an element in a list by text
- Parameters:
elements – List of WebElements
text – Text to search for
partial – Whether to match partially
- Returns:
WebElement or None
- get_element_containing_text(locator, text)#
Get the first element matching the locator that contains the text
- Parameters:
locator – Locator tuple
text – Text to search for
- Returns:
WebElement or None
- get_element_with_text(locator, text)#
Get the first element matching the locator with exact text
- Parameters:
locator – Locator tuple
text – Exact text to match
- Returns:
WebElement or None
- populate_generic_form(form_map, data_input)#
Iterates through data and populates the form using the provided map. Supports both explicit types: ((By.ID, ‘x’), ‘select’) And implicit defaults: (By.ID, ‘x’) -> defaults to ‘text’
- Parameters:
form_map – A dictionary of form elements (tuples)
data_input – A dictionary of data the user wishes to add to the form
- retry_click(locator: tuple, retries: int = 3, delay: float = 0.5)#
Retry clicking an element multiple times to handle flaky clicks
- Parameters:
locator – Locator tuple
retries – Number of retry attempts
delay – Delay between attempts in seconds
- Returns:
True if clicked, False otherwise
- send_keyboard_input(locator, *keys)#
Send keyboard input to an element using string names. Usage: self.send_keyboard_input(LOCATOR, “CONTROL”, “ENTER”)
- upload_file(locator, filepath)#
Executes the logic to upload a file to a standard file input element
- Parameters:
locator – The locator for the file input
filepath – The path where the file is located
- verify_column_headers(table_locator, expected_headers)#
Verifies that the table contains all expected column headers.
- Parameters:
table_locator – Locator for the table
expected_headers – List of expected column header names
- Returns:
True if all headers are present, raises AssertionError otherwise
- verify_row_does_not_exist(table_locator, expected_data: dict)#
Asserts that NO row matches the criteria.
- verify_row_exists(table_locator, expected_data: dict)#
Asserts that at least one row matches ALL keys/values in expected_data.
- Parameters:
table_locator – Locator for the table
expected_data – Dictionary of expected key-value pairs
- Returns:
True if a matching row is found, raises AssertionError otherwise
- verify_table_contains_count(table_locator, count: int, filter_data=None)#
Asserts that exactly X rows match the filter criteria.
- Parameters:
table_locator – Locator for the table
count – Expected number of rows (int or str convertible to int)
filter_data – Optional dict of filter criteria
- Returns:
True if count matches, raises AssertionError otherwise.
If filter_data is None, checks total row count.
- wait_for_text(locator, text)#
Wait for an element to have exact text
- Parameters:
locator – Locator tuple
text – Exact text to wait for
- Returns:
True if text matches, False if timeout
- wait_for_text_contains(locator: tuple, text: str)#
Wait for an element to contain text
- Parameters:
locator – Locator tuple
text – Text to wait for
- Returns:
True if text is contained, False if timeout
- wait_for_url_contains(partial_url: str)#
Wait for the current URL to contain a substring
- Parameters:
partial_url – Substring to wait for in the URL
- Returns:
True if URL contains substring, False if timeout
TL;DR#
The ActionsClass doesn’t contain any complex logic, any decisions and branching happens in the Steps. Actions simply chain together UI Interactions from the respective Page to make something happen.