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 +4 -4
- data/lib/percy/capybara.rb +3 -2
- data/lib/percy/capybara/client.rb +29 -8
- data/lib/percy/capybara/loaders/filesystem_loader.rb +59 -0
- data/lib/percy/capybara/loaders/sprockets_loader.rb +1 -1
- data/lib/percy/capybara/version.rb +1 -1
- data/spec/lib/percy/capybara/client_spec.rb +31 -2
- data/spec/lib/percy/capybara/loaders/filesystem_loader_spec.rb +113 -0
- data/spec/lib/percy/capybara_spec.rb +11 -4
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bb10aec66c3c56197c20d065c40d832e877a6f6c
|
4
|
+
data.tar.gz: c0ceaad44d882dd332bc311f9487254ebddd629e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8c77f2d2408b130ae4ddc0da23a4dc57ab2cfb17eeb7d0f70f95856bfd4b5f0d48c55f9098c002c5ff43e233621ab7329034b089dbb8943e132f15b1698a58d8
|
7
|
+
data.tar.gz: 61edd95f68244f5d7b63d169a9da0b95be1743c5ebfeaf96f9f226721467ec059f38d76722bd4b53e4dccf7ee562de2e818fd36647d6e40f0ee8d69df223a310
|
data/lib/percy/capybara.rb
CHANGED
@@ -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.
|
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 :
|
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
|
-
|
84
|
-
|
85
|
-
|
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
|
-
|
89
|
-
|
90
|
-
Percy::Capybara::Loaders::SprocketsLoader.new(
|
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(
|
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.
|
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?
|
@@ -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
|
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.
|
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
|
85
|
-
expect(Percy::Capybara.capybara_client.
|
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.
|
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.
|
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-
|
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.
|
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
|