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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1b9ab13cdb41b837b527594bbe81b6558b62fc5e
4
- data.tar.gz: 8a1cb46009774c52c868d8b14ef404b4d3d913a9
3
+ metadata.gz: f6b29e232904e95b181e02e0381bd459dfd09a49
4
+ data.tar.gz: e6c802f2770ba1ab8201838b315945adc3b54cf3
5
5
  SHA512:
6
- metadata.gz: 054078223dae7d409556cae8f308763e3552c5491e29e443a2411f928a23a5272e182e02c9c72b488eedf8f2b593b0830a2580ce7271ef15c4179a42a3f2a078
7
- data.tar.gz: 8145c3640a24875a8c10907194a9839da7c3958f97700d6ab338d20aadb65c9e571a04905b583715da78555b072b0f07e7c39c6b73301c7273c28fc3359c49a9
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 = /\/[^\\s\"']*/
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 !_is_valid_url?(url)
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 _is_valid_url?(url)
234
+ def _should_include_url?(url)
232
235
  # It is a URL or a path, but not a data URI.
233
- (URL_REGEX.match(url) || PATH_REGEX.match(url)) && !DATA_URL_REGEX.match(url)
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
@@ -1,5 +1,5 @@
1
1
  module Percy
2
2
  module Capybara
3
- VERSION = '0.2.5'
3
+ VERSION = '0.3.0'
4
4
  end
5
5
  end
@@ -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
- resource = find_resource(
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
- expect(resources.length).to eq(12)
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.2.5
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-30 00:00:00.000000000 Z
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.2.2
207
+ rubygems_version: 2.4.5
208
208
  signing_key:
209
209
  specification_version: 4
210
210
  summary: Percy::Capybara