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 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