metainspector 5.18.1 → 5.20.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.
@@ -70,6 +70,31 @@ describe MetaInspector do
70
70
  end
71
71
 
72
72
  describe "images.best" do
73
+ it 'should prefer the Parsely image over the largest image' do
74
+ html = '<meta name="parsely-image-url" content="/parsely.jpg"><img src="/largest.jpg" width="100" height="100">'
75
+ page = MetaInspector.new('http://example.com/', document: html)
76
+
77
+ expect(page.images.best).to eq('http://example.com/parsely.jpg')
78
+ end
79
+
80
+ ['', ' &#10; '].each do |value|
81
+ it "should fall back to the largest image when the Parsely image is empty (#{value.inspect})" do
82
+ html = %(<meta name="parsely-image-url" content="#{value}"><img src="/largest.jpg" width="100" height="100">)
83
+ page = MetaInspector.new('http://example.com/', document: html)
84
+
85
+ expect(page.images.best).to eq('http://example.com/largest.jpg')
86
+ end
87
+ end
88
+
89
+ it "should find a valid image when another image URL cannot be parsed" do
90
+ html = '<html><body><img src="http://exa mple.com/x.png"><img src="/100x100"></body></html>'
91
+ page = MetaInspector.new('http://example.com/', document: html)
92
+
93
+ allow(FastImage).to receive(:size).and_call_original
94
+ expect(FastImage).not_to receive(:size).with(nil)
95
+ expect(page.images.best).to eq("http://example.com/100x100")
96
+ end
97
+
73
98
  it "should find the og image" do
74
99
  page = MetaInspector.new('http://www.theonion.com/articles/apple-claims-new-iphone-only-visible-to-most-loyal,2772/')
75
100
 
@@ -103,6 +128,44 @@ describe MetaInspector do
103
128
  end
104
129
 
105
130
  describe "images.owner_suggested" do
131
+ it 'should find the Parsely image when no existing metadata is present' do
132
+ html = '<meta name="parsely-image-url" content="https://images.example.com/parsely.jpg?b=2&amp;a=1">'
133
+ page = MetaInspector.new('http://example.com/', document: html)
134
+
135
+ expect(page.images.owner_suggested).to eq('https://images.example.com/parsely.jpg?b=2&a=1')
136
+ end
137
+
138
+ it 'should resolve a relative Parsely image against the document base URL' do
139
+ html = '<base href="/assets/"><meta name="parsely-image-url" content="parsely.jpg">'
140
+ page = MetaInspector.new('http://example.com/articles/page', document: html)
141
+
142
+ expect(page.images.owner_suggested).to eq('http://example.com/assets/parsely.jpg')
143
+ end
144
+
145
+ it 'should use the Parsely image when existing metadata is empty' do
146
+ html = '<meta property="og:image" content=""><meta name="twitter:image" content=""><meta name="parsely-image-url" content="/parsely.jpg">'
147
+ page = MetaInspector.new('http://example.com/', document: html)
148
+
149
+ expect(page.images.owner_suggested).to eq('http://example.com/parsely.jpg')
150
+ end
151
+
152
+ ['og:image', 'twitter:image'].each do |candidate|
153
+ it "should prefer #{candidate} over the Parsely image" do
154
+ html = %(<meta name="parsely-image-url" content="/parsely.jpg"><meta property="#{candidate}" content="/existing.jpg">)
155
+ page = MetaInspector.new('http://example.com/', document: html)
156
+
157
+ expect(page.images.owner_suggested).to eq('http://example.com/existing.jpg')
158
+ end
159
+ end
160
+
161
+ ['', ' &#10; '].each do |value|
162
+ it "should ignore an empty Parsely image (#{value.inspect})" do
163
+ page = MetaInspector.new('http://example.com/', document: %(<meta name="parsely-image-url" content="#{value}">))
164
+
165
+ expect(page.images.owner_suggested).to be_nil
166
+ end
167
+ end
168
+
106
169
  it "should find the og image" do
