kontrast 0.2.1 → 0.6.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.
- checksums.yaml +4 -4
 - data/README.md +135 -96
 - data/bin/kontrast +9 -5
 - data/lib/kontrast.rb +17 -5
 - data/lib/kontrast/api_client.rb +56 -0
 - data/lib/kontrast/api_endpoint_comparator.rb +126 -0
 - data/lib/kontrast/api_endpoint_runner.rb +99 -0
 - data/lib/kontrast/api_endpoint_test.rb +8 -0
 - data/lib/kontrast/configuration.rb +36 -7
 - data/lib/kontrast/exceptions.rb +2 -1
 - data/lib/kontrast/gallery/template.erb +152 -21
 - data/lib/kontrast/gallery_creator.rb +105 -47
 - data/lib/kontrast/global_runner.rb +121 -0
 - data/lib/kontrast/image_helper.rb +63 -0
 - data/lib/kontrast/image_uploader.rb +18 -0
 - data/lib/kontrast/page_comparator.rb +46 -0
 - data/lib/kontrast/page_runner.rb +95 -0
 - data/lib/kontrast/page_test.rb +32 -0
 - data/lib/kontrast/selenium_handler.rb +18 -7
 - data/lib/kontrast/spec.rb +21 -0
 - data/lib/kontrast/spec_builder.rb +54 -0
 - data/lib/kontrast/test.rb +27 -0
 - data/lib/kontrast/test_builder.rb +25 -9
 - data/lib/kontrast/test_suite.rb +42 -0
 - data/lib/kontrast/thumbnail_creator.rb +18 -0
 - data/lib/kontrast/version.rb +1 -1
 - data/spec/api_endpoint_comparator_spec.rb +125 -0
 - data/spec/configuration_spec.rb +19 -0
 - data/spec/gallery_creator_spec.rb +26 -20
 - data/spec/{image_handler_spec.rb → global_runner_spec.rb} +17 -12
 - data/spec/page_comparator_spec.rb +31 -0
 - data/spec/page_runner_spec.rb +45 -0
 - data/spec/spec_builder_spec.rb +32 -0
 - data/spec/support/fixtures/image.jpg +0 -0
 - data/spec/support/fixtures/image_clone.jpg +0 -0
 - data/spec/support/fixtures/img1.jpg +0 -0
 - data/spec/support/fixtures/img2.jpg +0 -0
 - data/spec/support/fixtures/other_image.jpg +0 -0
 - data/spec/test_builder_spec.rb +6 -3
 - data/spec/test_spec.rb +53 -0
 - data/spec/test_suite_spec.rb +56 -0
 - metadata +91 -30
 - data/lib/kontrast/image_handler.rb +0 -119
 - data/lib/kontrast/runner.rb +0 -141
 - data/spec/runner_spec.rb +0 -37
 
| 
         @@ -12,7 +12,7 @@ module Kontrast 
     | 
|
| 
       12 
12 
     | 
    
         
             
                    def create_gallery(output_dir)
         
     | 
| 
       13 
13 
     | 
    
         
             
                        begin
         
     | 
| 
       14 
14 
     | 
    
         
             
                            @gallery_dir = FileUtils.mkdir_p("#{output_dir}/gallery").join('')
         
     | 
| 
       15 
     | 
    
         
            -
                        rescue  
     | 
| 
      
 15 
     | 
    
         
            +
                        rescue StandardError => e
         
     | 
| 
       16 
16 
     | 
    
         
             
                            raise GalleryException.new("An unexpected error occurred while trying to create the gallery's output directory: #{e.inspect}")
         
     | 
| 
       17 
17 
     | 
    
         
             
                        end
         
     | 
| 
       18 
18 
     | 
    
         | 
| 
         @@ -46,7 +46,7 @@ module Kontrast 
     | 
|
| 
       46 
46 
     | 
    
         | 
| 
       47 
47 
     | 
    
         
             
                    def generate_html(files, diffs)
         
     | 
| 
       48 
48 
     | 
    
         
             
                        # Template variables
         
     | 
| 
       49 
     | 
    
         
            -
                         
     | 
| 
      
 49 
     | 
    
         
            +
                        groups, without_diffs, with_diffs = parse_directories(files, diffs)
         
     | 
| 
       50 
50 
     | 
    
         | 
| 
       51 
51 
     | 
    
         
             
                        # HTML
         
     | 
| 
       52 
52 
     | 
    
         
             
                        template = File.read(Kontrast.root + '/lib/kontrast/gallery/template.erb')
         
     | 
| 
         @@ -83,66 +83,124 @@ module Kontrast 
     | 
|
| 
       83 
83 
     | 
    
         
             
                        }
         
     | 
| 
       84 
84 
     | 
    
         
             
                    end
         
     | 
| 
       85 
85 
     | 
    
         | 
| 
      
 86 
     | 
    
         
            +
                    def test_name_from_dir(dir)
         
     | 
| 
      
 87 
     | 
    
         
            +
                        # dir is a string prefixed with a group name:
         
     | 
| 
      
 88 
     | 
    
         
            +
                        # '1280_home' or '2x_home_screen'
         
     | 
| 
      
 89 
     | 
    
         
            +
                        return dir.split('_')[1..-1].join('_')
         
     | 
| 
      
 90 
     | 
    
         
            +
                    end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                    def base_path
         
     | 
| 
      
 93 
     | 
    
         
            +
                        # This determines where to display images from in the gallery
         
     | 
| 
      
 94 
     | 
    
         
            +
                        if Kontrast.configuration.run_parallel
         
     | 
| 
      
 95 
     | 
    
         
            +
                            # Build the remote path to S3
         
     | 
