Actions

Actions are the things that an Actor can do, using their Abilities.

Using Actions

Actions can be used pretty much anywhere. They will typically be used to create Tasks or move around in your Features. Here is an example of using the Click action:

from screenpy.actions import Click

from ..user_interface.homepage import LOGIN_LINK


Perry.attempts_to(Click.on_the(LOGIN_LINK))

Actors will always only attempt to perform an action. They may not actually have the correct Abilities, after all. If an actor is unable to perform an action or task, they will raise an UnableToPerformError.

Writing New Actions

Occasionally, you might find that the base actions don’t quite cover a unique use case you have for your test suite. Since Screenplay Pattern is built to be extensible, it is easy and encouraged to create your own custom actions to achieve what you need! The only requirement for creating more actions is that they have a perform_as method defined which takes in the actor who will perform the action.

A base class for Actions is provided to ensure the required methods are defined: screenpy.actions.base_action.BaseAction

Let’s take a look at what an extremely contrived custom action, ChecksTheSpelling, might look like:

# actions/checks_the_spelling.py
from screenpy.actions import BaseAction


class ChecksTheSpelling(BaseAction):
    @staticmethod
    def of_words_in_the(locator):
        return ChecksSpelling(locator)

    def perform_as(self, the_actor):
        the_actor.uses_ability_to(CheckSpelling).to_check()

    def __init__(self, locator):
        self.locator = locator

ScreenPy attempts to follow a convention of putting all the static methods first, then the perform_as function, and leaving the dunder methods at the bottom. This way the most important methods are first for someone perusing your code.

Tasks

Sometimes, your actors might repeat the same series of actions several times. A grouping of common actions can be abstracted into a Task in your Tasks.

A common task for Screenplay Pattern suites is logging in to your application under test. This login task might look something like this:

# tasks/login.py
import os

from screenpy import Actor
from screenpy.actions import BaseAction, Click, Enter

from ..user_interface.homepage import (
    SIGN_ON_LINK,
    THE_USERNAME_FIELD,
    THE_PASSWORD_FIELD,
    LOGIN_BUTTON,
)


class LoginSuccessfully(BaseAction):
    """
    Log in to the application successfully.
    """

    @staticmethod
    def using_credentials(username: str, password: str) -> "LoginSuccessfully":
        """
        Supply the credentials for the account.

        Args:
            username: the username to use.
            password: the password to use.
        """
        return LoginSuccessfully(username, password)

    def perform_as(self, the_actor: Actor) -> None:
        """
        Asks the actor to log in to the application.

        Args:
            the_actor: the actor who will perform this task.

        Raises:
            UnableToPerformError: the actor does not have the ability to
                BrowseTheWeb.
        """
        the_actor.attempts_to(
            Click.on(SIGN_ON_LINK),
            Wait.for_the(THE_USERNAME_FIELD).to_appear(),
            Enter.the_text(self.username).into(THE_USERNAME_FIELD),
            Enter.the_text(self.password).into(THE_PASSWORD_FIELD),
            Click.on_the(LOGIN_BUTTON)
        )

    def __init__(self, username: str, password: str):
        self.username = username
        self.password = password

And there you have it! Now all you have to do is ask your actor to attempt to LoginSuccessfully, and you’ve got the same set of actions everywhere.

Note that tasks, just like actions, are required to have a perform_as method defined. You can use the BaseAction class for tasks as well.

Provided Actions

Open

class screenpy.actions.open.Open(location: Union[str, object])

A very important action; opens the browser! An Open action is expected to be instantiated via its static browser_on() method. A typical invocation might look like:

Open.browser_on(the_homepage_url)

Open.browser_on(HomepageObject)

If you pass in an object, make sure the object has a url property that can be referenced by this action.

It can then be passed along to the Actor to perform the action.

static browser_on(location: Union[str, object]) → screenpy.actions.open.Open

Creates a new Open action which holds its destined location.