107
170
  page = MetaInspector.new('http://www.theonion.com/articles/apple-claims-new-iphone-only-visible-to-most-loyal,2772/')
108
171
 
@@ -135,6 +198,176 @@ describe MetaInspector do
135
198
  end
136
199
 
137
200
  describe "images.with_size" do
201
+ describe "max_image_downloads" do
202
+ let(:html) do
203
+ '<img src="/10x10"><img src="/100x100"><img src="/remaining.jpg">'
204
+ end
205
+
206
+ before do
207
+ stub_request(:get, 'http://example.com/remaining.jpg').to_return(status: 404)
208
+ end
209
+
210
+ it "should download only the first images needing dimensions in document order" do
211
+ page = MetaInspector.new('http://example.com/', document: html, max_image_downloads: 2)
212
+
213
+ expect(page.images.with_size).to eq([
214
+ ['http://example.com/100x100', 100, 100],
215
+ ['http://example.com/10x10', 10, 10],
216
+ ['http://example.com/remaining.jpg', 0, 0]
217
+ ])
218
+ expect(WebMock).to have_requested(:get, 'http://example.com/10x10').once
219
+ expect(WebMock).to have_requested(:get, 'http://example.com/100x100').once
220
+ expect(WebMock).not_to have_requested(:get, 'http://example.com/remaining.jpg')
221
+ end
222
+
223
+ it "should preserve HTML dimensions without consuming the download budget" do
224
+ html = '<img src="/known.jpg" width="200" height="200"><img src="/10x10"><img src="/100x100"><img src="/later.jpg" width="300" height="300">'
225
+ page = MetaInspector.new('http://example.com/', document: html, max_image_downloads: 1)
226
+
227
+ expect(page.images.with_size).to eq([
228
+ ['http://example.com/later.jpg', 300, 300],
229
+ ['http://example.com/known.jpg', 200, 200],
230
+ ['http://example.com/10x10', 10, 10],
231
+ ['http://example.com/100x100', 0, 0]
232
+ ])
233
+ expect(WebMock).to have_requested(:get, 'http://example.com/10x10').once
234
+ expect(WebMock).not_to have_requested(:get, 'http://example.com/100x100')
235
+ end
236
+
237
+ it "should exclude invalid and duplicate URLs before consuming the budget" do
238
+ html = '<img src="http://exa mple.com/broken.jpg"><img src="/10x10"><img src="http://example.com/10x10"><img src="/100x100"><img src="/remaining.jpg">'
239
+ page = MetaInspector.new('http://example.com/', document: html, max_image_downloads: 2)
240
+
241
+ expect(page.images.with_size).to eq([
242
+ ['http://example.com/100x100', 100, 100],
243
+ ['http://example.com/10x10', 10, 10],
244
+ ['http://example.com/remaining.jpg', 0, 0]
245
+ ])
246
+ expect(WebMock).to have_requested(:get, 'http://example.com/10x10').once
247
+ expect(WebMock).to have_requested(:get, 'http://example.com/100x100').once
248
+ expect(WebMock).not_to have_requested(:get, 'http://example.com/remaining.jpg')
249
+ end
250
+
251
+ it "should treat an image missing one HTML dimension as needing a download" do
252
+ html = '<img src="/10x10" width="500"><img src="/100x100" height="500">'
253
+ page = MetaInspector.new('http://example.com/', document: html, max_image_downloads: 1)
254
+
255
+ expect(page.images.with_size).to eq([
256
+ ['http://example.com/10x10', 10, 10],
257
+ ['http://example.com/100x100', 0, 0]
258
+ ])
259
+ expect(WebMock).to have_requested(:get, 'http://example.com/10x10').once
260
+ expect(WebMock).not_to have_requested(:get, 'http://example.com/100x100')
261
+ end
262
+
263
+ it "should disable downloads with a zero limit while preserving HTML dimensions" do
264
+ html = '<img src="/10x10"><img src="/known.jpg" width="200" height="100">'
265
+ page = MetaInspector.new('http://example.com/', document: html, max_image_downloads: 0)
266
+
267
+ expect(page.images.with_size).to eq([
268
+ ['http://example.com/known.jpg', 200, 100],
269
+ ['http://example.com/10x10', 0, 0]
270
+ ])
271
+ expect(WebMock).not_to have_requested(:get, 'http://example.com/10x10')
272
+ end
273
+
274
+ it "should respect download_images: false even with a positive limit" do
275
+ page = MetaInspector.new('http://example.com/', document: html, download_images: false, max_image_downloads: 2)
276
+
277
+ expect(page.images.with_size).to eq([
278
+ ['http://example.com/10x10', 0, 0],
279
+ ['http://example.com/100x100', 0, 0],
280
+ ['http://example.com/remaining.jpg', 0, 0]
281
+ ])
282
+ expect(WebMock).not_to have_requested(:get, %r{http://example.com/})
283
+ end
284
+
285
+ [nil, 10].each do |limit|
286
+ it "should download every candidate when the limit is #{limit.inspect}" do
287
+ page = MetaInspector.new('http://example.com/', document: html, max_image_downloads: limit)
288
+
289
+ expect(page.images.with_size).to eq([
290
+ ['http://example.com/100x100', 100, 100],
291
+ ['http://example.com/10x10', 10, 10],
292
+ ['http://example.com/remaining.jpg', 0, 0]
293
+ ])
294
+ expect(WebMock).to have_requested(:get, 'http://example.com/10x10').once
295
+ expect(WebMock).to have_requested(:get, 'http://example.com/100x100').once
296
+ expect(WebMock).to have_requested(:get, 'http://example.com/remaining.jpg').once
297
+ end
298
+ end
299
+
300
+ [:not_found, :invalid_image, :timeout].each do |failure|
301
+ it "should count a #{failure} image attempt toward the limit" do
302
+ request = stub_request(:get, 'http://example.com/broken.jpg')
303
+ case failure
304
+ when :not_found then request.to_return(status: 404)
305
+ when :invalid_image then request.to_return(body: 'not an image')
306
+ when :timeout then request.to_timeout
307
+ end
308
+ html = '<img src="/broken.jpg"><img src="/100x100">'
309
+ page = MetaInspector.new('http://example.com/', document: html, max_image_downloads: 1)
310
+
311
+ expect(page.images.with_size).to eq([
312
+ ['http://example.com/broken.jpg', 0, 0],
313
+ ['http://example.com/100x100', 0, 0]
314
+ ])
315
+ expect(request).to have_been_requested.once
316
+ expect(WebMock).not_to have_requested(:get, 'http://example.com/100x100')
317
+ end
318
+ end
319
+
320
+ it "should reuse the limited results for repeated size and best-image queries" do
321
+ page = MetaInspector.new('http://example.com/', document: html, max_image_downloads: 1)
322
+
323
+ 2.times do
324
+ expect(page.images.with_size.first).to eq(['http://example.com/10x10', 10, 10])
325
+ expect(page.images.largest).to eq('http://example.com/10x10')
326
+ expect(page.images.best).to eq('http://example.com/10x10')
327
+ end
328
+ expect(WebMock).to have_requested(:get, 'http://example.com/10x10').once
329
+ expect(WebMock).not_to have_requested(:get, 'http://example.com/100x100')
330
+ end
331
+
332
+ it "should keep the budget local to each document" do
333
+ 2.times do
334
+ page = MetaInspector.new('http://example.com/', document: html, max_image_downloads: 1)
335
+
336
+ expect(page.images.with_size.first).to eq(['http://example.com/10x10', 10, 10])
337
+ end
338
+ expect(WebMock).to have_requested(:get, 'http://example.com/10x10').twice
339
+ expect(WebMock).not_to have_requested(:get, 'http://example.com/100x100')
340
+ end
341
+
342
+ it "should keep all image URLs without downloading them when enumerating images" do
343
+ page = MetaInspector.new('http://example.com/', document: html, max_image_downloads: 1)
344
+
345
+ expect(page.images.to_a).to eq([
346
+ 'http://example.com/10x10',
347
+ 'http://example.com/100x100',
348
+ 'http://example.com/remaining.jpg'
349
+ ])
350
+ expect(WebMock).not_to have_requested(:get, %r{http://example.com/})
351
+ end
352
+ end
353
+
354
+ [true, false].each do |download_images|
355
+ it "should ignore unparseable image URLs with download_images: #{download_images}" do
356
+ html = '<html><body><img src="http://exa mple.com/x.png"><img src="/valid.png" width="100" height="100"></body></html>'
357
+ page = MetaInspector.new('https://example.com/', document: html, download_images: download_images)
358
+
359
+ expect(FastImage).not_to receive(:size).with(nil)
360
+ expect(page.images.with_size).to eq([["https://example.com/valid.png", 100, 100]])
361
+ end
362
+ end
363
+
364
+ it "should ignore unparseable image URLs even when HTML sizes are present" do
365
+ html = '<html><body><img src="http://exa mple.com/x.png" width="100" height="100"></body></html>'
366
+ page = MetaInspector.new('https://example.com/', document: html)
367
+
368
+ expect(page.images.with_size).to eq([])
369
+ end
370
+
138
371
  it "should return sorted by area array of [img_url, width, height] using html sizes" do
139
372
  page = MetaInspector.new('http://example.com/largest_image_in_html')
140
373
 
@@ -174,6 +174,28 @@ describe MetaInspector do
174
174
  end
175
175
 
176
176
  describe 'Relative links with relative base' do
177
+ [
178
+ ['assets/', 'https://example.com/posts/article', 'https://example.com/posts/assets/next.html'],
179
+ ['../assets/', 'https://example.com/posts/2026/article', 'https://example.com/posts/assets/next.html'],
180
+ ['assets/base.html', 'https://example.com/posts/article', 'https://example.com/posts/assets/next.html'],
181
+ ['assets/', 'https://example.com/posts/article/', 'https://example.com/posts/article/assets/next.html'],
182
+ ['/assets/', 'https://example.com:8443/posts/article', 'https://example.com:8443/assets/next.html']
183
+ ].each do |base_href, url, expected_link|
184
+ it "resolves base #{base_href.inspect} against #{url}" do
185
+ html = %(<html><head><base href="#{base_href}"></head><body><a href="next.html">Next</a></body></html>)
186
+ m = MetaInspector.new(url, document: html)
187
+
188
+ expect(m.links.all).to eq([expected_link])
189
+ end
190
+ end
191
+
192
+ it 'resolves image URLs against a document-relative base in a nested directory' do
193
+ html = '<html><head><base href="assets/"></head><body><img src="image.jpg"></body></html>'
194
+ m = MetaInspector.new('https://example.com/posts/article', document: html)
195
+
196
+ expect(m.images.to_a).to eq(['https://example.com/posts/assets/image.jpg'])
197
+ end
198
+
177
199
  it 'should get the relative links with relative directory base' do
178
200
  m = MetaInspector.new('http://relativewithrelativebase.com/relativedir')
179
201
  expect(m.links.all).to eq(['http://relativewithrelativebase.com/other/about',
@@ -5,14 +5,65 @@ describe MetaInspector do
5
5
  expect(MetaInspector.new('http://example.com').class).to eq(MetaInspector::Document)
6
6
  end
7
7
 
8
- it "cache request" do
9
- # Creates a memory cache (a Hash that responds to #read, #write and #delete)
10
- cache = Hash.new
11
- def cache.read(k) self[k]; end
12
- def cache.write(k, v) self[k] = v; end
8
+ describe "response caching" do
9
+ # A memory cache (a Hash that responds to #read and #write)
10
+ let(:cache) do
11
+ store = Hash.new
12
+ def store.read(k) self[k]; end
13
+ def store.write(k, v) self[k] = v; end
14
+ store
15
+ end
13
16
 
14
- MetaInspector.new('http://example.com', faraday_http_cache: { store: cache })
17
+ # The deprecation warning prints once per process, so each example starts as a fresh process would
18
+ before { MetaInspector::Request.instance_variable_set(:@faraday_http_cache_deprecation_warned, nil) }
15
19
 
16
- expect(cache.keys).not_to be_empty
20
+ it "caches responses with faraday_options[:faraday_http_cache]" do
21
+ MetaInspector.new('http://example.com', faraday_options: { faraday_http_cache: { store: cache } })
22
+
23
+ expect(cache.keys).not_to be_empty
24
+ end
25
+
26
+ it "does not warn when the cache is configured inside faraday_options" do
27
+ expect do
28
+ MetaInspector.new('http://example.com', faraday_options: { faraday_http_cache: { store: cache } })
29
+ end.not_to output.to_stderr
30
+ end
31
+
32
+ it "leaves the faraday_options hash it was given unchanged" do
33
+ cache_options = { store: cache }
34
+ faraday_options = { faraday_http_cache: cache_options }
35
+
36
+ MetaInspector.new('http://example.com', faraday_options: faraday_options)
37
+
38
+ expect(faraday_options).to eq({ faraday_http_cache: { store: cache } })
39
+ expect(cache_options).to eq({ store: cache })
40
+ end
41
+
42
+ it "still caches responses with the deprecated top-level faraday_http_cache option" do
43
+ expect do
44
+ MetaInspector.new('http://example.com', faraday_http_cache: { store: cache })
45
+ end.to output.to_stderr
46
+
47
+ expect(cache.keys).not_to be_empty
48
+ end
49
+
50
+ it "warns that the top-level faraday_http_cache option is deprecated" do
51
+ expect do
52
+ MetaInspector.new('http://example.com', faraday_http_cache: { store: cache })
53
+ end.to output(/DEPRECATION.*faraday_http_cache.*faraday_options/).to_stderr
54
+ end
55
+
56
+ it "prints the deprecation warning only once per process" do
57
+ expect do
58
+ 3.times { MetaInspector.new('http://example.com', faraday_http_cache: { store: cache }) }
59
+ end.to output(/\ADEPRECATION WARNING: [^\n]*\n\z/).to_stderr
60
+ end
61
+
62
+ it "raises ArgumentError when the cache is configured in both places" do
63
+ expect do
64
+ MetaInspector.new('http://example.com', faraday_http_cache: { store: cache },
65
+ faraday_options: { faraday_http_cache: { store: cache } })
66
+ end.to raise_error(ArgumentError, /faraday_http_cache/)
67
+ end
17
68
  end
18
69
  end
@@ -52,22 +52,36 @@ describe MetaInspector do
52
52
  end
53
53
 
54
54
  context "when there is a callback to be ran between redirects that blocks redirections to private IP addresses" do
55
- it "raises an exception" do
56
- stub_request(:get, "https://www.facebook.com/")
57
- .to_return(:status => 302,
58
- :headers => { "Location" => "http://10.0.0.0/" })
59
-
60
- redirect_options = {
55
+ let(:redirect_options) do
56
+ {
61
57
  callback: proc do |_previous_response, next_request|
62
58
  ip_address = Resolv.getaddress(next_request.url.host)
63
59
  raise PrivateIPAddressError if IPAddr.new(ip_address).private?
64
60
  end
65
61
  }
62
+ end
63
+
64
+ before do
65
+ stub_request(:get, "https://www.facebook.com/")
66
+ .to_return(:status => 302,
67
+ :headers => { "Location" => "http://10.0.0.0/" })
68
+ end
66
69
 
70
+ it "raises an exception" do
67
71
  expect {
68
72
  MetaInspector.new("https://www.facebook.com/", faraday_options: { redirect: redirect_options })
69
73
  }.to raise_error PrivateIPAddressError
70
74
  end
75
+
76
+ it "keeps running the callback when the same faraday_options are reused" do
77
+ faraday_options = { redirect: redirect_options }
78
+
79
+ 2.times do
80
+ expect {
81
+ MetaInspector.new("https://www.facebook.com/", faraday_options: faraday_options)
82
+ }.to raise_error PrivateIPAddressError
83
+ end
84
+ end
71
85
  end
72
86
  end
73
87
 
@@ -1,6 +1,50 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe MetaInspector do
4
+ describe '#language' do
5
+ ['en', 'en-US', 'zh-Hant-TW'].each do |language|
6
+ it "should return the declared language #{language.inspect}" do
7
+ page = MetaInspector.new('http://example.com/', document: %(<html lang="#{language}"><body></body></html>))
8
+
9
+ expect(page.language).to eq(language)
10
+ end
11
+ end
12
+
13
+ it 'should strip surrounding whitespace from the declared language' do
14
+ page = MetaInspector.new('http://example.com/', document: "<html lang=\" \t en-US \n \"><body></body></html>")
15
+
16
+ expect(page.language).to eq('en-US')
17
+ end
18
+
19
+ [nil, '', " \t\n "].each do |value|
20
+ it "should return nil for a missing or blank language (#{value.inspect})" do
21
+ attribute = value.nil? ? '' : %( lang="#{value}")
22
+ page = MetaInspector.new('http://example.com/', document: "<html#{attribute}><body></body></html>")
23
+
24
+ expect(page.language).to be_nil
25
+ end
26
+ end
27
+
28
+ it 'should read the root language rather than a descendant language' do
29
+ page = MetaInspector.new('http://example.com/', document: '<html lang="en"><body lang="es"></body></html>')
30
+
31
+ expect(page.language).to eq('en')
32
+ end
33
+
34
+ it 'should not infer language from xml:lang, metadata, or descendants' do
35
+ html = '<html xml:lang="fr"><head><meta http-equiv="content-language" content="de"></head><body lang="es">Hello</body></html>'
36
+ page = MetaInspector.new('http://example.com/', document: html)
37
+
38
+ expect(page.language).to be_nil
39
+ end
40
+
41
+ it 'should return the declared language from a fetched document' do
42
+ page = MetaInspector.new('http://pagerankalert.com/')
43
+
44
+ expect(page.language).to eq('en')
45
+ end
46
+ end
47
+
4
48
  it "should get the title from the head section" do
5
49
  page = MetaInspector.new('http://example.com')
6
50
  expect(page.title).to eq('An example page')
@@ -49,6 +93,42 @@ describe MetaInspector do
49
93
  end
50
94
 
51
95
  describe '#best_title' do
96
+ it 'should use the Parsely title when no existing candidate is present' do
97
+ page = MetaInspector.new('http://example.com/', document: '<meta name="parsely-title" content=" A Parsely&#10; title ">')
98
+
99
+ expect(page.best_title).to eq('A Parsely title')
100
+ end
101
+
102
+ it 'should use the Parsely title when existing candidates are empty' do
103
+ html = '<html><head><meta name="title" content=" "><meta property="og:title" content=""><title> </title><meta name="parsely-title" content="Parsely title"></head><body><h1> </h1></body></html>'
104
+ page = MetaInspector.new('http://example.com/', document: html)
105
+
106
+ expect(page.best_title).to eq('Parsely title')
107
+ end
108
+
109
+ [
110
+ ['<meta name="title" content="Existing title">', ''],
111
+ ['<meta property="og:title" content="Existing title">', ''],
112
+ ['<title>Existing title</title>', ''],
113
+ ['', '<title>Existing title</title>'],
114
+ ['', '<h1>Existing title</h1>']
115
+ ].each do |head, body|
116
+ it "should prefer #{head + body} over the Parsely title" do
117
+ html = %(<html><head><meta name="parsely-title" content="Parsely title">#{head}</head><body>#{body}</body></html>)
118
+ page = MetaInspector.new('http://example.com/', document: html)
119
+
120
+ expect(page.best_title).to eq('Existing title')
121
+ end
122
+ end
123
+
124
+ ['', ' &#10; '].each do |value|
125
+ it "should ignore an empty Parsely title (#{value.inspect})" do
126
+ page = MetaInspector.new('http://example.com/', document: %(<meta name="parsely-title" content="#{value}">))
127
+
128
+ expect(page.best_title).to be_nil
129
+ end
130
+ end
131
+
52
132
  it "should find 'head title' when that's the only thing" do
53
133
  page = MetaInspector.new('http://example.com/title_in_head')
54
134
  expect(page.best_title).to eq('This title came from the head')
@@ -105,6 +185,41 @@ describe MetaInspector do
105
185
  end
106
186
 
107
187
  describe "#best_author" do
188
+ it 'should use the Parsely author when no existing candidate is present' do
189
+ page = MetaInspector.new('http://example.com/', document: '<meta name="parsely-author" content=" A Parsely&#10; author ">')
190
+
191
+ expect(page.best_author).to eq('A Parsely author')
192
+ end
193
+
194
+ it 'should use the Parsely author when existing candidates are empty' do
195
+ html = '<meta name="author" content=" "><meta name="twitter:creator" content=""><meta name="parsely-author" content="Parsely author"><a rel="author"> </a><address> </address>'
196
+ page = MetaInspector.new('http://example.com/', document: html)
197
+
198
+ expect(page.best_author).to eq('Parsely author')
199
+ end
200
+
201
+ [
202
+ '<meta name="author" content="Existing author">',
203
+ '<a rel="author">Existing author</a>',
204
+ '<address>Existing author</address>',
205
+ '<meta name="twitter:creator" content="Existing author">'
206
+ ].each do |candidate|
207
+ it "should prefer #{candidate} over the Parsely author" do
208
+ html = '<meta name="parsely-author" content="Parsely author">' + candidate
209
+ page = MetaInspector.new('http://example.com/', document: html)
210
+
211
+ expect(page.best_author).to eq('Existing author')
212
+ end
213
+ end
214
+
215
+ ['', ' &#10; '].each do |value|
216
+ it "should ignore an empty Parsely author (#{value.inspect})" do
217
+ page = MetaInspector.new('http://example.com/', document: %(<meta name="parsely-author" content="#{value}">))
218
+
219
+ expect(page.best_author).to be_nil
220
+ end
221
+ end
222
+
108
223
  it "should return the author meta tag content if present" do
109
224
  page = MetaInspector.new('http://example.com/author_in_meta')
110
225
 
data/spec/request_spec.rb CHANGED
@@ -68,6 +68,35 @@ describe MetaInspector::Request do
68
68
  end
69
69
  end
70
70
 
71
+ describe "options it is given" do
72
+ it "accepts a frozen faraday_options hash" do
73
+ expect do
74
+ MetaInspector::Request.new(url('http://example.com'), faraday_options: { ssl: { verify: true } }.freeze)
75
+ end.not_to raise_error
76
+ end
77
+
78
+ it "leaves the faraday_options hash unchanged" do
79
+ callback = proc {}
80
+ faraday_options = { redirect: { callback: callback } }
81
+
82
+ MetaInspector::Request.new(url('http://example.com'), allow_redirections: true,
83
+ faraday_options: faraday_options)
84
+
85
+ expect(faraday_options).to eq({ redirect: { callback: callback } })
86
+ end
87
+
88
+ it "leaves the faraday_http_cache hash unchanged" do
89
+ cache = Hash.new
90
+ def cache.read(k) self[k]; end
91
+ def cache.write(k, v) self[k] = v; end
92
+ cache_options = { store: cache }
93
+
94
+ MetaInspector::Request.new(url('http://example.com'), faraday_options: { faraday_http_cache: cache_options })
95
+
96
+ expect(cache_options).to eq({ store: cache })
97
+ end
98
+ end
99
+
71
100
  describe 'exception handling' do
72
101
  before(:each) do
73
102
  WebMock.allow_net_connect!