nopo (not only page object) is a package for Page Object Model (POM), a tool based on Selenium that helps you build POM in web test.
View the development of it (in Chinese)
Features
- Define and operate an element or elements like using Selenium (but with advanced features)
- Auto wait and find the element(s)
- Cascading selectors support in an element
Install
Usage
Example
Here shows a simple usage example:
from selenium import webdriver from selenium.webdriver.common.keys import Keys from nopo import El, Els, By class GitHubPage: def __init__(self, drv): self.driver = drv # Define like Selenium textbox = El(By.XPATH, '//input[@aria-label="Search GitHub"]') main_page = El(By.TAG_NAME, 'main') user_a = El(By.CLASS_NAME, 'mr-1') name = El(By.XPATH, '//span[@itemprop="name"]') def search_user(self, name): # Operate like Selenium, but with advanced features. self.textbox.send_keys(name, clear=True) self.textbox.send_keys(Keys.ENTER) # Elements define # Use El_1 / El_2 to define cascading element(s) # Use El(el=El_old) or Els(el=El_old) to turn type lis = Els(el=(self.main_page / El(By.XPATH, './/nav[1]') / El(By.TAG_NAME, 'a'))) lis[-1].click() self.user_a.click() assert self.name.value == 'Ding Junyao' if __name__ == '__main__': driver = webdriver.Chrome() driver.maximize_window() driver.get('https://github.com/') gh_page = GitHubPage(driver) gh_page.search_user('DingJunyao') driver.quit()
Defining
In class which has driver
attribute to selenium webdriver, you can define it as a class attribute:
example_el = El(by, selector_str) example_els = Els(by, selector_str)
You can also use attribute driver
to specify a webdriver or use in other occasions:
example_el = El(by, selector_str, driver=driver) example_els = Els(by, selector_str, driver=driver)
Operating
el.text # Text of the element. el.value # Returns text. If text is None or '', return value property (mostly for input element). el.exist # To show if the element exists. el.exist_wait # To show if the element exists (with wait). el.is_selected # Returns if the element is selected. el.selectors_xpath # Returns selector to xpath. el.elem # Returns the WebElement instance of the element (with wait). el.elem_clickable # Returns the WebElement instance of the element (wait for clickable). el.elem_no_wait # Returns the WebElement instance of the element (without wait). el.options # Returns a list of all options belonging to this select tag el.all_selected_options # Returns a list of all selected options belonging to this select tag el.first_selected_option # Returns the first selected option in this select tag. el.click() # Click the element. el.clear(force=False) # Clear the element. Use force=True to ensure the element can be cleared to deal with some situation. el.send_keys(keys, clear=False, force_clear=False) # Send keys to element. If clear is True, clear the element before sending. If clear and force are True, clear will be in force mode. el.csk(keys, force_clear=False) # Clear and send keys to element. If force_clear is True, clear will be in force mode. el.nn_csk(keys, force_clear=False) # Clear and send keys if keys is not None. If force_clear is True, clear will be in force mode. el.get_attribute(attr) # Get attribute of the element. el.get_property(property_text) # Get property of the element. el.wait_for_click() # Wait until the element is clickable. el.wait_for_present() # Wait until the element is present. el.select_by_value(value) # Select options by given value argument. el.select_by_index(index) # Select the option at the given index. el.select_by_visible_text(text) # Select options by visible text. el.deselect_all() # Clear all selected entries. el.deselect_by_value(value) # Deselect options by given value argument. el.deselect_by_index(index) # Deselect the option at the given index. el.deselect_by_visible_text(text) # Deselect options by visible text. el.switch_in() # Switch in the frame. El.single_selector_to_xpath(by, selector) # Return single selector to xpath.
Cascading
You can use /
to cascading selectors:
el1 = El(by1, selector_str1) el2 = El(by2, selector_str2) example_el = el1 / el2
The type of example_el
above is same as el1
, and find element using selector of el1
and el2
, like the following code in selenium:
el1 = driver.find_element.by(by1, selector_str1) example_el = el1.find_element.by(by2, selector_str2)
Extending
el
attribute helps you transfer class type, which makes it easy to customize element(s):
class MyEl(El): pass example_el = MyEl(el=el1 / el2)
Build
pip install -r requirements.txt
python -m build
# or
python3 -m build
Further plan
- More operating functions
- Ready-to-use Element classes for frontend frameworks (like Ant Design and Element)
License
Apache License Version 2.0