_ruby
Example 1 - A Proxy Example
In this example we'll use Browsermob Proxy. For a primer on what this is and how to use it see tip 64.
# filename: broken_image_1.rb
require 'browsermob/proxy'
require 'selenium-webdriver'
require 'rspec/expectations'
include RSpec::Matchers
def configure_proxy
server = BrowserMob::Proxy::Server.new('./browsermob-proxy-2.0-beta-9/bin/browsermob-proxy')
server.start
@proxy = server.create_proxy
profile = Selenium::WebDriver::Firefox::Profile.new
profile.proxy = @proxy.selenium_proxy
return profile
end
def setup
@driver = Selenium::WebDriver.for :firefox, profile: configure_proxy
end
def teardown
@driver.quit
@proxy.close
end
def run
setup
yield
teardown
end
run do
@proxy.new_har
@driver.get 'http://the-internet.herokuapp.com/broken_images'
all_images = @driver.find_elements(tag_name: 'img')
broken_images = []
all_images.each do |img|
broken_images << @proxy.har.entries.find do |entry|
entry.request.url == img.attribute('src') && entry.response.status == 404
end
end
expect(broken_images).to be_empty
end
If you save this file and run it (e.g., ruby broken_image_1.rb
) here is what will happen:
- Proxy server starts
- Proxy server session created
- Browser opens
- Visit the page
- Iterate through each image in the HTTP Archive and see if it has a
404
status code - Store each broken image in a collection
- Check that the broken images collection is empty
Example 2 - An HTTP Library Example
For this example, we'll use a simple HTTP library called rest-client
.
# filename: broken_image_2.rb
require 'selenium-webdriver'
require 'rspec/expectations'
include RSpec::Matchers
def setup
@driver = Selenium::WebDriver.for :firefox
end
def teardown
@driver.quit
end
def run
setup
yield
teardown
end
run do
require 'rest-client'
@driver.get 'http://the-internet.herokuapp.com/broken_images'
all_images = @driver.find_elements(tag_name: 'img')
all_images.each do |img|
RestClient.get img.attribute('src') do |response, request, result|
expect(response.code).to eq 200
end
end
end
If you save this file and run it (e.g., ruby broken_images_2.rb
from the command-line) here is what will happen:
- Open the browser
- Find all images on the page
- Iterate through each image
- Perform a
GET
request on the image and grab it's response status code - Assert that the status code is
200
- Close the browser
By using an HTTP library we get the same outcome as we saw with a proxy server. There are additional requests being made, but it's substantially faster since it has less overhead.
Example 3 - A JavaScript Example
# filename: broken_image_3.rb
require 'selenium-webdriver'
require 'rspec/expectations'
include RSpec::Matchers
def setup
@driver = Selenium::WebDriver.for :firefox
end
def teardown
@driver.quit
end
def run
setup
yield
teardown
end
run do
@driver.get 'http://the-internet.herokuapp.com/broken_images'
all_images = @driver.find_elements tag_name: 'img'
broken_images = all_images.reject do |image|
@driver.execute_script(
"return arguments[0].complete && \
typeof arguments[0].naturalWidth != \"undefined\" && \
arguments[0].naturalWidth > 0",
image)
end
expect(broken_images).to be_empty
end
If you save this file and run it (e.g., broken_image_3.rb
from the command-line) here is what will happen:
- Open the browser
- Find all images on the page
- Iterate through each image and inspect that it finished loading and has a defined width
- Store images that fail inspection in a collection
- Assert that the collection is empty
This is the leanest approach since it requires no additional setup or extra requests. It's just a matter of executing some JavaScript code to inspect the images.
Summary
Your circumstance may vary, so choose the approach that works best for you and your team.
A big thanks to Brian Goad for the JavaScript solution and pointing me towards the StackOverflow post where he first came across this.
Happy Testing!