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.