link_thumbnailer 3.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/.rspec +2 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +5 -0
  6. data/CHANGELOG.md +334 -0
  7. data/Gemfile +12 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +210 -0
  10. data/Rakefile +9 -0
  11. data/lib/generators/link_thumbnailer/install_generator.rb +17 -0
  12. data/lib/generators/templates/initializer.rb +89 -0
  13. data/lib/link_thumbnailer.rb +38 -0
  14. data/lib/link_thumbnailer/configuration.rb +72 -0
  15. data/lib/link_thumbnailer/exceptions.rb +11 -0
  16. data/lib/link_thumbnailer/grader.rb +43 -0
  17. data/lib/link_thumbnailer/graders/base.rb +39 -0
  18. data/lib/link_thumbnailer/graders/html_attribute.rb +48 -0
  19. data/lib/link_thumbnailer/graders/length.rb +37 -0
  20. data/lib/link_thumbnailer/graders/link_density.rb +20 -0
  21. data/lib/link_thumbnailer/graders/position.rb +13 -0
  22. data/lib/link_thumbnailer/image_comparator.rb +26 -0
  23. data/lib/link_thumbnailer/image_comparators/base.rb +19 -0
  24. data/lib/link_thumbnailer/image_comparators/size.rb +13 -0
  25. data/lib/link_thumbnailer/image_parser.rb +62 -0
  26. data/lib/link_thumbnailer/image_validator.rb +32 -0
  27. data/lib/link_thumbnailer/model.rb +20 -0
  28. data/lib/link_thumbnailer/models/description.rb +37 -0
  29. data/lib/link_thumbnailer/models/favicon.rb +27 -0
  30. data/lib/link_thumbnailer/models/image.rb +56 -0
  31. data/lib/link_thumbnailer/models/title.rb +22 -0
  32. data/lib/link_thumbnailer/models/video.rb +44 -0
  33. data/lib/link_thumbnailer/models/website.rb +54 -0
  34. data/lib/link_thumbnailer/page.rb +43 -0
  35. data/lib/link_thumbnailer/parser.rb +15 -0
  36. data/lib/link_thumbnailer/processor.rb +128 -0
  37. data/lib/link_thumbnailer/railtie.rb +6 -0
  38. data/lib/link_thumbnailer/response.rb +39 -0
  39. data/lib/link_thumbnailer/scraper.rb +62 -0
  40. data/lib/link_thumbnailer/scrapers/base.rb +69 -0
  41. data/lib/link_thumbnailer/scrapers/default/base.rb +12 -0
  42. data/lib/link_thumbnailer/scrapers/default/description.rb +49 -0
  43. data/lib/link_thumbnailer/scrapers/default/favicon.rb +38 -0
  44. data/lib/link_thumbnailer/scrapers/default/images.rb +78 -0
  45. data/lib/link_thumbnailer/scrapers/default/title.rb +27 -0
  46. data/lib/link_thumbnailer/scrapers/default/videos.rb +18 -0
  47. data/lib/link_thumbnailer/scrapers/opengraph/base.rb +45 -0
  48. data/lib/link_thumbnailer/scrapers/opengraph/description.rb +12 -0
  49. data/lib/link_thumbnailer/scrapers/opengraph/favicon.rb +17 -0
  50. data/lib/link_thumbnailer/scrapers/opengraph/image.rb +107 -0
  51. data/lib/link_thumbnailer/scrapers/opengraph/images.rb +18 -0
  52. data/lib/link_thumbnailer/scrapers/opengraph/title.rb +12 -0
  53. data/lib/link_thumbnailer/scrapers/opengraph/video.rb +115 -0
  54. data/lib/link_thumbnailer/scrapers/opengraph/videos.rb +18 -0
  55. data/lib/link_thumbnailer/uri.rb +20 -0
  56. data/lib/link_thumbnailer/version.rb +5 -0
  57. data/lib/link_thumbnailer/video_parser.rb +47 -0
  58. data/link_thumbnailer.gemspec +29 -0
  59. data/spec/configuration_spec.rb +61 -0
  60. data/spec/fixture_spec.rb +114 -0
  61. data/spec/fixtures/bar.png +2907 -0
  62. data/spec/fixtures/default_from_body.html +13 -0
  63. data/spec/fixtures/default_from_meta.html +12 -0
  64. data/spec/fixtures/foo.png +0 -0
  65. data/spec/fixtures/google_shift_jis.html +6 -0
  66. data/spec/fixtures/google_utf8.html +6 -0
  67. data/spec/fixtures/og_not_valid_example.html +12 -0
  68. data/spec/fixtures/og_valid_example.html +18 -0
  69. data/spec/fixtures/og_valid_multi_image_example.html +13 -0
  70. data/spec/fixtures/og_valid_multi_video_example.html +13 -0
  71. data/spec/grader_spec.rb +27 -0
  72. data/spec/graders/base_spec.rb +14 -0
  73. data/spec/graders/html_attribute_spec.rb +50 -0
  74. data/spec/graders/length_spec.rb +93 -0
  75. data/spec/graders/link_density_spec.rb +52 -0
  76. data/spec/graders/position_spec.rb +49 -0
  77. data/spec/image_comparators/size_spec.rb +58 -0
  78. data/spec/image_validator_spec.rb +37 -0
  79. data/spec/model_spec.rb +27 -0
  80. data/spec/models/description_spec.rb +66 -0
  81. data/spec/models/favicon_spec.rb +12 -0
  82. data/spec/models/image_spec.rb +95 -0
  83. data/spec/models/title_spec.rb +26 -0
  84. data/spec/models/video_spec.rb +49 -0
  85. data/spec/models/website_spec.rb +51 -0
  86. data/spec/page_spec.rb +28 -0
  87. data/spec/processor_spec.rb +410 -0
  88. data/spec/response_spec.rb +62 -0
  89. data/spec/scraper_spec.rb +70 -0
  90. data/spec/scrapers/base_spec.rb +69 -0
  91. data/spec/scrapers/opengraph/base_spec.rb +96 -0
  92. data/spec/spec_helper.rb +11 -0
  93. data/spec/uri_spec.rb +44 -0
  94. data/spec/video_parser_spec.rb +148 -0
  95. metadata +271 -0
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe LinkThumbnailer::Response do
6
+ let(:url) { 'https://www.google.co.jp' }
7
+ let(:page) { ::LinkThumbnailer::Page.new(url, {}) }
8
+
9
+ let(:response) do
10
+ r = ::Net::HTTPSuccess.new('', 200, body_shift_jis)
11
+ r['Content-Type'] = 'text/html'
12
+ r.body = body_shift_jis
13
+ r.instance_variable_set(:@read, true)
14
+ r
15
+ end
16
+
17
+ let(:instance) { described_class.new(response) }
18
+
19
+ let(:body_shift_jis) do
20
+ File.read(File.expand_path('fixtures/google_shift_jis.html', File.dirname(__FILE__)))
21
+ end
22
+
23
+ let(:body_utf8) do
24
+ File.read(File.expand_path('fixtures/google_utf8.html', File.dirname(__FILE__)))
25
+ end
26
+
27
+ before do
28
+ allow(LinkThumbnailer).to receive(:page).and_return(page)
29
+ end
30
+
31
+ describe '#charset' do
32
+ context 'when charset provided in content-type' do
33
+ before do
34
+ response['Content-Type'] = 'text/html; charset=Shift_JIS'
35
+ end
36
+
37
+ it { expect(instance.charset).to eq 'Shift_JIS' }
38
+ end
39
+
40
+ context 'when no charset available in content-type' do
41
+ it { expect(instance.charset).to eq '' }
42
+ end
43
+ end
44
+
45
+ describe '#body' do
46
+ context 'when provide valid charset' do
47
+ before do
48
+ response['Content-Type'] = 'text/html; charset=Shift_JIS'
49
+ end
50
+
51
+ it { expect(instance.body).to eq body_utf8 }
52
+ end
53
+
54
+ context 'when provide invalid charset' do
55
+ before do
56
+ response['Content-Type'] = 'text/html; charset=Shift-JIS'
57
+ end
58
+
59
+ it { expect(instance.body).to eq body_shift_jis }
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe LinkThumbnailer::Scraper do
6
+
7
+ let(:source) { '' }
8
+ let(:url) { 'http://foo.com' }
9
+ let(:document) { double('document') }
10
+ let(:website) { double('website') }
11
+ let(:instance) { described_class.new(source, url) }
12
+
13
+ before do
14
+ allow(instance).to receive(:document).and_return(document)
15
+ allow(instance).to receive(:website).and_return(website)
16
+ end
17
+
18
+ describe '#call' do
19
+
20
+ let(:prefix_1) { 'prefix_1' }
21
+ let(:prefix_2) { 'prefix_2' }
22
+ let(:scraper_class) { double('scraper_class') }
23
+ let(:scraper) { double('scraper', call: true) }
24
+ let(:attributes) { [:bar] }
25
+ let(:scrapers) { [prefix_1, prefix_2] }
26
+ let(:action) { instance.call }
27
+ let(:config) { double(attributes: attributes, scrapers: scrapers) }
28
+
29
+ before do
30
+ allow(instance).to receive(:config).and_return(config)
31
+ end
32
+
33
+ context 'when first one return a result' do
34
+
35
+ let(:valid_scraper) { double('scraper') }
36
+ let(:not_valid_scraper) { double('scraper') }
37
+
38
+ before do
39
+ expect(website).to receive(:bar).once.and_return('bar')
40
+ expect(valid_scraper).to receive(:call).once.with('bar')
41
+ expect(not_valid_scraper).to_not receive(:call).with('bar')
42
+ expect(scraper_class).to receive(:new).with(document, website).once.and_return(valid_scraper)
43
+ expect(instance).to receive(:scraper_class).with(prefix_1, :bar).and_return(scraper_class)
44
+ end
45
+
46
+ it { expect(action).to eq(website) }
47
+
48
+ end
49
+
50
+ context 'when first one does not return any result' do
51
+
52
+ let(:valid_scraper) { double('scraper') }
53
+ let(:not_valid_scraper) { double('scraper') }
54
+
55
+ before do
56
+ expect(website).to receive(:bar).and_return('', 'bar')
57
+ expect(valid_scraper).to receive(:call).once.with('bar')
58
+ expect(not_valid_scraper).to receive(:call).once.with('bar')
59
+ expect(scraper_class).to receive(:new).with(document, website).and_return(not_valid_scraper, valid_scraper)
60
+ expect(instance).to receive(:scraper_class).with(prefix_1, :bar).and_return(scraper_class)
61
+ expect(instance).to receive(:scraper_class).with(prefix_2, :bar).and_return(scraper_class)
62
+ end
63
+
64
+ it { expect(action).to eq(website) }
65
+
66
+ end
67
+
68
+ end
69
+
70
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe LinkThumbnailer::Scrapers::Base do
6
+
7
+ let(:document) { double('document') }
8
+ let(:website) { LinkThumbnailer::Models::Website.new }
9
+ let(:instance) { described_class.new(document, website) }
10
+
11
+ describe '#call' do
12
+
13
+ let(:attr) { :title }
14
+ let(:value) { 'foo' }
15
+ let(:action) { instance.call(attr) }
16
+
17
+ before do
18
+ allow(instance).to receive(:value).and_return(value)
19
+ end
20
+
21
+ it { expect { action }.to change { website.title }.from(nil).to(value) }
22
+
23
+ end
24
+
25
+ describe '#model_class' do
26
+
27
+ let(:action) { instance.send(:model_class) }
28
+
29
+ before do
30
+ allow(instance).to receive(:attribute_name).and_return(attr)
31
+ end
32
+
33
+ context 'when internal class exists' do
34
+
35
+ let(:attr) { :title }
36
+
37
+ it { expect(action).to eq(::LinkThumbnailer::Models::Title) }
38
+
39
+ end
40
+
41
+ context 'when internal class does not exists' do
42
+
43
+ let(:attr) { :foo }
44
+
45
+ it { expect { action }.to raise_error(NameError) }
46
+
47
+ end
48
+
49
+ end
50
+
51
+ describe '#modelize' do
52
+
53
+ let(:node) { double('node') }
54
+ let(:text) { 'foo' }
55
+ let(:model_class) { double('model_class') }
56
+ let(:action) { instance.send(:modelize, node, text) }
57
+
58
+ before do
59
+ allow(instance).to receive(:model_class).and_return(model_class)
60
+ end
61
+
62
+ it 'instantiates a new model' do
63
+ expect(model_class).to receive(:new).with(node, text)
64
+ action
65
+ end
66
+
67
+ end
68
+
69
+ end
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe LinkThumbnailer::Scrapers::Opengraph::Base do
6
+
7
+ let(:node) { double('node') }
8
+ let(:document) { double('document') }
9
+ let(:instance) { described_class.new(document) }
10
+
11
+ describe '#applicable?' do
12
+
13
+ let(:meta) { [node, node] }
14
+ let(:action) { instance.applicable? }
15
+
16
+ before do
17
+ allow(instance).to receive(:meta).and_return(meta)
18
+ end
19
+
20
+ context 'when all node is an opengraph' do
21
+
22
+ before do
23
+ allow(instance).to receive(:opengraph_node?).and_return(true, true)
24
+ end
25
+
26
+ it { expect(action).to be_truthy }
27
+
28
+ end
29
+
30
+ context 'when any node is an opengraph' do
31
+
32
+ before do
33
+ allow(instance).to receive(:opengraph_node?).and_return(true, false)
34
+ end
35
+
36
+ it { expect(action).to be_truthy }
37
+
38
+ end
39
+
40
+ context 'when no node is an opengraph' do
41
+
42
+ before do
43
+ allow(instance).to receive(:opengraph_node?).and_return(false, false)
44
+ end
45
+
46
+ it { expect(action).to be_falsey }
47
+
48
+ end
49
+
50
+ end
51
+
52
+ describe '#opengraph_node?' do
53
+
54
+ let(:action) { instance.send(:opengraph_node?, node) }
55
+
56
+ before do
57
+ allow(node).to receive(:attribute).with('name').and_return(attribute_from_name)
58
+ end
59
+
60
+ context 'with attribute from name valid' do
61
+
62
+ let(:attribute_from_name) { 'og:foo' }
63
+
64
+ it { expect(action).to be_truthy }
65
+
66
+ end
67
+
68
+ context 'with attribute from name not valid' do
69
+
70
+ let(:attribute_from_name) { 'foo' }
71
+
72
+ before do
73
+ allow(node).to receive(:attribute).with('property').and_return(attribute_from_property)
74
+ end
75
+
76
+ context 'and attribute from property valid' do
77
+
78
+ let(:attribute_from_property) { 'og:bar' }
79
+
80
+ it { expect(action).to be_truthy }
81
+
82
+ end
83
+
84
+ context 'and attribute from property not valid' do
85
+
86
+ let(:attribute_from_property) { 'bar' }
87
+
88
+ it { expect(action).to be_falsey }
89
+
90
+ end
91
+
92
+ end
93
+
94
+ end
95
+
96
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'link_thumbnailer'
4
+ require 'rspec'
5
+ require 'webmock/rspec'
6
+
7
+ RSpec.configure do |config|
8
+ config.expect_with :rspec do |c|
9
+ c.syntax = :expect
10
+ end
11
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe LinkThumbnailer::URI do
6
+
7
+ let(:uri) { 'http://foo.com' }
8
+ let(:instance) { described_class.new(uri) }
9
+
10
+ describe '#valid?' do
11
+
12
+ let(:action) { instance.send(:valid?) }
13
+
14
+ context 'when bad format' do
15
+
16
+ before do
17
+ allow(instance).to receive(:attribute).and_return("/invalid/path")
18
+ end
19
+
20
+ it { expect(action).to be_falsey }
21
+
22
+ end
23
+
24
+ context 'when valid format' do
25
+
26
+ before do
27
+ allow(instance).to receive(:attribute).and_return("http://foo.com")
28
+ end
29
+
30
+ it { expect(action).to be_truthy }
31
+
32
+ end
33
+
34
+ end
35
+
36
+ describe '#to_s' do
37
+
38
+ let(:action) { instance.to_s }
39
+
40
+ it { expect(action).to eq(uri) }
41
+
42
+ end
43
+
44
+ end
@@ -0,0 +1,148 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe LinkThumbnailer::VideoParser do
6
+
7
+ let(:src) { 'http://foo.com/foo.swf' }
8
+ let(:video) { double(src: src) }
9
+ let(:parser) { double('parser') }
10
+ let(:instance) { described_class.new(video) }
11
+
12
+ before do
13
+ allow(instance).to receive(:parser).and_return(parser)
14
+ end
15
+
16
+ describe '#id' do
17
+
18
+ let(:action) { instance.id }
19
+
20
+ context 'when respond to video_id' do
21
+
22
+ before do
23
+ allow(parser).to receive(:video_id).and_return(1)
24
+ end
25
+
26
+ it { expect(action).to eq(parser.video_id) }
27
+
28
+ end
29
+
30
+ context 'when do not respond to video_id' do
31
+
32
+ before do
33
+ allow(parser).to receive(:video_id).and_raise(NoMethodError)
34
+ end
35
+
36
+ it { expect(action).to be_nil }
37
+
38
+ end
39
+
40
+ end
41
+
42
+ describe '#size' do
43
+
44
+ let(:action) { instance.size }
45
+
46
+ context 'when respond to width and height' do
47
+
48
+ before do
49
+ allow(parser).to receive(:width).and_return(1)
50
+ allow(parser).to receive(:height).and_return(1)
51
+ end
52
+
53
+ it { expect(action).to eq([parser.width, parser.height]) }
54
+
55
+ end
56
+
57
+ context 'when do not respond to width and height' do
58
+
59
+ before do
60
+ allow(parser).to receive(:width).and_raise(NoMethodError)
61
+ allow(parser).to receive(:height).and_raise(NoMethodError)
62
+ end
63
+
64
+ it { expect(action).to be_empty }
65
+
66
+ end
67
+
68
+ end
69
+
70
+ describe '#duration' do
71
+
72
+ let(:action) { instance.duration }
73
+
74
+ context 'when respond to duration' do
75
+
76
+ before do
77
+ allow(parser).to receive(:duration).and_return(1)
78
+ end
79
+
80
+ it { expect(action).to eq(parser.duration) }
81
+
82
+ end
83
+
84
+ context 'when do not respond to duration' do
85
+
86
+ before do
87
+ allow(parser).to receive(:duration).and_raise(NoMethodError)
88
+ end
89
+
90
+ it { expect(action).to be_nil }
91
+
92
+ end
93
+
94
+ end
95
+
96
+ describe '#provider' do
97
+
98
+ let(:action) { instance.provider }
99
+
100
+ context 'when respond to provider' do
101
+
102
+ before do
103
+ allow(parser).to receive(:provider).and_return(1)
104
+ end
105
+
106
+ it { expect(action).to eq(parser.provider) }
107
+
108
+ end
109
+
110
+ context 'when do not respond to provider' do
111
+
112
+ before do
113
+ allow(parser).to receive(:provider).and_raise(NoMethodError)
114
+ end
115
+
116
+ it { expect(action).to be_nil }
117
+
118
+ end
119
+
120
+ end
121
+
122
+ describe '#embed_code' do
123
+
124
+ let(:action) { instance.embed_code }
125
+
126
+ context 'when respond to embed_code' do
127
+
128
+ before do
129
+ allow(parser).to receive(:embed_code).and_return('')
130
+ end
131
+
132
+ it { expect(action).to eq(parser.embed_code) }
133
+
134
+ end
135
+
136
+ context 'when do not respond to embed_code' do
137
+
138
+ before do
139
+ allow(parser).to receive(:embed_code).and_raise(NoMethodError)
140
+ end
141
+
142
+ it { expect(action).to be_nil }
143
+
144
+ end
145
+
146
+ end
147
+
148
+ end