| 
      
 96 
     | 
    
         
            +
                            return "https://#{Kontrast.configuration.aws_bucket}.s3.amazonaws.com/#{Kontrast.configuration.remote_path}"
         
     | 
| 
      
 97 
     | 
    
         
            +
                        else
         
     | 
| 
      
 98 
     | 
    
         
            +
                            return ".."
         
     | 
| 
      
 99 
     | 
    
         
            +
                        end
         
     | 
| 
      
 100 
     | 
    
         
            +
                    end
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
                    def variants_for_page(directory, diffs)
         
     | 
| 
      
 103 
     | 
    
         
            +
                        # Return a hash that will be used in the erb template to show the
         
     | 
| 
      
 104 
     | 
    
         
            +
                        # diffs for a given test.
         
     | 
| 
      
 105 
     | 
    
         
            +
                        variants = []
         
     | 
| 
      
 106 
     | 
    
         
            +
                        ['test', 'production', 'diff'].each do |type|
         
     | 
| 
      
 107 
     | 
    
         
            +
                            variant = {
         
     | 
| 
      
 108 
     | 
    
         
            +
                                image: "#{base_path}/#{directory}/" + type + ".png",
         
     | 
| 
      
 109 
     | 
    
         
            +
                                thumb: "#{base_path}/#{directory}/" + type + "_thumb.png",
         
     | 
| 
      
 110 
     | 
    
         
            +
                                domain: type,
         
     | 
| 
      
 111 
     | 
    
         
            +
                                type: 'page',
         
     | 
| 
      
 112 
     | 
    
         
            +
                            }
         
     | 
| 
      
 113 
     | 
    
         
            +
                            if type == 'diff' && diffs[directory]
         
     | 
| 
      
 114 
     | 
    
         
            +
                                variant[:diff_amt] = diffs[directory]["diff"]
         
     | 
| 
      
 115 
     | 
    
         
            +
                            end
         
     | 
| 
      
 116 
     | 
    
         
            +
                            variants << variant
         
     | 
| 
      
 117 
     | 
    
         
            +
                        end
         
     | 
| 
      
 118 
     | 
    
         
            +
             
     | 
| 
      
 119 
     | 
    
         
            +
                        return variants
         
     | 
| 
      
 120 
     | 
    
         
            +
                    end
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
                    def variants_for_api_endpoint(directory, diffs, files)
         
     | 
| 
      
 123 
     | 
    
         
            +
                        # Return a hash that will be used in the erb template to show the
         
     | 
| 
      
 124 
     | 
    
         
            +
                        # diffs for a given test.
         
     | 
| 
      
 125 
     | 
    
         
            +
                        variants = []
         
     | 
| 
      
 126 
     | 
    
         
            +
                        ['test', 'production', 'diff'].each do |type|
         
     | 
| 
      
 127 
     | 
    
         
            +
                            variant = {
         
     | 
| 
      
 128 
     | 
    
         
            +
                                file: "#{base_path}/#{directory}/#{type}.json",
         
     | 
| 
      
 129 
     | 
    
         
            +
                                domain: type,
         
     | 
| 
      
 130 
     | 
    
         
            +
                                type: 'api_endpoint',
         
     | 
| 
      
 131 
     | 
    
         
            +
                                diff_amt: 0,
         
     | 
| 
      
 132 
     | 
    
         
            +
                            }
         
     | 
| 
      
 133 
     | 
    
         
            +
                            if diffs[directory]
         
     | 
| 
      
 134 
     | 
    
         
            +
                                variant[:diff_amt] = 1
         
     | 
| 
      
 135 
     | 
    
         
            +
                            end
         
     | 
| 
      
 136 
     | 
    
         
            +
             
     | 
| 
      
 137 
     | 
    
         
            +
                            # Get all images
         
     | 
| 
      
 138 
     | 
    
         
            +
                            image_files = files.select { |file_name|
         
     | 
| 
      
 139 
     | 
    
         
            +
                                file_name.match /#{directory}\/#{type}_\d+.(jpg|png)/
         
     | 
| 
      
 140 
     | 
    
         
            +
                            }.map { |file_name|
         
     | 
| 
      
 141 
     | 
    
         
            +
                                name_without_extension = file_name.split('.')[0..-2].join('.')
         
     | 
| 
      
 142 
     | 
    
         
            +
                                {
         
     | 
| 
      
 143 
     | 
    
         
            +
                                    image: "#{base_path}/#{file_name}",
         
     | 
| 
      
 144 
     | 
    
         
            +
                                    thumb: "#{base_path}/#{name_without_extension}_thumb.png",
         
     | 
| 
      
 145 
     | 
    
         
            +
                                }
         
     | 
| 
      
 146 
     | 
    
         
            +
                            }
         
     | 
| 
      
 147 
     | 
    
         
            +
                            variant[:images] = image_files
         
     | 
| 
      
 148 
     | 
    
         
            +
                            variants << variant
         
     | 
| 
      
 149 
     | 
    
         
            +
                        end
         
     | 
| 
      
 150 
     | 
    
         
            +
             
     | 
| 
      
 151 
     | 
    
         
            +
                        return variants
         
     | 
| 
      
 152 
     | 
    
         
            +
                    end
         
     | 
| 
      
 153 
     | 
    
         
            +
             
     | 
| 
       86 
154 
     | 
    
         
             
                    # This function just turns the list of files and diffs into a hash that the gallery
         
     | 
| 
       87 
155 
     | 
    
         
             
                    # creator can insert into a template. See an example of the created hash below.
         
     | 
| 
       88 
156 
     | 
    
         
             
                    def parse_directories(files, diffs)
         
     | 
