Tedium Logo

Gem Version Build Status Coverage Status Code Climate

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.

Usage

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
    .load
    .sign_in!('Stefano', '[email protected]', true)
    expect(page).to have_content t('user.create.success')
  end
end

SitePrism DSL

field

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

fields(*names)

If you need to declare multiple fields at once, you can use this batch method.

date_field

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

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

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

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 (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

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

actions(*names)

If you need to declare multiple actions at once, you can use this batch method.

Changes to the Capybara node element #set 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')

has_record?

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!