goggles 0.1.4 → 0.8.0

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2bd05fb9c67d3e55a5bb2d9a3c26d5c1ddd96636
4
+ data.tar.gz: 594c499843796017d18ca8d75588edc6ea3b7a8e
5
+ SHA512:
6
+ metadata.gz: ead73b5e863e59e3fefcad08225f1b144a6e7a7572902c333ff1ce7774041d24c7eecbb202ba933b3dff7a212e5aaa19b58d84f66712a75ab1fc687c6e6935d1
7
+ data.tar.gz: 616fddeeddf282c24a3ad9eeebfeb1cb8c82f1e79b4656360b8a68bdaa2357c8b996e148c2ca41ecef625bb54a3aa6eb8c93b8ede4d5b8aaf318a9777f291b70
@@ -0,0 +1,29 @@
1
+ # CHANGELOG
2
+
3
+ ## v0.8.0 (Apr 10, 2015)
4
+ * Remove `swim` executable.
5
+ * Remove YAML configuration.
6
+ * Add `Goggles.configure` for configuration through a block (like RSpec).
7
+ * Remove reserved instance variables like `@gg_url`.
8
+ * Scripts are executed via blocks passed to `Goggles.each`.
9
+ * `Goggles.each` yields a browser instance with the `#grab_screenshot` method.
10
+ * README updates.
11
+ * Add this CHANGELOG.
12
+
13
+ ## v0.1.4 (Jan 28, 2014)
14
+ * Small code enhancements with no user impact.
15
+
16
+ ## v0.1.3 (Jan 23, 2014)
17
+ * Do not delete cookies before each script.
18
+ * Make `@gg_url` variable available to scripts.
19
+
20
+ ## v0.1.2 (Jan 21, 2014)
21
+ * Add diff color configuration setting.
22
+ * Default color setting to blue.
23
+ * Prepend all instance variables with `gg_`.
24
+
25
+ ## v0.1.1 (Jan 20, 2014)
26
+ * Add command line option for generating default project
27
+
28
+ ## v0.1.0 (Jan 20, 2014)
29
+ * Initial release
data/README.md CHANGED
@@ -1,98 +1,149 @@
1
1
  # goggles
