Skip to main content

Selenium Actions

example workflow

PyPI - https://pypi.org/project/selenium-actions/

Simple action framework using selenium 🚀

Real life examples

Actions

Create actions object

from seleniumactions import Actions, FluentFinder

# all timeouts are in seconds
timeouts = {
    "short": 2,
    "medium": 3,
    "long": 5,
    "absurd": 10
}
finder = FluentFinder(
    driver,
    timeouts=timeouts,
    default_timeout=timeouts["medium"]
)
actions = Actions(
    finder,
    wait_for_condition_timeout=15,
    wait_between=0.5
)

Examples

from seleniumactions import Actions, LocatorExists


# locators (tuples)
main_header = ('xpath', '//h1[.="Home"]')
menu = ('id', 'menu')
news_option = ('xpath', '//menu-option[.="News"]')
search_input = ('xpath', '//search-news//input')
form = ('xpath', '//form')

# take some actions 🚀
actions.goto('https://some.site.io')  # open site
actions.wait_for(LocatorExists(main_header))  # wait for condition to be met with default timeout from configuration applied
actions.click(menu)  # default timeout from configuration applied
actions.click(news_option, timeout='medium')  # 'medium' timeout from configuration applied
actions.type_text(search_input, text='python', explicit_timeout=3)  # explicit timeout in seconds (always overrides any timeout from configuration)
actions.submit()  # submit default form (//form) - works when theres only one form on page
# actions.submit(form)  # u can pass form locator also
actions.wait_for(LocatorExists(('xpath', '//search-results')), timeout='long')  # wait for condition with 'long' timeout from configuration applied

# assert ect...

Locators

Lest say we have HTML component (simplified for example 👀)

<ul>
    <li class="menu"> Foo</li>
    <li class="menu"> Bar </li>
    <li class="menu">Baz </li>
</ul>

We want to be able to click each one of them. So the xpath values for them will be:

foo_xpath = "//ul/li[@class='menu' and contains(., 'Foo')]"
bar_xpath = "//ul/li[@class='menu' and contains(., 'Bar')]"
baz_xpath = "//ul/li[@class='menu' and contains(., 'Baz')]"

It can be painfull. Of course you can write a function and parametrize the string

def get_menu_xpath(label: str):
    return f"//ul/li[@class='menu' and contains(., '{label}')]"

It's kind of frustrating...

We can use Locator class to solve that problem

from seleniumactions import Locator

# You can define any parameters to a locator value template
menu_element = Locator(Using.XPATH, "//ul/li[@class='{class_name}' and contains(., '{label}')]")
menu_element.get_by(class_name='menu', label='Foo')
# >>> ("xpath", "//ul/li[@class='menu' and contains(., 'Foo')]")
menu_element.get_by(class_name='active-menu', label='Bar')
# >>> ("xpath", "//ul/li[@class='active-menu' and contains(., 'Bar')]")

# When you forget to pass values you'll get clear error
button = Locator(Using.NAME, '{action}-{foo}')
button.get_by()
# ValueError: get_by method is missing keyword arguments: ['action', 'foo']
button.get_by(action='goto')
# ValueError: get_by method is missing keyword argument: foo

# cool! 🕹 we can play with it!

Examples (advanced)

We can go step further and implement our own custom locators 🚀

# utils/locators.py
from seleniumactions import Using, Locator


class ButtonByLabel(Locator):
    def __init__(self) -> None:
        super().__init__(Using.XPATH, "//button[.='{label}']")


class ButtonSubmit(Locator):
    def __init__(self) -> None:
        super().__init__(Using.XPATH, "//button[@type='submit']")


class LinkByExactText(Locator):
    def __init__(self) -> None:
        super().__init__(Using.XPATH, "//a[.='{text}']")


class LinkByContainedText(Locator):
    def __init__(self) -> None:
        super().__init__(Using.XPATH, "//a[contains(.='{text}')]")


class HeaderByExactText(Locator):
    def __init__(self) -> None:
        super().__init__(Using.XPATH, "//h*[.='{text}']")


class Locators:
    # for importing and better intellisence in other modules
    link = LinkByExactText()
    link_contains = LinkByContainedText()
    button = ButtonByLabel()
    submit_button = ButtonSubmit()
    header = HeaderByExactText()


###########################################
# test.py
from utlis.locators import Locators as Loc

# raw calling
actions.click(Loc.link.get_by(text='HOME'))
actions.wait_for(Loc.header.get_by(text='Welcome home!'))
actions.click(Loc.link_contains.get_by(text='see more...'))
actions.click(Loc.button.get_by(label='Next'))
actions.click(Loc.submit_button.get_by())

# or for more readability
home_link = Loc.link.get_by(text='HOME')
see_more_link = Loc.link_contains.get_by(text='see more...')
next_button = Loc.button.get_by(label='Next')
submit_button = Loc.submit_button.get_by()
home_header = Loc.header.get_by(text='Welcome home!')

actions.click(home_button)
actions.wait_for(home_header)
actions.click(see_more_link)
actions.click(next_button)
actions.click(submit_button)

# SUPER DRY!

Release files for selenium-actions 1.0.6

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for selenium-actions 1.0.6
File Size Uploaded
selenium-actions-1.0.6.tar.gz 8.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for selenium-actions 1.0.6
File Interpreter ABI Platform
selenium_actions-1.0.6-py3-none-any.whl Python 3 none any Details

Total release size: 18.8 kB

Release files / selenium-actions-1.0.6.tar.gz

Download URL selenium-actions-1.0.6.tar.gz
Size 8.3 kB
Tags Source
SHA-256 checksum
How to use checksums
d6cf3f96262e89492e7fe5863ca9f913ab6de2ef3e31237a8e880e5dadd441ed
BLAKE2b-256 checksum
How to use checksums
a5c7fd33916f61c002132c4145d573b86ab1c53478f775ab0232be743ae4abf4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/4.0.1 CPython/3.9.15

Release files / selenium_actions-1.0.6-py3-none-any.whl

Download URL selenium_actions-1.0.6-py3-none-any.whl
Size 10.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
81c5b3f49aae1aa0a47174dccb2f20a0868c9d2086f7ec1a6cd7975ca8d5607a
BLAKE2b-256 checksum
How to use checksums
694fbb463b2f57fbebf06feacb4eba352efb227cb736bcc1ab01a4584bd8e4b1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/4.0.1 CPython/3.9.15

Release history Release notifications | RSS feed

This release

1.0.6 This release

2 release files

1.0.5

2 release files

1.0.3

2 release files

1.0.2

2 release files

1.0.1

2 release files

1.0.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page