Remove the tedium of formulaic form filling with SitePrism and Capybara. Tedium allows you to specify a set of fields and actions to be performed rather than procedurally calling Capybara’s DSL methods on SitePrism elements.
class SignInPage < SitePrism::Page
fields :name, :email, :terms_of_service
submit_button
submission :sign_in
end
feature 'New user registration' do
let(:sign_in_page) { SignInPage.new }
scenario 'successfull sign up' do
sign_in_page.load
sign_in_page.sign_in!('Stefano', 's.verna@cantierecreativo.net', true)
expect(page).to have_content t('user.create.success')
end
end
field(name, attribute_name = name)
Declares the presence of a field within the page. The selector used to find the input relies on Rails name="model[attribute]"
attribute convention: [name$="[attribute]"]
If the underlying attribute name differs from the name you want to give to the page object field, provide the attribute name as the second argument.
Once a :foobar
field is declared, the page object will define a #foobar_field
method, which will return the corresponding Capybara node element.
fields(*names)
If you need to declare multiple fields at once, you can use this batch method.
date_field(name, attribute_name = name)
Declares the presence of a date_select
set of selects within the page. Once a :date_of_birth
date_field is declared, the page object will define a #date_of_birth_field
method, which will return a Tedium::VirtualDateElement
instance. Calling date_of_birth_field.set(Date.new)
will fill in the year, month and day selects with the correct values.
You can access to the specific year select element with date_of_birth_field.year_element
method (the same applies also for month and day selects).
datetime_field(name, attribute_name = name)
Similar to date_field
, it declares the presence of a datetime_select
set of selects within the page.
You can access to the specific hour and minute select elements with .hour_element
and .minute_element
method.
submit_button(role = nil)
Declares the presence of a submit button within the page. It can be either a input[type=select]
or a button
. If you pass an argument to the method (ie. submit_button :sign_in
), the selector will be augmented with a [role='sign-in']
filter (please note the automatic conversion in snake-case).
Once the submit button is declared, the page object will define a #submit!
method which will press the button.
submission(name, fields = nil)
Declares a submission process.
Given the following page:
class SignInPage < SitePrism::Page
fields :name, :email, :terms_of_service
submit_button
submission :sign_in
end
The page object will define a #sign_in
method, which will perform the following steps:
def sign_in(name, email, terms_of_service)
name_field.set(name)
email_field.set(email)
terms_of_service_field.set(terms_of_service)
end
And a #sign_in!
method, which will also submit the form:
def sign_in!(name, email, terms_of_service)
name_field.set(name)
email_field.set(email)
terms_of_service_field.set(terms_of_service)
submit!
end
You can explicitly change the fields used during the submission (or their order) passing an array of field names as second argument:
class SignInPage < SitePrism::Page
fields :name, :email, :terms_of_service
submit_button
submission :sign_in, %w(email name)
end
action(name, role = name)
Declares the presence of an action button/link within the page. Once a :sign_out
action is declared, the page object will define a #sign_out_element
method, which will return the corresponding Capybara node and a #sign_out!
method, which will perform a click on the element.
The selector relies on a role
attribute present in the action element (see submit_button
for details). If the role attribute differs from the name you want to give to the page object action, provide it as a second argument.
<a href="/session" data-method="delete" role="sign-out">Sign out</a>
class DashboardPage < SitePrism::Page
action :sign_out
end
page = DashboardPage.load
page.sign_out_element # => <Capybara::Node::Element ...>
page.sign_out! # clicks on the link
actions(*names)
If you need to declare multiple actions at once, you can use this batch method.
In order to be able to fill in text inputs, selects and checkboxes using the same API, Tedium slightly extends the default Capybara::Node::Element#set
behaviour. If the element is a select, the first option with a value or text that matches the provided value will be selected:
<select>
<option value='1'>Option 1</option>
<option value='2'>Option 2</option>
<option value='3'>Option 3</option>
</select>
# both will select the second option
page.find_first('select').set('Option 2')
page.find_first('select').set('2')
Every SitePrism page inherits a :record
SitePrism dynamic element, useful in conjunction with the Rails div_for
helper or Showcase Record trait:
<%= div_for(@person, class: "foo") do %>
<%= @person.name %>
<% end %>
expect(page).to have_record(@person) # green!