This Tech Bite was brought to you by Amira Džanović, Test Engineer at Atlantbh.

Tech Bites are tips, tricks, snippets or explanations about various programming technologies and paradigms, which can help engineers with their everyday job.

Method chaining using Capybara and SitePrism

 

What are Capybara and SitePrism?

Capybara is a Ruby library that is used for automating web pages in concert with an underlying web-based driver. It consists of a user-friendly DSL, used to describe actions that are then executed by the web driver.

While the Capybara syntax is very easily readable as-is, it can be improved upon to produce tests that are more DRY. This is where the SitePrism gem comes in – a DSL on top of Capybara, used for implementing the Page Object Model. Out of the box, it comes with predefined classes for many common features of websites, such as pages and sections. 

Finally, to produce easily maintainable and completely readable tests, we can use method chaining with these tools. So, on an example of a page consisting of a login form and search function, here’s how we would go about doing that.

Setting up page objects

Firstly, we need to define the elements that make up the pages in the flow we are testing. Starting with the homepage, we will first define the URL and elements present, using SitePrism’s set_url and element methods:

class HomePage < SitePrism::Page

    set_url 'https://www.testsite.com'

    element :go_to_login, 'some-login-link'

    element :search_bar, 'some-search-bar'

    element :search_button, ‘some-search-icon'

end

Notice we are inheriting from SitePrism::Page class, a built-in abstract class within the SitePrism gem. It contains methods used for loading pages as well as checking different attributes, such as if a page is displayed, secure, on the expected URL, etc.

After setting up the home page, we do the same for the login page:

class LoginPage < SitePrism::Page

    set_url 'https://www.testsite.com/login'

    element :name, 'some-username-field'

    element :password, 'some-password-field'

    element :login_button, 'some-login-button'

end

Defining methods

Now that we’ve described these different views on our page, we can, likewise, describe actions that we want to be performed on each. We will add these methods to our page objects, so starting with the Homepage, let’s define a way to access the login form:

def go_to_login_page do

  go_to_login.click

  return(LoginPage.new)

end

Notice that our method returns a new instance of the LoginPage object. By doing this we avoid having to instantiate a new LoginPage within the test itself. 

Then we add the login method to the LoginPage class, as well as a search method to the HomePage class:

#In the LoginPage class:


def log_in_user(user_name, user_password) do

    fill_in(name, with: user_name)

    fill_in(password, with: user_password)

    login_button.click

    return(HomePage.new)

end
#In the HomePage class:

def search_for_something(query) do

    fill_in(search_bar, with: query)

    search_button.click

    return(SearchResults.new)

end

Method chaining in action

Finally, in our spec, we need to require the objects we’ve created and write some tests. In our case, the user should be able to log in and get search results for their query:

require_relative './page_objects/HomePage.rb'

require_relative './page_objects/LoginPage.rb'



describe 'test' do

    it 'should login and return search results' do

        @app.go_to_login_page

          .log_in_user('1337_Jane', 'aLamePassword420')

          .search_for_something('Tasty Donuts w chocolate glaze')

        expect(page).to have_content('Some results related to the search query')

    end

end

 

 

Leave a Reply