Parameters:location – The URL to open when this action is performed, or an object containing a url property that holds the URL to open when this action is performed.
Returns:Open
perform_as(the_actor: screenpy.actor.Actor) → None

Asks the supplied actor to perform this Open action, using their ability to browse the web.

Parameters:the_actor – The Actor who will perform the action.
Raises:|UnableToPerformError| – the actor does not have the ability to BrowseTheWeb.
static their_browser_on(location: Union[str, object]) → screenpy.actions.open.Open

Syntactic sugar for browser_on().

Click

class screenpy.actions.click.Click(target: screenpy.target.Target)

Clicks on an element! A Click action is expected to be instantiated via its static on() or on_the() methods. A typical invocation might look like:

Click.on_the(PROFILE_LINK)

It can then be passed along to the Actor to perform the action.

static on(target: screenpy.target.Target) → screenpy.actions.click.Click

Syntactic sugar for on_the().

static on_the(target: screenpy.target.Target) → screenpy.actions.click.Click

Creates a new Click action with its crosshairs aimed at the provided target.

Parameters:target – The Target describing the element to click.
Returns:Click
perform_as(the_actor: screenpy.actor.Actor) → None

Asks the actor to find the element described by the stored target, and then clicks it. May wait for another target to appear, if then_wait_for() had been called.

Parameters:

the_actor – the Actor who will perform the action.

Raises:
  • |DeliveryError| – an exception was raised by Selenium.
  • |UnableToPerformError| – the actor does not have the ability to BrowseTheWeb.
then_wait_for(target: screenpy.target.Target) → screenpy.actions.click.Click

Syntactic sugar for then_wait_for_the().

then_wait_for_the(target: screenpy.target.Target) → screenpy.actions.click.Click

Supplies a target to wait for after performing the click.

This method has been deprecated as of version 1.0.0. Please use the included Wait action instead. This method will be removed in version 2.0.0.

Parameters:target – The Target describing the element to wait for after performing the click.
Returns:Click

Clear

class screenpy.actions.clear.Clear(target: screenpy.target.Target)

Clears the text from an input field. A Clear action is expected to be instantiated by its static the_text_from() method. A typical invocation might look like:

Clear.the_text_from(COMMENT_FIELD)

It can then be passed along to the Actor to perform the action.

perform_as(the_actor: screenpy.actor.Actor) → None

Asks the actor to performs the Clear action, clearing the text from the targeted input field using their ability to browse the web.

Parameters:the_actor – The Actor who will perform this action.
Raises:|UnableToPerformError| – the actor does not have the ability to BrowseTheWeb.
static the_text_from(target: screenpy.target.Target) → screenpy.actions.clear.Clear

Syntactic sugar for the_text_from_the().

static the_text_from_the(target: screenpy.target.Target) → screenpy.actions.clear.Clear

Creates a new Clear action with the provided text.

Parameters:target – the Target from which to clear the text.
Returns:Clear

Enter

class screenpy.actions.enter.Enter(text: str, mask: bool = False)

Enters text into an input field. An Enter action is expected to be instantiated by its static the_text() method. A typical invocation might look like:

Enter.the_text(“Hello world!”).into(COMMENT_FIELD)

It can then be passed along to the Actor to perform the action.

into(target: screenpy.target.Target) → screenpy.actions.enter.Enter

Supplies the target to enter the text into. This is most likely an input field.

Parameters:target – The Target describing the input field.
Returns:Enter
into_the(target: screenpy.target.Target) → screenpy.actions.enter.Enter

Syntactic sugar for into()

on(target: screenpy.target.Target) → screenpy.actions.enter.Enter

Syntactic sugar for into()

perform_as(the_actor: screenpy.actor.Actor) → None

Asks the actor to perform the Enter action, entering the text into the targeted input field using their ability to browse the web.

If this Enter object’s then_hit() method was called, it will also hit the supplied keys. Finally, if the then_wait_for() method was called, it will wait for the supplied target to appear.

Parameters:

the_actor – the Actor who will perform this action.

Raises:
  • |DeliveryError| – an exception was raised by Selenium.
  • |UnableToActError| – no target was supplied.
  • |UnableToPerformError| – the actor does not have the ability to BrowseTheWeb.
static the_keys(text: str) → screenpy.actions.enter.Enter

Syntactic sugar for the_text().

static the_password(text: str) → screenpy.actions.enter.Enter

Syntactic sugar for the_secret().

static the_secret(text: str) → screenpy.actions.enter.Enter

Creates a new Enter action with the provided text, but will mask the text for logging. The text will appear as “[CENSORED]” in the report. It is expected that the next call will be to the instantiated Enter object’s into() method.

Parameters:text – the text to enter into the target, but it’s a secret.
Returns:Enter
static the_text(text: str) → screenpy.actions.enter.Enter

Creates a new Enter action with the provided text. It is expected that the next call will be to the instantiated Enter object’s into() method.

Parameters:text – the text to enter into the target.
Returns:Enter
then_hit(*keys) → screenpy.actions.enter.Enter

Supplies additional keys to hit after entering the text, for example if the keyboard ENTER key should be pressed.

Parameters:keys – the keys to hit afterwards. These are probably the constants from Selenium’s Keys, but they can be strings if you know the codes.
Returns:Enter
then_press(*keys) → screenpy.actions.enter.Enter

Syntactic sugar for then_hit().

then_wait_for(target: screenpy.target.Target) → screenpy.actions.enter.Enter

Supplies the target to wait for after entering text (and hitting any additional keys, if this object’s then_hit() method was called).

This method has been deprecated as of version 1.0.0. Please use the included Wait action instead. This method will be removed in version 2.0.0.

Parameters:target – the Target to wait for after entering text.
Returns:Enter

Enter2FAToken

class screenpy.actions.enter_2fa_token.Enter2FAToken(target: screenpy.target.Target)

Enters the current two-factor authentication token into an input field. An Enter2FAToken action is expected to be instantiated by its static into_the() method. A typical invocation might look like:

Enter2FAToken.into_the(2FA_INPUT_FIELD)

It can then be passed along to the Actor to perform the action.

static into(target: screenpy.target.Target) → screenpy.actions.enter_2fa_token.Enter2FAToken

Syntactic sugar for into_the()

static into_the(target: screenpy.target.Target) → screenpy.actions.enter_2fa_token.Enter2FAToken

Provide the input field into which to enter the 2FA token.

Parameters:target – the Target describing the input field.
Returns:Enter2FAToken
perform_as(the_actor: screenpy.actor.Actor) → None

Asks the actor to perform the Enter2FAToken action, which will get the current token using the actor’s AuthenticateWith2FA ability.

Parameters:the_actor – the Actor who will perform this action.
Raises:|UnableToPerformError| – if the actor does not have the abilities to AuthenticateWith2FA and BrowseTheWeb.

Select

class screenpy.actions.select.Select

Selects an option from a dropdown menu. This is an entry point that will create the correct specific Select action that will need to be used, depending on how the option needs to be selected. Some examples of invocations:

Select.the_option_named(“January”).from_the(MONTH_DROPDOWN)

Select.the_option_at_index(0).from_the(MONTH_DROPDOWN)

Select.the_option_with_value(“jan”).from_the(MONTH_DROPDOWN)

It can then be passed along to the Actor to perform the action.

static the_option_at_index(index: Union[int, str]) → screenpy.actions.select.SelectByIndex

Instantiate a SelectByIndex class which will select the option at the specified index. This index is 0-based.

Parameters:index – the index (0-based) of the option to select.
Returns:SelectByIndex
static the_option_named(text: str) → screenpy.actions.select.SelectByText

Instantiate a SelectByText class which will select the option with the given text.

Parameters:text – the text of the option to select.
Returns:SelectByText
static the_option_with_value(value: str) → screenpy.actions.select.SelectByValue

