percy-capybara 2.4.0 → 2.4.1
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/.rubocop.yml +42 -0
- data/.rubocop_todo.yml +98 -0
- data/.travis.yml +4 -1
- data/Gemfile +6 -1
- data/Rakefile +0 -1
- data/lib/percy/capybara.rb +2 -2
- data/lib/percy/capybara/client.rb +20 -22
- data/lib/percy/capybara/client/builds.rb +13 -13
- data/lib/percy/capybara/client/snapshots.rb +9 -10
- data/lib/percy/capybara/httpfetcher.rb +7 -7
- data/lib/percy/capybara/loaders/base_loader.rb +17 -16
- data/lib/percy/capybara/loaders/filesystem_loader.rb +10 -11
- data/lib/percy/capybara/loaders/native_loader.rb +14 -13
- data/lib/percy/capybara/loaders/sprockets_loader.rb +6 -6
- data/lib/percy/capybara/version.rb +1 -1
- data/percy-capybara.gemspec +1 -1
- data/spec/lib/percy/capybara/client/builds_spec.rb +10 -8
- data/spec/lib/percy/capybara/client/snapshots_spec.rb +12 -10
- data/spec/lib/percy/capybara/client_spec.rb +5 -4
- data/spec/lib/percy/capybara/{httpfetcher_spec.rb → http_fetcher_spec.rb} +2 -2
- data/spec/lib/percy/capybara/loaders/base_loader_spec.rb +3 -5
- data/spec/lib/percy/capybara/loaders/filesystem_loader_spec.rb +9 -5
- data/spec/lib/percy/capybara/loaders/native_loader_spec.rb +41 -41
- data/spec/lib/percy/capybara/loaders/sprockets_loader_spec.rb +14 -13
- data/spec/lib/percy/capybara_spec.rb +8 -8
- data/spec/spec_helper.rb +1 -1
- data/spec/support/test_helpers.rb +3 -3
- metadata +12 -4
| @@ -6,26 +6,25 @@ require 'pathname' | |
| 6 6 | 
             
            module Percy
         | 
| 7 7 | 
             
              module Capybara
         | 
| 8 8 | 
             
                module Loaders
         | 
| 9 | 
            -
             | 
| 10 9 | 
             
                  # Resource loader that looks for resources in the specified folder.
         | 
| 11 10 | 
             
                  class FilesystemLoader < BaseLoader
         | 
| 12 11 | 
             
                    SKIP_RESOURCE_EXTENSIONS = [
         | 
| 13 | 
            -
                      '.map', | 
| 14 | 
            -
                      '.gz', | 
| 15 | 
            -
                    ]
         | 
| 16 | 
            -
                    MAX_FILESIZE_BYTES = 15 * 1024**2 | 
| 12 | 
            +
                      '.map', # Ignore source maps.
         | 
| 13 | 
            +
                      '.gz', # Ignore gzipped files.
         | 
| 14 | 
            +
                    ].freeze
         | 
| 15 | 
            +
                    MAX_FILESIZE_BYTES = 15 * 1024**2 # 15 MB.
         | 
| 17 16 |  | 
| 18 17 | 
             
                    def initialize(options = {})
         | 
| 19 18 | 
             
                      # @assets_dir should point to a _compiled_ static assets directory, not source assets.
         | 
| 20 19 | 
             
                      @assets_dir = options[:assets_dir]
         | 
| 21 20 | 
             
                      @base_url = options[:base_url] || ''
         | 
| 22 21 |  | 
| 23 | 
            -
                      raise ArgumentError | 
| 24 | 
            -
                       | 
| 25 | 
            -
                        raise ArgumentError | 
| 22 | 
            +
                      raise ArgumentError, 'assets_dir is required' if @assets_dir.nil? || @assets_dir == ''
         | 
| 23 | 
            +
                      unless Pathname.new(@assets_dir).absolute?
         | 
| 24 | 
            +
                        raise ArgumentError, "assets_dir needs to be an absolute path. Received: #{@assets_dir}"
         | 
| 26 25 | 
             
                      end
         | 
| 27 | 
            -
                       | 
| 28 | 
            -
                        raise ArgumentError | 
| 26 | 
            +
                      unless Dir.exist?(@assets_dir)
         | 
| 27 | 
            +
                        raise ArgumentError, "assets_dir provided was not found. Received: #{@assets_dir}"
         | 
| 29 28 | 
             
                      end
         | 
| 30 29 |  | 
| 31 30 | 
             
                      super
         | 
| @@ -39,7 +38,7 @@ module Percy | |
| 39 38 | 
             
                      resources = []
         | 
| 40 39 | 
             
                      Find.find(@assets_dir).each do |path|
         | 
| 41 40 | 
             
                        # Skip directories.
         | 
| 42 | 
            -
                        next  | 
| 41 | 
            +
                        next unless FileTest.file?(path)
         | 
| 43 42 | 
             
                        # Skip certain extensions.
         | 
| 44 43 | 
             
                        next if SKIP_RESOURCE_EXTENSIONS.include?(File.extname(path))
         | 
| 45 44 | 
             
                        # Skip large files, these are hopefully downloads and not used in page rendering.
         | 
| @@ -5,7 +5,6 @@ require 'uri' | |
| 5 5 | 
             
            module Percy
         | 
| 6 6 | 
             
              module Capybara
         | 
