percy-capybara 0.2.5 → 0.3.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/client/snapshots.rb +23 -10
- data/lib/percy/capybara/version.rb +1 -1
- data/spec/lib/percy/capybara/client/snapshots_spec.rb +50 -29
- data/spec/lib/percy/capybara/client/testdata/test-css.html +2 -0
- data/spec/lib/percy/capybara/client/testdata/test-images.html +3 -3
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f6b29e232904e95b181e02e0381bd459dfd09a49
|
4
|
+
data.tar.gz: e6c802f2770ba1ab8201838b315945adc3b54cf3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 634f54da9d0ca8f752dc4c3f22fe151072b6064cd8045cb4a7ae280e624dd1090fa5591c898fa57ef83eec37b92049ecafaf44adcd9ef4e84d5af2a0b1b326b7
|
7
|
+
data.tar.gz: 997c23094a26023115a2a3245d3429329829e9136c84f3370aa9d54c75e40f6ccc8a233ab8078ac1acfbbb07bcb764443a832bee2ae3c6e15b316bb1aad83506
|
@@ -11,7 +11,7 @@ module Percy
|
|
11
11
|
URL_REGEX = Regexp.new(
|
12
12
|
# protocol identifier
|
13
13
|
"(?:(?:https?:)?//)" +
|
14
|
-
"(
|
14
|
+
"(" +
|
15
15
|
# IP address exclusion
|
16
16
|
# private & local networks
|
17
17
|
"(?!(?:10|127)(?:\\.\\d{1,3}){3})" +
|
@@ -30,16 +30,19 @@ module Percy
|
|
30
30
|
"(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)" +
|
31
31
|
# domain name
|
32
32
|
"(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*" +
|
33
|
-
# TLD identifier
|
34
|
-
"(?:\\.(?:[a-z\\u00a1-\\uffff]{2,}))" +
|
35
33
|
")" +
|
36
34
|
# port number
|
37
35
|
"(?::\\d{2,5})?" +
|
38
36
|
# resource path
|
39
37
|
"(?:/[^\\s\"']*)?"
|
40
38
|
)
|
41
|
-
PATH_REGEX =
|
39
|
+
PATH_REGEX = /\A\/[^\\s\"']*/
|
42
40
|
DATA_URL_REGEX = /\Adata:/
|
41
|
+
LOCAL_HOSTNAMES = [
|
42
|
+
'localhost',
|
43
|
+
'127.0.0.1',
|
44
|
+
'0.0.0.0',
|
45
|
+
].freeze
|
43
46
|
|
44
47
|
# Takes a snapshot of the given page HTML and its assets.
|
45
48
|
#
|
@@ -135,7 +138,7 @@ module Percy
|
|
135
138
|
resource_urls = _evaluate_script(page, script)
|
136
139
|
|
137
140
|
resource_urls.each do |url|
|
138
|
-
next if !
|
141
|
+
next if !_should_include_url?(url)
|
139
142
|
response = _fetch_resource_url(url)
|
140
143
|
next if !response
|
141
144
|
sha = Digest::SHA256.hexdigest(response.body)
|
@@ -201,16 +204,16 @@ module Percy
|
|
201
204
|
end
|
202
205
|
|
203
206
|
image_urls.each do |image_url|
|
204
|
-
next if !_is_valid_url?(image_url)
|
205
|
-
|
206
207
|
# If url references are blank, browsers will often fill them with the current page's
|
207
208
|
# URL, which makes no sense and will never be renderable. Strip these.
|
208
|
-
next if image_url == page.current_url
|
209
|
+
next if image_url == page.current_url || image_url.strip.empty?
|
209
210
|
|
210
211
|
# Make the resource URL absolute to the current page. If it is already absolute, this
|
211
212
|
# will have no effect.
|
212
213
|
resource_url = URI.join(page.current_url, image_url).to_s
|
213
214
|
|
215
|
+
next if !_should_include_url?(resource_url)
|
216
|
+
|
214
217
|
# Fetch the images.
|
215
218
|
# TODO(fotinakis): this can be pretty inefficient for image-heavy pages because the
|
216
219
|
# browser has already loaded them once and this fetch cannot easily leverage the
|
@@ -228,9 +231,19 @@ module Percy
|
|
228
231
|
private :_get_image_resources
|
229
232
|
|
230
233
|
# @private
|
231
|
-
def
|
234
|
+
def _should_include_url?(url)
|
232
235
|
# It is a URL or a path, but not a data URI.
|
233
|
-
|
236
|
+
url_match = URL_REGEX.match(url)
|
237
|
+
data_url_match = DATA_URL_REGEX.match(url)
|
238
|
+
result = (url_match || PATH_REGEX.match(url)) && !data_url_match
|
239
|
+
|
240
|
+
# Is not a remote URL.
|
241
|
+
if url_match && !data_url_match
|
242
|
+
host = url_match[1]
|
243
|
+
result = LOCAL_HOSTNAMES.include?(host)
|
244
|
+
end
|
245
|
+
|
246
|
+
!!result
|
234
247
|
end
|
235
248
|
|
236
249
|
# @private
|
@@ -24,7 +24,7 @@ RSpec.describe Percy::Capybara::Client::Snapshots, type: :feature do
|
|
24
24
|
end
|
25
25
|
after(:all) { Process.kill('INT', @process.pid) }
|
26
26
|
|
27
|
-
before(:each) do
|
27
|
+
before(:each, js: true) do
|
28
28
|
# Special setting for capybara-webkit. If clients are using capybara-webkit they would
|
29
29
|
# also have to have this setting enabled since apparently all resources are blocked by default.
|
30
30
|
page.driver.respond_to?(:allow_url) && page.driver.allow_url('*')
|
@@ -38,6 +38,40 @@ RSpec.describe Percy::Capybara::Client::Snapshots, type: :feature do
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
+
describe '#_should_include_url?' do
|
42
|
+
it 'returns true for valid, local URLs' do
|
43
|
+
expect(capybara_client._should_include_url?('http://localhost/')).to eq(true)
|
44
|
+
expect(capybara_client._should_include_url?('http://localhost:123/')).to eq(true)
|
45
|
+
expect(capybara_client._should_include_url?('http://localhost/foo')).to eq(true)
|
46
|
+
expect(capybara_client._should_include_url?('http://localhost:123/foo')).to eq(true)
|
47
|
+
expect(capybara_client._should_include_url?('http://localhost/foo/test.html')).to eq(true)
|
48
|
+
expect(capybara_client._should_include_url?('http://127.0.0.1/')).to eq(true)
|
49
|
+
expect(capybara_client._should_include_url?('http://127.0.0.1:123/')).to eq(true)
|
50
|
+
expect(capybara_client._should_include_url?('http://127.0.0.1/foo')).to eq(true)
|
51
|
+
expect(capybara_client._should_include_url?('http://127.0.0.1:123/foo')).to eq(true)
|
52
|
+
expect(capybara_client._should_include_url?('http://127.0.0.1/foo/test.html')).to eq(true)
|
53
|
+
expect(capybara_client._should_include_url?('http://0.0.0.0/foo/test.html')).to eq(true)
|
54
|
+
# Also works for paths:
|
55
|
+
expect(capybara_client._should_include_url?('/')).to eq(true)
|
56
|
+
expect(capybara_client._should_include_url?('/foo')).to eq(true)
|
57
|
+
expect(capybara_client._should_include_url?('/foo/test.png')).to eq(true)
|
58
|
+
end
|
59
|
+
it 'returns false for invalid URLs' do
|
60
|
+
expect(capybara_client._should_include_url?('')).to eq(false)
|
61
|
+
expect(capybara_client._should_include_url?('http://local host/foo')).to eq(false)
|
62
|
+
expect(capybara_client._should_include_url?('bad-url/')).to eq(false)
|
63
|
+
expect(capybara_client._should_include_url?('bad-url/foo/test.html')).to eq(false)
|
64
|
+
end
|
65
|
+
it 'returns false for data URLs' do
|
66
|
+
expect(capybara_client._should_include_url?('data:image/gif;base64,R0')).to eq(false)
|
67
|
+
end
|
68
|
+
it 'returns false for remote URLs' do
|
69
|
+
expect(capybara_client._should_include_url?('http://foo/')).to eq(false)
|
70
|
+
expect(capybara_client._should_include_url?('http://example.com/')).to eq(false)
|
71
|
+
expect(capybara_client._should_include_url?('http://example.com/foo')).to eq(false)
|
72
|
+
expect(capybara_client._should_include_url?('https://example.com/foo')).to eq(false)
|
73
|
+
end
|
74
|
+
end
|
41
75
|
describe '#_get_root_html_resource', type: :feature, js: true do
|
42
76
|
it 'includes the root DOM HTML' do
|
43
77
|
visit '/'
|
@@ -82,12 +116,7 @@ RSpec.describe Percy::Capybara::Client::Snapshots, type: :feature do
|
|
82
116
|
expect(resource.content).to include(".colored-by-level2-imports { color: red; }")
|
83
117
|
expect(resource.sha).to eq(Digest::SHA256.hexdigest(resource.content))
|
84
118
|
|
85
|
-
|
86
|
-
resources, /https:\/\/maxcdn.bootstrapcdn.com\/bootstrap\/3.3.4\/css\/bootstrap.min.css/)
|
87
|
-
expect(resource.content).to include('Bootstrap v3.3.4 (http://getbootstrap.com)')
|
88
|
-
expect(resource.sha).to eq(Digest::SHA256.hexdigest(resource.content))
|
89
|
-
|
90
|
-
expect(resources.length).to eq(7)
|
119
|
+
expect(resources.length).to eq(6)
|
91
120
|
expect(resources.collect(&:mimetype).uniq).to eq(['text/css'])
|
92
121
|
expect(resources.collect(&:is_root).uniq).to match_array([nil])
|
93
122
|
end
|
@@ -122,13 +151,6 @@ RSpec.describe Percy::Capybara::Client::Snapshots, type: :feature do
|
|
122
151
|
expect(Digest::SHA256.hexdigest(resource.content)).to eq(expected_sha)
|
123
152
|
expect(resource.sha).to eq(expected_sha)
|
124
153
|
|
125
|
-
resource = find_resource(resources, /http:\/\/i.imgur.com\/Umkjdao.png/)
|
126
|
-
content = Faraday.get('http://i.imgur.com/Umkjdao.png').body
|
127
|
-
expect(resource.mimetype).to eq('image/png')
|
128
|
-
expected_sha = Digest::SHA256.hexdigest(content)
|
129
|
-
expect(Digest::SHA256.hexdigest(resource.content)).to eq(expected_sha)
|
130
|
-
expect(resource.sha).to eq(expected_sha)
|
131
|
-
|
132
154
|
resource = find_resource(resources, /http:\/\/localhost:\d+\/images\/bg-relative\.png/)
|
133
155
|
content = File.read(File.expand_path('../testdata/images/bg-relative.png', __FILE__))
|
134
156
|
expect(resource.mimetype).to eq('image/png')
|
@@ -143,13 +165,6 @@ RSpec.describe Percy::Capybara::Client::Snapshots, type: :feature do
|
|
143
165
|
expect(Digest::SHA256.hexdigest(resource.content)).to eq(expected_sha)
|
144
166
|
expect(resource.sha).to eq(expected_sha)
|
145
167
|
|
146
|
-
resource = find_resource(resources, /http:\/\/i.imgur.com\/5mLoBs1.png/)
|
147
|
-
content = Faraday.get('http://i.imgur.com/5mLoBs1.png').body
|
148
|
-
expect(resource.mimetype).to eq('image/png')
|
149
|
-
expected_sha = Digest::SHA256.hexdigest(content)
|
150
|
-
expect(Digest::SHA256.hexdigest(resource.content)).to eq(expected_sha)
|
151
|
-
expect(resource.sha).to eq(expected_sha)
|
152
|
-
|
153
168
|
resource = find_resource(resources, /http:\/\/localhost:\d+\/images\/bg-stacked\.png/)
|
154
169
|
content = File.read(File.expand_path('../testdata/images/bg-stacked.png', __FILE__))
|
155
170
|
expect(resource.mimetype).to eq('image/png')
|
@@ -157,13 +172,6 @@ RSpec.describe Percy::Capybara::Client::Snapshots, type: :feature do
|
|
157
172
|
expect(Digest::SHA256.hexdigest(resource.content)).to eq(expected_sha)
|
158
173
|
expect(resource.sha).to eq(expected_sha)
|
159
174
|
|
160
|
-
resource = find_resource(resources, /http:\/\/i.imgur.com\/61AQuplb.jpg/)
|
161
|
-
content = Faraday.get('http://i.imgur.com/61AQuplb.jpg').body
|
162
|
-
expect(resource.mimetype).to eq('image/jpeg')
|
163
|
-
expected_sha = Digest::SHA256.hexdigest(content)
|
164
|
-
expect(Digest::SHA256.hexdigest(resource.content)).to eq(expected_sha)
|
165
|
-
expect(resource.sha).to eq(expected_sha)
|
166
|
-
|
167
175
|
resource = find_resource(resources, /http:\/\/localhost:\d+\/images\/srcset-base\.png/)
|
168
176
|
content = File.read(File.expand_path('../testdata/images/srcset-base.png', __FILE__))
|
169
177
|
expect(resource.mimetype).to eq('image/png')
|
@@ -185,7 +193,20 @@ RSpec.describe Percy::Capybara::Client::Snapshots, type: :feature do
|
|
185
193
|
expect(Digest::SHA256.hexdigest(resource.content)).to eq(expected_sha)
|
186
194
|
expect(resource.sha).to eq(expected_sha)
|
187
195
|
|
188
|
-
|
196
|
+
resource_urls = resources.collect(&:resource_url).map do |url|
|
197
|
+
url.gsub(/localhost:\d+/, 'localhost')
|
198
|
+
end
|
199
|
+
expect(resource_urls).to match_array([
|
200
|
+
"http://localhost/images/img-relative.png",
|
201
|
+
"http://localhost/images/img-relative-to-root.png",
|
202
|
+
"http://localhost/images/percy.svg",
|
203
|
+
"http://localhost/images/srcset-base.png",
|
204
|
+
"http://localhost/images/srcset-first.png",
|
205
|
+
"http://localhost/images/srcset-second.png",
|
206
|
+
"http://localhost/images/bg-relative.png",
|
207
|
+
"http://localhost/images/bg-relative-to-root.png",
|
208
|
+
"http://localhost/images/bg-stacked.png"
|
209
|
+
])
|
189
210
|
expect(resources.collect(&:is_root).uniq).to match_array([nil])
|
190
211
|
end
|
191
212
|
end
|
@@ -4,6 +4,8 @@
|
|
4
4
|
<link href="../css/base.css" rel="stylesheet" type="text/css">
|
5
5
|
<link href="/css/simple-imports.css" rel="stylesheet" type="text/css">
|
6
6
|
<link href="/css/level0-imports.css" rel="stylesheet" type="text/css">
|
7
|
+
|
8
|
+
<!-- remote resource, ignored -->
|
7
9
|
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet" type="text/css">
|
8
10
|
<style>
|
9
11
|
.colored-by-inline { color: red; }
|
@@ -9,7 +9,7 @@
|
|
9
9
|
<h2>img local PNG (relative to root)</h2>
|
10
10
|
<img src="/images/img-relative-to-root.png">
|
11
11
|
|
12
|
-
<h2>img PNG (remote)</h2>
|
12
|
+
<h2>img PNG (remote, ignored)</h2>
|
13
13
|
<img src="http://i.imgur.com/Umkjdao.png">
|
14
14
|
|
15
15
|
<h2>img SVG (relative)</h2>
|
@@ -21,7 +21,7 @@
|
|
21
21
|
<h2>CSS background-image (relative to root)</h2>
|
22
22
|
<div style="background-image: url(/images/bg-relative-to-root.png); width: 200px; height: 200px;"></div>
|
23
23
|
|
24
|
-
<h2>CSS background-image (remote)</h2>
|
24
|
+
<h2>CSS background-image (remote, ignored)</h2>
|
25
25
|
<div style="background-image: url(http://i.imgur.com/5mLoBs1.png); width: 408px; height: 376px;"></div>
|
26
26
|
|
27
27
|
<h2>img data-uri (ignored)</h2>
|
@@ -30,7 +30,7 @@
|
|
30
30
|
<h2>CSS background-image data-uri (ignored)</h2>
|
31
31
|
<div style="background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAMAAABHPGVmAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAZQTFRFVyxjAAAAmU4baAAAACNJREFUeNrswYEAAAAAw6D5U1/hAFUBAAAAAAAAAAAAjwkwACd0AAGLtJfaAAAAAElFTkSuQmCC); width: 100px; height: 100px;"></div>
|
32
32
|
|
33
|
-
<h2>CSS background stacked (local and remote)</h2>
|
33
|
+
<h2>CSS background stacked (local and remote, remote ignored)</h2>
|
34
34
|
<div style="background: url(/images/bg-stacked.png) 200px 200px no-repeat, url('http://i.imgur.com/61AQuplb.jpg'); width: 100px; height: 100px;"></div>
|
35
35
|
|
36
36
|
<h2>img srcset</h2>
|
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: 0.
|
4
|
+
version: 0.3.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: 2015-07-
|
11
|
+
date: 2015-07-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: percy-client
|
@@ -204,7 +204,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
204
204
|
version: '0'
|
205
205
|
requirements: []
|
206
206
|
rubyforge_project:
|
207
|
-
rubygems_version: 2.
|
207
|
+
rubygems_version: 2.4.5
|
208
208
|
signing_key:
|
209
209
|
specification_version: 4
|
210
210
|
summary: Percy::Capybara
|