watircats 0.2.3

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b5df83a0e30799d0a3c844005316edd2e0d5f87d
4
+ data.tar.gz: b7b07badae0c4ff54e8266afc594eac5cd3f6905
5
+ SHA512:
6
+ metadata.gz: 3285222f1d6dfcd699340ed5ddfddf4f83e1cab0c1be9ebe20d0b43758728fd0e0cd1cecba3db9c6c19315f7d956afe2034157cb742c1a93270a18b2bcc50560
7
+ data.tar.gz: bad339c10f794b8d610daeb67cc9e6c932ffcfacc4afcda6bc94c1df5267951f5e456e992b72ac1fe5c8756da68ab3367f96a24bd4fabe275479eb24df6ae59c
data/.autotest ADDED
@@ -0,0 +1,5 @@
1
+ require 'autotest/restart'
2
+
3
+ Autotest.add_hook :initialize do |at|
4
+ at.order = :random
5
+ end
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ ruby "2.0.0"
2
+
3
+ source "http://rubygems.org"
4
+
5
+ # Currently not specifying versions, but probably should
6
+
7
+ gem "require_all"
8
+ gem "xml-simple"
9
+ gem "watir-webdriver"
10
+ gem "thor"
11
+ gem "haml"
12
+ gem "psych"
13
+ gem "awesome_print"
14
+ gem "minitest"
data/Gemfile.lock ADDED
@@ -0,0 +1,38 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ awesome_print (1.2.0)
5
+ childprocess (0.3.9)
6
+ ffi (~> 1.0, >= 1.0.11)
7
+ ffi (1.9.0)
8
+ haml (4.0.3)
9
+ tilt
10
+ minitest (5.0.6)
11
+ multi_json (1.8.2)
12
+ psych (2.0.0)
13
+ require_all (1.3.1)
14
+ rubyzip (0.9.9)
15
+ selenium-webdriver (2.35.1)
16
+ childprocess (>= 0.2.5)
17
+ multi_json (~> 1.0)
18
+ rubyzip (< 1.0.0)
19
+ websocket (~> 1.0.4)
20
+ thor (0.18.1)
21
+ tilt (1.4.1)
22
+ watir-webdriver (0.6.4)
23
+ selenium-webdriver (>= 2.18.0)
24
+ websocket (1.0.7)
25
+ xml-simple (1.1.2)
26
+
27
+ PLATFORMS
28
+ ruby
29
+
30
+ DEPENDENCIES
31
+ awesome_print
32
+ haml
33
+ minitest
34
+ psych
35
+ require_all
36
+ thor
37
+ watir-webdriver
38
+ xml-simple
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Clockwork Active Media Systems
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,74 @@
1
+ # WatirCats
2
+
3
+ WatirCats began as a simple fork of Wraith, from the developers at BBC News.
4
+
5
+ Orignally, Wraith used Phantom.js as its browser, but it was too darned slow, so the browsing engine was converted to Watir-Webdriver. There were also several other limitations to Wraith that hampered its use at Clockwork, so it was enhanced to support a number of unique features.
6
+
7
+ Wraith's original comparison command lies at the heart of the comparison functionality of WatirCats.
8
+
9
+ Some of the features:
10
+ - Responsive Screenshots
11
+ - Multiple sources for URLs, but most rely on /sitemap.xml for use
12
+ - Multiple Browsing engines. Chrome, Firefox, FirefoxESR, and support for IE
13
+ - Proxy and custom binary path support for Firefox
14
+
15
+ ## What is it?
16
+
17
+ WatirCats uses Watir-Webdriver to grab screenshots of pages at multiple widths. It also grabs and parses a site's sitemap, assuming the site map is hosted at the site_root/sitemap.xml
18
+
19
+ ## Requirements
20
+
21
+ - ImageMagick
22
+ - Ruby 1.9.3 or greater
23
+ - Firefox
24
+
25
+ ## Installation
26
+
27
+ `gem install WatirCats`
28
+
29
+ or
30
+
31
+ - Checkout this repository
32
+ - `bundle install`
33
+ - `gem build watircats.gemspec`
34
+ - `gem install WatirCats-0.2.0.gem`
35
+
36
+ ## Usage
37
+
38
+ - Compare And Take Screenshots:
39
+ - `watircats compare http://my.example.com http://my-other.example.com`
40
+ - Compare two folders of screenshots:
41
+ - `watircats folders folder_a folder_b`
42
+ - Take screenshots at several widths:
43
+ - `watircats screenshots http://my.example.com --widths 1024 800 320`
44
+
45
+ ## Configuration
46
+
47
+ Configuration can be done at the command line or via a config file. See 'sample_config.yml' for the available parameters.
48
+
49
+ Specify a config file at runtime with `--config_file my_config_file.yml`
50
+
51
+
52
+ If you want to add functionality to this project, pull requests are welcome.
53
+
54
+ * Create a branch based off master and do all of your changes with in it.
55
+ * If it you have to pause to add a 'and' anywhere in the title, it should be two pull requests.
56
+ * Make commits of logical units and describe them properly
57
+ * Check for unnecessary whitespace with git diff --check before committing.
58
+ * If possible, submit tests to your patch / new feature so it can be tested easily.
59
+ * Assure nothing is broken by running all the test
60
+ * Please ensure that it complies with coding standards.
61
+
62
+ **Please raise any issues with this project as a GitHub issue.**
63
+
64
+
65
+ ## License
66
+
67
+ WatirCats is available to everyone under the terms of the MIT open source
68
+ licence. Take a look at the LICENSE file in the code.
69
+
70
+ ## Credits
71
+
72
+ * [Andrew Leaf](http://clockwork.net/people/andrew_leaf/)
73
+ * [Wraith from BBC News](http://github.com/bbc-news/wraith)
74
+
data/bin/watircats ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.push File.expand_path('../../lib/', __FILE__)
3
+
4
+ require 'watircats/cli'
5
+
6
+ WatirCats::CLI.start(ARGV)
@@ -0,0 +1,201 @@
1
+ require 'thor'
2
+ require 'watircats'
3
+ require 'yaml'
4
+
5
+ # CLI for WatirCats. Options and commands for any of the available utilities
6
+ # available through the watircats executable
7
+
8
+ module WatirCats
9
+ class CLI < Thor
10
+
11
+ # Options that are common for comparison operations
12
+ common_compare_options = {
13
+ [:output_dir, '-o'] => "comparison",
14
+ [:screenshot_dir, '-s'] => "screenshots",
15
+ [:working_dir, '-w'] => :string,
16
+ [:images_dir, '-i'] => :string,
17
+ [:reporting_enabled, '-r'] => :boolean,
18
+ [:csv_output] => :boolean,
19
+ [:verbose, '-v'] => :boolean,
20
+ [:strip_zero_differences, '-z'] => :boolean,
21
+ [:config_file, '-c'] => :string,
22
+ [:skip_existing, '-e'] => :boolean,
23
+ }
24
+
25
+ # Options that are common for screenshot operations
26
+ common_screenshot_options = {
27
+ [:browser, '-b'] => "firefox",
28
+ [:widths] => :array,
29
+ [:limit, '-l'] => :numeric,
30
+ [:url_list] => :string,
31
+ [:limit] => :string,
32
+ [:custom_body_class_tests] => :string,
33
+ [:proxy, '-p'] => :string,
34
+ [:limited_path] => :string,
35
+ [:avoided_path] => :string
36
+ }
37
+
38
+ # Description for the next-to-be-defined 'compare' task
39
+ desc 'compare http://SITE_A http://SITE_B', 'Compare Screenshots from two sites'
40
+
41
+ # Add the options for comparison and screenshot operations to the next task
42
+ method_options common_compare_options
43
+ method_options common_screenshot_options
44
+
45
+ def compare(*source_arguments)
46
+ ensure_imagemagick
47
+
48
+ # Configure options
49
+ handle_configuration( options )
50
+
51
+ # Setting an exit status to track for altered screens
52
+ @exit_status = 0
53
+
54
+ # Create an empty array of sources
55
+ sources = []
56
+
57
+ # Populate the sources array with each command line argument
58
+ source_arguments.each { |s| sources << s }
59
+
60
+ # Handle a working directory by calling the private method 'handle_working_dir'
61
+ handle_working_dir
62
+
63
+ # Run the comparison
64
+ WatirCats::Runner.new( :compare, sources )
65
+
66
+ # Handle the reporting functionality
67
+ handle_reporting
68
+
69
+ # Exit based on the exit status of the application
70
+ exit @exit_status
71
+ end
72
+
73
+ desc 'folders FOLDER_A FOLDER_B', 'Compare two folders of screenshots'
74
+
75
+ # Add the options for comparison operations
76
+ method_options common_compare_options
77
+
78
+ def folders(*source_arguments)
79
+ ensure_imagemagick
80
+
81
+ handle_configuration( options )
82
+ # Setting an exit status to track for altered screens
83
+ @exit_status = 0
84
+
85
+ # Create an empty array of sources
86
+ sources = [ ]
87
+
88
+ # Populate the sources array with each command line argument
89
+ source_arguments.each { |s| sources << s }
90
+
91
+ # Handle a working directory
92
+ handle_working_dir
93
+
94
+ # Run the folders command
95
+ WatirCats::Runner.new( :folders, sources )
96
+
97
+ # Handle reporting
98
+ handle_reporting
99
+
100
+ exit @exit_status
101
+ end
102
+
103
+ desc 'screenshots SITE_A [SITE_B SITE_C ...]', 'Take Screenshots of any number of sites'
104
+
105
+ method_options common_compare_options
106
+ method_options common_screenshot_options
107
+
108
+ def screenshots(*source_arguments)
109
+ ensure_imagemagick
110
+
111
+ handle_configuration( options )
112
+ # Setting an exit status to track for altered screens
113
+ @exit_status = 0
114
+
115
+ # Create an empty array of sources
116
+ sources = [ ]
117
+
118
+ # Populate the sources array with each command line argument
119
+ source_arguments.each { |s| sources << s }
120
+
121
+ # Handle a working directory
122
+ handle_working_dir
123
+
124
+ # Run the screenshots command
125
+ WatirCats::Runner.new( :screenshots_only, sources )
126
+
127
+ # Handle Reporting
128
+ handle_reporting
129
+
130
+ exit @exit_status
131
+ end
132
+
133
+ private
134
+
135
+ def handle_working_dir
136
+ # Handle a working directory
137
+ working_dir = WatirCats.config.working_dir
138
+ if working_dir
139
+ unless File.directory? working_dir
140
+ FileUtils.mkdir working_dir
141
+ end
142
+ Dir.chdir working_dir
143
+ end
144
+ end
145
+
146
+ def handle_reporting
147
+ # Handle standard reporting
148
+ reporting = WatirCats.config.reporting_enabled
149
+
150
+ if reporting
151
+ data = WatirCats::Comparer.the_results
152
+ data.each { |e| @exit_status = 1 unless e[:result].match(/0/) }
153
+
154
+ report = WatirCats::Reporter.new( data ).build_html
155
+ File.open("#{WatirCats.config.output_dir}/index.html", 'w') do |f|
156
+ f.write report
157
+ end
158
+ end
159
+
160
+ # Handle custom reporting
161
+ custom_tests = WatirCats.config.custom_body_class_tests
162
+
163
+ if custom_tests
164
+ results = WatirCats::Snapper.custom_test_results
165
+ report = WatirCats::Reporter.build_custom_results( results )
166
+
167
+ File.open("#{WatirCats.config.output_dir}/custom_report.html", 'w') do |f|
168
+ f.write report
169
+ end
170
+ end
171
+
172
+ end
173
+
174
+ def handle_configuration(options)
175
+ # Parse the command line options. If a config file if specified, merge
176
+ # those values into the options hash as long as keys don't collide.
177
+ # Command line options override the config file.
178
+
179
+ cloned_options = options.dup
180
+ if cloned_options[:config_file]
181
+ config = YAML::load_file cloned_options[:config_file]
182
+ config.each do |key,value|
183
+ cloned_options[key.to_sym] = value
184
+ end
185
+ end
186
+ merged_opts = cloned_options.merge(options)
187
+ WatirCats.configure merged_opts
188
+ end
189
+
190
+ def ensure_imagemagick
191
+ # Ensure that Imagemagick's compare is installed
192
+ begin
193
+ `compare --version`
194
+ rescue
195
+ puts "Please ensure ImageMagick is in your system path to use WatirCats. \nPlease visit http://www.imagemagick.org."
196
+ exit
197
+ end
198
+ end
199
+
200
+ end
201
+ end
@@ -0,0 +1,136 @@
1
+ module WatirCats
2
+ class Comparer
3
+
4
+ NO_CHANGE = "Snow"
5
+ ERROR = "Crimson"
6
+ CHANGE = "Khaki"
7
+
8
+
9
+ def initialize(source_a, source_b)
10
+
11
+ @@results = [ ]
12
+ @@strip_zero = WatirCats.config.strip_zero_differences || nil
13
+
14
+ @comparison_dir = WatirCats.config.output_dir.chomp("/")
15
+ # Get the last two directories that were created
16
+
17
+ previous_shots_folder = source_a.chomp("/")
18
+ latest_shots_folder = source_b.chomp("/")
19
+
20
+ # Cleanup the comparison folder
21
+ reset_comparison_folder
22
+
23
+ # Compare the directories
24
+ compare_directories(latest_shots_folder, previous_shots_folder)
25
+
26
+ # Return self
27
+ self
28
+ end
29
+
30
+ def reset_comparison_folder
31
+ if File.directory? @comparison_dir
32
+ dir_contents = Dir.glob("#{@comparison_dir}/*_compared.png")
33
+ if dir_contents.size > 0
34
+ dir_contents.each do |shot|
35
+ FileUtils.rm(shot)
36
+ end
37
+ end
38
+ else
39
+ FileUtils.mkdir_p(@comparison_dir)
40
+ end
41
+ end
42
+
43
+ def compare_directories(latest, previous)
44
+ # Grab the list of screenshots
45
+ old_shots = Dir.glob(previous + "/*.png")
46
+
47
+ old_shots.each do |old_shot|
48
+ new_shot = old_shot.gsub(previous, latest)
49
+
50
+ next unless File.exists? new_shot
51
+ # Set a file prefix for output and info
52
+ base_name = old_shot.split("/").last.split(".").first
53
+ output_file = base_name + "_compared.png"
54
+
55
+ comparison = compare_images(new_shot, old_shot, output_file)
56
+ status = NO_CHANGE
57
+ if comparison.match(/error/)
58
+ status = ERROR
59
+ elsif comparison.match(/^[1-9]/)
60
+ status = CHANGE
61
+ end
62
+ @@results << { :compared_shot => output_file,
63
+ :result => comparison, :status_color => status }
64
+
65
+ # Remove the file if there is no change to be concerned with
66
+ if @@strip_zero == true
67
+ begin
68
+ FileUtils.rm "#{@comparison_dir}/#{output_file}" if status == NO_CHANGE
69
+ rescue Exception => msg
70
+ print msg
71
+ print "\n"
72
+ end
73
+ end
74
+
75
+ end
76
+ # Run the generate thumbs
77
+ generate_thumbs if WatirCats.config.reporting_enabled
78
+ end
79
+
80
+ def generate_thumbs
81
+
82
+ unless results.size < 1
83
+ unless File.directory? "#{@comparison_dir}/thumbs"
84
+ FileUtils.mkdir "#{@comparison_dir}/thumbs"
85
+ end
86
+
87
+ # Generate thumbnails
88
+ `mogrify -format png -path #{@comparison_dir}/thumbs -thumbnail 50x100 #{@comparison_dir}/*.png`
89
+ end
90
+ end
91
+
92
+
93
+ def compare_images(latest_grab, previous_grab, output_file)
94
+ data = `compare -fuzz 20% -metric AE -highlight-color blue #{previous_grab} #{latest_grab} #{@comparison_dir}/#{output_file} 2>&1`.chomp
95
+ # Handle logging
96
+ return data if ( @@strip_zero == true && data.match(/^0/) )
97
+ csv = WatirCats.config.csv
98
+ verbose = WatirCats.config.verbose
99
+ print "#{output_file}" if ( csv || verbose )
100
+ print ",#{data}" if csv
101
+ print "\n" if ( csv || verbose )
102
+ # Return data
103
+ data
104
+ end
105
+
106
+ def results
107
+ sorted = @@results.sort_by { |k| k[:status] }
108
+ if @@strip_zero == true
109
+ return sorted.reject { |capture| true if capture[:result] == "0" }
110
+ else
111
+ return sorted
112
+ end
113
+ end
114
+
115
+
116
+ def self.sanitize_results(data)
117
+ data.each do | hash |
118
+ hash[:result] = 'image mismatch' if hash[:result].match(/compare/)
119
+ end
120
+ end
121
+
122
+ def self.the_results
123
+ sorted = @@results.sort_by { |k| k[:status] }
124
+
125
+ sanitize_results(sorted)
126
+
127
+ if @@strip_zero
128
+ return sorted.reject { |cap| true if cap[:result] == "0" }
129
+ else
130
+ return sorted
131
+ end
132
+
133
+ end
134
+
135
+ end
136
+ end
@@ -0,0 +1,58 @@
1
+ module WatirCats
2
+
3
+ @@config = nil
4
+
5
+ # Create a new Config object to store our settings
6
+ def self.configure( options_hash )
7
+ # Only allows for one time creation of the config
8
+ if @@config.is_a? Config
9
+ update_config( options_hash )
10
+ else
11
+ @@config = Config.new( options_hash )
12
+ end
13
+ # Return the @@config for chaining
14
+ @@config
15
+ end
16
+
17
+ # This allows us to get the config setting from anywhere within WatirCats
18
+ # by using WatirCats.config.setting_name
19
+ def self.config
20
+ # Return the @@config class var to allow chaining for values
21
+ @@config
22
+ end
23
+
24
+ def self.update_config( options_hash )
25
+ # Instantiate a new Config unless @@config already is a Config object
26
+ @@config = Config.new({ }) unless @@config.is_a? Config
27
+ options_hash.each do |key, value|
28
+ @@config.new_key( key, value )
29
+ end
30
+ end
31
+
32
+ # Create a configuration object
33
+ class Config
34
+
35
+ def initialize( options_hash )
36
+ # Iterate through the options hash, setting each key as an instance
37
+ # variable, and creating a getter method with the same name
38
+ options_hash.each do |key, value|
39
+ new_key(key, value)
40
+ end
41
+ end
42
+
43
+ def new_key(key, value)
44
+ # define getter
45
+ instance_eval( "def #{key}; @#{key}; end" ) unless self.respond_to? "#{key}"
46
+ # define setter
47
+ instance_eval( "def #{key}= (v); @#{key} = v; end" ) unless self.respond_to? "#{key}="
48
+ # Set the value on the instance variable, creating if necessary
49
+ instance_variable_set( "@#{key}".to_sym, value )
50
+ end
51
+
52
+ def method_missing( meth, *args, &blk )
53
+ # Return nil if an expected parameter isn't here. No need to die.
54
+ nil
55
+ end
56
+
57
+ end
58
+ end