Skip to content

Instantly share code, notes, and snippets.

@tgaff
Created March 28, 2019 22:20
Show Gist options
  • Save tgaff/6da5eccb2f9431a2213713b734c52c40 to your computer and use it in GitHub Desktop.
Save tgaff/6da5eccb2f9431a2213713b734c52c40 to your computer and use it in GitHub Desktop.

site prism

Page Object Model gem for ruby Page Objects are like react-components for integration spec code. They let you componentize pages or parts of pages so you don't use css-selectors every where.

If you have page.find('button', text: 'update section') in a lot of tests, when the PM says it should be 'Change Section' you have a lot of changes to make. By sticking this in the page-object it limits the needed scope of change to just that POM and possible the one test that regression checked this.

pages

Let you define elements on your page

class Login < SitePrism::Page
  element :username, '#username'
  element :password, '#password'
  element :sign_in_button, 'button'
end

Then use it in your tests

  @login = Login.new
  @login.load
  expect(@login).to have_username
  @login.user_name.set 'sam@example.com'
  @login.password.set 'password'
  @login.sign_in_button.click
  expect(@page).to have_content 'Thanks for signing in Sam'

capybara options

capybara options like text just pass straight through.

class HeaderSection < SitePrism::Section
  set_default_search_arguments '#header'
  element :header_logo, 'div#logo'
  element :courses, 'a', text: 'COURSES'
  element :departments, 'a', text: 'DEPARTMENTS'
  element :affordability, 'a', text: 'AFFORDABILITY'
  element :users, 'a', text: 'USERS'
  element :help, 'button', text: 'GET HELP'
end

# also possible inline in test code

@page.courses(text: 'ACCT').click

sections

You can break more complicated stuff into sections

class Menu < SitePrism::Section
  element :search, 'a.search'
  element :images, 'a.image-search'
  element :maps, 'a.map-search'
end

class Home < SitePrism::Page
  section :menu, Menu, '#gbx3'
end

Don't feel like you need to over-componentize though. - it doesn't need to be as scoped down as far as a react component would be.

methods

Pages and sections are just ruby classes

  • great place to put common methods that you might use a lot
class LogInPage < SitePrism::Page
  set_url '/session/new'
  element :login, 'div#login'
  element :email_field, 'input[id="user_email"]'
  element :password_field, 'input[id="user_password"]'
  element :submit_button, 'button', text: 'LOGIN'
  element :flash_message, 'div.alert'

  def visit_and_login_as(email, password)
    load
    email_field.set email
    password_field.set password
    submit_button.click
    wait_until_page_has_flash_message, text: 'Success'
    page.has_content? 'div#menu'  
  end
end

# now in my test code I just
let(:user) { create(:user) }

before do
  LoginPage.new.visit_and_login_as(user.email, 'password')
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment