compatriot 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +4 -0
- data/README.md +14 -8
- data/Rakefile +11 -1
- data/compatriot.gemspec +11 -7
- data/examples/compatriot_tests.rb +2 -2
- data/features/list_of_urls.feature +31 -0
- data/features/step_definitions/cli_steps.rb +60 -0
- data/features/support/env.rb +5 -0
- data/lib/compatriot.rb +1 -2
- data/lib/compatriot/image_differ/color_differ.rb +70 -0
- data/lib/compatriot/image_differ/image_differ.rb +41 -0
- data/lib/compatriot/results_presenter.rb +1 -1
- data/lib/compatriot/runner.rb +5 -3
- data/lib/compatriot/version.rb +1 -1
- data/spec/sample_app/{test_app.rb → sample_app.rb} +3 -3
- data/spec/spec_helper.rb +9 -35
- data/spec/unit/browser_spec.rb +4 -0
- data/spec/unit/image_differ/color_differ_spec.rb +39 -0
- data/spec/unit/image_differ/image_differ_spec.rb +67 -0
- data/spec/unit/runner_spec.rb +1 -1
- metadata +178 -48
- data/.rvmrc +0 -47
- data/lib/compatriot/image_differ.rb +0 -100
- data/spec/integration/full_stack_spec.rb +0 -36
- data/spec/unit/image_differ_spec.rb +0 -53
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e100d57f0086c254d7fcd46b1d615dc3ec7570a1
|
4
|
+
data.tar.gz: 3a474ae56359208e474ea4742b3092797e9a13e4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1f712342dfd796f65140fadb0251325d2e44f91d698f3c58859b721b010f3ca9ddd538ff0c8eb8275860b928ddeb2bf046c46c6cca9f6c16cfc63cfce7e91c53
|
7
|
+
data.tar.gz: bed0d7c8323e728fa30cadbb044b9ebe8e92829978da39516f7396fa650c91e4cf2b06a402dd0a20f8d50437cb7702438d65a19d0888bb63822875e1097b18fa
|
data/.gitignore
CHANGED
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
compatriot
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.1.7
|
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
Compatriot
|
2
2
|
==========
|
3
|
+
[](http://travis-ci.org/clnclarinet/compatriot)
|
3
4
|
|
4
5
|
**Compat**ibility + **riot**! It's the **friend** that helps with browser compatibility!
|
5
6
|
This Ruby gem makes cross-browser testing less painful.
|
@@ -11,6 +12,7 @@ Don't let your users find the inconsistencies and get to them first.
|
|
11
12
|
What it does now
|
12
13
|
----------------
|
13
14
|
|
15
|
+
* [Documentation on RelishApp](https://www.relishapp.com/clnclarinet/compatriot)
|
14
16
|
* In firefox and chrome, visits a list of paths to a Rack app and takes a screenshot on each page.
|
15
17
|
* Stores the screenshot in `tmp/results/_timestamp_/_browser_/`
|
16
18
|
* Creates `tmp/results/_timestamp_/index.html` that shows thumbnails of each screenshot plus a diff of the two in a table for easy comparison.
|
@@ -19,11 +21,9 @@ What it does now
|
|
19
21
|
What it will do in the future
|
20
22
|
-----------------------------
|
21
23
|
|
22
|
-
* Have documentation
|
24
|
+
* Have more documentation (a start is [on RelishApp](https://www.relishapp.com/clnclarinet/compatriot)!)
|
23
25
|
* Have a screenshot of sample results in the README
|
24
|
-
* Have
|
25
|
-
* Be on travis-ci
|
26
|
-
* Not have a diff that's a different size than the originals
|
26
|
+
* Have more and better tests
|
27
27
|
* Find the largest, darkest contiguous region in the image diff and have a threshold of pass/fail based on that
|
28
28
|
* Perform better on the image processing (by sampling/resizing, using oily_png, etc)
|
29
29
|
* Given a list of URLs/paths to visit, will take a screenshot of each and display which URL it came from in the index
|
@@ -31,6 +31,7 @@ What it will do in the future
|
|
31
31
|
* Automatically compare the screenshots across browsers and flags those that are more than some configurable threshold different
|
32
32
|
* Allow configuration of which browsers to use
|
33
33
|
* Connect to virtual machines so that you don't have to have all the browsers on the machine you're running the tests on
|
34
|
+
* Steal some of VCR's relish rake tasks
|
34
35
|
|
35
36
|
|
36
37
|
How To Use
|
@@ -38,17 +39,19 @@ How To Use
|
|
38
39
|
|
39
40
|
**Requirements**
|
40
41
|
|
41
|
-
* Ruby
|
42
|
+
* Ruby v2.1.7
|
42
43
|
* [Firefox](http://getfirefox.net)
|
43
44
|
* [chromedriver](http://code.google.com/p/selenium/wiki/ChromeDriver)
|
44
45
|
|
46
|
+
There are setup examples in the examples directory and [documentation on RelishApp](https://www.relishapp.com/clnclarinet/compatriot)
|
47
|
+
|
45
48
|
When you run a file similar to the examples it will save results in `_current-directory_/tmp/results/_timestamp_/_browser_`
|
46
49
|
|
47
50
|
|
48
51
|
What to do to run its tests
|
49
52
|
---------------------------
|
50
53
|
|
51
|
-
Using at least ruby 1.
|
54
|
+
Using at least ruby 2.1.7:
|
52
55
|
|
53
56
|
bundle install
|
54
57
|
bundle exec rake test
|
@@ -83,14 +86,17 @@ Many thanks to the wonderful libraries that make this gem possible:
|
|
83
86
|
* [capybara](https://github.com/jnicklas/capybara)
|
84
87
|
* [selenium-webdriver](http://seleniumhq.org/docs/01_introducing_selenium.html#selenium-2-aka-selenium-webdriver)
|
85
88
|
* [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)
|
89
|
+
* [travis](http://travis-ci.org/) for CI
|
90
|
+
* [relishapp](https://www.relishapp.com/) for documentation
|
91
|
+
* [vcr](https://github.com/myronmarston/vcr) for having such awesome documentation that it inspired me to use Relishapp
|
86
92
|
|
87
93
|
|
88
94
|
Contributors
|
89
95
|
------------
|
90
96
|
* Carol Nichols ([twitter](http://twitter.com/carols10cents), [website](http://carol-nichols.com))
|
91
97
|
* Andrew Cox ([twitter](https://twitter.com/coxandrew), [website](http://andrewcox.org/))
|
92
|
-
* Kurtis Rainbolt-Greene ([twitter](https://twitter.com/krainboltgreene)
|
93
|
-
* Steve Klabnik ([twitter](https://twitter.com/steveklabnik)
|
98
|
+
* Kurtis Rainbolt-Greene ([twitter](https://twitter.com/krainboltgreene), [website](http://kurtisrainboltgreene.name/))
|
99
|
+
* Steve Klabnik ([twitter](https://twitter.com/steveklabnik), [website](http://www.steveklabnik.com/))
|
94
100
|
* You???
|
95
101
|
|
96
102
|
|
data/Rakefile
CHANGED
@@ -13,4 +13,14 @@ end
|
|
13
13
|
desc "Run tests"
|
14
14
|
task :spec do
|
15
15
|
task("test").execute
|
16
|
-
end
|
16
|
+
end
|
17
|
+
|
18
|
+
task :travis do
|
19
|
+
puts "Grabbing chromedriver..."
|
20
|
+
mkdir_p "/tmp/bin"
|
21
|
+
system "cd /tmp/bin && wget http://chromium.googlecode.com/files/chromedriver_linux32_16.0.902.0.zip && unzip chromedriver_linux32_16.0.902.0.zip"
|
22
|
+
|
23
|
+
puts "Starting to run tests..."
|
24
|
+
system("export PATH=/tmp/bin:$PATH && export DISPLAY=:99.0 && bundle exec rake test && bundle exec cucumber features")
|
25
|
+
raise "`rake test` failed!" unless $?.exitstatus == 0
|
26
|
+
end
|
data/compatriot.gemspec
CHANGED
@@ -18,13 +18,17 @@ Gem::Specification.new do |gem|
|
|
18
18
|
gem.name = "compatriot"
|
19
19
|
gem.require_paths = ["lib"]
|
20
20
|
gem.version = Compatriot::VERSION
|
21
|
+
gem.licenses = "MIT"
|
21
22
|
|
22
|
-
|
23
|
-
gem.add_development_dependency '
|
24
|
-
gem.add_development_dependency '
|
25
|
-
gem.add_development_dependency '
|
23
|
+
gem.add_development_dependency 'minitest', '~> 5.8', '>= 5.8.2'
|
24
|
+
gem.add_development_dependency 'sinatra', '~> 1.4', '>= 1.4.6'
|
25
|
+
gem.add_development_dependency 'mocha', '~> 1.1', '>= 1.1.0'
|
26
|
+
gem.add_development_dependency 'cucumber', '~> 2.1', '>= 2.1.0'
|
27
|
+
gem.add_development_dependency 'aruba', '~> 0.10.0'
|
28
|
+
gem.add_development_dependency 'relish', '~> 0.7.1'
|
26
29
|
|
27
|
-
gem.
|
28
|
-
gem.
|
29
|
-
gem.
|
30
|
+
gem.add_runtime_dependency 'capybara', '~> 2.5', '>= 2.5.0'
|
31
|
+
gem.add_runtime_dependency 'selenium-webdriver', '~> 2.48', '>= 2.48.1'
|
32
|
+
gem.add_runtime_dependency 'rake', '~> 10.4', '>= 10.4.2'
|
33
|
+
gem.add_runtime_dependency 'chunky_png', '~> 1.3', '>= 1.3.5'
|
30
34
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
Feature: list_of_urls
|
2
|
+
|
3
|
+
Passing a list of URLs to Compatriot.run will visit each of them in each browser and take a screenshot.
|
4
|
+
|
5
|
+
Scenario: List of URLs
|
6
|
+
Given a Sinatra app named "simple_app.rb" with:
|
7
|
+
"""ruby
|
8
|
+
get '/' do
|
9
|
+
'Hello'
|
10
|
+
end
|
11
|
+
|
12
|
+
get '/goodbye' do
|
13
|
+
'Goodbye'
|
14
|
+
end
|
15
|
+
"""
|
16
|
+
And a file named "compatriot_urls.rb" with:
|
17
|
+
"""ruby
|
18
|
+
$:.unshift(File.expand_path('../../lib', File.dirname(__FILE__)))
|
19
|
+
require 'compatriot'
|
20
|
+
require_relative 'simple_app'
|
21
|
+
Compatriot.app = SimpleApp
|
22
|
+
Compatriot.run(%w[
|
23
|
+
/
|
24
|
+
/goodbye
|
25
|
+
])
|
26
|
+
|
27
|
+
"""
|
28
|
+
And the directory "tmp/results" does not exist
|
29
|
+
When I run `ruby compatriot_urls.rb`
|
30
|
+
Then "tmp/results" should have 1 subdirectory
|
31
|
+
And there should be results for 2 screenshots
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module CompatriotHelpers
|
2
|
+
def create_sinatra_app(file_name, content)
|
3
|
+
app_class = camelize(file_name.gsub(/\.rb$/, ''))
|
4
|
+
beginning_sinatra_app = <<-HERE
|
5
|
+
require 'sinatra/base'
|
6
|
+
require 'rack'
|
7
|
+
require 'yaml'
|
8
|
+
|
9
|
+
class #{app_class} < Sinatra::Base
|
10
|
+
set :root, File.dirname(__FILE__)
|
11
|
+
set :static, true
|
12
|
+
HERE
|
13
|
+
|
14
|
+
ending_sinatra_app = <<-HERE
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
if __FILE__ == $0
|
19
|
+
Rack::Handler::WEBrick.run #{app_class}, :Port => 8070
|
20
|
+
end
|
21
|
+
HERE
|
22
|
+
beginning_sinatra_app + content + ending_sinatra_app
|
23
|
+
end
|
24
|
+
|
25
|
+
def camelize(lower_case_and_underscored_word, first_letter_in_uppercase = true)
|
26
|
+
if first_letter_in_uppercase
|
27
|
+
lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
|
28
|
+
else
|
29
|
+
lower_case_and_underscored_word.to_s[0].chr.downcase + camelize(lower_case_and_underscored_word)[1..-1]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
World(CompatriotHelpers)
|
34
|
+
|
35
|
+
Given /^a Sinatra app named "([^"]*)" with:$/ do |file_name, content|
|
36
|
+
write_file(file_name, create_sinatra_app(file_name, content))
|
37
|
+
end
|
38
|
+
|
39
|
+
Then /^"([^"]*)" should have (\d+) subdir/ do |directory, subdirectory_count|
|
40
|
+
cd('.') {
|
41
|
+
expect((Dir.entries(directory) - [".", ".."]).size).to eql subdirectory_count.to_i
|
42
|
+
}
|
43
|
+
end
|
44
|
+
|
45
|
+
Then /^there should be results for (\d+) screenshots?$/ do |screenshot_count|
|
46
|
+
screenshot_count = screenshot_count.to_i
|
47
|
+
results_tmp_dir = "tmp/results"
|
48
|
+
cd('.') {
|
49
|
+
current_results_dir = (Dir.entries(results_tmp_dir) - [".", ".."]).first
|
50
|
+
current_results_dir = File.join(results_tmp_dir, current_results_dir)
|
51
|
+
|
52
|
+
firefox_dir = File.join(current_results_dir, "firefox")
|
53
|
+
chrome_dir = File.join(current_results_dir, "chrome")
|
54
|
+
diffs_dir = File.join(current_results_dir, "diffs")
|
55
|
+
|
56
|
+
expect(Dir.glob(File.join(firefox_dir, "*.png")).size).to eql 2
|
57
|
+
expect(Dir.glob(File.join(chrome_dir, "*.png")).size).to eql 2
|
58
|
+
expect(Dir.glob(File.join(diffs_dir, "*.png")).size).to eql 2
|
59
|
+
}
|
60
|
+
end
|
data/lib/compatriot.rb
CHANGED
@@ -2,8 +2,7 @@ require "compatriot/version"
|
|
2
2
|
require "compatriot/runner"
|
3
3
|
require "compatriot/browser"
|
4
4
|
require "compatriot/results_presenter"
|
5
|
-
require "compatriot/
|
6
|
-
require "compatriot/image_differ"
|
5
|
+
require "compatriot/image_differ/image_differ"
|
7
6
|
|
8
7
|
module Compatriot
|
9
8
|
class << self
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'chunky_png'
|
2
|
+
include ChunkyPNG::Color
|
3
|
+
|
4
|
+
module Compatriot
|
5
|
+
class ColorDiffer
|
6
|
+
|
7
|
+
def self.diff(filename1, filename2, results_directory)
|
8
|
+
image1 = ChunkyPNG::Image.from_file(filename1)
|
9
|
+
image2 = ChunkyPNG::Image.from_file(filename2)
|
10
|
+
@results_directory = results_directory
|
11
|
+
|
12
|
+
output = ChunkyPNG::Image.new(image1.width, image1.height, WHITE)
|
13
|
+
diff = []
|
14
|
+
|
15
|
+
each_pixel(image1) do |x, y|
|
16
|
+
pixel1 = image1[x,y]
|
17
|
+
pixel2 = image2[x,y]
|
18
|
+
unless pixel1 == pixel2
|
19
|
+
output[x,y], score = color_difference_of_pixels(pixel1, pixel2)
|
20
|
+
diff << score
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
save_diff_image(output, filename1, filename2)
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.save_diff_image(output, filename1, filename2)
|
28
|
+
filename = diff_name(filename1, filename2)
|
29
|
+
path = File.join(
|
30
|
+
@results_directory,
|
31
|
+
"diffs",
|
32
|
+
filename
|
33
|
+
)
|
34
|
+
output.save(path)
|
35
|
+
File.join("diffs", filename)
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.diff_name(image1, image2)
|
39
|
+
browser1 = File.basename(File.dirname(image1))
|
40
|
+
browser2 = File.basename(File.dirname(image2))
|
41
|
+
|
42
|
+
"color_#{browser1}_vs_#{browser2}_#{File.basename(image1)}"
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.color_difference_of_pixels(pixel1, pixel2)
|
46
|
+
score = Math.sqrt(
|
47
|
+
(r(pixel2) - r(pixel1)) ** 2 +
|
48
|
+
(g(pixel2) - g(pixel1)) ** 2 +
|
49
|
+
(b(pixel2) - b(pixel1)) ** 2
|
50
|
+
) / Math.sqrt(MAX ** 2 * 3)
|
51
|
+
|
52
|
+
[grayscale(MAX - (score * MAX).round), score]
|
53
|
+
end
|
54
|
+
|
55
|
+
# Not called anywhere
|
56
|
+
def color_difference_total_score
|
57
|
+
pixels_total = image1.width * image1.height
|
58
|
+
pixels_changed = diff.length
|
59
|
+
pixels_changed_percentage = (diff.inject {|sum, value| sum + value} / pixels_total) * 100
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.each_pixel(image)
|
63
|
+
image.width.times do |x|
|
64
|
+
image.height.times do |y|
|
65
|
+
yield(x, y)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require_relative 'color_differ'
|
2
|
+
|
3
|
+
module Compatriot
|
4
|
+
class ImageDiffer
|
5
|
+
|
6
|
+
def initialize(params = {})
|
7
|
+
@paths = params[:paths]
|
8
|
+
@browsers = params[:browsers]
|
9
|
+
@strategy = params[:strategy] || Compatriot::ColorDiffer
|
10
|
+
@results_directory = params[:results_directory]
|
11
|
+
@diffs = {}
|
12
|
+
|
13
|
+
create_diffs_path
|
14
|
+
end
|
15
|
+
|
16
|
+
def diff_for(path)
|
17
|
+
@diffs[path]
|
18
|
+
end
|
19
|
+
|
20
|
+
def compute!
|
21
|
+
@paths.map do |path|
|
22
|
+
images_to_diff = @browsers.map { |b| b.absolute_screenshot_for(path) }
|
23
|
+
@diffs[path] = diff(images_to_diff)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def diff(results)
|
28
|
+
@strategy.diff(results.first, results.last, @results_directory)
|
29
|
+
end
|
30
|
+
|
31
|
+
def diffs_path
|
32
|
+
File.join(@results_directory, "diffs")
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def create_diffs_path
|
38
|
+
FileUtils.mkdir_p(diffs_path)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/compatriot/runner.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
require
|
1
|
+
require 'fileutils'
|
2
|
+
require 'date'
|
2
3
|
|
3
4
|
module Compatriot
|
4
5
|
class Runner
|
@@ -42,7 +43,8 @@ module Compatriot
|
|
42
43
|
@differ = Compatriot::ImageDiffer.new(
|
43
44
|
:paths => @paths,
|
44
45
|
:browsers => @browsers,
|
45
|
-
:strategy =>
|
46
|
+
:strategy => Compatriot::ColorDiffer,
|
47
|
+
:results_directory => @results_directory
|
46
48
|
)
|
47
49
|
@differ.compute!
|
48
50
|
end
|
@@ -60,4 +62,4 @@ module Compatriot
|
|
60
62
|
FileUtils.mkdir_p(@results_directory)
|
61
63
|
end
|
62
64
|
end
|
63
|
-
end
|
65
|
+
end
|
data/lib/compatriot/version.rb
CHANGED
@@ -2,12 +2,12 @@ require 'sinatra/base'
|
|
2
2
|
require 'rack'
|
3
3
|
require 'yaml'
|
4
4
|
|
5
|
-
class
|
5
|
+
class SampleApp < Sinatra::Base
|
6
6
|
set :root, File.dirname(__FILE__)
|
7
7
|
set :static, true
|
8
8
|
|
9
9
|
get '/' do
|
10
|
-
"<h1>Hello world!</h1"
|
10
|
+
"<h1>Hello world!</h1><div><a href='chrome-css-bug'>Try another page</a></div>"
|
11
11
|
end
|
12
12
|
|
13
13
|
get "/chrome-css-bug" do
|
@@ -17,5 +17,5 @@ class TestApp < Sinatra::Base
|
|
17
17
|
end
|
18
18
|
|
19
19
|
if __FILE__ == $0
|
20
|
-
Rack::Handler::WEBrick.run
|
20
|
+
Rack::Handler::WEBrick.run SampleApp, :Port => 8070
|
21
21
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,13 +1,11 @@
|
|
1
1
|
$:.unshift(File.expand_path('../lib', File.dirname(__FILE__)))
|
2
2
|
|
3
|
-
require
|
4
|
-
|
5
|
-
require 'minitest/autorun'
|
6
|
-
require 'mocha'
|
3
|
+
require "minitest/autorun"
|
4
|
+
require "mocha/mini_test"
|
7
5
|
|
8
6
|
require 'compatriot'
|
9
7
|
|
10
|
-
require_relative "sample_app/
|
8
|
+
require_relative "sample_app/sample_app"
|
11
9
|
|
12
10
|
# A custom runner to enable before_suite and after_suite setup/teardown.
|
13
11
|
# http://bfts.rubyforge.org/minitest/index.html
|
@@ -15,37 +13,13 @@ require_relative "sample_app/test_app"
|
|
15
13
|
# before running the suite; it's useful to be able to look at the screenshots
|
16
14
|
# after a test run so we're not deleting them then.
|
17
15
|
|
18
|
-
module
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
def after_suites
|
24
|
-
end
|
25
|
-
|
26
|
-
def _run_suites(suites, type)
|
27
|
-
begin
|
28
|
-
before_suites
|
29
|
-
super(suites, type)
|
30
|
-
ensure
|
31
|
-
after_suites
|
32
|
-
end
|
33
|
-
end
|
16
|
+
module TestRunner
|
17
|
+
def before_setup
|
18
|
+
super
|
19
|
+
FileUtils.remove_dir(File.join("sample_app", "tmp", "results"), true)
|
34
20
|
end
|
35
21
|
end
|
36
22
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
def before_suites
|
41
|
-
super
|
42
|
-
FileUtils.remove_dir(File.join("sample_app", "tmp", "results"), true)
|
43
|
-
end
|
44
|
-
|
45
|
-
def after_suites
|
46
|
-
super
|
47
|
-
end
|
48
|
-
end
|
23
|
+
class Minitest::Spec
|
24
|
+
include TestRunner
|
49
25
|
end
|
50
|
-
|
51
|
-
MiniTest::Unit.runner = MiniTestRemoveScreenshots::Unit.new
|
data/spec/unit/browser_spec.rb
CHANGED
@@ -86,6 +86,8 @@ describe Compatriot::Browser do
|
|
86
86
|
:name => "foo",
|
87
87
|
:screenshot_directory => "bar"
|
88
88
|
)
|
89
|
+
app = stub
|
90
|
+
@b.initialize_capybara(app)
|
89
91
|
end
|
90
92
|
|
91
93
|
it "visits the path" do
|
@@ -132,6 +134,8 @@ describe Compatriot::Browser do
|
|
132
134
|
:name => "foo",
|
133
135
|
:screenshot_directory => "bar"
|
134
136
|
)
|
137
|
+
app = stub
|
138
|
+
@b.initialize_capybara(app)
|
135
139
|
end
|
136
140
|
|
137
141
|
it "returns nil if there is no screenshot for that path" do
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require_relative '../../spec_helper'
|
2
|
+
|
3
|
+
describe Compatriot::ColorDiffer do
|
4
|
+
it "calls chunky_png on each image path" do
|
5
|
+
image1 = stub_everything("1", :width => 1, :height => 2)
|
6
|
+
image2 = stub_everything("2", :width => 3, :height => 4)
|
7
|
+
|
8
|
+
ChunkyPNG::Image.expects(:from_file).with("file_one").returns(image1)
|
9
|
+
ChunkyPNG::Image.expects(:from_file).with("file_two").returns(image2)
|
10
|
+
Compatriot::ColorDiffer.stubs(:save_diff_image)
|
11
|
+
|
12
|
+
Compatriot::ColorDiffer.diff("file_one", "file_two", "some/dir")
|
13
|
+
end
|
14
|
+
|
15
|
+
it "starts a new white image with the same dimensions" do
|
16
|
+
diff_image = stub_everything
|
17
|
+
ChunkyPNG::Image.expects(:new).with(
|
18
|
+
1,
|
19
|
+
2,
|
20
|
+
ChunkyPNG::Image::WHITE
|
21
|
+
).returns(diff_image)
|
22
|
+
|
23
|
+
image1 = stub_everything("1", :width => 1, :height => 2)
|
24
|
+
image2 = stub_everything("2", :width => 3, :height => 4)
|
25
|
+
|
26
|
+
ChunkyPNG::Image.stubs(:from_file).returns(image1, image2)
|
27
|
+
Compatriot::ColorDiffer.stubs(:save_diff_image)
|
28
|
+
|
29
|
+
differ = Compatriot::ColorDiffer.diff(image1, image2, "some/dir")
|
30
|
+
end
|
31
|
+
|
32
|
+
it "names the image based on the strategy and the browsers" do
|
33
|
+
name = Compatriot::ColorDiffer.diff_name(
|
34
|
+
"/something/firefox/1.png",
|
35
|
+
"/something/chrome/1.png"
|
36
|
+
)
|
37
|
+
name.must_equal("color_firefox_vs_chrome_1.png")
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require_relative '../../spec_helper'
|
2
|
+
|
3
|
+
describe Compatriot::ImageDiffer do
|
4
|
+
describe "compute!" do
|
5
|
+
it "diffs each set of images and stores the location by path" do
|
6
|
+
Compatriot::ImageDiffer.any_instance.stubs(:create_diffs_path)
|
7
|
+
|
8
|
+
d = Compatriot::ImageDiffer.new(
|
9
|
+
:paths => ["/home"],
|
10
|
+
:browsers => [
|
11
|
+
stub(:absolute_screenshot_for => "1.png"),
|
12
|
+
stub(:absolute_screenshot_for => "2.png")
|
13
|
+
]
|
14
|
+
)
|
15
|
+
d.expects(:diff).with(["1.png", "2.png"]).returns("diff.png")
|
16
|
+
d.compute!
|
17
|
+
d.diff_for("/home").must_equal("diff.png")
|
18
|
+
end
|
19
|
+
|
20
|
+
it "creates a diffs dir" do
|
21
|
+
FileUtils.expects(:mkdir_p).with("foo/bar/diffs")
|
22
|
+
d = Compatriot::ImageDiffer.new(
|
23
|
+
:results_directory => "foo/bar"
|
24
|
+
)
|
25
|
+
d.diffs_path.must_equal("foo/bar/diffs")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "diff" do
|
30
|
+
it "returns the filename of the diff" do
|
31
|
+
file_one = stub
|
32
|
+
file_two = stub
|
33
|
+
strategy = stub(:diff => "diff_filename.png")
|
34
|
+
ChunkyPNG::Image.stubs(:from_file)
|
35
|
+
FileUtils.expects(:mkdir_p).with("something/diffs")
|
36
|
+
|
37
|
+
c = Compatriot::ImageDiffer.new(
|
38
|
+
:strategy => strategy,
|
39
|
+
:results_directory => "something"
|
40
|
+
)
|
41
|
+
|
42
|
+
c.diff([file_one, file_two]).must_equal("diff_filename.png")
|
43
|
+
end
|
44
|
+
|
45
|
+
it "uses the strategy passed in" do
|
46
|
+
file_one = stub
|
47
|
+
file_two = stub
|
48
|
+
strategy = stub
|
49
|
+
|
50
|
+
ChunkyPNG::Image.stubs(:from_file).returns(file_one, file_two)
|
51
|
+
FileUtils.expects(:mkdir_p).with("something/diffs")
|
52
|
+
|
53
|
+
strategy.expects(:diff).with(
|
54
|
+
file_one,
|
55
|
+
file_two,
|
56
|
+
"something"
|
57
|
+
).returns("diff_filename.png")
|
58
|
+
|
59
|
+
c = Compatriot::ImageDiffer.new(
|
60
|
+
:strategy => strategy,
|
61
|
+
:results_directory => "something"
|
62
|
+
)
|
63
|
+
|
64
|
+
c.diff([file_one, file_two]).must_equal("diff_filename.png")
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/spec/unit/runner_spec.rb
CHANGED
@@ -55,7 +55,7 @@ describe Compatriot::Runner do
|
|
55
55
|
|
56
56
|
describe "#results_directory" do
|
57
57
|
it "names a results directory in tmp/results based on the clock" do
|
58
|
-
runner = Compatriot::Runner.new(
|
58
|
+
runner = Compatriot::Runner.new(SampleApp, ["/"], @fixed_clock)
|
59
59
|
|
60
60
|
runner.results_directory.must_equal(@results_dir_name)
|
61
61
|
end
|
metadata
CHANGED
@@ -1,82 +1,203 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: compatriot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.0.5
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Carol Nichols
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2015-11-04 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: minitest
|
16
|
-
requirement:
|
17
|
-
none: false
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
18
16
|
requirements:
|
19
|
-
- - ~>
|
17
|
+
- - "~>"
|
20
18
|
- !ruby/object:Gem::Version
|
21
|
-
version:
|
19
|
+
version: '5.8'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 5.8.2
|
22
23
|
type: :development
|
23
24
|
prerelease: false
|
24
|
-
version_requirements:
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '5.8'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 5.8.2
|
25
33
|
- !ruby/object:Gem::Dependency
|
26
34
|
name: sinatra
|
27
|
-
requirement:
|
28
|
-
none: false
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
29
36
|
requirements:
|
30
|
-
- - ~>
|
37
|
+
- - "~>"
|
31
38
|
- !ruby/object:Gem::Version
|
32
|
-
version: 1.
|
39
|
+
version: '1.4'
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 1.4.6
|
33
43
|
type: :development
|
34
44
|
prerelease: false
|
35
|
-
version_requirements:
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '1.4'
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 1.4.6
|
36
53
|
- !ruby/object:Gem::Dependency
|
37
54
|
name: mocha
|
38
|
-
requirement:
|
39
|
-
none: false
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
40
56
|
requirements:
|
41
|
-
- - ~>
|
57
|
+
- - "~>"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '1.1'
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 1.1.0
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '1.1'
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: 1.1.0
|
73
|
+
- !ruby/object:Gem::Dependency
|
74
|
+
name: cucumber
|
75
|
+
requirement: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - "~>"
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '2.1'
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 2.1.0
|
83
|
+
type: :development
|
84
|
+
prerelease: false
|
85
|
+
version_requirements: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '2.1'
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: 2.1.0
|
93
|
+
- !ruby/object:Gem::Dependency
|
94
|
+
name: aruba
|
95
|
+
requirement: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - "~>"
|
42
98
|
- !ruby/object:Gem::Version
|
43
99
|
version: 0.10.0
|
44
100
|
type: :development
|
45
101
|
prerelease: false
|
46
|
-
version_requirements:
|
102
|
+
version_requirements: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - "~>"
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: 0.10.0
|
107
|
+
- !ruby/object:Gem::Dependency
|
108
|
+
name: relish
|
109
|
+
requirement: !ruby/object:Gem::Requirement
|
110
|
+
requirements:
|
111
|
+
- - "~>"
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: 0.7.1
|
114
|
+
type: :development
|
115
|
+
prerelease: false
|
116
|
+
version_requirements: !ruby/object:Gem::Requirement
|
117
|
+
requirements:
|
118
|
+
- - "~>"
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: 0.7.1
|
47
121
|
- !ruby/object:Gem::Dependency
|
48
122
|
name: capybara
|
49
|
-
requirement:
|
50
|
-
|
123
|
+
requirement: !ruby/object:Gem::Requirement
|
124
|
+
requirements:
|
125
|
+
- - "~>"
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
version: '2.5'
|
128
|
+
- - ">="
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: 2.5.0
|
131
|
+
type: :runtime
|
132
|
+
prerelease: false
|
133
|
+
version_requirements: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - "~>"
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '2.5'
|
138
|
+
- - ">="
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
version: 2.5.0
|
141
|
+
- !ruby/object:Gem::Dependency
|
142
|
+
name: selenium-webdriver
|
143
|
+
requirement: !ruby/object:Gem::Requirement
|
51
144
|
requirements:
|
52
|
-
- - ~>
|
145
|
+
- - "~>"
|
53
146
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
147
|
+
version: '2.48'
|
148
|
+
- - ">="
|
149
|
+
- !ruby/object:Gem::Version
|
150
|
+
version: 2.48.1
|
55
151
|
type: :runtime
|
56
152
|
prerelease: false
|
57
|
-
version_requirements:
|
153
|
+
version_requirements: !ruby/object:Gem::Requirement
|
154
|
+
requirements:
|
155
|
+
- - "~>"
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '2.48'
|
158
|
+
- - ">="
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: 2.48.1
|
58
161
|
- !ruby/object:Gem::Dependency
|
59
162
|
name: rake
|
60
|
-
requirement:
|
61
|
-
none: false
|
163
|
+
requirement: !ruby/object:Gem::Requirement
|
62
164
|
requirements:
|
63
|
-
- - ~>
|
165
|
+
- - "~>"
|
166
|
+
- !ruby/object:Gem::Version
|
167
|
+
version: '10.4'
|
168
|
+
- - ">="
|
64
169
|
- !ruby/object:Gem::Version
|
65
|
-
version:
|
170
|
+
version: 10.4.2
|
66
171
|
type: :runtime
|
67
172
|
prerelease: false
|
68
|
-
version_requirements:
|
173
|
+
version_requirements: !ruby/object:Gem::Requirement
|
174
|
+
requirements:
|
175
|
+
- - "~>"
|
176
|
+
- !ruby/object:Gem::Version
|
177
|
+
version: '10.4'
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: 10.4.2
|
69
181
|
- !ruby/object:Gem::Dependency
|
70
182
|
name: chunky_png
|
71
|
-
requirement:
|
72
|
-
none: false
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
73
184
|
requirements:
|
74
|
-
- - ~>
|
185
|
+
- - "~>"
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '1.3'
|
188
|
+
- - ">="
|
75
189
|
- !ruby/object:Gem::Version
|
76
|
-
version: 1.
|
190
|
+
version: 1.3.5
|
77
191
|
type: :runtime
|
78
192
|
prerelease: false
|
79
|
-
version_requirements:
|
193
|
+
version_requirements: !ruby/object:Gem::Requirement
|
194
|
+
requirements:
|
195
|
+
- - "~>"
|
196
|
+
- !ruby/object:Gem::Version
|
197
|
+
version: '1.3'
|
198
|
+
- - ">="
|
199
|
+
- !ruby/object:Gem::Version
|
200
|
+
version: 1.3.5
|
80
201
|
description: Finds likely UI browser cross-compatibility issues.
|
81
202
|
email:
|
82
203
|
- carol.nichols@gmail.com
|
@@ -84,57 +205,66 @@ executables: []
|
|
84
205
|
extensions: []
|
85
206
|
extra_rdoc_files: []
|
86
207
|
files:
|
87
|
-
- .gitignore
|
88
|
-
- .
|
208
|
+
- ".gitignore"
|
209
|
+
- ".ruby-gemset"
|
210
|
+
- ".ruby-version"
|
211
|
+
- ".travis.yml"
|
89
212
|
- CHANGELOG.md
|
90
213
|
- Gemfile
|
91
214
|
- README.md
|
92
215
|
- Rakefile
|
93
216
|
- compatriot.gemspec
|
94
217
|
- examples/compatriot_tests.rb
|
218
|
+
- features/list_of_urls.feature
|
219
|
+
- features/step_definitions/cli_steps.rb
|
220
|
+
- features/support/env.rb
|
95
221
|
- lib/compatriot.rb
|
96
222
|
- lib/compatriot/browser.rb
|
97
|
-
- lib/compatriot/image_differ.rb
|
223
|
+
- lib/compatriot/image_differ/color_differ.rb
|
224
|
+
- lib/compatriot/image_differ/image_differ.rb
|
98
225
|
- lib/compatriot/results_presenter.rb
|
99
226
|
- lib/compatriot/runner.rb
|
100
227
|
- lib/compatriot/version.rb
|
101
|
-
- spec/integration/full_stack_spec.rb
|
102
228
|
- spec/sample_app/public/images/smileyface.jpg
|
103
|
-
- spec/sample_app/
|
229
|
+
- spec/sample_app/sample_app.rb
|
104
230
|
- spec/spec_helper.rb
|
105
231
|
- spec/unit/browser_spec.rb
|
106
|
-
- spec/unit/
|
232
|
+
- spec/unit/image_differ/color_differ_spec.rb
|
233
|
+
- spec/unit/image_differ/image_differ_spec.rb
|
107
234
|
- spec/unit/runner_spec.rb
|
108
235
|
homepage: https://github.com/clnclarinet/compatriot
|
109
|
-
licenses:
|
236
|
+
licenses:
|
237
|
+
- MIT
|
238
|
+
metadata: {}
|
110
239
|
post_install_message:
|
111
240
|
rdoc_options: []
|
112
241
|
require_paths:
|
113
242
|
- lib
|
114
243
|
required_ruby_version: !ruby/object:Gem::Requirement
|
115
|
-
none: false
|
116
244
|
requirements:
|
117
|
-
- -
|
245
|
+
- - ">="
|
118
246
|
- !ruby/object:Gem::Version
|
119
247
|
version: '0'
|
120
248
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
121
|
-
none: false
|
122
249
|
requirements:
|
123
|
-
- -
|
250
|
+
- - ">="
|
124
251
|
- !ruby/object:Gem::Version
|
125
252
|
version: '0'
|
126
253
|
requirements: []
|
127
254
|
rubyforge_project:
|
128
|
-
rubygems_version:
|
255
|
+
rubygems_version: 2.4.8
|
129
256
|
signing_key:
|
130
|
-
specification_version:
|
257
|
+
specification_version: 4
|
131
258
|
summary: Runs a command in multiple browsers using selenium then compares the screenshots
|
132
259
|
and presents those likely to have cross-browser incompatibilities.
|
133
260
|
test_files:
|
134
|
-
-
|
261
|
+
- features/list_of_urls.feature
|
262
|
+
- features/step_definitions/cli_steps.rb
|
263
|
+
- features/support/env.rb
|
135
264
|
- spec/sample_app/public/images/smileyface.jpg
|
136
|
-
- spec/sample_app/
|
265
|
+
- spec/sample_app/sample_app.rb
|
137
266
|
- spec/spec_helper.rb
|
138
267
|
- spec/unit/browser_spec.rb
|
139
|
-
- spec/unit/
|
268
|
+
- spec/unit/image_differ/color_differ_spec.rb
|
269
|
+
- spec/unit/image_differ/image_differ_spec.rb
|
140
270
|
- spec/unit/runner_spec.rb
|
data/.rvmrc
DELETED
@@ -1,47 +0,0 @@
|
|
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
|
-
|
@@ -1,100 +0,0 @@
|
|
1
|
-
require 'chunky_png'
|
2
|
-
include ChunkyPNG::Color
|
3
|
-
|
4
|
-
module Compatriot
|
5
|
-
class ImageDiffer
|
6
|
-
|
7
|
-
attr_reader :diffs
|
8
|
-
|
9
|
-
def initialize(params = {})
|
10
|
-
@paths = params[:paths]
|
11
|
-
@browsers = params[:browsers]
|
12
|
-
@strategy = params[:strategy] || :color_difference
|
13
|
-
@diffs = {}
|
14
|
-
end
|
15
|
-
|
16
|
-
def compute!
|
17
|
-
@paths.map do |path|
|
18
|
-
images_to_diff = @browsers.map { |b| b.absolute_screenshot_for(path) }
|
19
|
-
@diffs[path] = diff(images_to_diff)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def diff(results)
|
24
|
-
images = results.map{|r| ChunkyPNG::Image.from_file(r) }
|
25
|
-
self.send(@strategy, images.first, images.last, results.first)
|
26
|
-
end
|
27
|
-
|
28
|
-
def same_pixels_exactly(image1, image2, name)
|
29
|
-
output = ChunkyPNG::Image.new(image1.width, image2.height, WHITE)
|
30
|
-
diff = []
|
31
|
-
|
32
|
-
each_pixel(image1) do |x, y|
|
33
|
-
pixel1 = image1[x, y]
|
34
|
-
pixel2 = image2[x, y]
|
35
|
-
output[x,y] = pixel1
|
36
|
-
diff << [x,y] unless pixel1 == pixel2
|
37
|
-
end
|
38
|
-
|
39
|
-
pixels_total = image1.pixels.length
|
40
|
-
pixels_changed = diff.length
|
41
|
-
pixels_changed_percentage = (diff.length.to_f / image1.pixels.length) * 100
|
42
|
-
|
43
|
-
x, y = diff.map{ |xy| xy[0] }, diff.map{ |xy| xy[1] }
|
44
|
-
|
45
|
-
output.rect(x.min, y.min, x.max, y.max, ChunkyPNG::Color.rgb(0,255,0))
|
46
|
-
filename = "#{name}-same_exactly.png"
|
47
|
-
output.save(filename)
|
48
|
-
File.join(
|
49
|
-
File.basename(File.dirname(filename)),
|
50
|
-
File.basename(filename)
|
51
|
-
)
|
52
|
-
end
|
53
|
-
|
54
|
-
def color_difference(image1, image2, name)
|
55
|
-
output = ChunkyPNG::Image.new(image1.width, image1.height, WHITE)
|
56
|
-
diff = []
|
57
|
-
|
58
|
-
each_pixel(image1) do |x, y|
|
59
|
-
pixel1 = image1[x,y]
|
60
|
-
pixel2 = image2[x,y]
|
61
|
-
unless pixel1 == pixel2
|
62
|
-
output[x,y], score = color_difference_of_pixels(pixel1, pixel2)
|
63
|
-
diff << score
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
filename = "#{name}-color_difference.png"
|
68
|
-
output.save(filename)
|
69
|
-
File.join(
|
70
|
-
File.basename(File.dirname(filename)),
|
71
|
-
File.basename(filename)
|
72
|
-
)
|
73
|
-
end
|
74
|
-
|
75
|
-
def color_difference_of_pixels(pixel1, pixel2)
|
76
|
-
score = Math.sqrt(
|
77
|
-
(r(pixel2) - r(pixel1)) ** 2 +
|
78
|
-
(g(pixel2) - g(pixel1)) ** 2 +
|
79
|
-
(b(pixel2) - b(pixel1)) ** 2
|
80
|
-
) / Math.sqrt(MAX ** 2 * 3)
|
81
|
-
|
82
|
-
[grayscale(MAX - (score * MAX).round), score]
|
83
|
-
end
|
84
|
-
|
85
|
-
# Not called anywhere
|
86
|
-
def color_difference_total_score
|
87
|
-
pixels_total = image1.width * image1.height
|
88
|
-
pixels_changed = diff.length
|
89
|
-
pixels_changed_percentage = (diff.inject {|sum, value| sum + value} / pixels_total) * 100
|
90
|
-
end
|
91
|
-
|
92
|
-
def each_pixel(image)
|
93
|
-
image.width.times do |x|
|
94
|
-
image.height.times do |y|
|
95
|
-
yield(x, y)
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
@@ -1,36 +0,0 @@
|
|
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
|
-
it "takes screenshots, diffs them, and creates an index" do
|
8
|
-
root_dir = Dir.getwd
|
9
|
-
Dir.chdir(File.join(File.dirname(__FILE__), '..', 'sample_app'))
|
10
|
-
|
11
|
-
results_tmp_dir = File.join("tmp", "results")
|
12
|
-
|
13
|
-
FileUtils.remove_dir(results_tmp_dir, true)
|
14
|
-
|
15
|
-
Compatriot.app = TestApp
|
16
|
-
Compatriot.run(%w[
|
17
|
-
/
|
18
|
-
/chrome-css-bug
|
19
|
-
])
|
20
|
-
|
21
|
-
current_results_dir = (Dir.entries(results_tmp_dir) - [".", ".."]).first
|
22
|
-
current_results_dir = File.join(results_tmp_dir, current_results_dir)
|
23
|
-
|
24
|
-
firefox_dir = File.join(current_results_dir, "firefox")
|
25
|
-
chrome_dir = File.join(current_results_dir, "chrome")
|
26
|
-
|
27
|
-
Dir.glob(File.join(firefox_dir, "*.png")).size.must_equal 4
|
28
|
-
Dir.glob(File.join(chrome_dir, "*.png")).size.must_equal 2
|
29
|
-
|
30
|
-
results_index = IO.read(File.join(current_results_dir, "index.html"))
|
31
|
-
xml = Nokogiri::XML(results_index)
|
32
|
-
xml.xpath("//tr[td]").size.must_equal(2)
|
33
|
-
|
34
|
-
Dir.chdir(root_dir)
|
35
|
-
end
|
36
|
-
end
|
@@ -1,53 +0,0 @@
|
|
1
|
-
require_relative '../spec_helper'
|
2
|
-
|
3
|
-
describe Compatriot::ImageDiffer do
|
4
|
-
describe "compute!" do
|
5
|
-
it "diffs each set of images and stores the location by path" do
|
6
|
-
d = Compatriot::ImageDiffer.new(
|
7
|
-
:paths => ["/home"],
|
8
|
-
:browsers => [
|
9
|
-
stub(:absolute_screenshot_for => "1.png"),
|
10
|
-
stub(:absolute_screenshot_for => "2.png")
|
11
|
-
]
|
12
|
-
)
|
13
|
-
d.expects(:diff).with(["1.png", "2.png"]).returns("diff.png")
|
14
|
-
d.compute!
|
15
|
-
d.diffs["/home"].must_equal("diff.png")
|
16
|
-
end
|
17
|
-
end
|
18
|
-
describe "diff" do
|
19
|
-
it "calls chunky_png on each image path" do
|
20
|
-
file_one = stub
|
21
|
-
file_two = stub
|
22
|
-
|
23
|
-
ChunkyPNG::Image.expects(:from_file).with(file_one)
|
24
|
-
ChunkyPNG::Image.expects(:from_file).with(file_two)
|
25
|
-
|
26
|
-
c = Compatriot::ImageDiffer.new
|
27
|
-
c.stubs(:color_difference)
|
28
|
-
c.diff([file_one, file_two])
|
29
|
-
end
|
30
|
-
|
31
|
-
it "returns the filename of the diff" do
|
32
|
-
end
|
33
|
-
|
34
|
-
it "uses the strategy passed in" do
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
describe "self#color_difference" do
|
39
|
-
it "starts a new white image with the same dimensions" do
|
40
|
-
diff = stub_everything
|
41
|
-
ChunkyPNG::Image.expects(:new).with(
|
42
|
-
1,
|
43
|
-
2,
|
44
|
-
ChunkyPNG::Image::WHITE
|
45
|
-
).returns(diff)
|
46
|
-
|
47
|
-
image1 = stub_everything("1", :width => 1, :height => 2)
|
48
|
-
image2 = stub_everything("2", :width => 3, :height => 4)
|
49
|
-
|
50
|
-
Compatriot::ImageDiffer.new.color_difference(image1, image2, stub)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|