Skip to content

Instantly share code, notes, and snippets.

@sb8244
Created May 7, 2016 13:49
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save sb8244/55246c51e469524f2abd0c17dd3c574e to your computer and use it in GitHub Desktop.
Save sb8244/55246c51e469524f2abd0c17dd3c574e to your computer and use it in GitHub Desktop.
Capybara Visual Regression Helper
module Support
module ScreenshotHelper
def ensure_pixel_perfection
PixelPerfect.new(page)
end
class PixelPerfect
attr_reader :page
def initialize(page)
@page = page
end
def of(name)
@name = name.parameterize
self
end
def using(selector)
@selector = selector
self
end
def retina
@retina = true
self
end
def call
raise ArgumentError unless @name && @selector
image = screenshot_element
if existing_image_path.exist?
diff_image, pixels_changed = existing_image.compare_channel(image, Magick::AbsoluteErrorMetric)
percent_change = pixels_changed / (existing_image.rows * existing_image.columns) * 100
if pixels_changed > 0
diff_image.write(diff_path)
raise "ScreenshotHelper: `#{@selector}` had %#{percent_change.round(2)} pixel change. A diff has been saved to #{diff_path}"
end
else
FileUtils.copy(image_path, existing_image_path)
end
ensure
image_path.delete
end
private
def image_path
Rails.root.join("tmp", "#{@name}.png")
end
def diff_path
Rails.root.join("tmp", "diff-#{@name}.png")
end
def existing_image_path
Rails.root.join("regression_specs", "fixtures", "#{@name}.png")
end
def existing_image
Magick::Image.read(existing_image_path)[0]
end
def screenshot_element(padding: 25)
el_count = page.all(@selector).count
raise "ScreenshotHelper: #{count} elements found on the page for `#{@selector}`" unless el_count == 1
el = page.find(@selector)
location = el.native.location
size = el.native.size
if @retina
location.x *= 2
location.y *= 2
size.width *= 2
size.height *= 2
padding *= 2
end
image = page.save_screenshot(image_path)
cropped_image = Magick::Image.read(image)[0].crop(location.x - padding/2, location.y - padding/2, size.width + padding, size.height + padding)
cropped_image.write(image)
cropped_image
end
end
end
end
@bubbaksmith
Copy link

Should line 68 be interpolating el_count as opposed to count?

Also I had to edit line 45 to be image_path.delete if File.file?(image_path). I had a new image that didn't have a screenshot saved and matched 2 elements in the dom. So it was triggering the raise on line 68, but I wasn't actually seeing that error message because it was failing again in the ensure since didn't exist to delete.

Errno::ENOENT: No such file or directory @ dir_s_rmdir - /Users/brian/src/project/tmp/person-row.png

@sb8244
Copy link
Author

sb8244 commented Apr 27, 2017

You are right @l3rl4n

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment