Logo: Relish

  1. Sign in

Project: Console

Pages

Page Objects

Wedeploy-functional-tests organize all UI related methods into page object classes for easier test maintenance and to reduce code duplication. Each class represents a UI page, section, tab, nav bar, etc. The page object class contains all UI element locator information pertaining to that page, and any UI interactions on the page are done by invoking the class methods.

This means that whenever there are changes to Console UI, there's a high likelihood that the page object corresponding to the UI page will need to be updated. The most common updates involve locators (CSS selectors and XPaths) which become outdated due to changes in the HTML DOM. It is crucial to keep the locators up-to-date in order to have passing tests.

Method types

Page object class methods are organized into three sections. They are:

Locator methods

These methods return locator information for a particular web element. This can be a CSS selector string, XPath string, or an element (Capybara::Node::Element) and the method names are prefixed with css_, xpath_, and el_, respectively. When adding a new locator method for a particular web element, make sure it's not already defined. There are some common elements that appear on multiple pages -- these locators are found in BasePage class.

Examples:

class ActivityPage < BasePage
  def css_activity_item
    "li.activity-item"
  end

  def xpath_activity_with_message(message)
    ".//*[@class='message-label' and contains(.,'#{message}')]/ancestor::li"
  end
end
class DatabasePage < BasePage
  def el_collections_dropdown
    page.find(:css, "small + .dropdown button")
  end
end

Assertion methods

Assertion methods check for a condition to be present (or not) on a page. These methods return true or false and follow the Ruby convention of ending the method name with '?'.

Example:

Given the assertion method has_heading?

class BasePage
  def css_page_title
    ".header-title"
  end

  def has_heading?(title)
    page.has_css?(css_page_title, text: title)
  end
end

we can use it in a step definition like this

Then("I should see the page title {string}" do |value|
  expect(BasePage).to have_heading(value)
end

or

Then("I should not see the page title {string}" do |value|
  expect(BasePage).not_to have_heading(value)
end

Ruby's RSpec Expectations syntactic sugar allows BasePage#has_heading? to be called with expect(BasePage).to have_heading syntax. Note the difference between has and have.

Action methods

Finally, we need methods for performing actions on the page. The method can contain one simple action, or combine several actions that are commonly performed together. Note that these methods utilize the locator methods defined at the top section of the class.

Examples:

class Topbar < BasePage
  # locator method
  def css_topbar_link
    ".topbar-link"
  end

  # action method
  def click_link(label)
    page.find(:css, css_topbar_link, text: label).click
  end
end
class EnvironmentVarsPage < BasePage
  # locator methods
  def xpath_row(rownum)
    ".//div[@class='input-matrix-fields'][#{rownum}]"
  end

  def xpath_eye(rownum)
    "#{xpath_row(rownum)}//span[@class='icon-12-eye']"
  end

  def xpath_key(rownum)
    "#{xpath_row(rownum)}//div[@class='form-group '][1]/input"
  end

  # action methods
  def set_key(key, rownum)
    show_value(rownum)
    page.find(xpath_key(rownum)).set(key)
  end

  def show_value(rownum)
    if page.has_xpath?(xpath_eye(rownum), wait: 1)
      page.find(xpath_eye(rownum)).click
    end
  end
end

Last published 13 days ago by Christie Yoo.