| 
       89 
157 
     | 
    
         
             
                        files.sort!
         
     | 
| 
       90 
158 
     | 
    
         | 
| 
       91 
     | 
    
         
            -
                         
     | 
| 
       92 
     | 
    
         
            -
                         
     | 
| 
      
 159 
     | 
    
         
            +
                        # Initialize those hashes, where each key will map to hash, in wich
         
     | 
| 
      
 160 
     | 
    
         
            +
                        # each key maps to an array:
         
     | 
| 
      
 161 
     | 
    
         
            +
                        # {
         
     | 
| 
      
 162 
     | 
    
         
            +
                        #   key1: {
         
     | 
| 
      
 163 
     | 
    
         
            +
                        #   },
         
     | 
| 
      
 164 
     | 
    
         
            +
                        #   key2: {
         
     | 
| 
      
 165 
     | 
    
         
            +
                        #   },
         
     | 
| 
      
 166 
     | 
    
         
            +
                        # }
         
     | 
| 
      
 167 
     | 
    
         
            +
                        #
         
     | 
| 
      
 168 
     | 
    
         
            +
                        without_diffs = Hash.new { |h,k| h[k] = {} }
         
     | 
| 
      
 169 
     | 
    
         
            +
                        with_diffs = Hash.new { |h,k| h[k] = {} }
         
     | 
| 
       93 
170 
     | 
    
         | 
| 
       94 
     | 
    
         
            -
                         
     | 
| 
       95 
     | 
    
         
            -
                         
     | 
| 
       96 
     | 
    
         
            -
                        sizes.each { |size|
         
     | 
| 
       97 
     | 
    
         
            -
                            dirs[size] = {}
         
     | 
| 
       98 
     | 
    
         
            -
             
     | 
| 
       99 
     | 
    
         
            -
                            # Get all directories for this size
         
     | 
| 
       100 
     | 
    
         
            -
                            tests_for_size = directories.select { |d| d.index(size + "_") == 0 }
         
     | 
| 
       101 
     | 
    
         
            -
                            tests_for_size.each do |dir|
         
     | 
| 
       102 
     | 
    
         
            -
                                array = dir.split('_')
         
     | 
| 
       103 
     | 
    
         
            -
                                array.delete_at(0)
         
     | 
| 
       104 
     | 
    
         
            -
                                test_name = array.join('_')
         
     | 
| 
       105 
     | 
    
         
            -
                                dirs[size][test_name] = {
         
     | 
| 
       106 
     | 
    
         
            -
                                    variants: []
         
     | 
| 
       107 
     | 
    
         
            -
                                }
         
     | 
| 
       108 
     | 
    
         
            -
                            end
         
     | 
| 
       109 
     | 
    
         
            -
                        }
         
     | 
| 
      
 171 
     | 
    
         
            +
                        directories = files.map { |f| f.split('/').first }.uniq
         
     | 
| 
      
 172 
     | 
    
         
            +
                        groups = directories.map { |dir| dir.split('_').first }.uniq
         
     | 
| 
       110 
173 
     | 
    
         | 
| 
       111 
     | 
    
         
            -
                        # This determines where to display images from in the gallery
         
     | 
| 
       112 
     | 
    
         
            -
                        if Kontrast.configuration.run_parallel
         
     | 
| 
       113 
     | 
    
         
            -
                            # Build the remote path to S3
         
     | 
| 
       114 
     | 
    
         
            -
                            base_path = "https://#{Kontrast.configuration.aws_bucket}.s3.amazonaws.com/#{Kontrast.configuration.remote_path}"
         
     | 
| 
       115 
     | 
    
         
            -
                        else
         
     | 
| 
       116 
     | 
    
         
            -
                            base_path = ".."
         
     | 
| 
       117 
     | 
    
         
            -
                        end
         
     | 
| 
       118 
174 
     | 
    
         | 
| 
       119 
175 
     | 
    
         
             
                        # Fill in the files as variants
         
     | 
| 
       120 
176 
     | 
    
         
             
                        directories.each do |directory|
         
     | 
| 
       121 
     | 
    
         
            -
                             
     | 
| 
       122 
     | 
    
         
            -
                             
     | 
| 
       123 
     | 
    
         
            -
             
     | 
| 
       124 
     | 
    
         
            -
                             
     | 
| 
       125 
     | 
    
         
            -
             
     | 
| 
       126 
     | 
    
         
            -
                            #  
     | 
| 
       127 
     | 
    
         
            -
                             
     | 
| 
       128 
     | 
    
         
            -
             
     | 
| 
       129 
     | 
    
         
            -
             
     | 
| 
       130 
     | 
    
         
            -
             
     | 
| 
       131 
     | 
    
         
            -
             
     | 
| 
       132 
     | 
    
         
            -
             
     | 
| 
       133 
     | 
    
         
            -
             
     | 
| 
       134 
     | 
    
         
            -
             
     | 
| 
       135 
     | 
    
         
            -
                                 
     | 
| 
      
 177 
     | 
    
         
            +
                            group = directory.split('_')[0]
         
     | 
| 
      
 178 
     | 
    
         
            +
                            test_name = test_name_from_dir(directory)
         
     | 
| 
      
 179 
     | 
    
         
            +
             
     | 
| 
      
 180 
     | 
    
         
            +
                            # Determines the type of test by the presence of the diff.png
         
     | 
| 
      
 181 
     | 
    
         
            +
                            # file in the folder.
         
     | 
| 
      
 182 
     | 
    
         
            +
                            # Ideally the manifest file format would be different and
         
     | 