Instantiate a SelectByText class which will select the option with the given text.

Parameters:value – the value of the option to select.
Returns:SelectByText
class screenpy.actions.select.SelectByText(text: str, target: Optional[screenpy.target.Target] = None)

A specialized Select action that chooses the option by text. This class is meant to be accessed via the Select action’s static the_option_named() method. A typical invocation might look like:

Select.the_option_named(“January”).from_the(MONTH_DROPDOWN)

It can then be passed along to the Actor to perform the action.

from_(target: screenpy.target.Target) → screenpy.actions.select.SelectByText

Syntactic sugar for from_the().

from_the(target: screenpy.target.Target) → screenpy.actions.select.SelectByText

Provides the target to select the option from.

Parameters:target – the Target describing the dropdown or multi-select element to select the option from.
Returns:SelectByText
perform_as(the_actor: screenpy.actor.Actor) → None

Asks the actor to attempt to find the dropdown element described by the stored target, then performs the select action.

Parameters:

the_actor – The Actor who will perform the action.

Raises:
  • |DeliveryError| – an exception was raised by Selenium.
  • |UnableToActError| – no target was supplied.
  • |UnableToPerformError| – the actor does not have the ability to BrowseTheWeb.
class screenpy.actions.select.SelectByIndex(index: Union[int, str], target: Optional[screenpy.target.Target] = None)

A specialized Select action that chooses the option by its index. This class is meant to be accessed via the Select action’s static the_option_at_index() method. A typical invocation might look like:

Select.the_option_at_index(0).from_the(MONTH_DROPDOWN)

It can then be passed along to the Actor to perform the action.

from_(target: screenpy.target.Target) → screenpy.actions.select.SelectByIndex

Syntactic sugar for from_the().

from_the(target: screenpy.target.Target) → screenpy.actions.select.SelectByIndex

Provides the target to select the option from.

Parameters:target – The Target describing the dropdown or multi-select element to select the option from.
Returns:SelectByIndex
perform_as(the_actor: screenpy.actor.Actor) → None

Asks the actor to attempt to find the dropdown element described by the stored target, then performs the select action.

Parameters:

the_actor – The Actor who will perform the action.

Raises:
  • |DeliveryError| – an exception was raised by Selenium.
  • |UnableToActError| – no target was supplied.
  • |UnableToPerformError| – the actor does not have the ability to BrowseTheWeb.
class screenpy.actions.select.SelectByValue(value: Union[int, str], target: Optional[screenpy.target.Target] = None)

A specialized Select action that chooses the option by its value. This class is meant to be accessed via the Select action’s static the_option_with_value() method. A typical invocation might look like:

Select.the_option_with_value(“jan”).from_the(MONTH_DROPDOWN)

It can then be passed along to the Actor to perform the action.

from_(target: screenpy.target.Target) → screenpy.actions.select.SelectByValue

Syntactic sugar for from_the().

from_the(target: screenpy.target.Target) → screenpy.actions.select.SelectByValue

Provides the target to select the option from.

Parameters:target – The Target describing the dropdown or multi-select element to select the option from.
Returns:SelectByValue
perform_as(the_actor: screenpy.actor.Actor) → None

Asks the actor to attempt to find the dropdown element described by the stored target, then performs the select action.

Parameters:

the_actor – The Actor who will perform the action.

Raises:
  • |DeliveryError| – an exception was raised by Selenium.
  • |UnableToActError| – no target was supplied.
  • |UnableToPerformError| – the actor does not have the ability to BrowseTheWeb.

AcceptAlert

class screenpy.actions.accept_alert.AcceptAlert

Accepts an alert. An AcceptAlert action is expected to be instantiated as it is, no static methods for this one. The only invocation looks like:

AcceptAlert()

It can then be passed along to the Actor to perform the action.

perform_as(the_actor: screenpy.actor.Actor) → None

