Permalink
Browse files

Wrapped gist up in an application

  • Loading branch information...
0 parents commit f8ad4d3178dd07238b1136b41e8aee49c5d63065 @techbelly committed Jun 26, 2012
7 .gitignore
@@ -0,0 +1,7 @@
+*.gem
+.rvmrc
+*.tar.gz
+rdoc
+Gemfile.lock
+html
+pkg
2 Gemfile
@@ -0,0 +1,2 @@
+source :rubygems
+gemspec
22 Rakefile
@@ -0,0 +1,22 @@
+require 'rubygems'
+require 'rubygems/package_task'
+require 'rdoc/task'
+
+RDoc::Task.new do |rd|
+ rd.main = "README.rdoc"
+ rd.rdoc_files.include("README.rdoc","lib/**/*.rb","bin/**/*")
+ rd.title = 'Your application title'
+end
+
+spec = eval(File.read('web_regression.gemspec'))
+
+Gem::PackageTask.new(spec) do |pkg|
+end
+
+require 'rake/testtask'
+Rake::TestTask.new do |t|
+ t.libs << "test"
+ t.test_files = FileList['test/**/*_test.rb']
+end
+
+task :default => :test
14 bin/web-regression
@@ -0,0 +1,14 @@
+#!/usr/bin/env ruby
+
+unless File.respond_to? :realpath
+ class File #:nodoc:
+ def self.realpath path
+ return realpath(File.readlink(path)) if symlink?(path)
+ path
+ end
+ end
+end
+$: << File.expand_path(File.dirname(File.realpath(__FILE__)) + '/../lib')
+require 'web_regression'
+
+WebRegression::Cli.execute($PROGRAM_NAME,ARGV)
8 lib/web_regression.rb
@@ -0,0 +1,8 @@
+module WebRegression
+end
+
+require 'web_regression/version'
+require 'web_regression/application'
+require 'web_regression/cli'
+require 'web_regression/comparator'
+
13 lib/web_regression/application.rb
@@ -0,0 +1,13 @@
+require 'uri'
+
+class WebRegression::Application
+ def initialize(options)
+ @options = options
+ end
+
+ def start
+ reference_file = @options.reference_file
+ uri = URI(@options.url)
+ return WebRegression::Comparator.new(reference_file,"#{uri.scheme}://#{uri.host}:#{uri.port}",uri.path,@options).compare
+ end
+end
59 lib/web_regression/cli.rb
@@ -0,0 +1,59 @@
+require 'optparse'
+require 'ostruct'
+
+module WebRegression
+ class Cli
+ def self.parse_options(program,args)
+ options = OpenStruct.new
+ options.fastfail = false
+ options.nodiff = false
+ options.opendiff = false
+ options.reference_file = "/tmp/reference.png"
+
+ opts = OptionParser.new do |opts|
+ executable = File.basename(program)
+ opts.banner = "Usage: #{executable} [options] URL"
+ opts.separator ""
+
+ opts.on_tail("-h", "--help", "Show this message") do
+ puts opts
+ exit
+ end
+
+ opts.on("-r","--reference_png PNG_FILE","Png file to compare against") do |f|
+ options.reference_file = f
+ end
+
+ opts.on("-f", "--fastfail","Fail as soon as a difference detected. Implies -n") do
+ options.fastfail = true
+ end
+
+ opts.on("-n", "--nodiff","Don't create a diff png") do
+ options.nodiff = true
+ end
+
+ opts.on("-o", "--opendiff","Open the diff file") do
+ options.opendiff = true
+ end
+
+ opts.on_tail("--version", "Show version") do
+ puts WebRegression::VERSION
+ exit
+ end
+ end
+ opts.parse!(args)
+ if ARGV.length != 1
+ puts opts
+ exit
+ end
+ options.url = ARGV[0]
+ options
+ end
+
+ def self.execute(program,args)
+ options = parse_options(program,args)
+ app = WebRegression::Application.new(options)
+ exit app.start
+ end
+ end
+end
88 lib/web_regression/comparator.rb
@@ -0,0 +1,88 @@
+require 'capybara'
+require 'capybara/dsl'
+require 'capybara/poltergeist'
+require 'chunky_png'
+require 'tempfile'
+
+Capybara.run_server = false
+Capybara.default_driver = :poltergeist
+Capybara.javascript_driver = :poltergeist
+
+class WebRegression::Comparator < Struct.new(:reference_file,:host,:path,:options)
+ include Capybara::DSL
+
+ SUCCESS, FAILURE = 0,1
+
+ def take_screenshot(name)
+ Capybara.app_host = self.host
+ visit(self.path);
+ page.driver.render(name,:full => true)
+ end
+
+ def ensure_reference_image
+ unless File.exists?(self.reference_file)
+ $stderr.puts "Creating a reference screenshot at #{self.reference_file}"
+ take_screenshot(self.reference_file)
+ end
+ end
+
+ def screenshot
+ @screenshot ||= begin
+ image_name = '/tmp/ss.png'
+ take_screenshot(image_name)
+ image_name
+ end
+ end
+
+ def checksum_match?(file1, file2)
+ ref_md5 = `md5 #{file1}`
+ new_md5 = `md5 #{file2}`
+ ref_md5 == new_md5
+ end
+
+ def reference_image
+ @reference_image ||= ChunkyPNG::Image.from_file(self.reference_file)
+ end
+
+ def new_image
+ @new_image ||= ChunkyPNG::Image.from_file(screenshot)
+ end
+
+ def highlight_diffs(new_image,diff)
+ x, y = diff.map{ |xy| xy[0] }, diff.map{ |xy| xy[1] }
+
+ new_image.rect(x.min, y.min, x.max, y.max, ChunkyPNG::Color.rgb(255,0,0))
+ diff_path = '/tmp/diff.png'
+ new_image.save(diff_path)
+
+ if options.opendiff
+ `open #{diff_path}`
+ end
+ end
+
+ def compare
+ ensure_reference_image
+
+ return SUCCESS if checksum_match?(self.reference_file,screenshot)
+
+ diff = []
+
+ reference_image.height.times do |y|
+ reference_image.row(y).each_with_index do |pixel, x|
+ unless pixel == new_image[x,y]
+ return FAILURE if options.fastfail
+ diff << [x,y]
+ end
+ end
+ end
+
+ return SUCCESS if diff.length == 0
+
+ unless options.nodiff
+ highlight_diffs(new_image,diff)
+ end
+
+ return FAILURE
+ end
+
+end
3 lib/web_regression/version.rb
@@ -0,0 +1,3 @@
+module WebRegression
+ VERSION = '0.9'
+end
14 test/null_test.rb
@@ -0,0 +1,14 @@
+require 'test/unit'
+
+class NullTest < Test::Unit::TestCase
+
+ def setup
+ end
+
+ def teardown
+ end
+
+ def test_the_truth
+ assert true
+ end
+end
23 web_regression.gemspec
@@ -0,0 +1,23 @@
+require File.join([File.dirname(__FILE__),'lib','web_regression','version.rb'])
+spec = Gem::Specification.new do |s|
+ s.name = 'web_regression'
+ s.version = WebRegression::VERSION
+ s.author = 'Ben Griffiths'
+ s.email = 'bengriffiths@gmail.com'
+ s.homepage = 'http://techbelly.com'
+ s.platform = Gem::Platform::RUBY
+ s.summary = 'Simple guard-friendly utility for diffing web screenshots to make css refactoring easier'
+ s.files = %w(
+bin/web-regression
+ )
+ s.require_paths << 'lib'
+ s.has_rdoc = false
+ s.bindir = 'bin'
+ s.executables << 'web-regression'
+
+ s.add_dependency('chunky_png')
+ s.add_dependency('poltergeist')
+
+ s.add_development_dependency('rake')
+ s.add_development_dependency('rdoc')
+end

0 comments on commit f8ad4d3

Please sign in to comment.