percy-capybara 0.2.5 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|