Appearance
Locator Aliases ๐
You can encapsulate locators for commonly used elements by defining aliases
.
These aliases can then be used on any of the actions, finders, matchers, or assertions.
As a result, when the UI changes it will be significantly easier to update the tests, because selectors and labels are not hardcoded all over the place ๐
class FormTestHelper < BaseTestHelper
aliases(
el: '.form',
error_summary: ['#error_explanation', visible: true],
name_input: [:fillable_field, 'Name'],
save_button: [:button, type: 'submit'],
)
end
# Finding an element
form.find(:save_button, visible: false)
# Interacting with an element
form.fill_in(:name_input, with: 'Jane')
# Making a query
form.has_selector?(:error_summary, text: "Can't be blank")
# Scoping interactions or assertions
form.within { form.should.have(:name_input, with: 'Jane') }
In a next section we will learn about how :el
plays a special role.
Aliases Shortcuts
To avoid repetition and to keep things concise, getters are available for every defined alias.
form.name_input
# same as
form.find(:fillable_field, 'Name')
You may provide options to the getter, which will be merged with any options defined in the alias.
form.error_summary(text: "Can't be blank")
# same as
form.find('#error_explanation', visible: true, text: "Can't be blank")
Using Selectors in Aliases
All capybara selectors can be used in the aliases, including any custom ones you define.
You can omit the selector when using the default one, which is usually css
.
class FormTestHelper < BaseTestHelper
aliases(
el: 'form',
city_input: [:field, 'City', readonly: false],
save_button: [:link_or_button, 'Save'],
contact_info: [:fieldset, legend: 'Contact Information'] ,
parent: [:xpath, '../..'],
)
end
form.within(:contact_info) {
form.city_input.fill_in('Montevideo')
form.click_on(:save_button)
}
Nested Aliases
When using css
or xpath
, you can reference other aliases in the test helper, and they will be joined together.
class ContainerTestHelper < BaseTestHelper
aliases(
el: '.container',
wide: [:el, '.wide'],
column: [:el, ' .column'],
sibling: [:el, ' + ', :el],
)
end
container.wide
# same as
find('.container.wide')
container.has?(:column)
# same as
has_selector?('.container .column')
container.should.have(:sibling)
# same as
expect(page).to have_selector('.container + .container')
Formatting ๐
Writing one alias per line and always using a trailing comma is highly recommended.
class DropdownTestHelper < BaseTestHelper
aliases(
el: '.dropdown',
toggle: '.dropdown-toggle',
)
end
It will minimize the amount of git conflicts, and keep the history a lot cleaner and more meaningful when using git blame
.