Finding Elements
note
Make sure you've gone through Building Selectors before going ahead.
Finding page elements in ZWL is much easier than you'd expect. We handle most edge cases and provide you with necessary information to customize the presets wherever needed.
#
Methods of finding elementsZWL provides two primary methods:
Finding only a single element
Using a given selector, the first element found is taken and returned. If no element is found, after waiting automatically for a fixed time, a timeout error is thrown and test is marked failed.
If you're finding just a single element and you're sure that it exists on page, use this method.
Finding multiple elements
Using a given selector, all the elements found are taken and returned. If no element is found, after waiting automatically for a fixed time, an empty list is returned. No error is thrown and test continues.
Use this method in following situations:
- Your selector returns (or may return) multiple elements.
- Your selector may return no element and you want to try another selector if first fails.
- Your are checking whether an element exists on page and expecting empty list.
#
Overview of ZWL functions for finding elementsTake a look at following element finding functions:
main = findElement('main', by.role)print(main)# prints main element's unique `string` id that can be used to# refer to this element in another functions such as:button = findElementFromElement(main, 'Submit', by.text)# We've narrowed the search scope for finding button to main container.
All functions that find elements return a unique element id. This id can be saved in a variable for later use in other functions to refer to the found element.
There are 3 important parameters used by all element finding functions as shown in following snippet:
findElement(using, by, noWait)
Here are the details of these parameters:
#
usingSelector used for finding the element. This could be element's text, one of it's attribute or a css selector. Building Selectors page has good details about selectors.
#
byExact type of selector you're using for finding the element. For instance, if you've used element's text as using, specify
by.text
for this parameter. Following are all the supportedby
's you can use:text: Expects selector to be element's text. You can either specify exact visible text of an element or a regex pattern.
labelText: Expects selector to be a label text. It finds the label and returns the associated element. You can either specify exact label name or a regex pattern.
placeholderText: Expects selector to be a placeholder text (such as the greyed out text in a text field that works as a label). You can either specify exact placeholder text or a regex pattern.
altText: Expects selector to be an alt text. You can either specify exact alt or a regex pattern.
testId: Expects selector to be element's
data-testid
attribute.role: Expects selector to be element's
role
attribute.arialLabel: Expects selector to be element's
aria-label
attribute. You can either specify exact aria label or a regex pattern.title: Expects selector to be element's
title
attribute. You can either specify exact title or a regex pattern.linkText: This is similar to finding by text but specific to links. Therefore if the element is a link, using this type will make searching little faster. Full text of the link must be provided as-is, no regex patterns are supported.
partialLinkText: Similar to linkText with added support for finding using partial link text.
name: Expects selector to be element's
name
attribute.tagName: Expects selector to be element's html
tag
such asheader
.id: Expects selector to be element's
id
attribute.cssSelector: Expects selector to be a css selector.
className: Expects selector to be element's
class
attribute.xPath: Expects selector to be a XPath expression.
You don't have to type these types by hand. Outomated IDE will auto complete them once you type
by.
.note
If you provide a regex pattern as selector, it must follow following rules:
It must be in form of a
string
and must contain/../
forward slashes around pattern.Unlike ZWL's regular expression, it is a pure
js
regex, therefore follow the rules ofjs
regular expression as described in mdn.Following example shows a find element search by text using a simple regex pattern:
# The button we're searching here has text 'Get Started For Free Today'.# Following code searches it using regexbutton = findElement('/^get started[a-z\s]*$/i', by.text)
#
noWaitBy default every element finding function waits for a fixed duration until at least one element is found (which can be customized). In certain circumstances when you don't want to wait, just specify boolean
true
for this parameter. Following example illustrate a use case for this:/*Imagine we've deleted some elements in a test andneed to confirm that none of them now exists.*/addressPanels = findElements('address', by.testId, true) # Find those elements/*Notice the use of noWait = 'true'. ZWL didn't waitfor elements to be found and immediately returnedan empty list finding no matching elements in DOM.If we don't use it, there will be a long useless wait beforeour test could pass.*/assertFalse(nonEmpty(addressPanels))
See Api Reference for all available element finding functions.
#
Customizing automatic wait timeEvery element finding function automatically waits until at least one element is found. This is very useful in tests as you can interact with elements in next line immediately after finding them without worrying about their existence on page. For instance, imagine an app where clicking a button initiates an ajax call that renders a new page. You can access elements from the new page without worrying about the time that ajax call and page updates are going to take. This is because, your findElementXX
calls will automatically wait until the desired element is rendered on the page. This makes tests look clean with no imperative code.
In some cases you may want to change the default maximum wait time (default timeout). Some of them are:
- Your ajax calls or full page loads may take longer than default timeout.
- You want to test your application with a shorter timeout settings. If some parts of the app fail, they may be taking longer to load new content and could be fixed.
Other than that there may not be a good reason to change it. No matter what the default timeout is, an element is returned immediately after it is found i.e there is no unnecessary wait in connection with the timeout. When you don't want to wait at all, the noWait parameter can always be used per function call.
See Timeouts for options to change the default timeout.