percy-capybara 2.3.6 → 2.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 09d303f9090ad8ce75b13714c58bcec25d711602
4
- data.tar.gz: 108512d47e2d4e67e84cdfa2b9456e5368ac58a2
3
+ metadata.gz: bb10aec66c3c56197c20d065c40d832e877a6f6c
4
+ data.tar.gz: c0ceaad44d882dd332bc311f9487254ebddd629e
5
5
  SHA512:
6
- metadata.gz: 67e7111b3708fbad2de5475ee88e8f74b9f47b25a30b66ba06e32372df70d15ccc8fb3d0e43052eeee3b82d1189209326c292691585c8d20b35a0205913184a2
7
- data.tar.gz: 2dd5b305baaa6f592c84218537f2d1a125b9a78ffbc6d59bfcf1cf442fba38719edc6006494de46ae6bc6134f900f0f8390feb56515f82e988d731fd7104f42d
6
+ metadata.gz: 8c77f2d2408b130ae4ddc0da23a4dc57ab2cfb17eeb7d0f70f95856bfd4b5f0d48c55f9098c002c5ff43e233621ab7329034b089dbb8943e132f15b1698a58d8
7
+ data.tar.gz: 61edd95f68244f5d7b63d169a9da0b95be1743c5ebfeaf96f9f226721467ec059f38d76722bd4b53e4dccf7ee562de2e818fd36647d6e40f0ee8d69df223a310
@@ -53,8 +53,9 @@ module Percy
53
53
  capybara_client.disable!
54
54
  end
55
55
 
56
- def self.use_loader(loader)
57
- capybara_client.custom_loader = loader
56
+ def self.use_loader(loader, options = {})
57
+ capybara_client.loader = loader
58
+ capybara_client.loader_options = options
58
59
  end
59
60
  end
60
61
  end
@@ -1,5 +1,6 @@
1
1
  require 'percy/capybara/client/builds'
2
2
  require 'percy/capybara/client/snapshots'
3
+ require 'percy/capybara/loaders/filesystem_loader'
3
4
  require 'percy/capybara/loaders/native_loader'
4
5
  require 'percy/capybara/loaders/sprockets_loader'
5
6
 
@@ -17,7 +18,8 @@ module Percy
17
18
 
18
19
  attr_accessor :sprockets_environment
19
20
  attr_accessor :sprockets_options
20
- attr_accessor :custom_loader
21
+ attr_accessor :loader
22
+ attr_accessor :loader_options
21
23
 
22
24
  def initialize(options = {})
23
25
  @failed = false
@@ -25,6 +27,8 @@ module Percy
25
27
  @client = options[:client] || Percy.client
26
28
  @enabled = options[:enabled]
27
29
 
30
+ @loader_options = options[:loader_options] || {}
31
+
28
32
  if defined?(Rails)
29
33
  @sprockets_environment = options[:sprockets_environment] || Rails.application.assets
30
34
  @sprockets_options = options[:sprockets_options] || Rails.application.config.assets
@@ -80,17 +84,34 @@ module Percy
80
84
  end
81
85
 
82
86
  def initialize_loader(options = {})
83
- if custom_loader
84
- Percy.logger.debug { 'Using a custom loader to discover assets.' }
85
- custom_loader.new(options)
87
+ merged_options = loader_options.merge(options)
88
+ if loader
89
+ case loader
90
+ when :filesystem
91
+ Percy.logger.debug { 'Using filesystem_loader to discover assets.' }
92
+ Percy::Capybara::Loaders::FilesystemLoader.new(merged_options)
93
+ when :native
94
+ Percy.logger.debug { 'Using native_loader to discover assets (slow).' }
95
+ Percy::Capybara::Loaders::NativeLoader.new(merged_options)
96
+ else
97
+ Percy.logger.debug { 'Using a custom loader to discover assets.' }
98
+ loader.new(merged_options)
99
+ end
86
100
  elsif sprockets_environment && sprockets_options
