compatriot 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .DS_STORE
19
+ spec/sample_app/chromedriver.log
data/.rvmrc ADDED
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # This is an RVM Project .rvmrc file, used to automatically load the ruby
4
+ # development environment upon cd'ing into the directory
5
+
6
+ # First we specify our desired <ruby>[@<gemset>], the @gemset name is optional.
7
+ environment_id="ruby-1.9.2@compatriot"
8
+
9
+ #
10
+ # First we attempt to load the desired environment directly from the environment
11
+ # file, this is very fast and efficicent compared to running through the entire
12
+ # CLI and selector. If you want feedback on which environment was used then
13
+ # insert the word 'use' after --create as this triggers verbose mode.
14
+ #
15
+ if [[ -d "${rvm_path:-$HOME/.rvm}/environments" \
16
+ && -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]] ; then
17
+ \. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
18
+ else
19
+ # If the environment file has not yet been created, use the RVM CLI to select.
20
+ rvm --create "$environment_id"
21
+ fi
22
+
23
+ #
24
+ # If you use an RVM gemset file to install a list of gems (*.gems), you can have
25
+ # it be automatically loaded, uncomment the following and adjust the filename if
26
+ # necessary.
27
+ #
28
+ # filename=".gems"
29
+ # if [[ -s "$filename" ]] ; then
30
+ # rvm gemset import "$filename" | grep -v already | grep -v listed | grep -v complete | sed '/^$/d'
31
+ # fi
32
+
33
+ #
34
+ # If you use bundler and would like to run bundle each time you enter the
35
+ # directory you can uncomment the following code.
36
+ #
37
+ # # Ensure that Bundler is installed, install it if it is not.
38
+ # if ! command -v bundle ; then
39
+ # printf "The rubygem 'bundler' is not installed, installing it now.\n"
40
+ # gem install bundler
41
+ # fi
42
+ #
43
+ # # Bundle while redcing excess noise.
44
+ # printf "Bundling your gems this may take a few minutes on a fresh clone.\n"
45
+ # bundle | grep -v 'Using' | grep -v 'complete' | sed '/^$/d'
46
+ #
47
+
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'http://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in compatriot.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,100 @@
1
+ Compatriot
2
+ ----------
3
+ **Compat**ibility + **riot**! It's your **friend** that helps you with browser compatibility!
4
+
5
+ What this is
6
+ ------------
7
+
8
+ This is a Ruby gem to make cross-browser testing less painful. Its goal is to help identify pages that appear to have significant variations when rendered in different browsers. That way, you can spend your time fixing the cross-browser incompatibilities rather than spending your time looking for them, or worse, not looking for them at all and letting your users find them.
9
+
10
+ What it does now
11
+ ----------------
12
+
13
+ * Goes to the root path of a Rack app in firefox and chrome and takes a screenshot in each.
14
+ * Stores the screenshot in tmp/results/_timestamp_/_browser_/
15
+ * Creates tmp/results/_timestamp_/index.html that shows thumbnails of each screenshot plus a diff of the two in a table for easy comparison.
16
+
17
+ What it will do in the future
18
+ -----------------------------
19
+ * Have documentation
20
+ * Have a screenshot of sample results in the README
21
+ * Have unit tests and better tests
22
+ * Be on travisci
23
+ * Not have a diff that's a different size than the originals
24
+ * Find the largest, darkest contiguous region in the image diff and have a threshold of pass/fail based on that
25
+ * Perform better on the image processing (by sampling/resizing, using oily_png, etc)
26
+ * Given a list of URLs/paths to visit, will take a screenshot of each and display which URL it came from in the index
27
+ * Given a test command that uses capybara, runs those tests and takes screenshots
28
+ * Automatically compare the screenshots across browsers and flags those that are more than some configurable threshold different
29
+ * Allow configuration of which browsers to use
30
+ * Connect to virtual machines so that you don't have to have all the browsers on the machine you're running the tests on
31
+
32
+ What to do to use it
33
+ --------------------
34
+
35
+ ### Firefox
36
+ * Need to have firefox installed
37
+
38
+ ### Chrome
39
+ * Need chromedriver in your path
40
+ * From: http://code.google.com/p/chromium/downloads/list
41
+ * More info: http://code.google.com/p/selenium/wiki/ChromeDriver
42
+
43
+ See examples in the examples directory. When you run a file similar to the examples, it will save results in _current-directory_/tmp/results/_timestamp_/_browser_
44
+
45
+ What to do to run its tests
46
+ ---------------------------
47
+ Using at least ruby 1.9.2:
48
+
49
+ bundle install
50
+ bundle exec rake test
51
+
52
+ This is using minispec for testing.
53
+
54
+ What to do to contribute
55
+ ------------------------
56
+
57
+ Contributions are very welcome! This is a very rough proof-of-concept at this point, so there are many opportunities for improvement. Feel free to:
58
+
59
+ * File a github issue with any problems or suggestions <3
60
+ * Fork and send a pull request with failing tests illustrating the bug or currently unsupported use case <3 <3
61
+ * Fork and send a pull request with bugfixes or new features with passing tests! <3 <3 <3
62
+
63
+ Standing on the shoulders of giants
64
+ -----------------------------------
65
+
66
+ Many thanks to the wonderful libraries that make this gem possible:
67
+
68
+ * [capybara](https://github.com/jnicklas/capybara)
69
+ * [selenium-webdriver](http://seleniumhq.org/docs/01_introducing_selenium.html#selenium-2-aka-selenium-webdriver)
70
+ * [chunky_png](https://github.com/wvanbergen/chunky_png) (and especially [this blog post about using chunky_png to create image diffs](http://jeffkreeftmeijer.com/2011/comparing-images-and-creating-image-diffs/?utm_source=rubyweekly&utm_medium=email) by Jeff Kreeftmeijer)
71
+
72
+ Contributors
73
+ ------------
74
+ * Carol Nichols ([twitter](http://twitter.com/carols10cents), [website](http://carol-nichols.com))
75
+ * Andrew Cox ([twitter](https://twitter.com/coxandrew), [website](http://andrewcox.org/))
76
+ * You???
77
+
78
+ License
79
+ -------
80
+
81
+ (The MIT License)
82
+
83
+ Permission is hereby granted, free of charge, to any person obtaining
84
+ a copy of this software and associated documentation files (the
85
+ 'Software'), to deal in the Software without restriction, including
86
+ without limitation the rights to use, copy, modify, merge, publish,
87
+ distribute, sublicense, and/or sell copies of the Software, and to
88
+ permit persons to whom the Software is furnished to do so, subject to
89
+ the following conditions:
90
+
91
+ The above copyright notice and this permission notice shall be
92
+ included in all copies or substantial portions of the Software.
93
+
94
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
95
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
96
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
97
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
98
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
99
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
100
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require 'rake/testtask'
4
+
5
+ desc "Run tests"
6
+ task :test do
7
+ test_task = Rake::TestTask.new("tests") do |t|
8
+ t.test_files = Dir.glob(File.join("spec", "**", "*_spec.rb"))
9
+ end
10
+ task("tests").execute
11
+ end
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/compatriot/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Carol Nichols"]
6
+ gem.email = ["carol.nichols@gmail.com"]
7
+ gem.description = %q{Finds likely UI browser cross-compatibility issues.}
8
+ gem.summary = %q{Runs a command in multiple browsers using selenium then compares the screenshots and presents those likely to have cross-browser incompatibilities.}
9
+ gem.homepage = "https://github.com/clnclarinet/compatriot"
10
+
11
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
12
+ gem.files = `git ls-files`.split("\n")
13
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
14
+ gem.name = "compatriot"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Compatriot::VERSION
17
+
18
+ gem.add_runtime_dependency "capybara", "~> 1.1.2"
19
+ gem.add_runtime_dependency "rake", "~> 0.9.2.2"
20
+ gem.add_runtime_dependency "chunky_png", "~> 1.2.5"
21
+
22
+ gem.add_development_dependency "sinatra", "~> 1.3.1"
23
+ end
@@ -0,0 +1,9 @@
1
+ require 'compatriot'
2
+ require_relative "../spec/sample_app/test_app"
3
+
4
+ Compatriot.app = TestApp
5
+
6
+ Compatriot.run(%w[
7
+ /
8
+ /chrome-css-bug
9
+ ])
data/lib/compatriot.rb ADDED
@@ -0,0 +1,16 @@
1
+ require "compatriot/version"
2
+ require "compatriot/runner"
3
+ require "compatriot/browser"
4
+ require "compatriot/results_presenter"
5
+ require "compatriot/results"
6
+ require "compatriot/image_differ"
7
+
8
+ module Compatriot
9
+ class << self
10
+ attr_accessor :app
11
+
12
+ def run(paths)
13
+ Compatriot::Runner.start(app, paths)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,56 @@
1
+ require "fileutils"
2
+ require 'capybara/dsl'
3
+
4
+ module Compatriot
5
+ class Browser
6
+ include Capybara::DSL
7
+
8
+ def initialize(browser_name, results_directory)
9
+ @results_directory = results_directory
10
+ @browser_name = browser_name
11
+ @browser_selenium_id = translate_to_selenium(@browser_name)
12
+ @file_id = 1
13
+ end
14
+
15
+ def initialize_capybara(app)
16
+ driver = "selenium_#{@browser_name}".to_sym
17
+ Capybara.register_driver driver do |a|
18
+ Capybara::Selenium::Driver.new(a, :browser => @browser_selenium_id)
19
+ end
20
+ Capybara.default_driver = driver
21
+ Capybara.app = app
22
+ end
23
+
24
+ def take_screenshots(paths)
25
+ results = {}
26
+ paths.each do |path|
27
+ visit path
28
+ results[path] = screenshot
29
+ end
30
+ # Reset the selenium session to avoid timeout errors
31
+ Capybara.send(:session_pool).delete_if { |key, value| key =~ /selenium/i }
32
+ results
33
+ end
34
+
35
+ def screenshot
36
+ file_base_name = "#{@file_id}.png"
37
+ @file_id += 1
38
+ filepath = File.join(screenshot_path, file_base_name)
39
+ Capybara.page.driver.browser.save_screenshot(filepath)
40
+ file_base_name
41
+ end
42
+
43
+ def screenshot_path
44
+ return @screenshot_path if @screenshot_path
45
+ @screenshot_path = "#{@results_directory}/#{@browser_name}"
46
+ FileUtils.mkdir_p(@screenshot_path)
47
+ @screenshot_path
48
+ end
49
+
50
+ private
51
+
52
+ def translate_to_selenium(browser_name)
53
+ browser_name.to_sym
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,67 @@
1
+ require 'chunky_png'
2
+ include ChunkyPNG::Color
3
+
4
+ module Compatriot
5
+ class ImageDiffer
6
+
7
+ def self.diff(results)
8
+ images = results.map{|r| ChunkyPNG::Image.from_file(r) }
9
+ f = self.color_difference(images, results.first)
10
+ File.join(
11
+ File.basename(File.dirname(f)),
12
+ File.basename(f)
13
+ )
14
+ end
15
+
16
+ def self.same_pixels_exactly(images, name)
17
+ output = ChunkyPNG::Image.new(images.first.width, images.last.width, WHITE)
18
+ diff = []
19
+
20
+ images.first.height.times do |y|
21
+ images.first.row(y).each_with_index do |pixel, x|
22
+ output[x,y] = pixel
23
+ diff << [x,y] unless pixel == images.last[x,y]
24
+ end
25
+ end
26
+
27
+ pixels_total = images.first.pixels.length
28
+ pixels_changed = diff.length
29
+ pixels_changed_percentage = (diff.length.to_f / images.first.pixels.length) * 100
30
+
31
+ x, y = diff.map{ |xy| xy[0] }, diff.map{ |xy| xy[1] }
32
+
33
+ output.rect(x.min, y.min, x.max, y.max, ChunkyPNG::Color.rgb(0,255,0))
34
+ filename = "#{name}-same_exactly.png"
35
+ output.save(filename)
36
+ filename
37
+ end
38
+
39
+ def self.color_difference(images, name)
40
+ output = ChunkyPNG::Image.new(images.first.width, images.last.width, WHITE)
41
+ diff = []
42
+
43
+ images.first.height.times do |y|
44
+ images.first.row(y).each_with_index do |pixel, x|
45
+ unless pixel == images.last[x,y]
46
+ score = Math.sqrt(
47
+ (r(images.last[x,y]) - r(pixel)) ** 2 +
48
+ (g(images.last[x,y]) - g(pixel)) ** 2 +
49
+ (b(images.last[x,y]) - b(pixel)) ** 2
50
+ ) / Math.sqrt(MAX ** 2 * 3)
51
+
52
+ output[x,y] = grayscale(MAX - (score * MAX).round)
53
+ diff << score
54
+ end
55
+ end
56
+ end
57
+
58
+ pixels_total = images.first.pixels.length
59
+ pixels_changed = diff.length
60
+ pixels_changed_percentage = (diff.inject {|sum, value| sum + value} / images.first.pixels.length) * 100
61
+
62
+ filename = "#{name}-color_difference.png"
63
+ output.save(filename)
64
+ filename
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,43 @@
1
+ module Compatriot
2
+ class Results
3
+ def initialize
4
+ @data = {}
5
+ @diffs = {}
6
+ end
7
+
8
+ def take_screenshots(params)
9
+ @results_directory = params[:results_directory]
10
+ @app = params[:app]
11
+ @paths = params[:paths]
12
+
13
+ @browser = Compatriot::Browser.new(params[:browser], @results_directory)
14
+ @browser.initialize_capybara(@app)
15
+
16
+ @data[params[:browser]] = @browser.take_screenshots(@paths)
17
+ end
18
+
19
+ def compute_diffs
20
+ paths.map do |path|
21
+ @diffs[path] = Compatriot::ImageDiffer.diff(
22
+ browsers.map{|b| File.join(@results_directory, b, screenshot_for(b, path))}
23
+ )
24
+ end
25
+ end
26
+
27
+ def browsers
28
+ @data.keys
29
+ end
30
+
31
+ def paths
32
+ @data[browsers.first].keys
33
+ end
34
+
35
+ def screenshot_for(browser, path)
36
+ @data[browser][path]
37
+ end
38
+
39
+ def diff_for(path)
40
+ @diffs[path]
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,62 @@
1
+ require 'erb'
2
+
3
+ module Compatriot
4
+ class ResultsPresenter
5
+ def initialize(results_directory)
6
+ @results_directory = results_directory
7
+ end
8
+
9
+ def make_index_page(results)
10
+ index_page_file = File.join(@results_directory, "index.html")
11
+
12
+ b = binding
13
+ browsers = results.browsers
14
+ paths = results.paths
15
+
16
+ html = ERB.new <<-EOF
17
+ <html>
18
+ <head>
19
+ <title>Cross browser test results</title>
20
+ <style type='text/css'>
21
+ table, tr, th, td {
22
+ border: 1px solid #aaa;
23
+ }
24
+ img {
25
+ width: 300px;
26
+ }
27
+ </style>
28
+ </head>
29
+ <body>
30
+ <h1>Results</h1>
31
+ <table>
32
+ <tr>
33
+ <th>Path</th>
34
+ <% browsers.each do |browser| %>
35
+ <th><%= browser %></th>
36
+ <% end %>
37
+ <th>Diff</th>
38
+ </tr>
39
+ <% paths.each do |path| %>
40
+ <tr>
41
+ <td>
42
+ <%= path %>
43
+ </td>
44
+ <% browsers.each do |browser| %>
45
+ <td>
46
+ <img src="<%= browser %>/<%= results.screenshot_for(browser, path) %>" />
47
+ </td>
48
+ <% end %>
49
+ <td>
50
+ <img src="<%= results.diff_for(path) %>" />
51
+ </td>
52
+ </tr>
53
+ <% end %>
54
+ </table>
55
+ </body>
56
+ </html>
57
+ EOF
58
+
59
+ File.open(index_page_file, 'w') {|f| f.write(html.result(b)) }
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,52 @@
1
+ require "fileutils"
2
+
3
+ module Compatriot
4
+ class Runner
5
+ def self.start(app, paths, clock = DateTime)
6
+ runner = new(app, paths, clock)
7
+ runner.take_screenshots
8
+ runner.compute_diffs
9
+ runner.make_index_page
10
+ runner
11
+ end
12
+
13
+ BROWSERS = ["firefox", "chrome"]
14
+
15
+ attr_reader :app, :results
16
+
17
+ def initialize(app, paths, clock)
18
+ @app = app
19
+ @paths = paths
20
+ @clock = clock
21
+ @results = Compatriot::Results.new
22
+ end
23
+
24
+ def take_screenshots
25
+ BROWSERS.each do |b|
26
+ @results.take_screenshots(
27
+ :browser => b,
28
+ :app => @app,
29
+ :paths => @paths,
30
+ :results_directory => results_directory
31
+ )
32
+ end
33
+ end
34
+
35
+ def compute_diffs
36
+ @results.compute_diffs
37
+ end
38
+
39
+ def make_index_page
40
+ presenter = Compatriot::ResultsPresenter.new(results_directory)
41
+ presenter.make_index_page(@results)
42
+ end
43
+
44
+ def results_directory
45
+ return @results_directory if @results_directory
46
+ timestamp = @clock.now.strftime("%Y-%m-%d-%H-%M-%S")
47
+ directory_name = "tmp/results/#{timestamp}"
48
+ FileUtils.mkdir_p(directory_name)
49
+ @results_directory = directory_name
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,3 @@
1
+ module Compatriot
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,53 @@
1
+ require_relative 'spec_helper'
2
+ require 'fileutils'
3
+ require 'date'
4
+
5
+ describe "The very basics" do
6
+ before do
7
+ @current_dir = Dir.getwd
8
+ Dir.chdir(File.join(File.dirname(__FILE__), 'sample_app'))
9
+
10
+ fake_date = DateTime.parse("2012-01-01 00:00:00 UTC")
11
+ fake_date_dir = fake_date.strftime("%Y-%m-%d-%H-%M-%S")
12
+ @fixed_clock = OpenStruct.new(:now => fake_date)
13
+
14
+ @results_directory = File.join("tmp", "results", fake_date_dir)
15
+ @firefox_directory = File.join(@results_directory, "firefox")
16
+ @chrome_directory = File.join(@results_directory, "chrome")
17
+ end
18
+
19
+ after do
20
+ Dir.chdir(@current_dir)
21
+ end
22
+
23
+ it "holds onto the app we give it" do
24
+ x = Compatriot::Runner.new(TestApp, ["/"], @fixed_clock)
25
+ x.app.must_equal(TestApp)
26
+ end
27
+
28
+ it "names a results directory based on the clock" do
29
+ x = Compatriot::Runner.new(TestApp, ["/"], @fixed_clock)
30
+ x.results_directory.must_equal(@results_directory)
31
+ end
32
+
33
+ describe "self#start" do
34
+ before do
35
+ Compatriot::Runner.start(TestApp, ["/"], @fixed_clock)
36
+ end
37
+
38
+ it "creates directories in which to store the results based on the date" do
39
+ assert File.exists?(@results_directory)
40
+ assert File.exists?(@firefox_directory)
41
+ assert File.exists?(@chrome_directory)
42
+ end
43
+
44
+ it "visits the home page and takes 1 screenshot per browser and diffs them" do
45
+ Dir.glob(File.join(@firefox_directory, "*.png")).size.must_equal 2
46
+ Dir.glob(File.join(@chrome_directory, "*.png")).size.must_equal 1
47
+ end
48
+
49
+ it "creates an index page that shows the screenshots" do
50
+ assert File.exists?(File.join(@results_directory, "index.html"))
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,55 @@
1
+ require_relative 'spec_helper'
2
+ require 'fileutils'
3
+ require 'date'
4
+ require 'nokogiri'
5
+
6
+ describe "Hit a list of paths for this app" do
7
+ before do
8
+ @current_dir = Dir.getwd
9
+ Dir.chdir(File.join(File.dirname(__FILE__), 'sample_app'))
10
+
11
+ fake_date = DateTime.parse("2012-01-02 00:00:00 UTC")
12
+ fake_date_dir = fake_date.strftime("%Y-%m-%d-%H-%M-%S")
13
+ @fixed_clock = OpenStruct.new(:now => fake_date)
14
+
15
+ @results_directory = File.join("tmp", "results", fake_date_dir)
16
+ @firefox_directory = File.join(@results_directory, "firefox")
17
+ @chrome_directory = File.join(@results_directory, "chrome")
18
+
19
+ @x = Compatriot::Runner.start(TestApp, ["/", "/chrome-css-bug"], @fixed_clock)
20
+ end
21
+
22
+ after do
23
+ Dir.chdir(@current_dir)
24
+ end
25
+
26
+ it "takes a screenshot for each path given and diffs them" do
27
+ Dir.glob(File.join(@firefox_directory, "*.png")).size.must_equal 6
28
+ Dir.glob(File.join(@chrome_directory, "*.png")).size.must_equal 2
29
+ end
30
+
31
+ it "has 2 rows of results in the table on the results index" do
32
+ results_index = IO.read(File.join(@results_directory, "index.html"))
33
+ xml = Nokogiri::XML(results_index)
34
+ xml.xpath("//tr[td]").size.must_equal(2)
35
+ end
36
+
37
+ it "gets a list of the browsers in the results" do
38
+ @x.results.browsers.must_equal(["firefox", "chrome"])
39
+ end
40
+
41
+ it "gets a list of the paths in the results" do
42
+ @x.results.paths.must_equal(["/", "/chrome-css-bug"])
43
+ end
44
+
45
+ it "gets the filename of the screenshot for a particular browser and path" do
46
+ @x.results.screenshot_for("firefox", "/").must_equal("1.png")
47
+ @x.results.screenshot_for("firefox", "/chrome-css-bug").must_equal("2.png")
48
+ @x.results.screenshot_for("chrome", "/").must_equal("1.png")
49
+ @x.results.screenshot_for("chrome", "/chrome-css-bug").must_equal("2.png")
50
+ end
51
+
52
+ it "should have the home page row colored green and the chrome bug row colored red" do
53
+ @x.compute_diffs
54
+ end
55
+ end
@@ -0,0 +1,21 @@
1
+ require 'sinatra/base'
2
+ require 'rack'
3
+ require 'yaml'
4
+
5
+ class TestApp < Sinatra::Base
6
+ set :root, File.dirname(__FILE__)
7
+ set :static, true
8
+
9
+ get '/' do
10
+ "<h1>Hello world!</h1"
11
+ end
12
+
13
+ get "/chrome-css-bug" do
14
+ "<table><tr style='background: url(/images/smileyface.jpg) no-repeat;'><td style='padding:30px;'>One</td><td style='padding:30px;'>Two</td></tr></table>"
15
+ end
16
+
17
+ end
18
+
19
+ if __FILE__ == $0
20
+ Rack::Handler::WEBrick.run TestApp, :Port => 8070
21
+ end
@@ -0,0 +1,8 @@
1
+ $:.unshift(File.expand_path('../lib', File.dirname(__FILE__)))
2
+
3
+ require 'minitest/autorun'
4
+ require 'compatriot'
5
+
6
+ require_relative "sample_app/test_app"
7
+
8
+ FileUtils.remove_dir(File.join("sample_app", "tmp", "results"), true)
metadata ADDED
@@ -0,0 +1,114 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: compatriot
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Carol Nichols
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-12-02 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: capybara
16
+ requirement: &2153232360 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 1.1.2
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *2153232360
25
+ - !ruby/object:Gem::Dependency
26
+ name: rake
27
+ requirement: &2153231860 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: 0.9.2.2
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *2153231860
36
+ - !ruby/object:Gem::Dependency
37
+ name: chunky_png
38
+ requirement: &2153231400 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 1.2.5
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *2153231400
47
+ - !ruby/object:Gem::Dependency
48
+ name: sinatra
49
+ requirement: &2153230940 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 1.3.1
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *2153230940
58
+ description: Finds likely UI browser cross-compatibility issues.
59
+ email:
60
+ - carol.nichols@gmail.com
61
+ executables: []
62
+ extensions: []
63
+ extra_rdoc_files: []
64
+ files:
65
+ - .gitignore
66
+ - .rvmrc
67
+ - Gemfile
68
+ - README.md
69
+ - Rakefile
70
+ - compatriot.gemspec
71
+ - examples/compatriot_tests.rb
72
+ - lib/compatriot.rb
73
+ - lib/compatriot/browser.rb
74
+ - lib/compatriot/image_differ.rb
75
+ - lib/compatriot/results.rb
76
+ - lib/compatriot/results_presenter.rb
77
+ - lib/compatriot/runner.rb
78
+ - lib/compatriot/version.rb
79
+ - spec/basic_behavior_spec.rb
80
+ - spec/list_of_app_paths_spec.rb
81
+ - spec/sample_app/public/images/smileyface.jpg
82
+ - spec/sample_app/test_app.rb
83
+ - spec/spec_helper.rb
84
+ homepage: https://github.com/clnclarinet/compatriot
85
+ licenses: []
86
+ post_install_message:
87
+ rdoc_options: []
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ! '>='
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ requirements: []
103
+ rubyforge_project:
104
+ rubygems_version: 1.8.8
105
+ signing_key:
106
+ specification_version: 3
107
+ summary: Runs a command in multiple browsers using selenium then compares the screenshots
108
+ and presents those likely to have cross-browser incompatibilities.
109
+ test_files:
110
+ - spec/basic_behavior_spec.rb
111
+ - spec/list_of_app_paths_spec.rb
112
+ - spec/sample_app/public/images/smileyface.jpg
113
+ - spec/sample_app/test_app.rb
114
+ - spec/spec_helper.rb