| 
      
 183 
     | 
    
         
            +
                            # include the test type with
         
     | 
| 
      
 184 
     | 
    
         
            +
                            if files.select { |file_name| file_name.start_with?(directory) }.any? { |file_name| file_name.include?('diff.png') }
         
     | 
| 
      
 185 
     | 
    
         
            +
                                variants = variants_for_page(directory, diffs)
         
     | 
| 
      
 186 
     | 
    
         
            +
                            else
         
     | 
| 
      
 187 
     | 
    
         
            +
                                variants = variants_for_api_endpoint(directory, diffs, files)
         
     | 
| 
      
 188 
     | 
    
         
            +
                            end
         
     | 
| 
      
 189 
     | 
    
         
            +
             
     | 
| 
      
 190 
     | 
    
         
            +
                            if diffs[directory]
         
     | 
| 
      
 191 
     | 
    
         
            +
                                with_diffs[group][test_name] = variants
         
     | 
| 
      
 192 
     | 
    
         
            +
                            else
         
     | 
| 
      
 193 
     | 
    
         
            +
                                without_diffs[group][test_name] = variants
         
     | 
| 
       136 
194 
     | 
    
         
             
                            end
         
     | 
| 
       137 
195 
     | 
    
         
             
                        end
         
     | 
| 
       138 
196 
     | 
    
         | 
| 
       139 
     | 
    
         
            -
                        return  
     | 
| 
      
 197 
     | 
    
         
            +
                        return groups, without_diffs, with_diffs
         
     | 
| 
       140 
198 
     | 
    
         | 
| 
       141 
199 
     | 
    
         
             
                        # For reference
         
     | 
| 
       142 
200 
     | 
    
         
             
                        # gallery_format = {
         
     | 
| 
       143 
201 
     | 
    
         
             
                        #     "1080" => {
         
     | 
| 
       144 
     | 
    
         
            -
                        #         "name" =>  
     | 
| 
       145 
     | 
    
         
            -
                        #              
     | 
| 
      
 202 
     | 
    
         
            +
                        #         "name" => [
         
     | 
| 
      
 203 
     | 
    
         
            +
                        #             {
         
     | 
| 
       146 
204 
     | 
    
         
             
                        #                 image: "full_img_src",
         
     | 
| 
       147 
205 
     | 
    
         
             
                        #                 thumb: "thumb_src",
         
     | 
| 
       148 
206 
     | 
    
         
             
                        #                 domain: "production"
         
     | 
| 
         @@ -154,8 +212,8 @@ module Kontrast 
     | 
|
| 
       154 
212 
     | 
    
         
             
                        #                 image: "diff_src",
         
     | 
| 
       155 
213 
     | 
    
         
             
                        #                 thumb: "diff_thumb_src",
         
     | 
| 
       156 
214 
     | 
    
         
             
                        #                 domain: "diff",
         
     | 
| 
       157 
     | 
    
         
            -
                        #                  
     | 
| 
       158 
     | 
    
         
            -
                        #             } 
     | 
| 
      
 215 
     | 
    
         
            +
                        #                 diff_amt: 0.1
         
     | 
| 
      
 216 
     | 
    
         
            +
                        #             }
         
     | 
| 
       159 
217 
     | 
    
         
             
                        #         }
         
     | 
| 
       160 
218 
     | 
    
         
             
                        #     }
         
     | 
| 
       161 
219 
     | 
    
         
             
                        # }
         
     | 
| 
         @@ -0,0 +1,121 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "yaml"
         
     | 
| 
      
 2 
     | 
    
         
            +
            require "net/http"
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module Kontrast
         
     | 
| 
      
 5 
     | 
    
         
            +
                class GlobalRunner
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                    def initialize
         
     | 
| 
      
 8 
     | 
    
         
            +
                        @page_runner = PageRunner.new
         
     | 
| 
      
 9 
     | 
    
         
            +
                        @api_endpont_runner = ApiEndpointRunner.new
         
     | 
| 
      
 10 
     | 
    
         
            +
                        @path = Kontrast.path
         
     | 
| 
      
 11 
     | 
    
         
            +
                        @current_node = 0
         
     | 
| 
      
 12 
     | 
    
         
            +
                    end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                    def run
         
     | 
| 
      
 15 
     | 
    
         
            +
                        # Make sure the local server is running
         
     | 
| 
      
 16 
     | 
    
         
            +
                        wait_for_server
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                        # Assign nodes
         
     | 
| 
      
 19 
     | 
    
         
            +
                        if Kontrast.configuration.run_parallel
         
     | 
| 
      
 20 
     | 
    
         
            +
                            total_nodes = Kontrast.configuration.total_nodes
         
     | 
| 
      
 21 
     | 
    
         
            +
                            @current_node = Kontrast.configuration.current_node
         
     | 
| 
      
 22 
     | 
    
         
            +
                        else
         
     | 
| 
      
 23 
     | 
    
         
            +
                            # Override the config for local use
         
     | 
| 
      
 24 
     | 
    
         
            +
                            total_nodes = 1
         
     | 
| 
      
 25 
     | 
    
         
            +
                        end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                        # Run both runners
         
     | 
| 
      
 28 
     | 
    
         
            +
                        @page_runner.run(total_nodes, @current_node)
         
     | 
| 
      
 29 
     | 
    
         
            +
                        @api_endpont_runner.run(total_nodes, @current_node)
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                        # Create manifest
         
     | 
| 
      
 32 
     | 
    
         
            +
                        create_manifest
         
     | 
| 
      
 33 
     | 
    
         
            +
                    end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                    # The manifest is a per-node .json file that is used to create the gallery
         
     | 
