Class: MiniAutobot::PageObjects::Base
- Inherits:
-
Object
- Object
- MiniAutobot::PageObjects::Base
- Includes:
- Utils::Castable, Utils::Loggable, Utils::OverlayAndWidgetHelper, Utils::PageObjectHelper, Minitest::Assertions
- Defined in:
- lib/mini_autobot/page_objects/base.rb
Overview
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.
Instance Attribute Summary collapse
-
#assertions ⇒ Object
Returns the value of attribute assertions.
-
#driver ⇒ Object
readonly
Returns the value of attribute driver.
-
#failures ⇒ Object
Returns the value of attribute failures.
Class Method Summary collapse
-
.expected_path(*args) ⇒ String
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.
Instance Method Summary collapse
-
#click_on_link!(link_text, page_name) ⇒ Object
click on a link on any page, cast a new page and return it.
-
#current_path ⇒ String
Returns the current path loaded in the driver.
-
#current_url ⇒ String
Returns the current URL loaded in the driver.
-
#go!(*args) ⇒ Object
Instructs the driver to visit the Base.expected_path.
- #go_to_page!(url, page_type = :base) ⇒ Object
- #go_to_subpage!(url_path, page_type = :base) ⇒ Object
- #headline ⇒ Object
-
#include?(value) ⇒ Boolean
Check that the page includes a certain string.
-
#initialize(driver) ⇒ Base
constructor
Initializes a new page object from the driver.
-
#meta ⇒ Object
Retrieves all META tags with a ‘name` attribute on the current page.
-
#page_object ⇒ Object
interface for Overlay And Widget Helper version of get_widgets! and get_overlay!.
-
#page_source ⇒ Object
returns the all the page source of a page, useful for debugging.
-
#raise_on_error_page ⇒ Object
PageObject validate! helper.
-
#title ⇒ Object
Get page title from any page.
-
#validate! ⇒ Object
By default, any driver state is accepted for any page.
-
#wait(opts = {}) ⇒ Object
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 when timeout is larger than 15, max timeout 15 sec will be used.
-
#wait_for_ajax(timeout = 15) ⇒ Object
Wait on all AJAX requests to finish.
-
#wait_for_dom(timeout = 15) ⇒ Object
Wait for all dom events to load.
- #wait_for_link(link_text) ⇒ Object
- #wait_for_title_change(title) ⇒ Object
-
#wait_for_url_change(original_url) ⇒ Object
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).
-
#with_page_title_wait(&blk) ⇒ Object
Wrap an action, wait for page title change.
-
#with_rescue(lbl, &blk) ⇒ Object
Wrap blocks acting on Selenium elements and catch errors they raise.
Methods included from Utils::OverlayAndWidgetHelper
Methods included from Utils::PageObjectHelper
#connector_is_saucelabs?, #current_page, #is_element_present?, #is_element_present_and_displayed?, #json_save_to_ever_failed, #page, #print_sauce_link, #put_value, #read_yml, #retry_with_count, #save_to_ever_failed, #take_screenshot, #teardown, #update_sauce_session, #wait_for_attribute_to_have_value, #wait_for_element_to_be_present, #wait_for_element_to_display, #with_url_change_wait
Methods included from Utils::Loggable
Methods included from Utils::Castable
Constructor Details
#initialize(driver) ⇒ Base
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.
40 41 42 43 44 45 |
# File 'lib/mini_autobot/page_objects/base.rb', line 40 def initialize(driver) @driver = driver @assertions = 0 @failures = [] end |
Instance Attribute Details
#assertions ⇒ Object
Returns the value of attribute assertions.
21 22 23 |
# File 'lib/mini_autobot/page_objects/base.rb', line 21 def assertions @assertions end |
#driver ⇒ Object (readonly)
Returns the value of attribute driver.
23 24 25 |
# File 'lib/mini_autobot/page_objects/base.rb', line 23 def driver @driver end |
#failures ⇒ Object
Returns the value of attribute failures.
22 23 24 |
# File 'lib/mini_autobot/page_objects/base.rb', line 22 def failures @failures end |
Class Method Details
.expected_path(*args) ⇒ String
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.
31 32 33 |
# File 'lib/mini_autobot/page_objects/base.rb', line 31 def self.expected_path(*args) raise NotImplementedError, "expected_path is not defined for #{self}" end |
Instance Method Details
#click_on_link!(link_text, page_name) ⇒ Object
click on a link on any page, cast a new page and return it
208 209 210 211 212 213 214 215 216 |
# File 'lib/mini_autobot/page_objects/base.rb', line 208 def click_on_link!(link_text, page_name) driver.find_element(:link, link_text).location_once_scrolled_into_view driver.find_element(:link, link_text).click # check user angent, if it's on IE, wait 2sec for the title change sleep 2 if driver.browser == :ie # todo remove this if every page has wait for title change in validate! #sleep 5 #wait for 5 secs logger.debug "click_on_link '#{link_text}'" cast(page_name) end |
#current_path ⇒ String
Returns the current path loaded in the driver.
50 51 52 |
# File 'lib/mini_autobot/page_objects/base.rb', line 50 def current_path current_url.path end |
#current_url ⇒ String
Returns the current URL loaded in the driver.
57 58 59 |
# File 'lib/mini_autobot/page_objects/base.rb', line 57 def current_url URI.parse(driver.current_url) end |
#go!(*args) ⇒ Object
Instructs the driver to visit the expected_path.
69 70 71 |
# File 'lib/mini_autobot/page_objects/base.rb', line 69 def go!(*args) driver.get(driver.url_for(self.class.expected_path(*args))) end |
#go_to_page!(url, page_type = :base) ⇒ Object
245 246 247 248 |
# File 'lib/mini_autobot/page_objects/base.rb', line 245 def go_to_page!(url, page_type = :base) driver.navigate.to(url) cast(page_type) end |
#go_to_subpage!(url_path, page_type = :base) ⇒ Object
250 251 252 253 |
# File 'lib/mini_autobot/page_objects/base.rb', line 250 def go_to_subpage!(url_path, page_type = :base) driver.navigate.to(driver.url_for(url_path)) cast(page_type) end |
#headline ⇒ Object
90 91 92 |
# File 'lib/mini_autobot/page_objects/base.rb', line 90 def headline driver.find_element(:css, 'body div.site-content h1').text end |
#include?(value) ⇒ Boolean
Check that the page includes a certain string.
77 78 79 |
# File 'lib/mini_autobot/page_objects/base.rb', line 77 def include?(value) driver.page_source.include?(value) end |
#meta ⇒ Object
Retrieves all META tags with a ‘name` attribute on the current page.
82 83 84 85 86 87 88 |
# File 'lib/mini_autobot/page_objects/base.rb', line 82 def = driver.all(:css, 'meta[name]') .inject(Hash.new) do |vals, tag| vals[tag.attribute(:name)] = tag.attribute(:content) if tag.attribute(:name) vals end end |
#page_object ⇒ Object
interface for Overlay And Widget Helper version of get_widgets! and get_overlay!
62 63 64 |
# File 'lib/mini_autobot/page_objects/base.rb', line 62 def page_object self end |
#page_source ⇒ Object
returns the all the page source of a page, useful for debugging
177 178 179 |
# File 'lib/mini_autobot/page_objects/base.rb', line 177 def page_source driver.page_source end |
#raise_on_error_page ⇒ Object
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]
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
# File 'lib/mini_autobot/page_objects/base.rb', line 184 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 ⇒ Object
Get page title from any page
95 96 97 |
# File 'lib/mini_autobot/page_objects/base.rb', line 95 def title driver.title end |
#validate! ⇒ Object
By default, any driver state is accepted for any page. This method should be overridden in subclasses.
101 102 103 |
# File 'lib/mini_autobot/page_objects/base.rb', line 101 def validate! true end |
#wait(opts = {}) ⇒ Object
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 when timeout is larger than 15, max timeout 15 sec will be used
133 134 135 136 137 138 139 140 |
# File 'lib/mini_autobot/page_objects/base.rb', line 133 def wait(opts = {}) if !opts[:timeout].nil? && opts[:timeout] > 15 puts "WARNING: #{opts[:timeout]} sec timeout is NOT supported by wait method, max timeout 15 sec will be used instead" opts[:timeout] = 15 end Selenium::WebDriver::Wait.new(opts) end |
#wait_for_ajax(timeout = 15) ⇒ Object
Wait on all AJAX requests to finish
123 124 125 126 127 |
# File 'lib/mini_autobot/page_objects/base.rb', line 123 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) ⇒ Object
Wait for all dom events to load
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/mini_autobot/page_objects/base.rb', line 106 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 " _.defer(function() {\n $('body').append(\"<div id='\#{uuid}'></div>\");\n });\n EOS\n wait(timeout: timeout, msg: \"Timeout after waiting \#{timeout} for all dom events to finish\").until do\n is_element_present?(:css, \"div[id='\#{uuid}']\")\n end\nend\n" |
#wait_for_link(link_text) ⇒ Object
226 227 228 229 230 231 232 233 |
# File 'lib/mini_autobot/page_objects/base.rb', line 226 def wait_for_link(link_text) = "waited 15 sec, can't find link #{link_text} on page" wait(timeout: 15, message: ).until{ driver.find_element(:link, link_text) } unless driver.find_element(:link, link_text).displayed? driver.navigate.refresh end end |
#wait_for_title_change(title) ⇒ Object
218 219 220 221 222 223 224 |
# File 'lib/mini_autobot/page_objects/base.rb', line 218 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) ⇒ Object
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)
239 240 241 242 243 |
# File 'lib/mini_autobot/page_objects/base.rb', line 239 def wait_for_url_change(original_url) time = 15 = "waited #{time} sec, url is still #{original_url}, was expecting it to change" wait(timeout: time, message: ).until { driver.current_url != original_url } end |
#with_page_title_wait(&blk) ⇒ Object
Wrap an action, wait for page title change. This function eliminates some error-prone boilerplate around fetching page titles
169 170 171 172 173 |
# File 'lib/mini_autobot/page_objects/base.rb', line 169 def with_page_title_wait(&blk) title = driver.title yield wait_for_title_change(title) end |
#with_rescue(lbl, &blk) ⇒ Object
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]
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/mini_autobot/page_objects/base.rb', line 145 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 |