Selenium Actions - Action Based Selenium library - selenium in more accessible way :)
Project description
Selenium Actions
PyPI - https://pypi.org/project/selenium-actions/
Simple action framework using selenium 🚀
Real life examples
- behave - https://github.com/bigSAS/selenium-actions-behave-example
- pytest - todo
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!
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file selenium-actions-1.0.6.tar.gz
.
File metadata
- Download URL: selenium-actions-1.0.6.tar.gz
- Upload date:
- Size: 8.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.1 CPython/3.9.15
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | d6cf3f96262e89492e7fe5863ca9f913ab6de2ef3e31237a8e880e5dadd441ed |
|
MD5 | 0937e06cce9b31a8b59e45f73cb86028 |
|
BLAKE2b-256 | a5c7fd33916f61c002132c4145d573b86ab1c53478f775ab0232be743ae4abf4 |
File details
Details for the file selenium_actions-1.0.6-py3-none-any.whl
.
File metadata
- Download URL: selenium_actions-1.0.6-py3-none-any.whl
- Upload date:
- Size: 10.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.1 CPython/3.9.15
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 81c5b3f49aae1aa0a47174dccb2f20a0868c9d2086f7ec1a6cd7975ca8d5607a |
|
MD5 | 3bbef091839af93cad87a3e7081b6f94 |
|
BLAKE2b-256 | 694fbb463b2f57fbebf06feacb4eba352efb227cb736bcc1ab01a4584bd8e4b1 |