link_thumbnailer 1.1.2 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/.travis.yml +1 -1
- data/CHANGELOG.md +117 -104
- data/Gemfile +1 -1
- data/{LICENSE → LICENSE.txt} +21 -21
- data/README.md +153 -184
- data/lib/generators/link_thumbnailer/install_generator.rb +0 -4
- data/lib/generators/templates/initializer.rb +63 -41
- data/lib/link_thumbnailer/configuration.rb +52 -10
- data/lib/link_thumbnailer/exceptions.rb +6 -0
- data/lib/link_thumbnailer/grader.rb +37 -0
- data/lib/link_thumbnailer/graders/base.rb +32 -0
- data/lib/link_thumbnailer/graders/html_attribute.rb +49 -0
- data/lib/link_thumbnailer/graders/length.rb +19 -0
- data/lib/link_thumbnailer/graders/link_density.rb +21 -0
- data/lib/link_thumbnailer/graders/position.rb +11 -0
- data/lib/link_thumbnailer/image_comparator.rb +24 -0
- data/lib/link_thumbnailer/image_comparators/base.rb +17 -0
- data/lib/link_thumbnailer/image_comparators/size.rb +11 -0
- data/lib/link_thumbnailer/image_parser.rb +18 -0
- data/lib/link_thumbnailer/image_parsers/size.rb +15 -0
- data/lib/link_thumbnailer/image_parsers/type.rb +15 -0
- data/lib/link_thumbnailer/image_validator.rb +30 -0
- data/lib/link_thumbnailer/model.rb +16 -0
- data/lib/link_thumbnailer/models/description.rb +34 -0
- data/lib/link_thumbnailer/models/image.rb +54 -0
- data/lib/link_thumbnailer/models/title.rb +20 -0
- data/lib/link_thumbnailer/models/website.rb +39 -0
- data/lib/link_thumbnailer/page.rb +40 -0
- data/lib/link_thumbnailer/parser.rb +13 -0
- data/lib/link_thumbnailer/processor.rb +94 -0
- data/lib/link_thumbnailer/railtie.rb +9 -9
- data/lib/link_thumbnailer/scraper.rb +64 -0
- data/lib/link_thumbnailer/scrapers/base.rb +63 -0
- data/lib/link_thumbnailer/scrapers/default/base.rb +10 -0
- data/lib/link_thumbnailer/scrapers/default/description.rb +47 -0
- data/lib/link_thumbnailer/scrapers/default/images.rb +64 -0
- data/lib/link_thumbnailer/scrapers/default/title.rb +25 -0
- data/lib/link_thumbnailer/scrapers/opengraph/base.rb +43 -0
- data/lib/link_thumbnailer/scrapers/opengraph/description.rb +10 -0
- data/lib/link_thumbnailer/scrapers/opengraph/image.rb +30 -0
- data/lib/link_thumbnailer/scrapers/opengraph/images.rb +16 -0
- data/lib/link_thumbnailer/scrapers/opengraph/title.rb +10 -0
- data/lib/link_thumbnailer/version.rb +3 -3
- data/lib/link_thumbnailer.rb +36 -119
- data/link_thumbnailer.gemspec +26 -28
- data/spec/configuration_spec.rb +51 -0
- data/spec/examples/empty_og_image_example.html +9 -0
- data/spec/fixture_spec.rb +88 -0
- data/spec/fixtures/bar.png +2907 -0
- data/spec/fixtures/default_from_body.html +12 -0
- data/spec/fixtures/default_from_meta.html +11 -0
- data/spec/{examples → fixtures}/example.html +53 -53
- data/spec/fixtures/foo.png +0 -0
- data/spec/fixtures/og_not_valid_example.html +12 -0
- data/spec/fixtures/og_valid_example.html +12 -0
- data/spec/fixtures/og_valid_multi_image_example.html +13 -0
- data/spec/grader_spec.rb +24 -0
- data/spec/graders/base_spec.rb +12 -0
- data/spec/graders/html_attribute_spec.rb +48 -0
- data/spec/graders/length_spec.rb +81 -0
- data/spec/graders/link_density_spec.rb +22 -0
- data/spec/image_comparators/size_spec.rb +39 -0
- data/spec/image_parsers/size_spec.rb +34 -0
- data/spec/image_parsers/type_spec.rb +34 -0
- data/spec/image_validator_spec.rb +35 -0
- data/spec/model_spec.rb +17 -0
- data/spec/models/description_spec.rb +64 -0
- data/spec/models/image_spec.rb +71 -0
- data/spec/models/title_spec.rb +24 -0
- data/spec/models/website_spec.rb +49 -0
- data/spec/page_spec.rb +26 -0
- data/spec/processor_spec.rb +349 -0
- data/spec/scraper_spec.rb +95 -0
- data/spec/scrapers/base_spec.rb +67 -0
- data/spec/scrapers/opengraph/base_spec.rb +94 -0
- data/spec/spec_helper.rb +15 -13
- metadata +126 -120
- data/app/controllers/link_thumbnailer/application_controller.rb +0 -4
- data/app/controllers/link_thumbnailer/previews_controller.rb +0 -11
- data/lib/link_thumbnailer/doc.rb +0 -65
- data/lib/link_thumbnailer/doc_parser.rb +0 -15
- data/lib/link_thumbnailer/engine.rb +0 -4
- data/lib/link_thumbnailer/fetcher.rb +0 -34
- data/lib/link_thumbnailer/img_comparator.rb +0 -17
- data/lib/link_thumbnailer/img_parser.rb +0 -41
- data/lib/link_thumbnailer/img_url_filter.rb +0 -13
- data/lib/link_thumbnailer/object.rb +0 -41
- data/lib/link_thumbnailer/opengraph.rb +0 -20
- data/lib/link_thumbnailer/rails/routes/mapper.rb +0 -30
- data/lib/link_thumbnailer/rails/routes/mapping.rb +0 -33
- data/lib/link_thumbnailer/rails/routes.rb +0 -47
- data/lib/link_thumbnailer/web_image.rb +0 -19
- data/spec/doc_parser_spec.rb +0 -25
- data/spec/doc_spec.rb +0 -23
- data/spec/examples/empty_example.html +0 -11
- data/spec/examples/og_example.html +0 -12
- data/spec/fetcher_spec.rb +0 -97
- data/spec/img_comparator_spec.rb +0 -16
- data/spec/img_url_filter_spec.rb +0 -31
- data/spec/link_thumbnailer_spec.rb +0 -205
- data/spec/object_spec.rb +0 -130
- data/spec/opengraph_spec.rb +0 -7
- data/spec/web_image_spec.rb +0 -57
@@ -2,7 +2,7 @@
|
|
2
2
|
<!-- saved from url=(0019)http://www.foo.com/ -->
|
3
3
|
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
4
4
|
<meta charset="UTF-8">
|
5
|
-
<title>
|
5
|
+
<title>Title</title>
|
6
6
|
<link href="./example_files/style-3706572431311a3a4cf5c6f3266c9bce.css" media="all" rel="stylesheet" type="text/css">
|
7
7
|
<link href="./example_files/belt_layout1_google-1c8ee8bd905a6121e7a7ac73b7ffb888.css" media="all" rel="stylesheet" type="text/css">
|
8
8
|
<script src="./example_files/application-e8b3208729190cb9cc8a800ff3283fd8.js" type="text/javascript"></script>
|
@@ -111,9 +111,9 @@ function gadlink(ga, inner_text, visible_url){
|
|
111
111
|
visible_url = visible_url.replace(/<b>/gi,'')
|
112
112
|
visible_url = visible_url.replace(/<\/b>/gi,'')
|
113
113
|
return '<a ' +
|
114
|
-
'href="http://' + visible_url + '"' +
|
114
|
+
'href="http://' + visible_url + '"' +
|
115
115
|
' onclick="window.open(\'' + ga.url + '\');return false;"' +
|
116
|
-
' target="_blank" ' +
|
116
|
+
' target="_blank" ' +
|
117
117
|
'>' +
|
118
118
|
inner_text + '</a>';
|
119
119
|
|
@@ -138,7 +138,7 @@ function google_afd_ad_request_done(google_afd_response) {
|
|
138
138
|
ads="";
|
139
139
|
ads +=
|
140
140
|
'<div class="listing"><div class="url">' +
|
141
|
-
gadlink(google_ads[i], google_ads[i].line1, google_ads[i].visible_url) +
|
141
|
+
gadlink(google_ads[i], google_ads[i].line1, google_ads[i].visible_url) +
|
142
142
|
'</div>';
|
143
143
|
if (seller_ratings) {
|
144
144
|
ads += '<div class="ratings">'+seller_ratings.advertiser_info+' <img src="/assets/'+seller_ratings.rating+'star.gif" border="0"> <a href="'+seller_ratings.source_url+'" target="_blank">('+seller_ratings.review_count+')</a></div>';
|
@@ -147,7 +147,7 @@ function google_afd_ad_request_done(google_afd_response) {
|
|
147
147
|
'<div class="description">' + google_ads[i].line2 + ' ' +
|
148
148
|
(google_ads[i].line3 != undefined ? google_ads[i].line3 + '' : '') +
|
149
149
|
'</div>' +
|
150
|
-
'<div class="host">' +
|
150
|
+
'<div class="host">' +
|
151
151
|
gadlink(google_ads[i], google_ads[i].visible_url, google_ads[i].visible_url) +
|
152
152
|
'</div>';
|
153
153
|
if (site_links && site_links.length > 0) {
|
@@ -156,8 +156,8 @@ function google_afd_ad_request_done(google_afd_response) {
|
|
156
156
|
if(x % 2 == 0){
|
157
157
|
ads += '<tr>';
|
158
158
|
}
|
159
|
-
ads +=
|
160
|
-
'<td class="sitelink">' +
|
159
|
+
ads +=
|
160
|
+
'<td class="sitelink">' +
|
161
161
|
gadlink(site_links[x], site_links[x].link_text, google_ads[i].visible_url) +
|
162
162
|
'</td>';
|
163
163
|
if(x % 2 == 1){
|
@@ -183,26 +183,26 @@ function google_afd_ad_request_done(google_afd_response) {
|
|
183
183
|
var google_categories = google_afd_response.categories;
|
184
184
|
for (var i = 0; i < google_categories.length; i++) {
|
185
185
|
subcats = google_categories[i].subcategories;
|
186
|
-
popularCategories =
|
187
|
-
'<div class="termgroup">' +
|
188
|
-
'<h3><a class="popular_category" ' +
|
189
|
-
'href="/#' + google_categories[i].term + '"' +
|
186
|
+
popularCategories =
|
187
|
+
'<div class="termgroup">' +
|
188
|
+
'<h3><a class="popular_category" ' +
|
189
|
+
'href="/#' + google_categories[i].term + '"' +
|
190
190
|
' onclick="window.location=\'/results' +
|
191
191
|
'?q=' + encodeURIComponent(google_categories[i].term) +
|
192
192
|
'&token=' + google_categories[i].token + '\';return false;"' +
|
193
|
-
'>' +
|
194
|
-
google_categories[i].term +
|
193
|
+
'>' +
|
194
|
+
google_categories[i].term +
|
195
195
|
'</a></h3>';
|
196
196
|
for(var gci =0; gci < subcats.length; gci++){
|
197
197
|
popularCategories = popularCategories +
|
198
|
-
'<div class="term">' +
|
199
|
-
'<a class="popular_category" ' +
|
200
|
-
'href="/#' + subcats[gci].term + '"' +
|
198
|
+
'<div class="term">' +
|
199
|
+
'<a class="popular_category" ' +
|
200
|
+
'href="/#' + subcats[gci].term + '"' +
|
201
201
|
' onclick="window.location=\'/results' +
|
202
202
|
'?q=' + encodeURIComponent(subcats[gci].term) +
|
203
203
|
'&token=' + subcats[gci].token + '\';return false;"' +
|
204
|
-
'>' +
|
205
|
-
subcats[gci].term +
|
204
|
+
'>' +
|
205
|
+
subcats[gci].term +
|
206
206
|
'</a></div>';
|
207
207
|
}
|
208
208
|
popularCategories = popularCategories + '</div>';
|
@@ -214,58 +214,58 @@ function google_afd_ad_request_done(google_afd_response) {
|
|
214
214
|
var google_link_units = google_afd_response.link_units;
|
215
215
|
for (var i = 0; i < google_link_units.length; i++) {
|
216
216
|
relatedSearches =
|
217
|
-
'<div class="term">' +
|
218
|
-
'<a class="related_searches" ' +
|
219
|
-
'href="/#' + google_link_units[i].term + '"' +
|
217
|
+
'<div class="term">' +
|
218
|
+
'<a class="related_searches" ' +
|
219
|
+
'href="/#' + google_link_units[i].term + '"' +
|
220
220
|
' onclick="window.location=\'/results' +
|
221
221
|
'?q=' + encodeURIComponent(google_link_units[i].term) +
|
222
222
|
'&token=' + google_link_units[i].token + '\';return false;"' +
|
223
223
|
'>' +
|
224
|
-
google_link_units[i].term +
|
225
|
-
'</a>' +
|
224
|
+
google_link_units[i].term +
|
225
|
+
'</a>' +
|
226
226
|
'</div>';
|
227
227
|
relatedSearches_array.push(relatedSearches);
|
228
228
|
}
|
229
|
-
|
229
|
+
|
230
230
|
}
|
231
231
|
if (google_afd_response.link_units && google_afd_response.link_units.length > 0) {
|
232
|
-
var google_link_units = google_afd_response.link_units;
|
233
|
-
for (var i = 0; i < google_link_units.length; i++) {
|
234
|
-
relatedSearches = "";
|
235
|
-
if(i % 5 == 0){
|
236
|
-
relatedSearches += "<div class='termgroup'>";
|
237
|
-
}
|
238
|
-
relatedSearches +=
|
239
|
-
'<div class="term">' +
|
240
|
-
'<a class="related_searches" ' +
|
241
|
-
'href="/#' + google_link_units[i].term + '"' +
|
242
|
-
' onclick="window.location=\'/results' +
|
243
|
-
'?q=' + encodeURIComponent(google_link_units[i].term) +
|
244
|
-
'&token=' + google_link_units[i].token + '\';return false;"' +
|
245
|
-
'>' +
|
246
|
-
google_link_units[i].term +
|
247
|
-
'</a>' +
|
248
|
-
'</div>';
|
232
|
+
var google_link_units = google_afd_response.link_units;
|
233
|
+
for (var i = 0; i < google_link_units.length; i++) {
|
234
|
+
relatedSearches = "";
|
235
|
+
if(i % 5 == 0){
|
236
|
+
relatedSearches += "<div class='termgroup'>";
|
237
|
+
}
|
238
|
+
relatedSearches +=
|
239
|
+
'<div class="term">' +
|
240
|
+
'<a class="related_searches" ' +
|
241
|
+
'href="/#' + google_link_units[i].term + '"' +
|
242
|
+
' onclick="window.location=\'/results' +
|
243
|
+
'?q=' + encodeURIComponent(google_link_units[i].term) +
|
244
|
+
'&token=' + google_link_units[i].token + '\';return false;"' +
|
245
|
+
'>' +
|
246
|
+
google_link_units[i].term +
|
247
|
+
'</a>' +
|
248
|
+
'</div>';
|
249
249
|
if(((i % 5) == 4) || ((i-1)==google_link_units.length)){
|
250
|
-
relatedSearches += "</div>";
|
251
|
-
}
|
252
|
-
if(((i+1) % 10 == 0)){
|
253
|
-
relatedSearches += "<div class='clear'> </div>";
|
254
|
-
}
|
255
|
-
genCatSearches_array.push(relatedSearches);
|
256
|
-
}
|
257
|
-
|
250
|
+
relatedSearches += "</div>";
|
251
|
+
}
|
252
|
+
if(((i+1) % 10 == 0)){
|
253
|
+
relatedSearches += "<div class='clear'> </div>";
|
254
|
+
}
|
255
|
+
genCatSearches_array.push(relatedSearches);
|
256
|
+
}
|
257
|
+
|
258
258
|
}
|
259
259
|
try{document.getElementById('results').innerHTML = ads_array.join("\n");}catch(error){}
|
260
260
|
try{document.getElementById('bottomresults').innerHTML = bottom_ads_array.join("\n");}catch(error){}
|
261
|
-
|
261
|
+
|
262
262
|
if(ads_array.length>1){
|
263
263
|
document.getElementById('sponsoredresults').style.display='block';
|
264
264
|
}
|
265
265
|
if(bottom_ads_array.length>1){
|
266
266
|
document.getElementById('bottomsponsoredresults').style.display='block';
|
267
267
|
}
|
268
|
-
|
268
|
+
|
269
269
|
try{document.getElementById('keywords').innerHTML = relatedSearches_array.join("\n");}catch(error){}
|
270
270
|
try{document.getElementById('gencats').innerHTML = genCatSearches_array.join("\n");}catch(error){}
|
271
271
|
// if(genCatSearches_array.length==0){
|
@@ -325,7 +325,7 @@ function getParam(name) {
|
|
325
325
|
|
326
326
|
<div id="footer">
|
327
327
|
<a href="http://www.foo.com/digimedia_privacy_policy.html" target="_blank">Privacy Policy</a>
|
328
|
-
-
|
328
|
+
-
|
329
329
|
© 2012 Digimedia.com, L.P.
|
330
330
|
</div>
|
331
331
|
|
@@ -360,4 +360,4 @@ channel: 'afsonly'
|
|
360
360
|
|
361
361
|
|
362
362
|
|
363
|
-
</body></html>
|
363
|
+
</body></html>
|
Binary file
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<html xmlns:og="http://opengraphprotocol.org/schema/">
|
2
|
+
<head>
|
3
|
+
<meta charset="utf-8"/>
|
4
|
+
<meta name="og:type" content="website"/>
|
5
|
+
<meta name="og:site_name" content="foo.com">
|
6
|
+
<meta name="og:title" content="Title from og">
|
7
|
+
<meta name="og:description" content="Description from og">
|
8
|
+
<meta name="og:image" content="http://foo.com/foo.png">
|
9
|
+
<title>Title</title>
|
10
|
+
</head>
|
11
|
+
|
12
|
+
</html>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<html xmlns:og="http://opengraphprotocol.org/schema/">
|
2
|
+
<head>
|
3
|
+
<meta charset="utf-8"/>
|
4
|
+
<meta property="og:type" content="website"/>
|
5
|
+
<meta property="og:site_name" content="foo.com">
|
6
|
+
<meta property="og:title" content="Title from og">
|
7
|
+
<meta property="og:description" content="Description from og">
|
8
|
+
<meta property="og:image" content="http://foo.com/foo.png">
|
9
|
+
<title>Title</title>
|
10
|
+
</head>
|
11
|
+
|
12
|
+
</html>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<html xmlns:og="http://opengraphprotocol.org/schema/">
|
2
|
+
<head>
|
3
|
+
<meta charset="utf-8"/>
|
4
|
+
<meta property="og:type" content="website"/>
|
5
|
+
<meta property="og:site_name" content="foo.com">
|
6
|
+
<meta property="og:title" content="Title from og">
|
7
|
+
<meta property="og:description" content="Description from og">
|
8
|
+
<meta property="og:image" content="http://foo.com/foo.png">
|
9
|
+
<meta property="og:image" content="http://foo.com/bar.png">
|
10
|
+
<title>Title</title>
|
11
|
+
</head>
|
12
|
+
|
13
|
+
</html>
|
data/spec/grader_spec.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe LinkThumbnailer::Grader do
|
4
|
+
|
5
|
+
let(:description) { double('description') }
|
6
|
+
let(:instance) { described_class.new(description) }
|
7
|
+
|
8
|
+
describe '#call' do
|
9
|
+
|
10
|
+
let(:score) { 10 }
|
11
|
+
let(:grader) { double('grader', call: score) }
|
12
|
+
let(:lambda) { ->(_) { grader } }
|
13
|
+
let(:graders) { [lambda, lambda] }
|
14
|
+
let(:action) { instance.call }
|
15
|
+
|
16
|
+
before do
|
17
|
+
instance.stub(:graders).and_return(graders)
|
18
|
+
end
|
19
|
+
|
20
|
+
it { expect(action).to eq(score * graders.size) }
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe LinkThumbnailer::Graders::Base do
|
4
|
+
|
5
|
+
let(:description) { double('description', node: node) }
|
6
|
+
let(:node) { double('node', text: 'foo') }
|
7
|
+
let(:instance) { described_class.new(description) }
|
8
|
+
|
9
|
+
it { expect(instance.send(:node)).to eq(description.node) }
|
10
|
+
it { expect(instance.send(:text)).to eq(description.node.text) }
|
11
|
+
|
12
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe LinkThumbnailer::Graders::HtmlAttribute do
|
4
|
+
|
5
|
+
let(:description) { double('description') }
|
6
|
+
let(:instance) { described_class.new(description, :class) }
|
7
|
+
|
8
|
+
describe '#call' do
|
9
|
+
|
10
|
+
let(:action) { instance.call(0) }
|
11
|
+
|
12
|
+
context 'when current node does not match attribute' do
|
13
|
+
|
14
|
+
before do
|
15
|
+
instance.stub(:attribute?).and_return(false)
|
16
|
+
end
|
17
|
+
|
18
|
+
it { expect(action).to eq(0) }
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'when current node has a negative attribute' do
|
23
|
+
|
24
|
+
before do
|
25
|
+
instance.stub(:attribute?).and_return(true)
|
26
|
+
instance.stub(:negative?).and_return(true)
|
27
|
+
instance.stub(:positive?).and_return(false)
|
28
|
+
end
|
29
|
+
|
30
|
+
it { expect(action).to eq(-25) }
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'when current node has a positive attribute' do
|
35
|
+
|
36
|
+
before do
|
37
|
+
instance.stub(:attribute?).and_return(true)
|
38
|
+
instance.stub(:negative?).and_return(false)
|
39
|
+
instance.stub(:positive?).and_return(true)
|
40
|
+
end
|
41
|
+
|
42
|
+
it { expect(action).to eq(25) }
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe LinkThumbnailer::Graders::Length do
|
4
|
+
|
5
|
+
let(:config) { double('config') }
|
6
|
+
let(:description) { double('description') }
|
7
|
+
let(:instance) { described_class.new(description) }
|
8
|
+
|
9
|
+
before do
|
10
|
+
instance.stub(:config).and_return(config)
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#call' do
|
14
|
+
|
15
|
+
let(:action) { instance.call(0) }
|
16
|
+
|
17
|
+
context 'when text is too short' do
|
18
|
+
|
19
|
+
before do
|
20
|
+
instance.stub(:too_short?).and_return(true)
|
21
|
+
end
|
22
|
+
|
23
|
+
it { expect(action).to eq(-Float::INFINITY) }
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'when text is not too short' do
|
28
|
+
|
29
|
+
before do
|
30
|
+
instance.stub(:too_short?).and_return(false)
|
31
|
+
instance.stub(:text).and_return(text)
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'when text length is greater than 400' do
|
35
|
+
|
36
|
+
let(:text) { 'f' * 400 }
|
37
|
+
|
38
|
+
it { expect(action).to eq(3) }
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'when text length is less than 300' do
|
43
|
+
|
44
|
+
let(:text) { 'f' * 299 }
|
45
|
+
|
46
|
+
it { expect(action).to eq(2) }
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
describe '#too_short?' do
|
55
|
+
|
56
|
+
let(:action) { instance.send(:too_short?) }
|
57
|
+
|
58
|
+
before do
|
59
|
+
instance.stub_chain(:config, :description_min_length).and_return(10)
|
60
|
+
instance.stub(:text).and_return(text)
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'when true' do
|
64
|
+
|
65
|
+
let(:text) { 'f' * 9 }
|
66
|
+
|
67
|
+
it { expect(action).to be_true }
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'when false' do
|
72
|
+
|
73
|
+
let(:text) { 'f' * 10 }
|
74
|
+
|
75
|
+
it { expect(action).to be_false }
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe LinkThumbnailer::Graders::LinkDensity do
|
4
|
+
|
5
|
+
let(:description) { double('description') }
|
6
|
+
let(:instance) { described_class.new(description) }
|
7
|
+
|
8
|
+
describe '#call' do
|
9
|
+
|
10
|
+
let(:previous_score) { 1 }
|
11
|
+
let(:density) { 10 }
|
12
|
+
let(:action) { instance.call(previous_score) }
|
13
|
+
|
14
|
+
before do
|
15
|
+
instance.stub(:density).and_return(density)
|
16
|
+
end
|
17
|
+
|
18
|
+
it { expect(action).to eq(-9) }
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe LinkThumbnailer::ImageComparators::Size do
|
4
|
+
|
5
|
+
let(:image) { double(size: [20, 20]) }
|
6
|
+
let(:instance) { described_class.new(image) }
|
7
|
+
|
8
|
+
describe '#call' do
|
9
|
+
|
10
|
+
let(:other) { double(size: other_size) }
|
11
|
+
let(:action) { instance.call(other) }
|
12
|
+
|
13
|
+
context 'when other has a better image' do
|
14
|
+
|
15
|
+
let(:other_size) { [10, 10] }
|
16
|
+
|
17
|
+
it { expect(action).to eq(-1) }
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'when other has an identical image' do
|
22
|
+
|
23
|
+
let(:other_size) { [20, 20] }
|
24
|
+
|
25
|
+
it { expect(action).to eq(0) }
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'when other has a weaker image' do
|
30
|
+
|
31
|
+
let(:other_size) { [30, 30] }
|
32
|
+
|
33
|
+
it { expect(action).to eq(1) }
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe LinkThumbnailer::ImageParsers::Size do
|
4
|
+
|
5
|
+
describe '.perform' do
|
6
|
+
|
7
|
+
let(:size) { [10, 10] }
|
8
|
+
let(:src) { 'http://foo.com' }
|
9
|
+
let(:image) { double(src: src) }
|
10
|
+
let(:action) { described_class.perform(image) }
|
11
|
+
|
12
|
+
context 'when no exception is raised' do
|
13
|
+
|
14
|
+
before do
|
15
|
+
expect(FastImage).to receive(:size).with(src, raise_on_failure: true).and_return(size)
|
16
|
+
end
|
17
|
+
|
18
|
+
it { expect(action).to eq(size) }
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'when an exception is raised' do
|
23
|
+
|
24
|
+
before do
|
25
|
+
expect(FastImage).to receive(:size).with(src, raise_on_failure: true).and_raise(FastImage::FastImageException)
|
26
|
+
end
|
27
|
+
|
28
|
+
it { expect(action).to eq([0, 0]) }
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe LinkThumbnailer::ImageParsers::Type do
|
4
|
+
|
5
|
+
describe '.perform' do
|
6
|
+
|
7
|
+
let(:type) { 'png' }
|
8
|
+
let(:src) { 'http://foo.com' }
|
9
|
+
let(:image) { double(src: src) }
|
10
|
+
let(:action) { described_class.perform(image) }
|
11
|
+
|
12
|
+
context 'when no exception is raised' do
|
13
|
+
|
14
|
+
before do
|
15
|
+
expect(FastImage).to receive(:type).with(src, raise_on_failure: true).and_return(type)
|
16
|
+
end
|
17
|
+
|
18
|
+
it { expect(action).to eq(type) }
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'when an exception is raised' do
|
23
|
+
|
24
|
+
before do
|
25
|
+
expect(FastImage).to receive(:type).with(src, raise_on_failure: true).and_raise(FastImage::FastImageException)
|
26
|
+
end
|
27
|
+
|
28
|
+
it { expect(action).to eq(:jpg) }
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe LinkThumbnailer::ImageValidator do
|
4
|
+
|
5
|
+
let(:src) { 'http://foo.com' }
|
6
|
+
let(:image) { double(src: src) }
|
7
|
+
let(:instance) { described_class.new(image) }
|
8
|
+
|
9
|
+
describe '#call' do
|
10
|
+
|
11
|
+
let(:action) { instance.call }
|
12
|
+
|
13
|
+
before do
|
14
|
+
instance.stub(:blacklist_urls).and_return(blacklist_urls)
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'when image url is blacklisted' do
|
18
|
+
|
19
|
+
let(:blacklist_urls) { [src] }
|
20
|
+
|
21
|
+
it { expect(action).to be_false }
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'when image url is not blacklisted' do
|
26
|
+
|
27
|
+
let(:blacklist_urls) { [] }
|
28
|
+
|
29
|
+
it { expect(action).to be_true }
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
data/spec/model_spec.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe LinkThumbnailer::Model do
|
4
|
+
|
5
|
+
let(:instance) { described_class.new }
|
6
|
+
|
7
|
+
describe '#sanitize' do
|
8
|
+
|
9
|
+
let(:str) { "foo\r\n" }
|
10
|
+
let(:result) { "foo" }
|
11
|
+
let(:action) { instance.send(:sanitize, str) }
|
12
|
+
|
13
|
+
it { expect(action).to eq(result) }
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|