class MiniAutobot::PageObjects::Base

The base page object. All page objects should be a subclass of this. Every subclass must implement the following class methods:

expected_path

All methods added here will be available to all subclasses, so do so sparingly. This class has access to assertions, which should only be used to validate the page.

Attributes

assertions[RW]
driver[R]
failures[RW]

Public Class Methods

expected_path(*args) click to toggle source

Given a set of arguments (no arguments by default), return the expected path to the page, which must only have file path and query-string.

@param args [String] one or more arguments to be used in calculating

the expected path, if any.

@return [String] the expected path.

# File lib/mini_autobot/page_objects/base.rb, line 32
def self.expected_path(*args)
  raise NotImplementedError, "expected_path is not defined for #{self}"
end
new(driver) click to toggle source

Initializes a new page object from the driver. When a page is initialized, no validation occurs. As such, do not call this method directly. Rather, use PageObjectHelper#page in a test case, or cast in another page object.

@param driver [Selenium::WebDriver] The WebDriver instance.

# File lib/mini_autobot/page_objects/base.rb, line 41
def initialize(driver)
  @driver = driver

  @assertions = 0
  @failures   = []
end

Public Instance Methods

current_path() click to toggle source

Returns the current path loaded in the driver.

@return [String] The current path, without hostname.

# File lib/mini_autobot/page_objects/base.rb, line 59
def current_path
  current_url.path
end
current_url() click to toggle source

Returns the current URL loaded in the driver.

@return [String] The current URL, including hostname.

# File lib/mini_autobot/page_objects/base.rb, line 66
def current_url
  URI.parse(driver.current_url)
end
find_all(how, what) click to toggle source
# File lib/mini_autobot/page_objects/base.rb, line 52
def find_all(how, what)
  driver.all(how, what)
end
find_first(how, what) click to toggle source
# File lib/mini_autobot/page_objects/base.rb, line 48
def find_first(how, what)
  driver.find_element(how, what)
end
go!(*args) click to toggle source

Instructs the driver to visit the {expected_path}.

@param args [*Object] optional parameters to pass into {expected_path}.

# File lib/mini_autobot/page_objects/base.rb, line 78
def go!(*args)
  driver.get(driver.url_for(self.class.expected_path(*args)))
end
go_to_page!(url, page_type = :base) click to toggle source
# File lib/mini_autobot/page_objects/base.rb, line 248
def go_to_page!(url, page_type = :base)
  driver.navigate.to(url)
  cast(page_type)
end
go_to_subpage!(url_path, page_type = :base) click to toggle source
# File lib/mini_autobot/page_objects/base.rb, line 253
def go_to_subpage!(url_path, page_type = :base)
  driver.navigate.to(driver.url_for(url_path))
  cast(page_type)
end
headline() click to toggle source
# File lib/mini_autobot/page_objects/base.rb, line 99
def headline
  driver.find_element(:css, 'body div.site-content h1').text
end
include?(value) click to toggle source

Check that the page includes a certain string.

@param value [String] the string to search @return [Boolean]

# File lib/mini_autobot/page_objects/base.rb, line 86
def include?(value)
  driver.page_source.include?(value)
end
meta() click to toggle source

Retrieves all META tags with a `name` attribute on the current page.

# File lib/mini_autobot/page_objects/base.rb, line 91
def meta
  tags = driver.all(:css, 'meta[name]')
  tags.inject(Hash.new) do |vals, tag|
    vals[tag.attribute(:name)] = tag.attribute(:content) if tag.attribute(:name)
    vals
  end
end
page_object() click to toggle source

interface for Overlay And Widget Helper version of get_widgets! and get_overlay!

# File lib/mini_autobot/page_objects/base.rb, line 71
def page_object
  self
end
page_source() click to toggle source

returns the all the page source of a page, useful for debugging

# File lib/mini_autobot/page_objects/base.rb, line 180
def page_source
  driver.page_source
end
raise_on_error_page() click to toggle source

PageObject validate! helper. Raises RuntimeError if one of our error pages is displaying. This can prevent a test from taking the entire implicit_wait before announcing error. [~jacord]

# File lib/mini_autobot/page_objects/base.rb, line 187
def raise_on_error_page
  logger.debug "raise_on_error_page"
  title = ''
  begin
    title = driver.title
  rescue ReadTimeout
    logger.debug 'ReadTimeout exception was thrown while trying to execute driver.title'
    logger.debug 'ignore exception and proceed'
  end
  title = driver.title
  logger.debug "Page Title: '#{title}'"
  raise "HTTP 500 Error" if %r/Internal Server Error/ =~ title
  raise "HTTP 503 Error" if %r/503 Service Temporarily Unavailable/ =~ title
  raise "HTTP 404 Error" if %r/Error 404: Page Not Found/ =~ title

  header = driver.find_element('body h1') rescue nil

  unless header.nil?
    raise "HTTP 500 Error" if header.text == 'Internal Server Error'
  end