| 
      
 36 
     | 
    
         
            +
                    # without having to download all assets from S3 to the test environment
         
     | 
| 
      
 37 
     | 
    
         
            +
                    def create_manifest
         
     | 
| 
      
 38 
     | 
    
         
            +
                        # Create manifest
         
     | 
| 
      
 39 
     | 
    
         
            +
                        puts "Creating manifest..."
         
     | 
| 
      
 40 
     | 
    
         
            +
                        if Kontrast.configuration.run_parallel
         
     | 
| 
      
 41 
     | 
    
         
            +
                            build = Kontrast.configuration.remote_path
         
     | 
| 
      
 42 
     | 
    
         
            +
                        else
         
     | 
| 
      
 43 
     | 
    
         
            +
                            build = nil
         
     | 
| 
      
 44 
     | 
    
         
            +
                        end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                        diffs = {}
         
     | 
| 
      
 47 
     | 
    
         
            +
                        diffs.merge!(@page_runner.diffs)
         
     | 
| 
      
 48 
     | 
    
         
            +
                        diffs.merge!(@api_endpont_runner.diffs)
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                        # Set up structure
         
     | 
| 
      
 51 
     | 
    
         
            +
                        manifest = {
         
     | 
| 
      
 52 
     | 
    
         
            +
                            diffs: diffs,
         
     | 
| 
      
 53 
     | 
    
         
            +
                            files: []
         
     | 
| 
      
 54 
     | 
    
         
            +
                        }
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                        # Dump directories
         
     | 
| 
      
 57 
     | 
    
         
            +
                        Dir.foreach(@path) do |subdir|
         
     | 
| 
      
 58 
     | 
    
         
            +
                            next if ['.', '..'].include?(subdir)
         
     | 
| 
      
 59 
     | 
    
         
            +
                            next if subdir.index('manifest_')
         
     | 
| 
      
 60 
     | 
    
         
            +
                            Dir.foreach("#{@path}/#{subdir}") do |img|
         
     | 
| 
      
 61 
     | 
    
         
            +
                                next if ['.', '..'].include?(img)
         
     | 
| 
      
 62 
     | 
    
         
            +
                                manifest[:files] << "#{subdir}/#{img}"
         
     | 
| 
      
 63 
     | 
    
         
            +
                            end
         
     | 
| 
      
 64 
     | 
    
         
            +
                        end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                        if Kontrast.configuration.run_parallel
         
     | 
| 
      
 67 
     | 
    
         
            +
                            # Upload manifest
         
     | 
| 
      
 68 
     | 
    
         
            +
                            Kontrast.fog.directories.get(Kontrast.configuration.aws_bucket).files.create(
         
     | 
| 
      
 69 
     | 
    
         
            +
                                key: "#{build}/manifest_#{@current_node}.json",
         
     | 
| 
      
 70 
     | 
    
         
            +
                                body: manifest.to_json
         
     | 
| 
      
 71 
     | 
    
         
            +
                            )
         
     | 
| 
      
 72 
     | 
    
         
            +
                        else
         
     | 
| 
      
 73 
     | 
    
         
            +
                            # Write manifest
         
     | 
| 
      
 74 
     | 
    
         
            +
                            File.open("#{@path}/manifest_#{@current_node}.json", 'w') do |outf|
         
     | 
| 
      
 75 
     | 
    
         
            +
                                outf.write(manifest.to_json)
         
     | 
| 
      
 76 
     | 
    
         
            +
                            end
         
     | 
| 
      
 77 
     | 
    
         
            +
                        end
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                        return manifest
         
     | 
| 
      
 80 
     | 
    
         
            +
                    end
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                    private
         
     | 
| 
      
 83 
     | 
    
         
            +
                        def wait_for_server
         
     | 
| 
      
 84 
     | 
    
         
            +
                            # Test server
         
     | 
| 
      
 85 
     | 
    
         
            +
                            tries = 30
         
     | 
| 
      
 86 
     | 
    
         
            +
                            uri = URI(Kontrast.configuration.test_domain)
         
     | 
| 
      
 87 
     | 
    
         
            +
                            begin
         
     | 
| 
      
 88 
     | 
    
         
            +
                                Net::HTTP.get(uri)
         
     | 
| 
      
 89 
     | 
    
         
            +
                            rescue Errno::ECONNREFUSED => e
         
     | 
| 
      
 90 
     | 
    
         
            +
                                tries -= 1
         
     | 
| 
      
 91 
     | 
    
         
            +
                                if tries > 0
         
     | 
| 
      
 92 
     | 
    
         
            +
                                    puts "Waiting for test server..."
         
     | 
| 
      
 93 
     | 
    
         
            +
                                    sleep 2
         
     | 
| 
      
 94 
     | 
    
         
            +
                                    retry
         
     | 
| 
      
 95 
     | 
    
         
            +
                                else
         
     | 
| 
      
 96 
     | 
    
         
            +
                                    raise RunnerException.new("Could not reach the test server at '#{uri}'.")
         
     | 
| 
      
 97 
     | 
    
         
            +
                                end
         
     | 
| 
      
 98 
     | 
    
         
            +
                            rescue StandardError => e
         
     | 
| 
      
 99 
     | 
    
         
            +
                                raise RunnerException.new("An unexpected error occured while trying to reach the test server at '#{uri}': #{e.inspect}")
         
     | 
| 
      
 100 
     | 
    
         
            +
                            end
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
                            # Production server
         
     | 
| 
      
 103 
     | 
    
         
            +
                            tries = 30
         
     | 
| 
      
 104 
     | 
    
         
            +
                            uri = URI(Kontrast.configuration.production_domain)
         
     | 