| 7 7 | 
             
                module Loaders
         | 
| 8 | 
            -
             | 
| 9 8 | 
             
                  # Resource loader that uses the native Capybara browser interface to discover resources.
         | 
| 10 9 | 
             
                  # This loader uses JavaScript to discover page resources, so specs must be tagged with
         | 
| 11 10 | 
             
                  # "js: true" because the default Rack::Test driver does not support executing JavaScript.
         | 
| @@ -73,12 +72,13 @@ module Percy | |
| 73 72 | 
             
                      resource_urls = _evaluate_script(page, script)
         | 
| 74 73 |  | 
| 75 74 | 
             
                      resource_urls.each do |url|
         | 
| 76 | 
            -
                        next  | 
| 75 | 
            +
                        next unless _should_include_url?(url)
         | 
| 77 76 | 
             
                        response = _fetch_resource_url(url)
         | 
| 78 77 | 
             
                        _absolute_url_to_relative!(url, _current_host_port)
         | 
| 79 | 
            -
                        next  | 
| 78 | 
            +
                        next unless response
         | 
| 80 79 | 
             
                        resources << Percy::Client::Resource.new(
         | 
| 81 | 
            -
                          url, mimetype: 'text/css', content: response.body | 
| 80 | 
            +
                          url, mimetype: 'text/css', content: response.body
         | 
| 81 | 
            +
                        )
         | 
| 82 82 | 
             
                      end
         | 
| 83 83 | 
             
                      resources
         | 
| 84 84 | 
             
                    end
         | 
| @@ -92,7 +92,7 @@ module Percy | |
| 92 92 | 
             
                      # Find all image tags on the page.
         | 
| 93 93 | 
             
                      page.all('img').each do |image_element|
         | 
| 94 94 | 
             
                        srcs = []
         | 
| 95 | 
            -
                        srcs << image_element[:src]  | 
| 95 | 
            +
                        srcs << image_element[:src] unless image_element[:src].nil?
         | 
| 96 96 |  | 
| 97 97 | 
             
                        srcset_raw_urls = image_element[:srcset] || ''
         | 
| 98 98 | 
             
                        temp_urls = srcset_raw_urls.split(',')
         | 
| @@ -152,7 +152,7 @@ module Percy | |
| 152 152 | 
             
                        # Skip duplicates.
         | 
| 153 153 | 
             
                        next if resources.find { |r| r.resource_url == resource_url }
         | 
| 154 154 |  | 
| 155 | 
            -
                        next  | 
| 155 | 
            +
                        next unless _should_include_url?(resource_url)
         | 
| 156 156 |  | 
| 157 157 | 
             
                        # Fetch the images.
         | 
| 158 158 | 
             
                        # TODO(fotinakis): this can be pretty inefficient for image-heavy pages because the
         | 
| @@ -161,10 +161,11 @@ module Percy | |
| 161 161 | 
             
                        # development server, so it may not be so bad. Re-evaluate if this becomes an issue.
         | 
| 162 162 | 
             
                        response = _fetch_resource_url(resource_url)
         | 
| 163 163 | 
             
                        _absolute_url_to_relative!(resource_url, _current_host_port)
         | 
| 164 | 
            -
                        next  | 
| 164 | 
            +
                        next unless response
         | 
| 165 165 |  | 
| 166 166 | 
             
                        resources << Percy::Client::Resource.new(
         | 
| 167 | 
            -
                          resource_url, mimetype: response.content_type, content: response.body | 
| 167 | 
            +
                          resource_url, mimetype: response.content_type, content: response.body
         | 
| 168 | 
            +
                        )
         | 
| 168 169 | 
             
                      end
         | 
| 169 170 | 
             
                      resources
         | 
| 170 171 | 
             
                    end
         | 
| @@ -173,8 +174,9 @@ module Percy | |
| 173 174 | 
             
                    # @private
         | 
| 174 175 | 
             
                    def _fetch_resource_url(url)
         | 
| 175 176 | 
             
                      response = Percy::Capybara::HttpFetcher.fetch(url)
         | 
| 176 | 
            -
                       | 
| 177 | 
            -
                        STDERR.puts  | 
| 177 | 
            +
                      unless response
         | 
| 178 | 
            +
                        STDERR.puts '[percy] Warning: failed to fetch page resource, ' \
         | 
| 179 | 
            +
                          "this might be a bug: #{url}"
         | 
| 178 180 | 
             
                        return nil
         | 
| 179 181 | 
             
                      end
         | 
| 180 182 | 
             
                      response
         | 
| @@ -216,15 +218,14 @@ module Percy | |
| 216 218 |  | 
| 217 219 | 
             
                    # @private
         | 
| 218 220 | 
             
                    def _same_server?(url, host_port)
         | 
