_ruby
A Solution
Instead of hard-coding logging requests all over the place, we can leverage an event listener to give us the information we want -- automatically and for each Selenium action.
This functionality is built in to Selenium in what's called the AbstractEventListener. This is a class which comes preloaded with helper methods that enable us to add behavior before and after common Selenium actions -- here's a list of the available methods:
before_navigate_to
after_navigate_to
before_navigate_back
after_navigate_back
before_navigate_forward
after_navigate_forward
before_find
after_find
before_click
after_click
before_change_value_of
after_change_value_of
before_execute_script
after_execute_script
before_quit
after_quit
before_close
after_close
We can pick and choose from each of these methods and specify the additional behavior we want to occur. After that, it's just a simple matter of passing this information to Selenium when creating a browser instance.
Here is an example.
Example
To start, let's create a Wrapper
class that inherits from AbstractEventListener
and add our behavior there.
The helper methods we're interested in are after_navigate_to
, before_find
, after_find
, before_click
, and after_click
and they each require different arguments to be specified. See here for details.
And to make things interesting, let's wire up jQuery Growl notifications.
# filename: wrapper.rb
class Wrapper < Selenium::WebDriver::Support::AbstractEventListener
def after_navigate_to(url, driver)
add_growl(driver)
display_growl(driver, "Navigated to #{url}")
end
def before_find(by, what, driver)
display_growl(driver, "Finding element #{what}")
end
def after_find(by, what, driver)
display_growl(driver, "Found element #{what}")
end
def before_click(element, driver)
display_growl(driver, "Clicking on #{element.text}")
@pre_click_url = driver.current_url
end
def after_click(element, driver)
unless @pre_click_url == driver.current_url
add_growl(driver)
display_growl(driver, "URL changed to #{driver.current_url}")
end
end
private
def add_growl(driver)
driver.execute_script("if (!window.jQuery) {
var jquery = document.createElement('script'); jquery.type = 'text/javascript';
jquery.src = 'https://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js';
document.getElementsByTagName('head')[0].appendChild(jquery);
}")
driver.execute_script("$.getScript('http://the-internet.herokuapp.com/js/vendor/jquery.growl.js')")
driver.execute_script("$('head').append('<link rel=\"stylesheet\" href=\"http://the-internet.herokuapp.com/css/jquery.growl.css\" type=\"text/css\" />');")
sleep 1
end
def display_growl(driver, message)
driver.execute_script("$.growl({ title: 'Selenium', message: '#{message}' });")
sleep 0.5
end
end
Our Event Listener helper methods give us access to the driver object at the precise moments we want in our test steps, and by wiring up growl notifications (see add_growl
and display_growl
) we can now display notification messages in the browser window automatically without any additional work in our test code.
Let's go ahead and wire up our test code to use this new wrapper.
# filename: wrapper_test.rb
require 'selenium-webdriver'
require_relative 'wrapper'
require 'rspec/expectations'
include RSpec::Matchers
def setup
@driver = Selenium::WebDriver.for :firefox, listener: Wrapper.new
end
def teardown
@driver.quit
end
def run
setup
yield
teardown
end
run do
@driver.get 'http://the-internet.herokuapp.com'
@driver.find_elements(css: 'a').last.click
end
Everything here is pretty standard with the exception of two small changes to handle our wrapper. We first need to include the file (require_relative 'wrapper'
) and then pass in an instance of the wrapper to Selenium (listener: Wrapper.new
).
Now if we run our test (ruby wrapper_test.rb
) then we will see notification messages appear around each of the test actions as they occur.
Expected Behavior
- Load the browser
- Load jQuery if it's not already loaded
- Load jQuery Growl and it's styles
- Display notifications in the browser window for each of the test actions
Summary
To see a video demo of this test, click here.
Happy Testing!