end
title() click to toggle source

Get page title from any page

# File lib/mini_autobot/page_objects/base.rb, line 104
def title
  driver.title
end
validate!() click to toggle source

By default, any driver state is accepted for any page. This method should be overridden in subclasses.

# File lib/mini_autobot/page_objects/base.rb, line 110
def validate!
  true
end
wait(opts = {}) click to toggle source

Explicitly wait for a certain condition to be true:

wait.until { driver.find_element(:css, 'body.tmpl-srp') }

when timeout is not specified, default timeout 5 sec will be used

# File lib/mini_autobot/page_objects/base.rb, line 141
def wait(opts = {})
  Selenium::WebDriver::Wait.new(opts)
end
wait_for_ajax(timeout = 15) click to toggle source

Wait on all AJAX requests to finish

# File lib/mini_autobot/page_objects/base.rb, line 132
def wait_for_ajax(timeout = 15)
  wait(timeout: timeout, msg: "Timeout after waiting #{timeout} for all ajax requests to finish").until do
    driver.execute_script 'return window.jQuery != undefined && jQuery.active == 0'
  end
end
wait_for_dom(timeout = 15) click to toggle source

Wait for all dom events to load

# File lib/mini_autobot/page_objects/base.rb, line 115
      def wait_for_dom(timeout = 15)
        uuid = SecureRandom.uuid
        # make sure body is loaded before appending anything to it
        wait(timeout: timeout, msg: "Timeout after waiting #{timeout} for body to load").until do
          is_element_present?(:css, 'body')
        end
        driver.execute_script <<-EOS
            _.defer(function() {
            $('body').append("<div id='#{uuid}'></div>");
            });
        EOS
        wait(timeout: timeout, msg: "Timeout after waiting #{timeout} for all dom events to finish").until do
          is_element_present?(:css, "div[id='#{uuid}']")
        end
      end
wait_for_title_change(title) click to toggle source
# File lib/mini_autobot/page_objects/base.rb, line 221
def wait_for_title_change(title)
  title = driver.title if title.nil?
  logger.debug("Waiting for title change from '#{title}'")
  wait(timeout: 15, message: "Waited 15 sec for page transition")
    .until { driver.title != title }
  logger.debug("Arrived at #{driver.title}")
end
wait_for_url_change(original_url) click to toggle source

example usage: original_url = driver.current_url driver.find_element(*LINK_REGISTER).click # do some action that should cause url to change wait_for_url_change(original_url)

# File lib/mini_autobot/page_objects/base.rb, line 242
def wait_for_url_change(original_url)
  time = 15
  message = "waited #{time} sec, url is still #{original_url}, was expecting it to change"
  wait(timeout: time, message: message).until { driver.current_url != original_url }
end
with_page_title_wait() { || ... } click to toggle source

Wrap an action, wait for page title change. This function eliminates some error-prone boilerplate around fetching page titles

# File lib/mini_autobot/page_objects/base.rb, line 172
def with_page_title_wait(&blk)
  title = driver.title
  yield
  wait_for_title_change(title)
end
with_rescue(lbl) { || ... } click to toggle source

Wrap blocks acting on Selenium elements and catch errors they raise. This probably qualifies as a Dumb LISPer Trick. If there's a better Ruby-ish way to do this, I welcome it. [~jacord]

# File lib/mini_autobot/page_objects/base.rb, line 148
def with_rescue(lbl, &blk)
  yield ## run the block
  ## rescue errors. Rerunning may help, but we can also test for specific
  ## problems.
rescue Selenium::WebDriver::Error::ElementNotVisibleError => e
  ## The element is in the DOM but e.visible? is 'false'. Retry may help.
  logger.debug "Retrying #{lbl}: #{e.class}"
  yield
rescue Selenium::WebDriver::Error::StaleElementReferenceError => e
  ## The page has changed and invalidated your element. Retry may help.
  logger.debug "Retrying #{lbl}: #{e.class}"
  yield
rescue Selenium::WebDriver::Error::NoSuchElementError => e
  ## Raised by get_element(s). Retry MAY help, but check first for HTTP
  ## 500, which may be best handled higher up the stack.
  logger.debug "Recovering from NoSuchElementError during #{lbl}"
  raise_on_error_page
  ## If we got past the above, retry the block.
  logger.debug "Retrying #{lbl}: #{e.class}"
  yield
end