Asks the actor to perform the AcceptAlert action.

Parameters:

the_actor – The Actor who will perform this action.

Raises:
  • |BrowsingError| – no alert was present.
  • |UnableToPerformError| – the actor does not have the ability to BrowseTheWeb.

DismissAlert

class screenpy.actions.dismiss_alert.DismissAlert

Dismisses an alert. An DismissAlert action is expected to be instantiated as it is, no static methods for this one. The only invocation looks like:

DismissAlert()

It can then be passed along to the Actor to perform the action.

perform_as(the_actor: screenpy.actor.Actor) → None

Asks the actor to perform the DismissAlert action.

Parameters:

the_actor – The Actor who will perform this action.

Raises:
  • |BrowsingError| – no alert was present.
  • |UnableToPerformError| – the actor does not have the ability to BrowseTheWeb.

RespondToThePrompt

class screenpy.actions.respond_to_the_prompt.RespondToThePrompt(text: str)

Responds to a javascript prompt by entering the specified text and accepting the prompt. RespondToThePrompt is expected to be instantiated using its with_() static method. A typical instantiation might look like:

RespondToThePrompt.with_(“I am big. It’s the pictures that got small.”)

It can then be passed along to the Actor to perform the action.

perform_as(the_actor: screenpy.actor.Actor) → None

Asks the actor to perform the RespondToPrompt action.

Parameters:

the_actor – The Actor who will perform this action.

Raises:
  • |BrowsingError| – no alert was present.
  • |UnableToPerformError| – the actor does not have the ability to BrowseTheWeb.
static with_(text: str) → screenpy.actions.respond_to_the_prompt.RespondToThePrompt

Specifies the text to enter into the prompt.

Parameters:text – the text to enter.
Returns:RespondToTheText

SwitchTo

class screenpy.actions.switch_to.SwitchTo(target: Optional[screenpy.target.Target])

Switches to something, most likely an iframe, or back to default. A SwitchTo action is expected to be instantiated by its static the() or default() methods, or on its own. A typical invocation might look like:

SwitchTo.the(ORDERS_FRAME)

SwitchTo.default()

It can then be passed along to the Actor to perform the action.

static default() → screenpy.actions.switch_to.SwitchTo

Switches back to the default frame, the browser window.

Returns:SwitchTo
perform_as(the_actor: screenpy.actor.Actor) → None

Asks the actor to perform the SwitchTo action.

Parameters:the_actor – The Actor who will perform this action.
Raises:|UnableToPerformError| – the actor does not have the ability to BrowseTheWeb.
static the(target: screenpy.target.Target) → screenpy.actions.switch_to.SwitchTo

Provide the element to switch to.

Parameters:target – the Target describing the element to switch to.
Returns:SwitchTo

Wait

class screenpy.actions.wait.Wait(seconds: int = 20, target: Optional[screenpy.target.Target] = None)

Waits for an element to fulfill a certain condition. A Wait action is expected to be instantiated by its for_() method, followed by one of its strategies. By default, the to_appear() strategy is used. Wait can also be instantiated with an integer, like Wait(30), which will set the timeout to be used. Some examples of invocations:

Wait.for_the(LOGIN_FORM)

Wait.for_the(WELCOME_BANNER).to_contain_text(“Welcome!”)

Wait.for(CONFETTI).to_disappear()

Wait(10).seconds_for_the(PARADE_FLOATS).to_appear()

It can then be passed along to the Actor to perform the action.

static for_(target: screenpy.target.Target) → screenpy.actions.wait.Wait

Creates a new Wait action holding the provided target.

Parameters:target – The Target to wait for.
Returns:Wait
static for_the(target: screenpy.target.Target) → screenpy.actions.wait.Wait

Syntactic sugar for for_()

perform_as(the_actor: screenpy.actor.Actor) → None

Asks the actor to perform the Wait action, using the contained strategy and any extra arguments provided.

Parameters:

the_actor – The Actor who will perform this action.