| 219 | 
            -
                      url.start_with?(host_port +  | 
| 221 | 
            +
                      url.start_with?(host_port + '/') || url == host_port
         | 
| 220 222 | 
             
                    end
         | 
| 221 223 |  | 
| 222 224 | 
             
                    # @private
         | 
| 223 225 | 
             
                    def _absolute_url_to_relative!(url, host_port)
         | 
| 224 | 
            -
                      url.gsub!(host_port + '/','/') if url.start_with?(host_port +  | 
| 226 | 
            +
                      url.gsub!(host_port + '/', '/') if url.start_with?(host_port + '/')
         | 
| 225 227 | 
             
                    end
         | 
| 226 228 | 
             
                    private :_absolute_url_to_relative!
         | 
| 227 | 
            -
             | 
| 228 229 | 
             
                  end
         | 
| 229 230 | 
             
                end
         | 
| 230 231 | 
             
              end
         | 
| @@ -14,10 +14,10 @@ module Percy | |
| 14 14 | 
             
                    attr_reader :sprockets_options
         | 
| 15 15 |  | 
| 16 16 | 
             
                    SKIP_RESOURCE_EXTENSIONS = [
         | 
| 17 | 
            -
                      '.map', | 
| 18 | 
            -
                      '.gz', | 
| 19 | 
            -
                    ]
         | 
| 20 | 
            -
                    MAX_FILESIZE_BYTES = 15 * 1024**2 | 
| 17 | 
            +
                      '.map', # Ignore source maps.
         | 
| 18 | 
            +
                      '.gz', # Ignore gzipped files.
         | 
| 19 | 
            +
                    ].freeze
         | 
| 20 | 
            +
                    MAX_FILESIZE_BYTES = 15 * 1024**2 # 15 MB.
         | 
| 21 21 |  | 
| 22 22 | 
             
                    def initialize(options = {})
         | 
| 23 23 | 
             
                      @sprockets_environment = options[:sprockets_environment]
         | 
| @@ -47,7 +47,7 @@ module Percy | |
| 47 47 |  | 
| 48 48 | 
             
                        if defined?(ActionController)
         | 
| 49 49 | 
             
                          # Ask Rails where this asset is (this handles asset_hosts, digest paths, etc.).
         | 
| 50 | 
            -
                          resource_url = ActionController::Base.helpers. | 
| 50 | 
            +
                          resource_url = ActionController::Base.helpers.asset_path(logical_path)
         | 
| 51 51 | 
             
                        else
         | 
| 52 52 | 
             
                          # TODO: more robust support for Sprockets usage outside Rails, ie Sinatra.
         | 
| 53 53 | 
             
                          # How do we find the correct path in that case?
         | 
| @@ -66,7 +66,7 @@ module Percy | |
| 66 66 | 
             
                        public_path = _rails.public_path.to_s
         | 
| 67 67 | 
             
                        Find.find(public_path).each do |path|
         | 
| 68 68 | 
             
                          # Skip directories.
         | 
| 69 | 
            -
                          next  | 
| 69 | 
            +
                          next unless FileTest.file?(path)
         | 
| 70 70 | 
             
                          # Skip certain extensions.
         | 
| 71 71 | 
             
                          next if SKIP_RESOURCE_EXTENSIONS.include?(File.extname(path))
         | 
| 72 72 | 
             
                          # Skip large files, these are hopefully downloads and not used in page rendering.
         | 
    
        data/percy-capybara.gemspec
    CHANGED
    
    | @@ -24,7 +24,7 @@ Gem::Specification.new do |spec| | |
| 24 24 | 
             
              spec.add_development_dependency 'rake', '~> 10.0'
         | 
| 25 25 | 
             
              spec.add_development_dependency 'rspec', '~> 3.2'
         | 
| 26 26 | 
             
              spec.add_development_dependency 'capybara', '~> 2.4'
         | 
| 27 | 
            -
              spec.add_development_dependency 'capybara-webkit', '>= 1.6'
         | 
| 27 | 
            +
              spec.add_development_dependency 'capybara-webkit', '>= 1.6', '< 1.12.0' # 1.12.0 breaks specs
         | 
| 28 28 | 
             
              spec.add_development_dependency 'selenium-webdriver'
         | 
| 29 29 | 
             
              spec.add_development_dependency 'webmock', '~> 1'
         | 
| 30 30 | 
             
              spec.add_development_dependency 'mime-types', '< 3'  # For Ruby 1.9 testing support.
         | 
| @@ -1,10 +1,12 @@ | |
| 1 1 | 
             
            RSpec.describe Percy::Capybara::Client::Builds do
         | 
| 2 2 | 
             
              let(:enabled) { true }
         | 
| 3 3 | 
             
              let(:capybara_client) { Percy::Capybara::Client.new(enabled: enabled) }
         | 
| 4 | 
            -
              let(:builds_api_url)  | 
| 4 | 
            +
              let(:builds_api_url) do
         | 
| 5 | 
            +
                "https://percy.io/api/v1/repos/#{Percy::Client::Environment.repo}/builds/"
         | 
| 6 | 
            +
              end
         | 
| 5 7 |  | 
| 6 8 | 
             
              describe '#initialize_build', type: :feature, js: true do
         | 
| 7 | 
            -
                before | 
| 9 | 
            +
                before { setup_sprockets(capybara_client) }
         | 
| 8 10 |  | 
| 9 11 | 
             
                context 'percy is not enabled' do
         | 
| 10 12 | 
             
                  let(:enabled) { false }
         | 
| @@ -31,7 +33,7 @@ RSpec.describe Percy::Capybara::Client::Builds do | |
| 31 33 | 
             
                      'id' => '123',
         | 
| 32 34 | 
             
                      'type' => 'builds',
         | 
| 33 35 | 
             
                      'relationships' => {
         | 
| 34 | 
            -
                        'self' =>  | 
| 36 | 
            +
                        'self' => '/api/v1/snapshots/123',
         | 
| 35 37 | 
             
                        'missing-resources' => {
         | 
| 36 38 | 
             
                          'data' => [
         | 
| 37 39 | 
             
                            {
         | 
| @@ -48,7 +50,7 @@ RSpec.describe Percy::Capybara::Client::Builds do | |
| 48 50 | 
             
                    .to_return(status: 201, body: mock_response.to_json)
         | 
| 49 51 |  | 
| 50 52 | 
             
                  # Stub resource upload.
         | 
| 51 | 
            -
                  resources_stub = stub_request(:post,  | 
| 53 | 
            +
                  resources_stub = stub_request(:post, 'https://percy.io/api/v1/builds/123/resources/')
         | 
| 52 54 | 
             
                    .to_return(status: 201, body: {success: true}.to_json)
         | 
| 53 55 | 
             
                  capybara_client.initialize_build
         | 
| 54 56 |  | 
| @@ -69,7 +71,7 @@ RSpec.describe Percy::Capybara::Client::Builds do | |
| 69 71 | 
             
                      'id' => '123',
         | 
| 70 72 | 
             
                      'type' => 'builds',
         | 
| 71 73 | 
             
                      'relationships' => {
         | 
| 72 | 
            -
                        'self' =>  | 
| 74 | 
            +
                        'self' => '/api/v1/snapshots/123',
         | 
| 73 75 | 
             
                        'missing-resources' => {
         | 
| 74 76 | 
             
                          'data' => [
         | 
| 75 77 | 
             
                            {
         | 
| @@ -147,7 +149,7 @@ RSpec.describe Percy::Capybara::Client::Builds do | |
| 147 149 | 
             
                end
         | 
| 148 150 | 
             
              end
         | 
| 149 151 | 
             
              describe '#_upload_missing_build_resources', type: :feature, js: true do
         | 
| 150 | 
            -
                before | 
| 152 | 
            +
                before { setup_sprockets(capybara_client) }
         | 
| 151 153 |  | 
| 152 154 | 
             
                it 'returns 0 if there are no missing build resources to upload' do
         | 
| 153 155 | 
             
                  mock_response = {
         | 
| @@ -161,8 +163,8 @@ RSpec.describe Percy::Capybara::Client::Builds do | |
| 161 163 | 
             
                  capybara_client.initialize_build
         | 
| 162 164 |  | 
| 163 165 | 
             
                  loader = capybara_client.initialize_loader
         | 
| 164 | 
            -
                   | 
| 166 | 
            +
                  result = capybara_client.send(:_upload_missing_build_resources, loader.build_resources)
         | 
| 167 | 
            +
                  expect(result).to eq(0)
         | 
| 165 168 | 
             
                end
         | 
| 166 169 | 
             
              end
         | 
| 167 | 
            -
             | 
| 168 170 | 
             
            end
         | 
| @@ -8,7 +8,6 @@ RSpec.describe Percy::Capybara::Client::Snapshots, type: :feature do | |
| 8 8 |  | 
| 9 9 | 
             
              describe '#snapshot', type: :feature, js: true do
         | 
| 10 10 | 
             
                context 'simple page with no resources' do
         | 
| 11 | 
            -
                  before(:each) { setup_sprockets(capybara_client) }
         | 
| 12 11 | 
             
                  let(:loader) { capybara_client.initialize_loader(page: page) }
         | 
| 13 12 | 
             
                  let(:build_resource_sha) { loader.build_resources.first.sha }
         | 
| 14 13 | 
             
                  let(:snapshot_resource_sha) { loader.snapshot_resources.first.sha }
         | 
| @@ -18,7 +17,7 @@ RSpec.describe Percy::Capybara::Client::Snapshots, type: :feature do | |
| 18 17 | 
             
                        'id' => '123',
         | 
| 19 18 | 
             
                        'type' => 'builds',
         | 
| 20 19 | 
             
                        'relationships' => {
         | 
| 21 | 
            -
                          'self' =>  | 
| 20 | 
            +
                          'self' => '/api/v1/snapshots/123',
         | 
| 22 21 | 
             
                          'missing-resources' => {},
         | 
| 23 22 | 
             
                        },
         | 
| 24 23 | 
             
                      },
         | 
| @@ -30,7 +29,7 @@ RSpec.describe Percy::Capybara::Client::Snapshots, type: :feature do | |
| 30 29 | 
             
                        'id' => '256',
         | 
| 31 30 | 
             
                        'type' => 'snapshots',
         | 
| 32 31 | 
             
                        'relationships' => {
         | 
| 33 | 
            -
                          'self' =>  | 
| 32 | 
            +
                          'self' => '/api/v1/snapshots/123',
         | 
| 34 33 | 
             
                          'missing-resources' => {
         | 
| 35 34 | 
             
                            'data' => [
         | 
| 36 35 | 
             
                              {
         | 
| @@ -43,18 +42,20 @@ RSpec.describe Percy::Capybara::Client::Snapshots, type: :feature do | |
| 43 42 | 
             
                      },
         | 
| 44 43 | 
             
                    }
         | 
| 45 44 | 
             
                  end
         | 
| 46 | 
            -
                  before  | 
| 45 | 
            +
                  before do
         | 
| 46 | 
            +
                    setup_sprockets(capybara_client)
         | 
| 47 | 
            +
             | 
| 47 48 | 
             
                    visit '/'
         | 
| 48 | 
            -
                    loader | 
| 49 | 
            +
                    loader # Force evaluation now.
         | 
| 49 50 | 
             
                    repo = Percy::Client::Environment.repo
         | 
| 50 51 | 
             
                    stub_request(:post, "https://percy.io/api/v1/repos/#{repo}/builds/")
         | 
| 51 52 | 
             
                      .to_return(status: 201, body: mock_build_response.to_json)
         | 
| 52 53 | 
             
                    stub_request(:post, 'https://percy.io/api/v1/builds/123/snapshots/')
         | 
| 53 54 | 
             
                      .to_return(status: 201, body: mock_snapshot_response.to_json)
         | 
| 54 | 
            -
                    stub_request(:post,  | 
| 55 | 
            +
                    stub_request(:post, 'https://percy.io/api/v1/builds/123/resources/')
         | 
| 55 56 | 
             
                      .with(body: /#{snapshot_resource_sha}/)
         | 
| 56 57 | 
             
                      .to_return(status: 201, body: {success: true}.to_json)
         | 
| 57 | 
            -
                    stub_request(:post,  | 
| 58 | 
            +
                    stub_request(:post, 'https://percy.io/api/v1/snapshots/256/finalize')
         | 
| 58 59 | 
             
                      .to_return(status: 200, body: {success: true}.to_json)
         | 
| 59 60 | 
             
                    capybara_client.initialize_build
         | 
| 60 61 | 
             
                  end
         | 
| @@ -71,11 +72,12 @@ RSpec.describe Percy::Capybara::Client::Snapshots, type: :feature do | |
| 71 72 | 
             
                  end
         | 
| 72 73 | 
             
                  it 'passes through options to the percy client if given' do
         | 
| 73 74 | 
             
                    expect(capybara_client.client).to receive(:create_snapshot)
         | 
| 74 | 
            -
                      .with(anything, anything,  | 
| 75 | 
            +
                      .with(anything, anything, name: 'foo', widths: [320, 1024], enable_javascript: true)
         | 
| 75 76 | 
             
                      .and_call_original
         | 
| 76 77 |  | 
| 77 78 | 
             
                    result = capybara_client.snapshot(
         | 
| 78 | 
            -
                      page, name: 'foo', widths: [320, 1024], enable_javascript: true | 
| 79 | 
            +
                      page, name: 'foo', widths: [320, 1024], enable_javascript: true
         | 
| 80 | 
            +
                    )
         | 
| 79 81 | 
             
                    expect(result).to eq(true)
         | 
| 80 82 | 
             
                    expect(capybara_client.failed?).to eq(false)
         | 
| 81 83 | 
             
                  end
         | 
| @@ -83,7 +85,7 @@ RSpec.describe Percy::Capybara::Client::Snapshots, type: :feature do | |
| 83 85 | 
             
                    error = Percy::Client::BadRequestError.new(400, '', '', '', 'snapshot error msg')
         | 
| 84 86 | 
             
                    expect(capybara_client.client).to receive(:create_snapshot).and_raise(error)
         | 
| 85 87 | 
             
                    expect(capybara_client.snapshot(page)).to eq(nil)
         | 
| 86 | 
            -
                    expect(capybara_client.failed?).to eq(false) | 
| 88 | 
            +
                    expect(capybara_client.failed?).to eq(false) # Build is not failed.
         | 
| 87 89 | 
             
                  end
         | 
| 88 90 | 
             
                  it 'safely handles connection errors' do
         | 
| 89 91 | 
             
                    expect(capybara_client.client).to receive(:create_snapshot)
         | 
| @@ -6,8 +6,8 @@ RSpec.describe Percy::Capybara::Client do | |
| 6 6 | 
             
              end
         | 
| 7 7 | 
             
              describe '#enabled?' do
         | 
| 8 8 | 
             
                context 'when required environment variables set' do
         | 
| 9 | 
            -
                  before | 
| 10 | 
            -
                  after | 
| 9 | 
            +
                  before { set_required_env_variables }
         | 
| 10 | 
            +
                  after { clear_percy_env_variables }
         | 
| 11 11 |  | 
| 12 12 | 
             
                  it 'is true when PERCY_ENABLE is 1' do
         | 
| 13 13 | 
             
                    ENV['PERCY_ENABLE'] = '1'
         | 
| @@ -28,7 +28,7 @@ RSpec.describe Percy::Capybara::Client do | |
| 28 28 | 
             
                end
         | 
| 29 29 |  | 
| 30 30 | 
             
                context 'when required environment variables not set' do
         | 
| 31 | 
            -
                  before | 
| 31 | 
            +
                  before { clear_percy_env_variables }
         | 
| 32 32 |  | 
| 33 33 | 
             
                  it 'is false' do
         | 
| 34 34 | 
             
                    ENV.delete 'PERCY_ENABLE'
         | 
| @@ -131,7 +131,8 @@ RSpec.describe Percy::Capybara::Client do | |
| 131 131 |  | 
| 132 132 | 
             
                context 'when no configuration has been set' do
         | 
| 133 133 | 
             
                  it 'returns a NativeLoader' do
         | 
| 134 | 
            -
                    expect(capybara_client.initialize_loader.class) | 
| 134 | 
            +
                    expect(capybara_client.initialize_loader.class)
         | 
| 135 | 
            +
                      .to eq(Percy::Capybara::Loaders::NativeLoader)
         | 
| 135 136 | 
             
                  end
         | 
| 136 137 | 
             
                end
         | 
| 137 138 |  | 
| @@ -4,7 +4,8 @@ RSpec.describe Percy::Capybara::HttpFetcher do | |
| 4 4 |  | 
| 5 5 | 
             
                # Slightly magical hash, just a SHA-256 sum of the image above.
         | 
| 6 6 | 
             
                expect(Digest::SHA256.hexdigest(response.body)).to eq(
         | 
| 7 | 
            -
                  '4beb51550bef8e9e30d37ea8c13658e99bb01722062f218185e419af5ad93e13' | 
| 7 | 
            +
                  '4beb51550bef8e9e30d37ea8c13658e99bb01722062f218185e419af5ad93e13'
         | 
| 8 | 
            +
                )
         | 
| 8 9 | 
             
                expect(response.content_type).to eq('image/png')
         | 
| 9 10 | 
             
              end
         | 
| 10 11 | 
             
              it 'returns nil if fetch failed' do
         | 
| @@ -14,4 +15,3 @@ RSpec.describe Percy::Capybara::HttpFetcher do | |
| 14 15 | 
             
                # expect(Percy::Capybara::HttpFetcher.fetch('bad-url')).to be_nil
         | 
| 15 16 | 
             
              end
         | 
| 16 17 | 
             
            end
         | 
| 17 | 
            -
             | 
| @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            IFRAME_PATH = File.expand_path('../../client/testdata/test-iframe.html', __FILE__)
         | 
| 2 2 |  | 
| 3 3 | 
             
            class RackAppWithIframe
         | 
| 4 | 
            -
              def self.call( | 
| 4 | 
            +
              def self.call(_env)
         | 
| 5 5 | 
             
                [200, {}, File.read(IFRAME_PATH)]
         | 
| 6 6 | 
             
              end
         | 
| 7 7 | 
             
            end
         | 
| @@ -75,8 +75,8 @@ RSpec.describe Percy::Capybara::Loaders::BaseLoader do | |
| 75 75 | 
             
              end
         | 
| 76 76 |  | 
| 77 77 | 
             
              context 'Rack::Test', type: :feature do
         | 
| 78 | 
            -
                before | 
| 79 | 
            -
                after | 
| 78 | 
            +
                before { Capybara.app = RackAppWithIframe }
         | 
| 79 | 
            +
                after { Capybara.app = nil }
         | 
| 80 80 |  | 
| 81 81 | 
             
                describe '#iframes_resources' do
         | 
| 82 82 | 
             
                  it 'is silently ignored' do
         | 
| @@ -87,5 +87,3 @@ RSpec.describe Percy::Capybara::Loaders::BaseLoader do | |
| 87 87 | 
             
                end
         | 
| 88 88 | 
             
              end
         | 
| 89 89 | 
             
            end
         | 
| 90 | 
            -
             | 
| 91 | 
            -
             | 
| @@ -18,7 +18,7 @@ RSpec.describe Percy::Capybara::Loaders::FilesystemLoader do | |
| 18 18 | 
             
                  end
         | 
| 19 19 | 
             
                end
         | 
| 20 20 | 
             
                context 'assets_dir doesn\'t exist' do
         | 
| 21 | 
            -
                  let(:assets_dir) { File.expand_path( | 
| 21 | 
            +
                  let(:assets_dir) { File.expand_path('../../client/testdata-doesnt-exist', __FILE__) }
         | 
| 22 22 | 
             
                  it 'raises an error' do
         | 
| 23 23 | 
             
                    expect { loader }.to raise_error(ArgumentError)
         | 
| 24 24 | 
             
                  end
         | 
| @@ -42,9 +42,12 @@ RSpec.describe Percy::Capybara::Loaders::FilesystemLoader do | |
| 42 42 | 
             
              describe '#build_resources' do
         | 
| 43 43 | 
             
                context 'assets_dir including all test files' do
         | 
| 44 44 | 
             
                  it 'returns all included assets as resources' do
         | 
| 45 | 
            -
                    actual_paths = loader.build_resources.collect  | 
| 45 | 
            +
                    actual_paths = loader.build_resources.collect do |resource|
         | 
| 46 | 
            +
                      resource.path.gsub(assets_dir, '')
         | 
| 47 | 
            +
                    end
         | 
| 46 48 | 
             
                    expected_paths = [
         | 
| 47 | 
            -
                      '/assets/css/digested- | 
| 49 | 
            +
                      '/assets/css/digested-f3420c6aee71c137a3ca39727052811ba' \
         | 
| 50 | 
            +
                        'e84b2f37d898f4db242e20656a1579e.css',
         | 
| 48 51 | 
             
                      '/css/base.css',
         | 
| 49 52 | 
             
                      '/css/digested.css',
         | 
| 50 53 | 
             
                      '/css/imports.css',
         | 
| @@ -72,9 +75,10 @@ RSpec.describe Percy::Capybara::Loaders::FilesystemLoader do | |
| 72 75 | 
             
                    ]
         | 
| 73 76 | 
             
                    expect(actual_paths).to eq(expected_paths)
         | 
| 74 77 |  | 
| 75 | 
            -
                    expected_urls = loader.build_resources.collect | 
| 78 | 
            +
                    expected_urls = loader.build_resources.collect(&:resource_url)
         | 
| 76 79 | 
             
                    actual_urls = [
         | 
| 77 | 
            -
                      '/url-prefix/assets/css/digested- | 
| 80 | 
            +
                      '/url-prefix/assets/css/digested-f3420c6aee71c137a3ca' \
         | 
| 81 | 
            +
                        '39727052811bae84b2f37d898f4db242e20656a1579e.css',
         | 
| 78 82 | 
             
                      '/url-prefix/css/base.css',
         | 
| 79 83 | 
             
                      '/url-prefix/css/digested.css',
         | 
| 80 84 | 
             
                      '/url-prefix/css/imports.css',
         | 
| @@ -1,5 +1,5 @@ | |
| 1 1 | 
             
            RSpec.describe Percy::Capybara::Loaders::NativeLoader do
         | 
| 2 | 
            -
              let(:fake_page) { OpenStruct.new(current_url:  | 
| 2 | 
            +
              let(:fake_page) { OpenStruct.new(current_url: 'http://localhost/foo') }
         | 
| 3 3 | 
             
              let(:loader) { described_class.new(page: fake_page) }
         | 
| 4 4 |  | 
| 5 5 | 
             
              describe '#build_resources' do
         | 
| @@ -18,13 +18,13 @@ RSpec.describe Percy::Capybara::Loaders::NativeLoader do | |
| 18 18 | 
             
                  loader = described_class.new(page: page)
         | 
| 19 19 | 
             
                  resource_urls = loader.snapshot_resources.collect(&:resource_url)
         | 
| 20 20 | 
             
                  expect(resource_urls).to match_array([
         | 
| 21 | 
            -
                     | 
| 22 | 
            -
                     | 
| 23 | 
            -
                     | 
| 24 | 
            -
                     | 
| 25 | 
            -
                     | 
| 26 | 
            -
                     | 
| 27 | 
            -
                     | 
| 21 | 
            +
                    '/test-css.html',
         | 
| 22 | 
            +
                    '/css/base.css',
         | 
| 23 | 
            +
                    '/css/imports.css',
         | 
| 24 | 
            +
                    '/css/level0-imports.css',
         | 
| 25 | 
            +
                    '/css/level1-imports.css',
         | 
| 26 | 
            +
                    '/css/level2-imports.css',
         | 
| 27 | 
            +
                    '/css/simple-imports.css',
         | 
| 28 28 | 
             
                  ])
         | 
| 29 29 | 
             
                end
         | 
| 30 30 | 
             
                it 'returns the root HTML and image resources' do
         | 
| @@ -32,36 +32,36 @@ RSpec.describe Percy::Capybara::Loaders::NativeLoader do | |
| 32 32 | 
             
                  loader = described_class.new(page: page)
         | 
| 33 33 | 
             
                  resource_urls = loader.snapshot_resources.collect(&:resource_url)
         | 
| 34 34 | 
             
                  expect(resource_urls).to match_array([
         | 
| 35 | 
            -
                     | 
| 36 | 
            -
                     | 
| 37 | 
            -
                     | 
| 38 | 
            -
                     | 
| 39 | 
            -
                     | 
| 40 | 
            -
                     | 
| 41 | 
            -
                     | 
| 42 | 
            -
                     | 
| 43 | 
            -
                     | 
| 44 | 
            -
                     | 
| 35 | 
            +
                    '/test-images.html',
         | 
| 36 | 
            +
                    '/images/img-relative.png',
         | 
| 37 | 
            +
                    '/images/img-relative-to-root.png',
         | 
| 38 | 
            +
                    '/images/percy.svg',
         | 
| 39 | 
            +
                    '/images/srcset-base.png',
         | 
| 40 | 
            +
                    '/images/srcset-first.png',
         | 
| 41 | 
            +
                    '/images/srcset-second.png',
         | 
| 42 | 
            +
                    '/images/bg-relative.png',
         | 
| 43 | 
            +
                    '/images/bg-relative-to-root.png',
         | 
| 44 | 
            +
                    '/images/bg-stacked.png',
         | 
| 45 45 | 
             
                  ])
         | 
| 46 46 | 
             
                end
         | 
| 47 47 | 
             
              end
         | 
| 48 | 
            -
              describe  | 
| 49 | 
            -
                 | 
| 50 | 
            -
             | 
| 48 | 
            +
              describe 'nonlocal.me', type: :feature, js: true do
         | 
| 49 | 
            +
                let(:orig_app_host) { Capybara.app_host }
         | 
| 50 | 
            +
                before do
         | 
| 51 51 | 
             
                  Capybara.app_host = Capybara.app_host.gsub('http://localhost:', 'http://localtest.me:')
         | 
| 52 52 | 
             
                end
         | 
| 53 | 
            -
                after  | 
| 54 | 
            -
                  Capybara.app_host =  | 
| 53 | 
            +
                after do
         | 
| 54 | 
            +
                  Capybara.app_host = orig_app_host
         | 
| 55 55 | 
             
                end
         | 
| 56 56 | 
             
                it 'returns the root HTML and image resources' do
         | 
| 57 57 | 
             
                  visit '/test-localtest-me-images.html'
         | 
| 58 58 | 
             
                  loader = described_class.new(page: page)
         | 
| 59 59 | 
             
                  resource_urls = loader.snapshot_resources.collect(&:resource_url)
         | 
| 60 60 | 
             
                  expect(resource_urls).to eq([
         | 
| 61 | 
            -
                     | 
| 62 | 
            -
                     | 
| 61 | 
            +
                    '/test-localtest-me-images.html',
         | 
| 62 | 
            +
                    '/images/img-relative.png',
         | 
| 63 63 | 
             
                  ])
         | 
| 64 | 
            -
                  expect(loader.snapshot_resources.collect(&:is_root)).to eq([true,nil])
         | 
| 64 | 
            +
                  expect(loader.snapshot_resources.collect(&:is_root)).to eq([true, nil])
         | 
| 65 65 | 
             
                end
         | 
| 66 66 | 
             
              end
         | 
| 67 67 | 
             
              describe '#_should_include_url?' do
         | 
| @@ -97,19 +97,19 @@ RSpec.describe Percy::Capybara::Loaders::NativeLoader do | |
| 97 97 | 
             
                  expect(loader._should_include_url?('http://example.com/foo')).to eq(false)
         | 
| 98 98 | 
             
                  expect(loader._should_include_url?('https://example.com/foo')).to eq(false)
         | 
| 99 99 | 
             
                end
         | 
| 100 | 
            -
                context  | 
| 101 | 
            -
                  let(:fake_page) { OpenStruct.new(current_url:  | 
| 102 | 
            -
                  it  | 
| 100 | 
            +
                context 'for nonlocal hosts' do
         | 
| 101 | 
            +
                  let(:fake_page) { OpenStruct.new(current_url: 'http://foo:123/') }
         | 
| 102 | 
            +
                  it 'returns true for the same host port' do
         | 
| 103 103 | 
             
                    expect(loader._should_include_url?('http://foo:123/')).to eq(true)
         | 
| 104 104 | 
             
                    expect(loader._should_include_url?('http://foo:123/bar')).to eq(true)
         | 
| 105 105 | 
             
                  end
         | 
| 106 | 
            -
                  it  | 
| 106 | 
            +
                  it 'returns false for different port' do
         | 
| 107 107 | 
             
                    expect(loader._should_include_url?('http://foo/')).to eq(false)
         | 
| 108 108 | 
             
                    expect(loader._should_include_url?('http://foo/bar')).to eq(false)
         | 
| 109 109 | 
             
                    expect(loader._should_include_url?('http://foo:1234/')).to eq(false)
         | 
| 110 110 | 
             
                    expect(loader._should_include_url?('http://foo:1234/bar')).to eq(false)
         | 
| 111 111 | 
             
                  end
         | 
| 112 | 
            -
                  it  | 
| 112 | 
            +
                  it 'returns false for different host' do
         | 
| 113 113 | 
             
                    expect(loader._should_include_url?('http://afoo:123/')).to eq(false)
         | 
| 114 114 | 
             
                    expect(loader._should_include_url?('http://afoo:123/bar')).to eq(false)
         | 
| 115 115 | 
             
                  end
         | 
| @@ -146,7 +146,7 @@ RSpec.describe Percy::Capybara::Loaders::NativeLoader do | |
| 146 146 | 
             
                  expect(resource.sha).to eq(Digest::SHA256.hexdigest(resource.content))
         | 
| 147 147 |  | 
| 148 148 | 
             
                  resource = find_resource(resources, '/css/level2-imports.css')
         | 
| 149 | 
            -
                  expect(resource.content).to include( | 
| 149 | 
            +
                  expect(resource.content).to include('.colored-by-level2-imports { color: red; }')
         | 
| 150 150 | 
             
                  expect(resource.sha).to eq(Digest::SHA256.hexdigest(resource.content))
         | 
| 151 151 |  | 
| 152 152 | 
             
                  expect(resources.length).to eq(6)
         | 
| @@ -239,15 +239,15 @@ RSpec.describe Percy::Capybara::Loaders::NativeLoader do | |
| 239 239 |  | 
| 240 240 | 
             
                  resource_urls = resources.collect(&:resource_url)
         | 
| 241 241 | 
             
                  expect(resource_urls).to match_array([
         | 
| 242 | 
            -
                     | 
| 243 | 
            -
                     | 
| 244 | 
            -
                     | 
| 245 | 
            -
                     | 
| 246 | 
            -
                     | 
| 247 | 
            -
                     | 
| 248 | 
            -
                     | 
| 249 | 
            -
                     | 
| 250 | 
            -
                     | 
| 242 | 
            +
                    '/images/img-relative.png',
         | 
| 243 | 
            +
                    '/images/img-relative-to-root.png',
         | 
| 244 | 
            +
                    '/images/percy.svg',
         | 
| 245 | 
            +
                    '/images/srcset-base.png',
         | 
| 246 | 
            +
                    '/images/srcset-first.png',
         | 
| 247 | 
            +
                    '/images/srcset-second.png',
         | 
| 248 | 
            +
                    '/images/bg-relative.png',
         | 
| 249 | 
            +
                    '/images/bg-relative-to-root.png',
         | 
| 250 | 
            +
                    '/images/bg-stacked.png',
         | 
| 251 251 | 
             
                  ])
         | 
| 252 252 | 
             
                  expect(resources.collect(&:is_root).uniq).to match_array([nil])
         | 
| 253 253 | 
             
                end
         |