87
101
  Percy.logger.debug { 'Using sprockets_loader to discover assets.' }
88
- options[:sprockets_environment] = sprockets_environment
89
- options[:sprockets_options] = sprockets_options
90
- Percy::Capybara::Loaders::SprocketsLoader.new(options)
102
+ merged_options[:sprockets_environment] = sprockets_environment
103
+ merged_options[:sprockets_options] = sprockets_options
104
+ Percy::Capybara::Loaders::SprocketsLoader.new(merged_options)
91
105
  else
106
+ unless @warned_about_native_loader
107
+ Percy.logger.warn \
108
+ '[DEPRECATED] The native_loader is deprecated and will be opt-in in a future release. ' +
109
+ 'You should move to the faster, more reliable filesystem_loader. See the docs for ' +
110
+ 'Non-Rails frameworks: https://percy.io/docs/clients/ruby/capybara '
111
+ @warned_about_native_loader = true
112
+ end
92
113
  Percy.logger.debug { 'Using native_loader to discover assets (slower).' }
93
- Percy::Capybara::Loaders::NativeLoader.new(options)
114
+ Percy::Capybara::Loaders::NativeLoader.new(merged_options)
94
115
  end
95
116
  end
96
117
  end
@@ -0,0 +1,59 @@
1
+ require 'percy/capybara/loaders/base_loader'
2
+ require 'digest'
3
+ require 'find'
4
+ require 'pathname'
5
+
6
+ module Percy
7
+ module Capybara
8
+ module Loaders
9
+
10
+ # Resource loader that looks for resources in the specified folder.
11
+ class FilesystemLoader < BaseLoader
12
+ SKIP_RESOURCE_EXTENSIONS = [
13
+ '.map', # Ignore source maps.
14
+ '.gz', # Ignore gzipped files.
15
+ ]
16
+ MAX_FILESIZE_BYTES = 15 * 1024**2 # 15 MB.
17
+
18
+ def initialize(options = {})
19
+ # @assets_dir should point to a _compiled_ static assets directory, not source assets.
20
+ @assets_dir = options[:assets_dir]
21
+ @base_url = options[:base_url] || ''
22
+
23
+ raise ArgumentError.new('assets_dir is required') if @assets_dir.nil? || @assets_dir == ''
24
+ if !Pathname.new(@assets_dir).absolute?
25
+ raise ArgumentError.new("assets_dir needs to be an absolute path. Received: #{@assets_dir}")
26
+ end
27
+ if !Dir.exist?(@assets_dir)
28
+ raise ArgumentError.new("assets_dir provided was not found. Received: #{@assets_dir}")
29
+ end
30
+
31
+ super
32
+ end
33
+
34
+ def snapshot_resources
35
+ [root_html_resource]
36
+ end
37
+
38
+ def build_resources
39
+ resources = []
40
+ Find.find(@assets_dir).each do |path|
41
+ # Skip directories.
42
+ next if !FileTest.file?(path)
43
+ # Skip certain extensions.
44
+ next if SKIP_RESOURCE_EXTENSIONS.include?(File.extname(path))
45
+ # Skip large files, these are hopefully downloads and not used in page rendering.
46
+ next if File.size(path) > MAX_FILESIZE_BYTES
47
+
48
+ # Replace the assets_dir with the base_url to generate the resource_url
49
+ resource_url = path.sub(@assets_dir, @base_url)
50
+
51
+ sha = Digest::SHA256.hexdigest(File.read(path))
52
+ resources << Percy::Client::Resource.new(resource_url, sha: sha, path: path)
53
+ end
54
+ resources
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -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.asset_path(logical_path)
50
+ resource_url = ActionController::Base.helpers.assets_dir(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?
@@ -1,5 +1,5 @@
1
1
  module Percy
2
2
  module Capybara
3
- VERSION = '2.3.6'
3
+ VERSION = '2.4.0'
4
4
  end
5
5
  end
@@ -94,10 +94,27 @@ RSpec.describe Percy::Capybara::Client do
94
94
  describe '#initialize_loader' do
95
95
  let(:capybara_client) { Percy::Capybara::Client.new }
96
96
 
97
- context 'when a custom loader has been set' do
97
+ context 'when loader has been set to :native' do
98
+ it 'returns a NativeLoader' do
99
+ capybara_client.loader = :native
100
+ loader = capybara_client.initialize_loader
101
+ expect(loader.class).to eq(Percy::Capybara::Loaders::NativeLoader)
102
+ end
103
+ end
104
+
105
+ context 'when loader has been set to :filesystem' do
106
+ it 'returns a FilesystemLoader' do
107
+ capybara_client.loader = :filesystem
108
+ capybara_client.loader_options = {assets_dir: '/', base_url: '/'}
109
+ loader = capybara_client.initialize_loader
110
+ expect(loader.class).to eq(Percy::Capybara::Loaders::FilesystemLoader)
111
+ end
112
+ end
113
+
114
+ context 'when loader has been set to a class' do
98
115
  it 'returns an instance of the clients custom loader' do
99
116
  class DummyLoader < Percy::Capybara::Loaders::NativeLoader; end
100
- capybara_client.custom_loader = DummyLoader
117
+ capybara_client.loader = DummyLoader
101
118
  loader = capybara_client.initialize_loader
102
119
  expect(loader.class).to eq(DummyLoader)
103
120
  end
@@ -117,5 +134,17 @@ RSpec.describe Percy::Capybara::Client do
117
134
  expect(capybara_client.initialize_loader.class).to eq(Percy::Capybara::Loaders::NativeLoader)
118
135
  end
119
136
  end
137
+
138
+ context 'when loader_options are set' do
139
+ let(:loader_class) { Percy::Capybara::Loaders::FilesystemLoader }
140
+ let(:options) { {assets_dir: 'xyz'} }
141
+
142
+ it 'initializes the loader with them' do
143
+ capybara_client.loader = :filesystem
144
+ capybara_client.loader_options = options
145
+ expect(loader_class).to receive(:new).with(options).once
146
+ capybara_client.initialize_loader
147
+ end
148
+ end
120
149
  end
121
150
  end
@@ -0,0 +1,113 @@
1
+ RSpec.describe Percy::Capybara::Loaders::FilesystemLoader do
2
+ let(:fake_page) { OpenStruct.new(current_url: 'http://localhost/foo') }
3
+ let(:assets_dir) { File.expand_path('../../client/testdata', __FILE__) }
4
+ let(:base_url) { '/url-prefix' }
5
+ let(:loader) { described_class.new(base_url: base_url, assets_dir: assets_dir, page: fake_page) }
6
+
7
+ describe 'initialize' do
8
+ context 'assets_dir not specified' do
9
+ let(:assets_dir) { nil }
10
+ it 'raises an error' do
11
+ expect { loader }.to raise_error(ArgumentError)
12
+ end
13
+ end
14
+ context 'assets_dir is not an absolute path' do
15
+ let(:assets_dir) { '../../client/testdata' }
16
+ it 'raises an error' do
17
+ expect { loader }.to raise_error(ArgumentError)
18
+ end
19
+ end
20
+ context 'assets_dir doesn\'t exist' do
21
+ let(:assets_dir) { File.expand_path("../../client/testdata-doesnt-exist", __FILE__) }
22
+ it 'raises an error' do
23
+ expect { loader }.to raise_error(ArgumentError)
24
+ end
25
+ end
26
+ end
27
+
28
+ describe '#snapshot_resources', type: :feature, js: true do
29
+ it 'returns the root HTML' do
30
+ visit '/'
31
+ loader = described_class.new(base_url: base_url, assets_dir: assets_dir, page: page)
32
+ expect(loader.snapshot_resources.collect(&:resource_url)).to match_array(['/'])
33
+ end
34
+ it 'returns the visited html resource' do
35
+ visit '/test-css.html'
36
+ loader = described_class.new(base_url: base_url, assets_dir: assets_dir, page: page)
37
+ resource_urls = loader.snapshot_resources.collect(&:resource_url)
38
+ expect(resource_urls).to match_array(['/test-css.html'])
39
+ end
40
+ end
41
+
42
+ describe '#build_resources' do
43
+ context 'assets_dir including all test files' do
44
+ it 'returns all included assets as resources' do
45
+ actual_paths = loader.build_resources.collect { |resource| resource.path.gsub(assets_dir, '') }
46
+ expected_paths = [
47
+ '/assets/css/digested-f3420c6aee71c137a3ca39727052811bae84b2f37d898f4db242e20656a1579e.css',
48
+ '/css/base.css',
49
+ '/css/digested.css',
50
+ '/css/imports.css',
51
+ '/css/level0-imports.css',
52
+ '/css/level1-imports.css',
53
+ '/css/level2-imports.css',
54
+ '/css/simple-imports.css',
55
+ '/iframe.html',
56
+ '/images/bg-relative-to-root.png',
57
+ '/images/bg-relative.png',
58
+ '/images/bg-stacked.png',
59
+ '/images/img-relative-to-root.png',
60
+ '/images/img-relative.png',
61
+ '/images/percy.svg',
62
+ '/images/srcset-base.png',
63
+ '/images/srcset-first.png',
64
+ '/images/srcset-second.png',
65
+ '/index.html',
66
+ '/js/base.js',
67
+ '/public/percy-from-public.svg',
68
+ '/test-css.html',
69
+ '/test-iframe.html',
70
+ '/test-images.html',
71
+ '/test-localtest-me-images.html',
72
+ ]
73
+ expect(actual_paths).to eq(expected_paths)
74
+
75
+ expected_urls = loader.build_resources.collect { |resource| resource.resource_url }
76
+ actual_urls = [
77
+ '/url-prefix/assets/css/digested-f3420c6aee71c137a3ca39727052811bae84b2f37d898f4db242e20656a1579e.css',
78
+ '/url-prefix/css/base.css',
79
+ '/url-prefix/css/digested.css',
80
+ '/url-prefix/css/imports.css',
81
+ '/url-prefix/css/level0-imports.css',
82
+ '/url-prefix/css/level1-imports.css',
83
+ '/url-prefix/css/level2-imports.css',
84
+ '/url-prefix/css/simple-imports.css',
85
+ '/url-prefix/iframe.html',
86
+ '/url-prefix/images/bg-relative-to-root.png',
87
+ '/url-prefix/images/bg-relative.png',
88
+ '/url-prefix/images/bg-stacked.png',
89
+ '/url-prefix/images/img-relative-to-root.png',
90
+ '/url-prefix/images/img-relative.png',
91
+ '/url-prefix/images/percy.svg',
92
+ '/url-prefix/images/srcset-base.png',
93
+ '/url-prefix/images/srcset-first.png',
94
+ '/url-prefix/images/srcset-second.png',
95
+ '/url-prefix/index.html',
96
+ '/url-prefix/js/base.js',
97
+ '/url-prefix/public/percy-from-public.svg',
98
+ '/url-prefix/test-css.html',
99
+ '/url-prefix/test-iframe.html',
100
+ '/url-prefix/test-images.html',
101
+ '/url-prefix/test-localtest-me-images.html',
102
+ ]
103
+ expect(actual_urls).to eq(expected_urls)
104
+ end
105
+ end
106
+ context 'assets_dir with only skippable resources' do
107
+ let(:assets_dir) { File.expand_path('../../client/testdata/assets/images', __FILE__) }
108
+ it 'returns an empty list' do
109
+ expect(loader.build_resources).to eq([])
110
+ end
111
+ end
112
+ end
113
+ end
@@ -70,7 +70,7 @@ RSpec.describe Percy::Capybara do
70
70
  end
71
71
  describe '#disable!' do
72
72
  it 'sets the current capybara_client to disabled' do
73
- capybara_client = Percy::Capybara::Client.new(enabled:true)
73
+ capybara_client = Percy::Capybara::Client.new(enabled: true)
74
74
  expect(Percy::Capybara).to receive(:capybara_client)
75
75
  .and_return(capybara_client).exactly(3).times
76
76
  expect(Percy::Capybara.capybara_client.enabled?).to eq(true)
@@ -81,10 +81,17 @@ RSpec.describe Percy::Capybara do
81
81
  describe '#use_loader' do
82
82
  class DummyLoader < Percy::Capybara::Loaders::NativeLoader; end
83
83
 
84
- it 'sets the current capybara clients custom loader' do
85
- expect(Percy::Capybara.capybara_client.custom_loader).to_not be
84
+ it 'sets the current capybara client\'s loader' do
85
+ expect(Percy::Capybara.capybara_client.loader).to_not be
86
86
  Percy::Capybara.use_loader(DummyLoader)
87
- expect(Percy::Capybara.capybara_client.custom_loader).to be
87
+ expect(Percy::Capybara.capybara_client.loader).to be
88
+ end
89
+
90
+ it 'sets the current capybara client\'s loader options' do
91
+ expect(Percy::Capybara.capybara_client.loader_options).to eq({})
92
+ Percy::Capybara.use_loader(DummyLoader, {test_option: 3})
93
+ expect(Percy::Capybara.capybara_client.loader_options).to be
94
+ expect(Percy::Capybara.capybara_client.loader_options[:test_option]).to eq(3)
88
95
  end
89
96
  end
90
97
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: percy-capybara
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.6
4
+ version: 2.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Perceptual Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-01-26 00:00:00.000000000 Z
11
+ date: 2017-02-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: percy-client
@@ -187,6 +187,7 @@ files:
187
187
  - lib/percy/capybara/client/snapshots.rb
188
188
  - lib/percy/capybara/httpfetcher.rb
189
189
  - lib/percy/capybara/loaders/base_loader.rb
190
+ - lib/percy/capybara/loaders/filesystem_loader.rb
190
191
  - lib/percy/capybara/loaders/native_loader.rb
191
192
  - lib/percy/capybara/loaders/sprockets_loader.rb
192
193
  - lib/percy/capybara/rspec.rb
@@ -225,6 +226,7 @@ files:
225
226
  - spec/lib/percy/capybara/client_spec.rb
226
227
  - spec/lib/percy/capybara/httpfetcher_spec.rb
227
228
  - spec/lib/percy/capybara/loaders/base_loader_spec.rb
229
+ - spec/lib/percy/capybara/loaders/filesystem_loader_spec.rb
228
230
  - spec/lib/percy/capybara/loaders/native_loader_spec.rb
229
231
  - spec/lib/percy/capybara/loaders/sprockets_loader_spec.rb
230
232
  - spec/lib/percy/capybara_spec.rb
@@ -250,7 +252,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
250
252
  version: '0'
251
253
  requirements: []
252
254
  rubyforge_project:
253
- rubygems_version: 2.4.8
255
+ rubygems_version: 2.6.7
254
256
  signing_key:
255
257
  specification_version: 4
256
258
  summary: Percy::Capybara
@@ -288,6 +290,7 @@ test_files:
288
290
  - spec/lib/percy/capybara/client_spec.rb
289
291
  - spec/lib/percy/capybara/httpfetcher_spec.rb
290
292
  - spec/lib/percy/capybara/loaders/base_loader_spec.rb
293
+ - spec/lib/percy/capybara/loaders/filesystem_loader_spec.rb
291
294
  - spec/lib/percy/capybara/loaders/native_loader_spec.rb
292
295
  - spec/lib/percy/capybara/loaders/sprockets_loader_spec.rb
293
296
  - spec/lib/percy/capybara_spec.rb