| 
      
 105 
     | 
    
         
            +
                            begin
         
     | 
| 
      
 106 
     | 
    
         
            +
                                Net::HTTP.get(uri)
         
     | 
| 
      
 107 
     | 
    
         
            +
                            rescue Errno::ECONNREFUSED => e
         
     | 
| 
      
 108 
     | 
    
         
            +
                                tries -= 1
         
     | 
| 
      
 109 
     | 
    
         
            +
                                if tries > 0
         
     | 
| 
      
 110 
     | 
    
         
            +
                                    puts "Waiting for production server..."
         
     | 
| 
      
 111 
     | 
    
         
            +
                                    sleep 2
         
     | 
| 
      
 112 
     | 
    
         
            +
                                    retry
         
     | 
| 
      
 113 
     | 
    
         
            +
                                else
         
     | 
| 
      
 114 
     | 
    
         
            +
                                    raise RunnerException.new("Could not reach the production server at '#{uri}'.")
         
     | 
| 
      
 115 
     | 
    
         
            +
                                end
         
     | 
| 
      
 116 
     | 
    
         
            +
                            rescue StandardError => e
         
     | 
| 
      
 117 
     | 
    
         
            +
                                raise RunnerException.new("An unexpected error occured while trying to reach the production server at '#{uri}': #{e.inspect}")
         
     | 
| 
      
 118 
     | 
    
         
            +
                            end
         
     | 
| 
      
 119 
     | 
    
         
            +
                        end
         
     | 
| 
      
 120 
     | 
    
         
            +
                end
         
     | 
| 
      
 121 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,63 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "RMagick"
         
     | 
| 
      
 2 
     | 
    
         
            +
            require "workers"
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module Kontrast
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                class ImageHelper
         
     | 
| 
      
 7 
     | 
    
         
            +
                    def initialize(img1_path, img2_path)
         
     | 
| 
      
 8 
     | 
    
         
            +
                        @img1_path, @img2_path = img1_path, img2_path
         
     | 
| 
      
 9 
     | 
    
         
            +
                        @img1 = load_image(@img1_path)
         
     | 
| 
      
 10 
     | 
    
         
            +
                        @img2 = load_image(@img2_path)
         
     | 
| 
      
 11 
     | 
    
         
            +
                        @path = Kontrast.path
         
     | 
| 
      
 12 
     | 
    
         
            +
                    end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                    def reload_images
         
     | 
| 
      
 15 
     | 
    
         
            +
                        @img1 = load_image(@img1_path)
         
     | 
| 
      
 16 
     | 
    
         
            +
                        @img2 = load_image(@img2_path)
         
     | 
| 
      
 17 
     | 
    
         
            +
                    end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                    def load_image(path)
         
     | 
| 
      
 20 
     | 
    
         
            +
                        return Magick::Image.read(path).first
         
     | 
| 
      
 21 
     | 
    
         
            +
                    end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                    def crop(width)
         
     | 
| 
      
 24 
     | 
    
         
            +
                        # Let's not do anything if the images are already the same size
         
     | 
| 
      
 25 
     | 
    
         
            +
                        return if @img1.rows == @img2.rows
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                        # Get max height of both images
         
     | 
| 
      
 28 
     | 
    
         
            +
                        max_height = [@img1.rows, @img2.rows].max
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                        # Crop
         
     | 
| 
      
 31 
     | 
    
         
            +
                        Workers.map([@img1, @img2]) do |image|
         
     | 
| 
      
 32 
     | 
    
         
            +
                            image.extent(width, max_height).write(image.filename)
         
     | 
| 
      
 33 
     | 
    
         
            +
                        end
         
     | 
| 
      
 34 
     | 
    
         
            +
                        reload_images
         
     | 
| 
      
 35 
     | 
    
         
            +
                    end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                    # Uses the compare_channel function to highlight the differences between
         
     | 
| 
      
 38 
     | 
    
         
            +
                    # two images Docs:
         
     | 
| 
      
 39 
     | 
    
         
            +
                    # http://www.rubydoc.info/github/gemhome/rmagick/Magick%2FImage%3Acompare_channel
         
     | 
| 
      
 40 
     | 
    
         
            +
                    def compare(output_dir, output_file_name)
         
     | 
| 
      
 41 
     | 
    
         
            +
                        begin
         
     | 
| 
      
 42 
     | 
    
         
            +
                            distortion_metric = Magick.const_get(Kontrast.configuration.distortion_metric)
         
     | 
| 
      
 43 
     | 
    
         
            +
                            diff = @img1.compare_channel(@img2, distortion_metric) do |options|
         
     | 
| 
      
 44 
     | 
    
         
            +
                                options.highlight_color = Kontrast.configuration.highlight_color
         
     | 
| 
      
 45 
     | 
    
         
            +
                                options.lowlight_color = Kontrast.configuration.lowlight_color
         
     | 
| 
      
 46 
     | 
    
         
            +
                            end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                            output_path = "#{Kontrast.path}/#{output_dir}"
         
     | 
| 
      
 49 
     | 
    
         
            +
                            FileUtils.mkdir_p(output_path) # Just in case
         
     | 
| 
      
 50 
     | 
    
         
            +
                            diff.first.write(File.join(output_path, output_file_name))
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                            # diff is an array, the last (second) value is the diff value,
         
     | 
| 
      
 53 
     | 
    
         
            +
                            # a float between 0 and 1, 0 being the same image, 1 being an
         
     | 
| 
      
 54 
     | 
    
         
            +
                            # entirely different image
         
     | 
| 
      
 55 
     | 
    
         
            +
                            return diff.last
         
     | 
