Page Object Prototype Syntax¶
Contents
Overview¶
To simplify the process of creating new page objects, some page object prototype
classes support YAML representations of the object. Prototype classes that
support this will generate a .yml
file in addition to a Python module when
using the new page --prototype <prototype>
command.
The following sections detail YAML syntax specifically for
webdriver_test_tools
as well as the non-YAML alternative syntax for each
page object prototype. For a basic introduction to YAML
syntax in general, see Ansible’s YAML documentation.
Supported Prototype Classes¶
The following prototype classes support YAML parsing:
When initialized, these classes check to see if the YAML_FILE
attribute is
set. If YAML_FILE
is not None
, the contents will be parsed and used to
set the page object’s attributes.
Configure Defaults¶
Whether YAML files or Python-only files are generated by default when using the
new page
command is configured in <test_package>/config/projectfiles.py
by setting the ENABLE_PAGE_OBJECT_YAML
variable of the
ProjectFilesConfig
class.
Override Default Setting¶
The default setting can be overridden using command line arguments. If
ENABLE_PAGE_OBJECT_YAML
is True
, the --no-yaml
(or -Y
) argument
can be used to only generate .py
files:
<test_package> new page <args> --no-yaml
If ENABLE_PAGE_OBJECT_YAML
is False
, the --yaml
(or -y
) argument
can be used to generate .py
and .yml
files for supported prototypes:
<test_package> new page <args> --yaml
General Syntax¶
This section documents the syntax of general page object constructs.
Locator Dictionaries¶
Element locators are represented by YAML dictionaries with the following required keys:
by
: Locator strategy to use when finding the element. Use variable names of attributes inselenium.webdriver.common.by.By
:
CLASS_NAME
CSS_SELECTOR
ID
LINK_TEXT
NAME
PARTIAL_LINK_TEXT
TAG_NAME
XPATH
locator
: Value used to locate element with the specified locator strategy
Note
For non-YAML page objects, any instances of a locator dictionary can be
replaced with a Python locator tuple i.e. (By.<STRATEGY>, '<locator>')
Relative URL Dictionaries¶
URLs that are relative to attributes specified in a project’s SiteConfig
are
specified with dictionaries using the following keys:
path
: The path to the page, relative to theSiteConfig
attribute specified inrelative_to
relative_to
: A valid attribute declared in the project’sSiteConfig
class to use as a base URL
Note
Internally, these URL dictionaries are parsed using
SiteConfig.parse_relative_url_dict
. If
the attribute that relative_to
specifies does not have a trailing ‘/’,
this method adds one before building the full URL
FormObjects¶
FormObjects
support
YAML representations of the form element using the following syntax.
Syntax¶
Forms¶
Form objects have 3 required keys:
form_locator
: Locator dictionary for the<form>
element
submit_locator
: Locator dictionary for the form’s submit button
inputs
: List of form inputs
Inputs¶
The items in the form inputs
list have the following keys:
name
: (Required) Thename
attribute of the element. If the element doesn’t have a name attribute, set this to any unique identifier (i.e. not used as thename
value for another input in the form)
input_locator
: (Required if element has noname
attribute) Locator dictionary for the element. If provided, this will be used instead ofname
to find the element
type
: (Default:text
) Thetype
attribute of the input
required
: (Default:true
) Whether or not the input is required to submit the form
options
: (Required iftype
isradio
,select
, or acheckbox
group (i.e. multiple checkboxes with the same name)) List ofvalue
attributes of radio inputs, select options, or checkboxes. A dictionary mapping values to labels is also valid (though only the map keys will be used, so the labels can be set to anything)
Example¶
With YAML¶
import os
from selenium.webdriver.common.by import By
from webdriver_test_tools.pageobject import *
from webdriver_test_tools.webdriver import actions, locate
class ExampleForm(prototypes.FormObject):
"""YAML FormObject example"""
# Path to YAML file representing the object
YAML_FILE = os.path.join(os.path.dirname(__file__), 'form.yml')
# (Optional) Page object of the modal/webpage/etc that should appear on
# successful form submission. If set to a subclass of BasePage, the
# click_submit() method will return an instance of the page object
SUBMIT_SUCCESS_CLASS = None
form:
# Locator for the form
form_locator:
by: ID
locator: example-form-id
# Locator for the submit button
submit_locator:
by: CSS_SELECTOR
locator: '#example-form-id button[type="submit"]'
# List of inputs in the form
inputs:
# Basic syntax:
- name: email
type: email
# 'type' defaults to 'text' if not specified:
- name: text_input
# Inputs are assumed to be required by default, use 'required' to specify
# otherwise:
- name: optional_input
required: false
# For input elements with no name attribute, the 'input_locator' key is
# used to locate the element (though the 'name' key is still required for
# identification):
- name: unique_identifier
input_locator:
by: CLASS_NAME
locator: input-with-no-name-attribute
type: text
# Selects and radios take a list of options:
- name: select_example
type: select
options:
- option1
- option2
- option3
- option4
# 'options' can bet a dictionary too. Only the keys are used, so the values
# can be set to anything:
- name: radio_example
type: radio
# NOTE: numeric options keys/list entries should be in quotes
options:
'001': Helpful label
'002': Another helpful label
'003': An even more helpful label
# Supports select elements with the 'multiple' attribute:
- name: multiple_select_example
type: select
multiple: true
options:
- option0
- option1
- option2
# Checkbox groups can accept a list of options too:
- name: checkboxes[]
type: checkbox
# NOTE: set 'multiple' to true when multiple checkboxes have the same
# name and different values
multiple: true
options:
- box0
- box1
- box2
Without YAML¶
from selenium.webdriver.common.by import By
from webdriver_test_tools.pageobject import *
from webdriver_test_tools.webdriver import actions, locate
class ExampleForm(prototypes.FormObject):
"""Non-YAML FormObject example"""
# REQUIRED: Locator for the form element
FORM_LOCATOR = (By.ID, 'example-form-id')
# REQUIRED: Locator for the form submit button
SUBMIT_LOCATOR = (By.CSS_SELECTOR, '#example-form-id button[type="submit"]')
# Inputs are specified here:
INPUT_DICTS = [
# Basic syntax:
{
'name': 'email',
'type': 'email'
},
# 'type' defaults to 'text' if not specified:
{'name': 'text_input'},
# Inputs are assumed to be required by default, use 'required' to
# specify otherwise:
{
'name': 'optional_input',
'required': False
},
# For input elements with no name attribute, the 'input_locator' key is
# used to locate the element (though the 'name' key is still required
# for identification):
{
'name': 'unique_identifier',
'input_locator': (By.CLASS_NAME, 'input-with-no-name-attribute')
},
# Selects and radios take a list of options:
{
'name': 'select_example',
'type': 'select',
'options': [
'option1',
'option2',
'option3',
'option4',
]
},
# 'options' can bet a dictionary too. Only the keys are used, so the
# values can be set to anything:
{
'name': 'radio_example',
'type': 'radio',
'options': {
# NOTE: numeric options keys/list entries should be in quotes
'001': 'Helpful label',
'002': 'Another helpful label',
'003': 'An even more helpful label',
}
},
# Supports select elements with the 'multiple' attribute:
{
'name': 'multiple_select_example',
'type': 'select',
'multiple': True,
'options': [
'option1',
'option2',
'option3',
]
},
# Checkbox groups can accept a list of options too:
{
'name': 'checkboxes[]',
'type': 'checkbox',
# NOTE: set 'multiple' to True when multiple checkboxes have the
# same name and different values
'multiple': True,
'options': [
'box0',
'box1',
'box2',
]
},
]
# (Optional) Page object of the modal/webpage/etc that should appear on
# successful form submission. If set to a subclass of BasePage, the
# click_submit() method will return an instance of the page object
SUBMIT_SUCCESS_CLASS = None
ModalObjects¶
ModalObjects
support YAML representations of the modal using the following syntax.
Syntax¶
Modal objects have 2 required keys:
modal_locator
: Locator dictionary for the modal container element
close_locator
: Locator dictionary for the modal close button
Example¶
With YAML¶
import os
from selenium.webdriver.common.by import By
from webdriver_test_tools.pageobject import *
from webdriver_test_tools.webdriver import actions, locate
class ExampleModal(prototypes.ModalObject):
"""YAML ModalObject example"""
# Path to YAML file representing the object
YAML_FILE = os.path.join(os.path.dirname(__file__), 'modal.yml')
# (Optional) Page object of the contents of the modal body. If set to a
# subclass of BasePage, the get_modal_body() method will return an instance
# of the page object
MODAL_BODY_CLASS = None
modal:
# Locator for the modal
modal_locator:
by: ID
locator: test-modal
# Locator for the close button
close_locator:
by: CSS_SELECTOR
locator: "#test-modal button.close"
Without YAML¶
from selenium.webdriver.common.by import By
from webdriver_test_tools.pageobject import *
from webdriver_test_tools.webdriver import actions, locate
class ExampleModal(prototypes.ModalObject):
"""Non-YAML ModalObject example"""
# REQUIRED: Locator for the modal element
MODAL_LOCATOR = (By.ID, 'test-modal')
# REQUIRED: Locator for the modal's close button
CLOSE_LOCATOR = (By.CSS_SELECTOR, '#test-modal button.close')
# (Optional) Page object of the contents of the modal body. If set to a
# subclass of BasePage, the get_modal_body() method will return an instance
# of the page object
MODAL_BODY_CLASS = None
WebPageObjects¶
WebPageObjects
support YAML representations of the modal using the following syntax.
Syntax¶
Web page objects have one required key url
, which can be set to either the
full URL to the page or a relative URL dictionary
Note
If ‘url’ is set to just the full URL to the page, the attribute
PAGE_FILENAME
will not be set in the WebPageObject
. If it is set to a
dictionary, PAGE_FILENAME
will be set to the value of ‘path’
Example¶
With YAML¶
import os
from selenium.webdriver.common.by import By
from webdriver_test_tools.pageobject import *
from webdriver_test_tools.webdriver import actions, locate
from yaml_example.config import SiteConfig
class FullURLExampleWebPage(prototypes.WebPageObject):
"""YAML WebPageObject example (full URL)"""
# Path to YAML file representing the object
YAML_FILE = os.path.join(os.path.dirname(__file__), 'web_page_full.yml')
# Used for internal methods (do not modify)
SITE_CONFIG = SiteConfig
class RelativeURLExampleWebPage(prototypes.WebPageObject):
"""YAML WebPageObject example (relative URL)"""
# Path to YAML file representing the object
YAML_FILE = os.path.join(os.path.dirname(__file__), 'web_page_relative.yml')
# Used for internal methods (do not modify)
SITE_CONFIG = SiteConfig
# Example 1: Full URL to page
web_page:
url: http://example.com/
# Example 2: Relative to a URL declared in SiteConfig
web_page:
url:
# Page path, relative to the SiteConfig attribute specified below
path: path/to/page.html
# A valid attribute in project SiteConfig to use as the base URL for page
relative_to: BASE_URL
Without YAML¶
from selenium.webdriver.common.by import By
from webdriver_test_tools.pageobject import *
from webdriver_test_tools.webdriver import actions, locate
from no_yaml_example.config import SiteConfig
class FullURLExampleWebPage(prototypes.WebPageObject):
"""Non-YAML WebPageObject example (full URL)"""
# Full URL of the page
PAGE_URL = 'http://example.com/'
class RelativeURLExampleWebPage(prototypes.WebPageObject):
"""Non-YAML WebPageObject example (relative URL)"""
# File name of the page relative to a base URL declared in SiteConfig
PAGE_FILENAME = 'page.html'
# Full URL of the page
PAGE_URL = SiteConfig.BASE_URL + PAGE_FILENAME