Raises:
  • |UnableToActError| – no target was supplied.
  • |UnableToPerformError| – the actor does not have the ability to BrowseTheWeb.
seconds_for(target: screenpy.target.Target) → screenpy.actions.wait.Wait

Sets the target after invoking Wait with the number of seconds you want wait to allow the target to fulfill the expected condition. For example:

Wait(60).seconds_for(CONFETTI).to_disappear()

This will ask the actor to wait up to 60 seconds for CONFETTI to disappear before throwing an exception.

Parameters:target – The Target to wait for.
Returns:Wait
seconds_for_the(target: screenpy.target.Target) → screenpy.actions.wait.Wait

Syntactic sugar for seconds_for()

to_appear() → screenpy.actions.wait.Wait

Uses Selenium’s “visibility of element located” strategy. This is the default strategy, so calling this is not strictly necessary.

Returns:Wait
to_be_clickable() → screenpy.actions.wait.Wait

Uses Selenium’s “to be clickable” strategy.

Returns:Wait
to_contain_text(text: str) → screenpy.actions.wait.Wait

Uses Selenium’s “text to be present in element” strategy.

Parameters:text – the text to expect to be present.
Returns:Wait
to_disappear() → screenpy.actions.wait.Wait

Uses Selenium’s “invisibility of element located” strategy.

Returns:Wait
using(strategy: object) → screenpy.actions.wait.Wait

Uses the given strategy to wait for the target.

Parameters:strategy – the condition to use to wait. This can be one of Selenium’s Expected Conditions, or it can be a custom Callable that accepts a Tuple[By, str] locator.
Returns:Wait

Pause

class screenpy.actions.pause.Pause(number: float)

Pauses the actor’s actions for a set amount of time. This class should only be used when absolutely necessary. You must call one of the “…_because” methods to pass in the reason for your pause; an UnableToActError will be raised if no reason was given when the actor attempts to perform this action.

A Pause action is expected to be instantiated by its static for_() method, followed by one of the methods that supply a reason (seconds_because, second_because, or milliseconds_because). A typical invocation might look like:

Pause.for_(500).milliseconds_because(“the welcome banner needs to hide.”)

It can then be passed along to the Actor to perform the action.

static for_(number: int) → screenpy.actions.pause.Pause

How many seconds or milliseconds to wait for.

Parameters:number – the number of seconds or milliseconds to sleep for.
Returns:Pause
milliseconds_because(reason: str) → screenpy.actions.pause.Pause

Tells the Pause instance to use milliseconds and provides a reason for the pause. Hard waits are the worst of all wait strategies, so providing a reason will help explain why it was necessary to use this strategy.

Parameters:reason – the reason for needing to pause.
Returns:Pause
perform_as(the_actor: screenpy.actor.Actor) → None

Asks the actor to take their union-mandated break.

Parameters:the_actor – the Actor who will perform this action.
Raises:|UnableToActError| – no reason was supplied.
second_because(reason: str) → screenpy.actions.pause.Pause

Syntactic sugar for Pause.seconds_because

seconds_because(reason: str) → screenpy.actions.pause.Pause

Tells the Pause instance to use seconds and provides a reason for the pause. Hard waits are the worst of all wait strategies, so providing a reason will help explain why it was necessary to use this strategy.

Parameters:reason – the reason for needing to pause.
Returns:Pause

Debug

class screenpy.actions.debug.Debug

In long chains of actions, it can be difficult to drop a debugger in the right place. This action can be placed anywhere in the chain to give you a debugger in the middle of the action chain. This action uses Python 3.7+’s breakpoint() call if it can, otherwise it will default to pdb.set_trace().

A Debug action is expected to be instantiated in the standard way. A typical instantiation will always look like:

Debug()

It can then be passed along to the Actor to perform the action.

perform_as(the_actor: screenpy.actor.Actor) → None

Activates a debugger.

Parameters:the_actor – the Actor who will perform this action.