| 
      
 56 
     | 
    
         
            +
                        rescue Magick::ImageMagickError => e
         
     | 
| 
      
 57 
     | 
    
         
            +
                            puts "Error comparing images: #{e.message}"
         
     | 
| 
      
 58 
     | 
    
         
            +
                            # 1 means that both images are different
         
     | 
| 
      
 59 
     | 
    
         
            +
                            return 1
         
     | 
| 
      
 60 
     | 
    
         
            +
                        end
         
     | 
| 
      
 61 
     | 
    
         
            +
                    end
         
     | 
| 
      
 62 
     | 
    
         
            +
                end
         
     | 
| 
      
 63 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,18 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Kontrast
         
     | 
| 
      
 2 
     | 
    
         
            +
                module ImageUploader
         
     | 
| 
      
 3 
     | 
    
         
            +
                    def upload_images(test)
         
     | 
| 
      
 4 
     | 
    
         
            +
                        worker_pool = Workers::Pool.new
         
     | 
| 
      
 5 
     | 
    
         
            +
                        worker_pool.resize(Kontrast.configuration.workers_pool_size)
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                        Workers.map(Dir.entries("#{Kontrast.path}/#{test}"), pool: worker_pool) do |file|
         
     | 
| 
      
 8 
     | 
    
         
            +
                            next if ['.', '..'].include?(file)
         
     | 
| 
      
 9 
     | 
    
         
            +
                            Kontrast.fog.directories.get(Kontrast.configuration.aws_bucket).files.create(
         
     | 
| 
      
 10 
     | 
    
         
            +
                                key: "#{Kontrast.configuration.remote_path}/#{test}/#{file}",
         
     | 
| 
      
 11 
     | 
    
         
            +
                                body: File.open("#{Kontrast.path}/#{test}/#{file}"),
         
     | 
| 
      
 12 
     | 
    
         
            +
                                public: true
         
     | 
| 
      
 13 
     | 
    
         
            +
                            )
         
     | 
| 
      
 14 
     | 
    
         
            +
                        end
         
     | 
| 
      
 15 
     | 
    
         
            +
                    end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,46 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
             
     | 
| 
      
 2 
     | 
    
         
            +
            module Kontrast
         
     | 
| 
      
 3 
     | 
    
         
            +
                class PageComparator
         
     | 
| 
      
 4 
     | 
    
         
            +
                    include Magick
         
     | 
| 
      
 5 
     | 
    
         
            +
                    attr_reader :diffs, :path
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                    def initialize
         
     | 
| 
      
 8 
     | 
    
         
            +
                        @path = Kontrast.path
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                        # This is where failed diffs will be stored
         
     | 
| 
      
 11 
     | 
    
         
            +
                        @diffs = {}
         
     | 
| 
      
 12 
     | 
    
         
            +
                    end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                    def test_image_path(test)
         
     | 
| 
      
 15 
     | 
    
         
            +
                        return "#{@path}/#{test}/test.png"
         
     | 
| 
      
 16 
     | 
    
         
            +
                    end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                    def production_image_path(test)
         
     | 
| 
      
 19 
     | 
    
         
            +
                        return "#{@path}/#{test}/production.png"
         
     | 
| 
      
 20 
     | 
    
         
            +
                    end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                    def diff(test)
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                        image_helper = Kontrast::ImageHelper.new(
         
     | 
| 
      
 25 
     | 
    
         
            +
                            test_image_path(test),
         
     | 
| 
      
 26 
     | 
    
         
            +
                            production_image_path(test),
         
     | 
| 
      
 27 
     | 
    
         
            +
                        )
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                        # In order for images to be diff'ed, they need to have the same dimensions
         
     | 
| 
      
 30 
     | 
    
         
            +
                        print "Cropping... "
         
     | 
| 
      
 31 
     | 
    
         
            +
                        image_helper.crop(test.width)
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                        diff = image_helper.compare(test.to_s, "diff.png")
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                        # If the images are different, let the class know about it so that it gets added to the manifest
         
     | 
| 
      
 36 
     | 
    
         
            +
                        if diff > 0
         
     | 
| 
      
 37 
     | 
    
         
            +
                            @diffs["#{test}"] = {
         
     | 
| 
      
 38 
     | 
    
         
            +
                                type: 'page',
         
     | 
| 
      
 39 
     | 
    
         
            +
                                width: test.width,
         
     | 
| 
      
 40 
     | 
    
         
            +
                                name: test.name,
         
     | 
| 
      
 41 
     | 
    
         
            +
                                diff: diff,
         
     | 
| 
      
 42 
     | 
    
         
            +
                            }
         
     | 
| 
      
 43 
     | 
    
         
            +
                        end
         
     | 
| 
      
 44 
     | 
    
         
            +
                    end
         
     | 
| 
      
 45 
     | 
    
         
            +
                end
         
     | 
| 
      
 46 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,95 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Kontrast
         
     | 
| 
      
 2 
     | 
    
         
            +
                class PageRunner
         
     | 
| 
      
 3 
     | 
    
         
            +
                    include ImageUploader
         
     | 
| 
      
 4 
     | 
    
         
            +
                    include ThumbnailCreator
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                    attr_reader :diffs
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                    def initialize
         
     | 
| 
      
 9 
     | 
    
         
            +
                        @diffs = {}
         
     | 
| 
      
 10 
     | 
    
         
            +
                        @selenium_handler = nil
         
     | 
| 
      
 11 
     | 
    
         
            +
                        @page_comparator = nil
         
     | 
| 
      
 12 
     | 
    
         
            +
                    end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                    def run(total_nodes, current_node)
         
     | 