2
2
  [![Gem Version](https://badge.fury.io/rb/goggles.png)](http://badge.fury.io/rb/goggles)
3
3
 
4
- Goggles is a visual testing tool inspired by [wraith](http://github.com/bbc-news/wraith) and powered by [watir-webdriver](http://github.com/watir/watir-webdriver). It allows you to compare screenshots of your web application in different browsers, and you can execute Ruby scripts to setup as many screenshots as you need.
4
+ Goggles is a visual testing tool inspired by [wraith](http://github.com/bbc-news/wraith) and powered by [watir-webdriver](http://github.com/watir/watir-webdriver). It compares screenshots of your web applications in different browsers at differents sizes.
5
5
 
6
- ## Installation
6
+ ## Usage
7
7
 
8
- Install ImageMagick:
8
+ ### Configuration
9
9
 
10
- * OSX: `$ brew install imagemagick`
11
- * Linux: `$ sudo apt-get install imagemagick`
12
- * Windows: [Download](http://www.imagemagick.org/script/binary-releases.php#windows) installer and add to your PATH.
10
+ Configure Goggles with a block passed to the `Goggles.configure` method, which will yield a config object to your block for manipulation. The `directory` setting must be configured for Goggles to work. You'll also need to provide `browsers` and `sizes` that you'd like to compare, but those can be configured with the script.
13
11
 
14
- Add this line to your application's Gemfile:
12
+ The `fuzzing` and `color` attributes default to "blue" and "20%" respectively.
15
13
 
16
- gem 'goggles'
14
+ ```ruby
15
+ Goggles.configure do |config|
16
+ config.directory = "/path/to/my/results"
17
+ config.browsers = [:chrome, :firefox, :phantomjs]
18
+ config.sizes = [1080, 600]
19
+ config.color = "red"
20
+ end
21
+ ```
17
22
 
18
- And then execute:
23
+ ### Scripting
19
24
 
20
- $ bundle
25
+ Your Scripts are passed to `Goggles.each` as blocks. Goggles will iterate over the block with each combination of browser/browser size configured, and the method will yield a browser object to your script block.
21
26
 
22
- Or install it yourself with:
27
+ ```ruby
28
+ Goggles.each do |browser|
29
+ browser.goto "http://www.google.com"
30
+ browser.text_field(id: "lst-ib").value = "Google"
31
+ end
32
+ ```
23
33
 
24
- $ gem install goggles
34
+ #### Browsers and sizes
25
35
 
26
- ## Usage
36
+ You can pass additional browsers or browser sizes to `Goggles.each` as arrays. With version 0.8.0, these arguments will overwrite what you've configured through `Goggles.configure`.
37
+
38
+ ```ruby
39
+ Goggles.each([:chrome, :firefox], [1080]) do |browser|
40
+ # ...
41
+ end
42
+ ```
27
43
 
28
- Generate a config file with `swim --init` to point goggles in the right direction.
44
+ **TODO**
29
45
 
30
- $ swim -i /home/configs/config.yaml
46
+ Before the 1.0.0 release, these arguments will act as additonal browsers/sizes to script against. That way, the base configuration can be extended for particular script instances.
31
47
 
32
- ``` yaml
33
- # config.yaml
34
- # Directory where you want to store your results. Required.
35
- results_directory: "/home/example/results"
48
+ #### Screenshots
36
49
 
37
- # Directory where you're storing your scripts. Optional.
38
- scripts_directory: "/home/example/scripts"
50
+ Your script blocks should include the `Watir::Browser#grab_screenshot` method, which has been patched onto the browser objects yielded to your blocks. Simply give the method a description argument and the screenshot will be saved to your configured directory.
39
51
 
40
- # Scripts to execute in the scripts directory. Optional.
41
- scripts_to_execute:
42
- - "first_script.rb"
43
- - "second_script.rb"
52
+ ```ruby
53
+ Goggles.each do |browser|
54
+ browser.goto "http://www.google.com"
55
+ browser.grab_screenshot "homepage"
56
+ end
57
+ ```
44
58
 
45
- # Domain to test. Required.
46
- domain_under_test: "http://www.google.com"
59
+ #### Closing the browser
47
60
 
48
- # Paths to pages you want to test. Label them with a page name. Required.
49
- paths_to_capture:
50
- home: "/"
51
- gmail: "/gmail"
61
+ There's no need to explicitly close the browser objects in your script blocks. Goggles will handle that.
52
62
 
53
- # Browsers you want to compare. Cannot specify more than two (yet). Required.
54
- browsers:
55
- - "chrome"
56
- - "firefox"
63
+ #### Results
57
64
 
58
- # Widths at which you would like screenshots compared. All screenshots will be taken at a height of 768. Required.
59
- browser_widths:
60
- - 1024
65
+ Screenshots are saved to your configured directory. Screenshot comparison results are saved to a sub-folder based on the screenshot description and browser size. Results include a diff image and data file.
61
66
 
62
- # Fuzzing percentage. Play around with this to find the right fit. Required.
63
- image_fuzzing: "20%"
67
+ ```ruby
68
+ Goggles.configure do |c|
69
+ c.directory = "/goggles/results"
70
+ c.browsers = [:chrome, :firefox, :phantomjs]
71
+ c.sizes = [1080, 600]
72
+ end
64
73
 
65
- # Color for diffing images. Defaults to blue. Optional.
66
- diff_color: "blue"
74
+ Goggles.each do |browser|
75
+ browser.goto "http://www.google.com"
76
+ browser.grab_screenshot "google"
77
+ end
67
78
  ```
68
79
 
69
- If you pass scripts to goggles as part of your testing, you **must** specify when screenshots should be taken with the `#grab_screenshot` method. If you do not specify scripts in configuration, goggles will open each of your paths and take a screenshot.
70
80
 
71
- NOTE: I've tried to keep variable names as unlikely to interrupt your code as possible, but `@watir` is reserved for the browser instance currently executing scripts.
81
+ ```
82
+ /goggles/results
83
+ |- google_1080_chrome.png
84
+ |- google_1080_firefox.png
85
+ |- google_1080_phantomjs.png
86
+ |- google_600_chrome.png
87
+ |- google_600_firefox.png
88
+ |- google_600_phantomjs.png
89
+ |- /google_1080
90
+ |- chrome_firefox_data.txt
91
+ |- chrome_firefox_diff.png
92
+ |- chrome_phantomjs_data.txt
93
+ |- chrome_phantomjs_diff.png
94
+ |- firefox_phantomjs_data.txt
95
+ |- firefox_phantomjs_diff.png
96
+ |- /google_600
97
+ |- chrome_firefox_data.txt
98
+ |- chrome_firefox_diff.png
99
+ |- chrome_phantomjs_data.txt
100
+ |- chrome_phantomjs_diff.png
101
+ |- firefox_phantomjs_data.txt
102
+ |- firefox_phantomjs_diff.png
103
+ ```
72
104
 
73
- ``` ruby
74
- # script_to_execute.rb
75
- require 'goggles'
76
- @watir.cookies.add("cookie_name", "cookie_value")
105
+ ## Road to 1.0.0
77
106
 
78
- # Pass a short description to the method for naming the resultant screenshot
79
- Goggles.grab_screenshot("with_cookie_set")
80
- ```
107
+ I've made a lot of changes recently and bumped the version up to 0.8.0. Check the [/CHANGELOG.md](changelog) for more information about those changes.
108
+
109
+ ### v0.9.0
81
110
 
82
- Execute a goggles test through the command line with `swim --config CONFIG_FILE` or use `swim --help` to see command options.
111
+ * Browser/size arguments against `Goggles.each` extend configuration instead of overwriting it.
112
+ * End-to-end Cucumber tests
83
113
 
84
- $ swim -c config.yml
114
+ ### v1.0.0
115
+
116
+ * Documentation
117
+ * Examples
118
+ * TravisCI integration for specs (but not features)
119
+
120
+ ## Installation
121
+
122
+ Install ImageMagick:
123
+
124
+ * OSX: `$ brew install imagemagick`
125
+ * Ubuntu: `$ sudo apt-get install imagemagick`
126
+ * Windows: [Download](http://www.imagemagick.org/script/binary-releases.php#windows) installer and add to your PATH.
127
+
128
+ Add this line to your application's Gemfile:
129
+
130
+ gem 'goggles'
131
+
132
+ And then execute:
133
+
134
+ $ bundle
135
+
136
+ Or install it yourself with:
137
+
138
+ $ gem install goggles
85
139
 
86
140
  ## Contributing
87
141
 
88
142
  1. Fork it ( http://github.com/jdenen/goggles/fork )
89
143
  2. Create your feature branch (`git checkout -b my-new-feature`)
90
- 3. Code until specs pass (`rspec`)*
91
- 4. Commit your changes (`git commit -am 'Add some feature'`)
92
- 5. Push to the branch (`git push origin my-new-feature`)
93
- 6. Create new Pull Request
94
-
95
- \*Chrome and [ChromeDriver](http://code.google.com/p/selenium/wiki/ChromeDriver) are required to pass specs. Download the latest version and add it to your PATH before running `rspec`.
144
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
145
+ 4. Push to the branch (`git push origin my-new-feature`)
146
+ 5. Create new Pull Request
96
147
 
97
148
  ## Questions, Comments, Concerns
98
- Easiest place to reach me is Twitter, [@jpdenen](http://twitter.com/jpdenen)
149
+ Find me on Twitter ([@jpdenen](http://twitter.com/jpdenen)) or write up an issue.
@@ -7,9 +7,9 @@ Gem::Specification.new do |spec|
7
7
  spec.name = "goggles"
8
8
  spec.version = Goggles::VERSION
9
9
  spec.authors = ["Johnson Denen"]
10
- spec.email = ["jdenen@manta.com"]
11
- spec.summary = %q{comparing responsive screenshots under watir-webdriver}
12
- spec.description = %q{comparing responsive screenshots under watir-webdriver}
10
+ spec.email = ["johnson.denen@gmail.com"]
11
+ spec.summary = %q{Compare screenshots in different browers at differnt sizes}
12
+ spec.description = %q{Compare screenshots in different browers at differnt sizes}
13
13
  spec.homepage = "http://github.com/jdenen/goggles"
14
14
  spec.license = "MIT"
15
15
 
@@ -23,6 +23,4 @@ Gem::Specification.new do |spec|
23
23
 
24
24
  spec.add_runtime_dependency "watir-webdriver"
25
25
  spec.add_runtime_dependency "image_size"
26
-
27
- spec.executables << "swim"
28
26
  end
@@ -1,81 +1,28 @@
1
- require "goggles/version"
1
+ require "goggles/configuration"
2
2
  require "goggles/comparison"
3
- require "goggles/error"
4
-
5
- require "watir-webdriver"
6
- require "yaml"
7
- require "fileutils"
3
+ require "goggles/iteration"
8
4
 
9
5
  module Goggles
10
6
  extend self
11
-
12
- def swim(config_path)
13
- conf = YAML::load(File.open(config_path))
14
-
15
- @gg_result_dir = conf['results_directory']
16
- @gg_script_dir = conf['scripts_directory']
17
- @gg_domain = conf['domain_under_test']
18
- @gg_paths = conf['paths_to_capture']
19
- @gg_scripts = conf['scripts_to_execute']
20
- @gg_platforms = conf['browsers']
21
- @gg_widths = conf['browser_widths']
22
- @gg_fuzz = conf['image_fuzzing']
23
- @gg_color = conf['diff_color'] || 'blue'
24
-
25
- embark!
26
- diff_images
7
+
8
+ def configure &block
9
+ configuration.tap { |conf| yield conf }
27
10
  end
28
11
 
29
- def grab_screenshot(detail)
30
- make_result_dir
31
-
32
- image_dir = "#{@gg_result_dir}/#{@gg_label}"
33
- image_name = "#{detail}_#{@gg_size}_#{@gg_browser}"
34
-
35
- @watir.screenshot.save "#{image_dir}/#{image_name}.png"
36
- end
37
-
38
- private
39
-
40
- def embark!
41
- ensure_fresh_start
12
+ def each browsers = nil, sizes = nil, &block
13
+ browsers ||= configuration.browsers
14
+ sizes ||= configuration.sizes
42
15
 
43
- @gg_widths.each do |size|
44
- @gg_size = size.to_i
45
-
46
- @gg_platforms.each do |pf|
47
- @gg_browser = pf
48
-
49
- @watir = Watir::Browser.new pf.to_sym
50
- @watir.driver.manage.window.resize_to(@gg_size, 768)
51
-
52
- @gg_paths.each do |label, path|
53
- @gg_label = label
54
- @gg_url = "#{@gg_domain}#{path}"
55
-
56
- if @gg_scripts.nil?
57
- @watir.goto @gg_url
58
- grab_screenshot("screenshot")
59
- else
60
- @gg_scripts.each do |script|
61
- script = "#{@gg_script_dir}/#{script}"
62
- @watir.goto @gg_url
63
- eval(File.read(script))
64
- end
65
- end
66
- end
67
-
68
- @watir.close
69
- end
16
+ browsers.product(sizes).each do |browser, size|
17
+ Iteration.new browser, size, configuration, &block
70
18
  end
19
+
20
+ Comparison.new(configuration).tap { |comparison| comparison.make! }
71
21
  end
72
22
 
73
- def ensure_fresh_start
74
- FileUtils.rm_rf("#{@gg_result_dir}")
75
- end
23
+ private
76
24
 
77
- def make_result_dir
78
- FileUtils.mkdir_p("#{@gg_result_dir}/#{@gg_label}")
25
+ def configuration
26
+ @configuration ||= Configuration.new
79
27
  end
80
-
81
28
  end
@@ -1,50 +1,84 @@
1
1
  require "image_size"
2
2
 
3
3
  module Goggles
4
+ class Comparison
5
+ attr_reader :directory, :fuzzing, :color, :groups, :results_dir
6
+
7
+ def initialize config
8
+ @directory = config.directory
9
+ @fuzzing = config.fuzzing
10
+ @color = config.color
11
+ @groups = config.groups
12
+ end
13
+
14
+ def make!
15
+ cut_to_common_size
16
+ highlight_differences
17
+ end
18
+
19
+ def cut_to_common_size
20
+ groups.each_with_object([]) do |group, sizes|
21
+ collection = find_comparable group
22
+
23
+ collection.each do |img|
24
+ File.open(img, 'rb'){ |file| sizes << read_size(file) }
25
+ end
4
26
 
5
- def diff_images
6
- images = Dir.glob("#{@gg_result_dir}/*/*.png").sort
7
- raise Goggles::EmptyResultError, "No screenshots found in results directory: #{@gg_result_dir}" if images.empty?
8
-
9
- size_to_smallest!
27
+ cut! collection, sizes
28
+ end
29
+ end
10
30
 
11
- until images.empty?
12
- one = images.slice!(0)
13
- two = images.slice!(0)
31
+ def highlight_differences
32
+ groups.each do |desc|
33
+ ensure_result_directory desc
34
+ find_comparable(desc).combination(2).to_a.each { |imgs| diff imgs[0], imgs[1] }
35
+ end
36
+ end
14
37
 
15
- out_path = one.gsub(/[^_]*$/, '')
38
+ def find_comparable description
39
+ Dir.glob("#{directory}/*.png").grep(/#{description}_/).sort
40
+ end
16
41
 
17
- diff_out = "#{out_path}diff.png"
18
- data_out = "#{out_path}data.txt"
42
+ def find_common_width array
43
+ array.collect(&:first).sort.first
44
+ end
19
45
 
20
- `compare -fuzz #{@gg_fuzz} -metric AE -highlight-color #{@gg_color} #{one} #{two} #{diff_out} 2>#{data_out}`
46
+ def find_common_height array
47
+ array.collect(&:last).sort.first
21
48
  end
22
- end
23
49
 
24
- def size_to_smallest!
25
- images = Dir.glob("#{@gg_result_dir}/*/*.png").sort
50
+ private
26
51
 
27
- until images.empty?
28
- pair = images.slice!(0..1)
29
- widths = []
30
- heights = []
52
+ attr_writer :results_dir
31
53
 
32
- File.open(pair[0], 'rb') do |one|
33
- size = ImageSize.new(one.read).size
34
- widths << size[0]
35
- heights << size[1]
54
+ def cut! images, sizes
55
+ w = find_common_width sizes
56
+ h = find_common_height sizes
57
+ images.each { |img| `convert #{img} -background none -extent #{w}x#{h} #{img}` }
58
+ end
36
59
 
37
- File.open(pair[1], 'rb') do |two|
38
- size = ImageSize.new(two.read).size
39
- widths << size[0]
40
- heights << size[1]
60
+ def diff img_one, img_two
61
+ b1 = diffed img_one
62
+ b2 = diffed img_two
63
+
64
+ fuzz = "#{results_dir}/#{b1}_#{b2}_diff.png"
65
+ data = "#{results_dir}/#{b1}_#{b2}_data.txt"
66
+
67
+ `compare -fuzz #{fuzzing} -metric AE -highlight-color #{color} #{img_one} #{img_two} #{fuzz} 2>#{data}`
68
+ end
41
69
 
42
- pair.each do |file|
43
- `convert #{file} -background none -extent #{widths.sort[0]}x#{heights.sort[0]} #{file}`
44
- end
45
- end
46
- end
70
+ def diffed img
71
+ File.basename(img).match(/\d+_(.*)\.png/)[1]
72
+ end
73
+
74
+ def read_size file
75
+ ImageSize.new(file.read).size
47
76
  end
48
- end
49
77
 
78
+ def ensure_result_directory description
79
+ self.results_dir = "#{directory}/#{description}"
80
+ FileUtils.rm_rf results_dir
81
+ FileUtils.mkdir_p results_dir
82
+ end
83
+ end
50
84
  end
@@ -0,0 +1,20 @@
1
+ module Goggles
2
+ class Configuration
3
+ attr_accessor :browsers, :sizes, :fuzzing, :color, :groups
4
+ attr_reader :directory
5
+
6
+ def initialize
7
+ @browsers = []
8
+ @sizes = []
9
+ @groups = []
10
+ @directory = ""
11
+ @color = "blue"
12
+ @fuzzing = "20%"
13
+ end
14
+
15
+ def directory=(path)
16
+ @directory = path
17
+ FileUtils.mkdir_p path unless path.empty?
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,38 @@
1
+ require "watir-webdriver"
2
+
3
+ module Watir
4
+ class Browser
5
+ attr_accessor :goggles, :iteration
6
+
7
+ def grab_screenshot name
8
+ description = "#{name}_#{iteration.size}"
9
+ goggles.groups << description unless goggles.groups.include? description
10
+ screenshot.save "#{goggles.directory}/#{description}_#{iteration.browser_name}.png"
11
+ end
12
+ end
13
+ end
14
+
15
+ module Goggles
16
+ class Iteration
17
+ attr_reader :browser, :browser_name, :size, :config
18
+
19
+ def initialize driver, width, config, &block
20
+ @browser_name = driver
21
+ @config = config
22
+ @size = width
23
+ build_browser
24
+ yield browser
25
+ browser.close
26
+ end
27
+
28
+ private
29
+
30
+ def build_browser
31
+ @browser = Watir::Browser.new(browser_name).tap do |engine|
32
+ engine.goggles = config
33
+ engine.iteration = self
34
+ engine.driver.manage.window.resize_to size, 768
35
+ end
36
+ end
37
+ end
38
+ end
@@ -1,3 +1,3 @@
1
1
  module Goggles
2
- VERSION = "0.1.4"
2
+ VERSION = "0.8.0"
3
3
  end
@@ -0,0 +1,99 @@
1
+ require "spec_helper"
2
+
3
+ describe Goggles::Comparison do
4
+ let(:config){ instance_double "configuration" }
5
+ let(:comparison){ Goggles::Comparison.new config }
6
+
7
+ before do
8
+ allow(config).to receive_messages(
9
+ directory: "dir",
10
+ fuzzing: "20%",
11
+ color: "blue",
12
+ groups: [1])
13
+ end
14
+
15
+ it "reads attributes from a given configuration object" do
16
+ expect(config).to receive(:directory)
17
+ expect(config).to receive(:fuzzing)
18
+ expect(config).to receive(:color)
19
+ Goggles::Comparison.new config
20
+ end
21
+
22
+ describe "#make!" do
23
+ it "cuts images and highlights their differences" do
24
+ expect(comparison).to receive(:cut_to_common_size)
25
+ expect(comparison).to receive(:highlight_differences)
26
+ comparison.make!
27
+ end
28
+ end
29
+
30
+ describe "#cut_to_common_size" do
31
+ it "iterates over screenshot descriptions" do
32
+ groups = instance_double "[groups]"
33
+ expect(comparison).to receive(:groups).and_return groups
34
+ expect(groups).to receive(:each_with_object).with([])
35
+ comparison.cut_to_common_size
36
+ end
37
+
38
+ it "collects comparable screenshots" do
39
+ expect(comparison).to receive(:groups).and_return [1, 2]
40
+ expect(comparison).to receive(:find_comparable).with(1).and_return([])
41
+ expect(comparison).to receive(:find_comparable).with(2).and_return([])
42
+ comparison.cut_to_common_size
43
+ end
44
+
45
+ context "with collection of comparable screenshots" do
46
+ it "iterates over the collection" do
47
+ screens = instance_double "[screenshots]"
48
+ expect(comparison).to receive(:groups).and_return ["foo"]
49
+ expect(comparison).to receive(:find_comparable).and_return screens
50
+ expect(screens).to receive(:each)
51
+ expect(comparison).to receive(:cut!).with(screens, [])
52
+ comparison.cut_to_common_size
53
+ end
54
+ end
55
+
56
+ context "while iterating over collected comparable images" do
57
+ it "opens each image in binary mode" do
58
+ expect(comparison).to receive(:find_comparable).and_return [:foo]
59
+ expect(File).to receive(:open).with(:foo, 'rb')
60
+ expect(comparison).to receive(:cut!)
61
+ comparison.cut_to_common_size
62
+ end
63
+ end
64
+ end
65
+
66
+ describe "#highlight_differences" do
67
+ it "diffs every combination of comparable screenshots" do
68
+ images = ["foo_1.png", "foo_2.png", "foo_3.png"]
69
+ expect(comparison).to receive(:groups).and_return ["foo"]
70
+ expect(comparison).to receive(:find_comparable).with("foo").and_return images
71
+ images.combination(2).to_a.each do |i|
72
+ expect(comparison).to receive(:diff).with i[0], i[1]
73
+ end
74
+ comparison.highlight_differences
75
+ end
76
+ end
77
+
78
+ describe "#find_comparable" do
79
+ it "returns an array of file paths" do
80
+ array = ["/foo_chrome.png", "/bar_chrome.png", "/foo_ff.png", "/bar_ff.png"]
81
+ expect(Dir).to receive(:glob).and_return array
82
+ expect(comparison.find_comparable "foo").to eq ["/foo_chrome.png", "/foo_ff.png"]
83
+ end
84
+ end
85
+
86
+ describe "#find_common_width" do
87
+ it "returns the smallest number from first items in an array of arrays" do
88
+ arrays = [[100,40], [68,300], [104,98]]
89
+ expect(comparison.find_common_width arrays).to eq 68
90
+ end
91
+ end
92
+
93
+ describe "#find_common_height" do
94
+ it "returns the smallest number from second items in an array of arrays" do
95
+ arrays = [[100,40], [68,300], [104,98]]
96
+ expect(comparison.find_common_height arrays).to eq 40
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,47 @@
1
+ require "spec_helper"
2
+
3
+ describe Goggles::Configuration do
4
+ let(:config) { Goggles::Configuration.new }
5
+
6
+ it "has attributes by default" do
7
+ expect(config).to have_attributes(
8
+ :browsers => [],
9
+ :sizes => [],
10
+ :groups => [],
11
+ :directory => "",
12
+ :color => "blue",
13
+ :fuzzing => "20%"
14
+ )
15
+ end
16
+
17
+ it "has attributes that can be set" do
18
+ config.browsers << "chrome"
19
+ config.sizes << 100
20
+ config.groups << "foo"
21
+ config.color = "red"
22
+ config.fuzzing = "10%"
23
+
24
+ expect(config).to have_attributes(
25
+ :browsers => ["chrome"],
26
+ :sizes => [100],
27
+ :groups => ["foo"],
28
+ :color => "red",
29
+ :fuzzing => "10%"
30
+ )
31
+ end
32
+
33
+ describe "#directory=" do
34
+ it "ensures the directory exists" do
35
+ expect(FileUtils).to receive(:mkdir_p).with "/foo/bar"
36
+ config.directory = "/foo/bar"
37
+ expect(config.directory).to eq "/foo/bar"
38
+ end
39
+
40
+ context "when attribute is empty" do
41
+ it "does not create the directory" do
42
+ expect(FileUtils).to_not receive(:mkdir_p)
43
+ config.directory = ""
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,32 @@
1
+ require "spec_helper"
2
+
3
+ describe Goggles::Iteration do
4
+ let(:watir) { instance_double("browser") }
5
+
6
+ before do
7
+ allow(watir).to receive_messages(
8
+ :driver => watir,
9
+ :manage => watir,
10
+ :window => watir,
11
+ :goggles= => nil,
12
+ :iteration= => nil,
13
+ :resize_to => nil,
14
+ :close => nil)
15
+ end
16
+
17
+ it "yields an instantiated browser" do
18
+ expect(Watir::Browser).to receive(:new).and_return watir
19
+ expect { |b| Goggles::Iteration.new "", "", "", &b }.to yield_with_args watir
20
+ end
21
+
22
+ it "yields the browser based on the browser_name attribute" do
23
+ expect(Watir::Browser).to receive(:new).with(:foo).and_return watir
24
+ Goggles::Iteration.new(:foo, "", ""){ "bar" }
25
+ end
26
+
27
+ it "resizes the browser based on the size attribute" do
28
+ expect(Watir::Browser).to receive(:new).with(:foo).and_return watir
29
+ expect(watir).to receive(:resize_to).with(500, 768)
30
+ Goggles::Iteration.new(:foo, 500, ""){ "bar" }
31
+ end
32
+ end
@@ -1,41 +1,68 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe Goggles do
4
- Given(:config_path) { "./spec/support/configs" }
5
- Given(:images) { Dir.glob("./spec/support/results/*/*.png") }
6
- Given(:diffs) { Dir.glob("./spec/support/results/*/*diff.png") }
7
- Given(:datas) { Dir.glob("./spec/support/results/*/*data.txt") }
4
+ before { allow(FileUtils).to receive(:mkdir_p) }
5
+
6
+ describe ".configure" do
7
+ it "yields a configuration object" do
8
+ expect { |b| Goggles.configure &b }.to yield_with_args Goggles::Configuration
9
+ end
8
10
 
9
- context "swimming with one script at multiple sizes" do
10
- describe "taking screenshots" do
11
- Given(:sizes_config) { "#{config_path}/test_config_1024_600.yml" }
12
- When { Goggles.swim(sizes_config) }
13
- Then { images.size.should == 6 }
14
- And { diffs.size.should == 2 }
15
- And { datas.size.should == 2 }
11
+ it "returns a configuration object" do
12
+ expect(Goggles.configure { "foo" }).to be_a Goggles::Configuration
16
13
  end
17
14
 
18
- describe "generating error" do
19
- Given(:no_shot_config) { "#{config_path}/test_config_no_screenshot.yml" }
20
- Then { expect{ Goggles.swim(no_shot_config) }.to raise_error(Goggles::EmptyResultError) }
15
+ it "memoizes the configuration object" do
16
+ expect(Goggles.configure { "foo" }).to equal Goggles.configure { "bar" }
21
17
  end
22
18
  end
23
19
 
24
- context "swimming against multiple paths with no scripts" do
25
- describe "taking screenshots when commanded" do
26
- Given(:scriptless_config) { "#{config_path}/test_config_scriptless.yml" }
27
- When { Goggles.swim(scriptless_config) }
28
- Then { images.size.should == 6 }
29
- And { diffs.size.should == 2 }
30
- And { datas.size.should == 2 }
20
+ describe ".each" do
21
+ let(:config) do
22
+ Goggles.configure do |conf|
23
+ conf.browsers = [:foo]
24
+ conf.sizes = [500]
25
+ end
31
26
  end
32
- end
33
27
 
34
- describe "creating empty configuration with --init" do
35
- Given(:conf) { "spec/support/configs/empty_config.yml" }
36
- Given { FileUtils.rm_f conf }
37
- When { `swim -i #{conf}` }
38
- Then { File.exists?(conf).should be_true }
39
- end
28
+ before do
29
+ allow(config).to receive_messages(directory: "/dir", fuzzing: "20%", color: "blue", groups: [])
30
+ end
31
+
32
+ it "passes browser, width, and configuration to an iteration object" do
33
+ expect(Goggles::Iteration).to receive(:new).with(:foo, 500, config)
34
+ Goggles.each { "foo" }
35
+ end
36
+
37
+ it "accepts non-configured browser and size arguments" do
38
+ expect(Goggles::Iteration).to receive(:new).with(:bar, 300, config)
39
+ Goggles.each([:bar], [300]) { "foo" }
40
+ end
41
+
42
+ it "returns a comparison object" do
43
+ expect(Goggles::Iteration).to receive(:new).with(:foo, 500, config)
44
+ expect(Goggles.each { "foo" }).to be_a Goggles::Comparison
45
+ end
46
+
47
+ context "when configured for browsers at one size" do
48
+ it "creates an iteration for each browser with the width" do
49
+ config.browsers << :bar
50
+ [:foo, :bar].each { |browser| expect(Goggles::Iteration).to receive(:new).with browser, 500, config }
51
+ Goggles.each { "foo" }
52
+ end
53
+ end
54
+
55
+ context "when configured for browsers at different sizes" do
56
+ it "creates an iteration for every browser and width combination" do
57
+ config.browsers << :bar
58
+ config.sizes << 1000
40
59
 
60
+ [:foo, :bar].product([500, 1000]).each do |browser, width|
61
+ expect(Goggles::Iteration).to receive(:new).with browser, width, Object
62
+ end
63
+
64
+ Goggles.each { "foo" }
65
+ end
66
+ end
67
+ end
41
68
  end
@@ -1,10 +1,2 @@
1
- require 'rspec'
2
- require 'rspec-given'
1
+ require "goggles"
3
2
 
4
- require 'goggles'
5
-
6
- RSpec.configure do |config|
7
- config.order = 'default'
8
- config.treat_symbols_as_metadata_keys_with_true_values = true
9
- config.filter_run_excluding :skip => true
10
- end
metadata CHANGED
@@ -1,20 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: goggles
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
5
- prerelease:
4
+ version: 0.8.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Johnson Denen
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2014-01-28 00:00:00.000000000 Z
11
+ date: 2015-04-10 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: bundler
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
17
  - - ~>
20
18
  - !ruby/object:Gem::Version
@@ -22,7 +20,6 @@ dependencies:
22
20
  type: :development
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
24
  - - ~>
28
25
  - !ruby/object:Gem::Version
@@ -30,124 +27,111 @@ dependencies:
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: rake
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ! '>='
31
+ - - '>='
36
32
  - !ruby/object:Gem::Version
37
33
  version: '0'
38
34
  type: :development
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ! '>='
38
+ - - '>='
44
39
  - !ruby/object:Gem::Version
45
40
  version: '0'
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: rspec
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ! '>='
45
+ - - '>='
52
46
  - !ruby/object:Gem::Version
53
47
  version: '0'
54
48
  type: :development
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ! '>='
52
+ - - '>='
60
53
  - !ruby/object:Gem::Version
61
54
  version: '0'
62
55
  - !ruby/object:Gem::Dependency
63
56
  name: watir-webdriver
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
- - - ! '>='
59
+ - - '>='
68
60
  - !ruby/object:Gem::Version
69
61
  version: '0'
70
62
  type: :runtime
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
- - - ! '>='
66
+ - - '>='
76
67
  - !ruby/object:Gem::Version
77
68
  version: '0'
78
69
  - !ruby/object:Gem::Dependency
79
70
  name: image_size
80
71
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
72
  requirements:
83
- - - ! '>='
73
+ - - '>='
84
74
  - !ruby/object:Gem::Version
85
75
  version: '0'
86
76
  type: :runtime
87
77
  prerelease: false
88
78
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
79
  requirements:
91
- - - ! '>='
80
+ - - '>='
92
81
  - !ruby/object:Gem::Version
93
82
  version: '0'
94
- description: comparing responsive screenshots under watir-webdriver
83
+ description: Compare screenshots in different browers at differnt sizes
95
84
  email:
96
- - jdenen@manta.com
97
- executables:
98
- - swim
85
+ - johnson.denen@gmail.com
86
+ executables: []
99
87
  extensions: []
100
88
  extra_rdoc_files: []
101
89
  files:
102
90
  - .gitignore
91
+ - CHANGELOG.md
103
92
  - Gemfile
104
93
  - LICENSE.txt
105
94
  - README.md
106
95
  - Rakefile
107
- - bin/swim
108
96
  - goggles.gemspec
109
97
  - lib/goggles.rb
110
- - lib/goggles/cli.rb
111
98
  - lib/goggles/comparison.rb
112
- - lib/goggles/error.rb
99
+ - lib/goggles/configuration.rb
100
+ - lib/goggles/iteration.rb
113
101
  - lib/goggles/version.rb
102
+ - spec/goggles/comparison_spec.rb
103
+ - spec/goggles/configuration_spec.rb
104
+ - spec/goggles/iteration_spec.rb
114
105
  - spec/goggles_spec.rb
115
106
  - spec/spec_helper.rb
116
- - spec/support/configs/test_config_1024_600.yml
117
- - spec/support/configs/test_config_no_screenshot.yml
118
- - spec/support/configs/test_config_scriptless.yml
119
- - spec/support/scripts/google_search.rb
120
- - spec/support/scripts/no_screenshot.rb
121
107
  homepage: http://github.com/jdenen/goggles
122
108
  licenses:
123
109
  - MIT
110
+ metadata: {}
124
111
  post_install_message:
125
112
  rdoc_options: []
126
113
  require_paths:
127
114
  - lib
128
115
  required_ruby_version: !ruby/object:Gem::Requirement
129
- none: false
130
116
  requirements:
131
- - - ! '>='
117
+ - - '>='
132
118
  - !ruby/object:Gem::Version
133
119
  version: '0'
134
120
  required_rubygems_version: !ruby/object:Gem::Requirement
135
- none: false
136
121
  requirements:
137
- - - ! '>='
122
+ - - '>='
138
123
  - !ruby/object:Gem::Version
139
124
  version: '0'
140
125
  requirements: []
141
126
  rubyforge_project:
142
- rubygems_version: 1.8.23
127
+ rubygems_version: 2.0.14
143
128
  signing_key:
144
- specification_version: 3
145
- summary: comparing responsive screenshots under watir-webdriver
129
+ specification_version: 4
130
+ summary: Compare screenshots in different browers at differnt sizes
146
131
  test_files:
132
+ - spec/goggles/comparison_spec.rb
133
+ - spec/goggles/configuration_spec.rb
134
+ - spec/goggles/iteration_spec.rb
147
135
  - spec/goggles_spec.rb
148
136
  - spec/spec_helper.rb
149
- - spec/support/configs/test_config_1024_600.yml
150
- - spec/support/configs/test_config_no_screenshot.yml
151
- - spec/support/configs/test_config_scriptless.yml
152
- - spec/support/scripts/google_search.rb
153
- - spec/support/scripts/no_screenshot.rb
137
+ has_rdoc:
data/bin/swim DELETED
@@ -1,5 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'goggles/cli'
4
-
5
- Goggles::CLI.new ARGV
@@ -1,60 +0,0 @@
1
- require 'goggles'
2
- require 'optparse'
3
- require 'pathname'
4
-
5
- module Goggles
6
- class CLI
7
-
8
- def initialize(argv)
9
- opt_parser = OptionParser.new do |opts|
10
- opts.banner = "Goggles: Compare responsive screenshots in multiple browsers"
11
- opts.separator ""
12
- opts.separator "Options"
13
-
14
- opts.on("-c", "--config CONFIG_FILE", "configuration to execute") do |config|
15
- run_conf(config)
16
- end
17
-
18
- opts.on("-i", "--init CONFIG_FILE", "create empty config file") do |config|
19
- file = Pathname.new(config)
20
-
21
- if file.exist?
22
- puts "Configuration file already exists: #{Pathname.new(config).realpath}"
23
- else
24
- File.open(file, 'w+') { |f| f.write(YAML::dump(EMPTY_CONFIG)) }
25
- end
26
- end
27
-
28
- opts.on("-v", "--version", "Goggles::VERSION") do
29
- puts Goggles::VERSION
30
- end
31
-
32
- opts.on("-h", "--help", "help text") do
33
- puts opt_parser
34
- end
35
- end
36
-
37
- opt_parser.parse!
38
- end
39
-
40
- def run_conf(config)
41
- if File.exists? config
42
- Goggles.swim config
43
- else
44
- puts "Not a valid configuration file: #{config}"
45
- end
46
- end
47
-
48
- EMPTY_CONFIG = {
49
- 'results_directory' => "/home/example/results",
50
- 'scripts_directory' => "/home/example/scripts",
51
- 'scripts_to_execute' => ["first_example.rb", "second_example.rb"],
52
- 'domain_under_test' => "http://www.google.com",
53
- 'paths_to_capture' => { 'home' => "/", 'gmail' => "/gmail" },
54
- 'browsers' => ["chrome", "firefox"],
55
- 'browser_widths' => [1024, 600],
56
- 'image_fuzzing' => "20%",
57
- 'diff_color' => "blue"
58
- }
59
- end
60
- end
@@ -1,3 +0,0 @@
1
- module Goggles
2
- class EmptyResultError < StandardError; end
3
- end
@@ -1,20 +0,0 @@
1
- results_directory: "spec/support/results"
2
- scripts_directory: "spec/support/scripts"
3
-
4
- domain_under_test: "http://www.google.com"
5
-
6
- paths_to_capture:
7
- home: "/"
8
-
9
- scripts_to_execute:
10
- - "google_search.rb"
11
-
12
- browsers:
13
- - "firefox"
14
- - "chrome"
15
-
16
- browser_widths:
17
- - 1024
18
- - 600
19
-
20
- image_fuzzing: "20%"
@@ -1,19 +0,0 @@
1
- results_directory: "spec/support/results"
2
- scripts_directory: "spec/support/scripts"
3
-
4
- domain_under_test: "http://www.google.com"
5
-
6
- paths_to_capture:
7
- home: "/"
8
-
9
- scripts_to_execute:
10
- - "no_screenshot.rb"
11
-
12
- browsers:
13
- - "firefox"
14
- - "chrome"
15
-
16
- browser_widths:
17
- - 320
18
-
19
- image_fuzzing: "20%"
@@ -1,19 +0,0 @@
1
- results_directory: "spec/support/results"
2
- scripts_directory: "spec/support/scripts"
3
-
4
- domain_under_test: "http://www.google.com"
5
-
6
- paths_to_capture:
7
- home: "/"
8
- email: "/gmail"
9
-
10
- scripts_to_execute:
11
-
12
- browsers:
13
- - "firefox"
14
- - "chrome"
15
-
16
- browser_widths:
17
- - 1024
18
-
19
- image_fuzzing: "20%"
@@ -1,14 +0,0 @@
1
- require 'goggles'
2
- require 'page-object'
3
-
4
- class Search
5
- include PageObject
6
-
7
- text_field(:search_box, :id => "gbqfq")
8
- end
9
-
10
- Goggles.grab_screenshot("homepage")
11
-
12
- page = Search.new(@watir)
13
- page.search_box = "manta"
14
- sleep 1
@@ -1,12 +0,0 @@
1
- require 'goggles'
2
- require 'page-object'
3
-
4
- class Search
5
- include PageObject
6
-
7
- text_field(:search_box, :id => "gbqfq")
8
- end
9
-
10
- page = Search.new(@watir)
11
- page.search_box = "manta"
12
- sleep 1