| 
      
 15 
     | 
    
         
            +
                        # Nothing to run
         
     | 
| 
      
 16 
     | 
    
         
            +
                        return if Kontrast.page_test_suite.nil?
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                        # Load & bind specs
         
     | 
| 
      
 19 
     | 
    
         
            +
                        Kontrast.page_test_suite.bind_specs
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                        # Assign tests and run them
         
     | 
| 
      
 22 
     | 
    
         
            +
                        suite = split_run(total_nodes, current_node)
         
     | 
| 
      
 23 
     | 
    
         
            +
                        parallel_run(suite, current_node)
         
     | 
| 
      
 24 
     | 
    
         
            +
                    end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                    # Given the total number of nodes and the index of the current node,
         
     | 
| 
      
 27 
     | 
    
         
            +
                    # we determine which tests the current node will run
         
     | 
| 
      
 28 
     | 
    
         
            +
                    def split_run(total_nodes, current_node)
         
     | 
| 
      
 29 
     | 
    
         
            +
                        test_suite = Kontrast.page_test_suite
         
     | 
| 
      
 30 
     | 
    
         
            +
                        tests_to_run = []
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                        index = 0
         
     | 
| 
      
 33 
     | 
    
         
            +
                        test_suite.tests.each do |test|
         
     | 
| 
      
 34 
     | 
    
         
            +
                            if index % total_nodes == current_node
         
     | 
| 
      
 35 
     | 
    
         
            +
                                tests_to_run << test
         
     | 
| 
      
 36 
     | 
    
         
            +
                            end
         
     | 
| 
      
 37 
     | 
    
         
            +
                            index += 1
         
     | 
| 
      
 38 
     | 
    
         
            +
                        end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                        return tests_to_run
         
     | 
| 
      
 41 
     | 
    
         
            +
                    end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                    # Runs tests, handles all image operations, creates manifest for current node
         
     | 
| 
      
 44 
     | 
    
         
            +
                    def parallel_run(suite, current_node)
         
     | 
| 
      
 45 
     | 
    
         
            +
                        # Load test handlers
         
     | 
| 
      
 46 
     | 
    
         
            +
                        @selenium_handler = SeleniumHandler.new
         
     | 
| 
      
 47 
     | 
    
         
            +
                        @page_comparator = PageComparator.new
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                        # Run per-page tasks
         
     | 
| 
      
 50 
     | 
    
         
            +
                        suite.each do |test|
         
     | 
| 
      
 51 
     | 
    
         
            +
                            begin
         
     | 
| 
      
 52 
     | 
    
         
            +
                                print "Processing #{test.name} @ #{test.width}... "
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                                # Run the browser and take screenshots
         
     | 
| 
      
 55 
     | 
    
         
            +
                                @selenium_handler.run_comparison(test)
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                                # Compare images
         
     | 
| 
      
 58 
     | 
    
         
            +
                                print "Diffing... "
         
     | 
| 
      
 59 
     | 
    
         
            +
                                @page_comparator.diff(test)
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                                # Create thumbnails for gallery
         
     | 
| 
      
 62 
     | 
    
         
            +
                                print "Creating thumbnails... "
         
     | 
| 
      
 63 
     | 
    
         
            +
                                create_thumbnails(test, ['test.png', 'production.png', 'diff.png'])
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                                # Upload to S3
         
     | 
| 
      
 66 
     | 
    
         
            +
                                if Kontrast.configuration.run_parallel
         
     | 
| 
      
 67 
     | 
    
         
            +
                                    print "Uploading... "
         
     | 
| 
      
 68 
     | 
    
         
            +
                                    upload_images(test)
         
     | 
| 
      
 69 
     | 
    
         
            +
                                end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                                puts "\n", ("=" * 85)
         
     | 
| 
      
 72 
     | 
    
         
            +
                            rescue Net::ReadTimeout => e
         
     | 
| 
      
 73 
     | 
    
         
            +
                                puts "Test timed out. Message: #{e.inspect}"
         
     | 
| 
      
 74 
     | 
    
         
            +
                                if Kontrast.configuration.fail_build
         
     | 
| 
      
 75 
     | 
    
         
            +
                                    raise e
         
     | 
| 
      
 76 
     | 
    
         
            +
                                end
         
     | 
| 
      
 77 
     | 
    
         
            +
                            rescue StandardError => e
         
     | 
| 
      
 78 
     | 
    
         
            +
                                puts "Exception: #{e.inspect}"
         
     | 
| 
      
 79 
     | 
    
         
            +
                                puts e.backtrace.inspect
         
     | 
| 
      
 80 
     | 
    
         
            +
                                if Kontrast.configuration.fail_build
         
     | 
| 
      
 81 
     | 
    
         
            +
                                    raise e
         
     | 
| 
      
 82 
     | 
    
         
            +
                                end
         
     | 
| 
      
 83 
     | 
    
         
            +
                            end
         
     | 
| 
      
 84 
     | 
    
         
            +
                        end
         
     | 
| 
      
 85 
     | 
    
         
            +
                    ensure
         
     | 
| 
      
 86 
     | 
    
         
            +
                        # Log diffs
         
     | 
| 
      
 87 
     | 
    
         
            +
                        puts @page_comparator.diffs
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                        # We need the diff at the runner level to create the manifest
         
     | 
| 
      
 90 
     | 
    
         
            +
                        @diffs = @page_comparator.diffs
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                        @selenium_handler.cleanup
         
     | 
| 
      
 93 
     | 
    
         
            +
                    end
         
     | 
| 
      
 94 
     | 
    
         
            +
                end
         
     | 
| 
      
 95 
     | 
    
         
            +
            end
         
     |