link_thumbnailer 3.3.0 → 3.3.1

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: 62e43acf3460b4ef3da648fa16fb8f3f970d88b8
4
- data.tar.gz: 4768729820579a8387d692ddba91a3557f548d60
3
+ metadata.gz: fef68fdf205078290139fd831a9b8d46581e64eb
4
+ data.tar.gz: 27a3e86b0181068e06bd80e8f053fca17d3a906b
5
5
  SHA512:
6
- metadata.gz: 1e4a5a30c0166b19f57a0e2dbc57fda86074ad26caa28fde4ad8c15e1afe278478c4ca27223a155b66ce777765a729e78f5a95ddd080abb535fa5b806eaeafbb
7
- data.tar.gz: 93464538468ced5cb85119c2e85219f592c33a91733bf1e89741d074253e9a540f949355258a723db38698e712c7c2d079ec6d75539fb249f48cb25109ab772b
6
+ metadata.gz: 5dcfa7683c65f546ce8e794d51c9d7103736fb3cf9f5919ddbcea611fbe7243faf3ef76ed372d99ea316a6d193032d9b47e48411dc9c0fb1c972d77c29bc2a2a
7
+ data.tar.gz: e041d9174be5b066fac70b70b965bc28b053235bffa808c0a109c3c1f10512643ae58dc21b3f8691ca3ff6a3b9f5346e31c4b0cf1430d16ac829244d3252ab96
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.4.0
data/.travis.yml CHANGED
@@ -1,4 +1,5 @@
1
1
  bundler_args: --without development
2
2
  language: ruby
3
3
  rvm:
4
- - 2.2.0
4
+ - 2.2.2
5
+ - 2.4.0
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ # 3.3.1
2
+
3
+ Gem upgrade (json)
4
+
1
5
  # 3.3.0
2
6
 
3
7
  - Allows to configure overrided http headers
data/Gemfile CHANGED
@@ -4,7 +4,7 @@ source 'https://rubygems.org'
4
4
  gemspec
5
5
 
6
6
  group :development, :test do
7
- gem 'rspec', '~> 2.14'
8
- gem 'webmock', '~> 1.14'
9
- gem 'pry', '~> 0.9'
7
+ gem 'rspec', '~> 3.5.0'
8
+ gem 'webmock', '~> 2.3.2'
9
+ gem 'pry', '~> 0.10.4'
10
10
  end
data/README.md CHANGED
@@ -165,6 +165,10 @@ LinkThumbnailer.configure do |config|
165
165
  # Sets number of concurrent http connections that can be opened to fetch images informations such as size and type.
166
166
  #
167
167
  # config.max_concurrency = 20
168
+
169
+ # Sets the default encoding.
170
+ #
171
+ # config.encoding = 'utf-8'
168
172
  end
169
173
  ```
170
174
 
@@ -80,4 +80,8 @@ LinkThumbnailer.configure do |config|
80
80
  # Defines the strategies to use to scrap the website. See the [Open Graph Protocol](http://ogp.me/) for more information.
81
81
  #
82
82
  # config.scrapers = [:opengraph, :default]
83
+
84
+ # Sets the default encoding.
85
+ #
86
+ # config.encoding = 'utf-8'
83
87
  end
@@ -26,7 +26,7 @@ module LinkThumbnailer
26
26
  :verify_ssl, :http_open_timeout, :http_read_timeout, :attributes,
27
27
  :graders, :description_min_length, :positive_regex, :negative_regex,
28
28
  :image_limit, :image_stats, :raise_on_invalid_format, :max_concurrency,
29
- :scrapers, :http_override_headers
29
+ :scrapers, :http_override_headers, :encoding
30
30
 
31
31
  alias_method :http_timeout, :http_open_timeout
32
32
  alias_method :http_timeout=, :http_open_timeout=
@@ -63,6 +63,7 @@ module LinkThumbnailer
63
63
  @max_concurrency = 20
64
64
  @scrapers = [:opengraph, :default]
65
65
  @http_override_headers = { 'Accept-Encoding' => 'none' }
66
+ @encoding = 'utf-8'
66
67
  end
67
68
 
68
69
  end
@@ -1,3 +1,4 @@
1
+ require 'link_thumbnailer/response'
1
2
  require 'link_thumbnailer/processor'
2
3
  require 'link_thumbnailer/scraper'
3
4
 
@@ -4,7 +4,7 @@ module LinkThumbnailer
4
4
  class Parser
5
5
 
6
6
  def call(source)
7
- ::Nokogiri::HTML(source)
7
+ ::Nokogiri::HTML(source, nil, LinkThumbnailer.page.config.encoding)
8
8
  rescue ::Nokogiri::XML::SyntaxError => e
9
9
  raise ::LinkThumbnailer::SyntaxError.new(e.message)
10
10
  end
@@ -59,7 +59,7 @@ module LinkThumbnailer
59
59
 
60
60
  case response
61
61
  when ::Net::HTTPSuccess
62
- response.body
62
+ Response.new(response).body
63
63
  when ::Net::HTTPRedirection
64
64
  call(
65
65
  resolve_relative_url(response['location'].to_s),
@@ -0,0 +1,37 @@
1
+ module LinkThumbnailer
2
+ class Response
3
+ def initialize(response)
4
+ @response = response
5
+ end
6
+
7
+ def charset
8
+ @charset ||= extract_charset
9
+ end
10
+
11
+ def body
12
+ @body ||= extract_body
13
+ end
14
+
15
+ private
16
+
17
+ def extract_charset
18
+ content_type = @response['Content-Type'] || ''
19
+ m = content_type.match(/charset=(\w+)/)
20
+ (m && m[1]) || ''
21
+ end
22
+
23
+ def extract_body
24
+ should_convert_body_to_utf8? ? convert_encoding_to_utf8(@response.body, charset) : @response.body
25
+ end
26
+
27
+ def should_convert_body_to_utf8?
28
+ charset != '' && charset != 'utf-8'
29
+ end
30
+
31
+ def convert_encoding_to_utf8(body, from)
32
+ Encoding::Converter.new(from, 'utf-8').convert(body)
33
+ rescue EncodingError
34
+ body
35
+ end
36
+ end
37
+ end
@@ -1,3 +1,3 @@
1
1
  module LinkThumbnailer
2
- VERSION = '3.3.0'
2
+ VERSION = '3.3.1'
3
3
  end
@@ -18,10 +18,10 @@ Gem::Specification.new do |spec|
18
18
  spec.require_paths = ['lib']
19
19
 
20
20
  spec.add_dependency 'activesupport', '>= 3.0'
21
- spec.add_dependency 'json', ['>= 1.7.7', '~> 1.8']
22
- spec.add_dependency 'rake', '>= 0.9'
23
- spec.add_dependency 'nokogiri', '~> 1.6'
24
- spec.add_dependency 'net-http-persistent', '~> 2.9'
25
- spec.add_dependency 'video_info', '~> 2.6'
26
- spec.add_dependency 'image_info', '~> 1.0'
21
+ spec.add_dependency 'json', '~> 2.1'
22
+ spec.add_dependency 'rake', ['>= 0.9']
23
+ spec.add_dependency 'nokogiri', '~> 1.7'
24
+ spec.add_dependency 'net-http-persistent', '~> 3.0'
25
+ spec.add_dependency 'video_info', '~> 2.7'
26
+ spec.add_dependency 'image_info', '~> 1.1'
27
27
  end
@@ -18,6 +18,7 @@ describe LinkThumbnailer::Configuration do
18
18
  it { expect(instance.image_limit).to eq(5) }
19
19
  it { expect(instance.image_stats).to eq(true) }
20
20
  it { expect(instance.max_concurrency).to eq(20) }
21
+ it { expect(instance.encoding).to eq('utf-8') }
21
22
 
22
23
  describe "#http_timeout" do
23
24
  it { expect(instance.method(:http_timeout)).to eq(instance.method(:http_open_timeout)) }
@@ -33,7 +34,7 @@ describe LinkThumbnailer::Configuration do
33
34
  describe '.configure' do
34
35
 
35
36
  before do
36
- LinkThumbnailer.stub(:config).and_return(instance)
37
+ allow(LinkThumbnailer).to receive(:config).and_return(instance)
37
38
  end
38
39
 
39
40
  context 'when block given' do
@@ -56,4 +57,3 @@ describe LinkThumbnailer::Configuration do
56
57
  end
57
58
 
58
59
  end
59
-
@@ -0,0 +1,6 @@
1
+ <!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="ja"><head><meta content="���E���̂���������������邽�߂̃c�[����񋟂��Ă��܂��B���܂��܂Ȍ����@�\�����p���āA���T���̏������‚��Ă��������B" name="description"><meta content="noodp" name="robots"><meta content="text/html; charset=UTF-8" http-equiv="Content-Type"><meta content="/images/branding/googleg/1x/googleg_standard_color_128dp.png" itemprop="image"><title>Google</title><script>(function(){window.google={kEI:'716VWJL3JYq18QWo_qzoAg',kEXPI:'750722,1351903,1352241,1352381,3700253,3700347,4028875,4029815,4032677,4038012,4043492,4045839,4048347,4062666,4065787,4068816,4069773,4069838,4069840,4070138,4072773,4073405,4073726,4073959,4076096,4076931,4076999,4077777,4078438,4079081,4079105,4079894,4081038,4081485,4082194,4082201,4082298,4082619,4083044,4083476,4084343,4084673,4085336,4085412,4085683,4086011,4089003,4089144,4089183,4089427,4089538,4089913,4090414,4090547,4090549,4090598,4090657,4090806,4090893,4091966,4092028,4092182,4092218,4092474,4092478,4092598,4092864,4092867,4092875,4092897,4092934,4093073,4093948,4094169,4094250,4094769,4094987,4094997,4095554,4095771,4095907,4095998,8300096,8300272,8507380,8507419,8507861,8507940,8508624,8510023,10200083,13500022,13500024',authuser:0,kscs:'c9c918f0_24'};google.kHL='ja';})();(function(){google.lc=[];google.li=0;google.getEI=function(a){for(var b;a&&(!a.getAttribute||!(b=a.getAttribute("eid")));)a=a.parentNode;return b||google.kEI};google.getLEI=function(a){for(var b=null;a&&(!a.getAttribute||!(b=a.getAttribute("leid")));)a=a.parentNode;return b};google.https=function(){return"https:"==window.location.protocol};google.ml=function(){return null};google.wl=function(a,b){try{google.ml(Error(a),!1,b)}catch(c){}};google.time=function(){return(new Date).getTime()};google.log=function(a,b,c,d,g){a=google.logUrl(a,b,c,d,g);if(""!=a){b=new Image;var e=google.lc,f=google.li;e[f]=b;b.onerror=b.onload=b.onabort=function(){delete e[f]};window.google&&window.google.vel&&window.google.vel.lu&&window.google.vel.lu(a);b.src=a;google.li=f+1}};google.logUrl=function(a,b,c,d,g){var e="",f=google.ls||"";c||-1!=b.search("&ei=")||(e="&ei="+google.getEI(d),-1==b.search("&lei=")&&(d=google.getLEI(d))&&(e+="&lei="+d));a=c||"/"+(g||"gen_204")+"?atyp=i&ct="+a+"&cad="+b+e+f+"&zx="+google.time();/^http:/i.test(a)&&google.https()&&(google.ml(Error("a"),!1,{src:a,glmm:1}),a="");return a};google.y={};google.x=function(a,b){google.y[a.id]=[a,b];return!1};google.lq=[];google.load=function(a,b,c){google.lq.push([[a],b,c])};google.loadAll=function(a,b){google.lq.push([a,b])};}).call(this);var a=window.location,b=a.href.indexOf("#");if(0<=b){var c=a.href.substring(b+1);/(^|&)q=/.test(c)&&-1==c.indexOf("#")&&a.replace("/search?"+c.replace(/(^|&)fp=[^&]*/g,"")+"&cad=h")};</script><style>#gbar,#guser{font-size:13px;padding-top:1px !important;}#gbar{height:22px}#guser{padding-bottom:7px !important;text-align:right}.gbh,.gbd{border-top:1px solid #c9d7f1;font-size:1px}.gbh{height:0;position:absolute;top:24px;width:100%}@media all{.gb1{height:22px;margin-right:.5em;vertical-align:top}#gbar{float:left}}a.gb1,a.gb4{text-decoration:underline !important}a.gb1,a.gb4{color:#00c !important}.gbi .gb4{color:#dd8e27 !important}.gbf .gb4{color:#900 !important}
2
+ </style><style>body,td,a,p,.h{font-family:arial,sans-serif}body{margin:0;overflow-y:scroll}#gog{padding:3px 8px 0}td{line-height:.8em}.gac_m td{line-height:17px}form{margin-bottom:20px}.h{color:#36c}.q{color:#00c}.ts td{padding:0}.ts{border-collapse:collapse}em{font-weight:bold;font-style:normal}.lst{height:25px;width:496px}.gsfi,.lst{font:18px arial,sans-serif}.gsfs{font:17px arial,sans-serif}.ds{display:inline-box;display:inline-block;margin:3px 0 4px;margin-left:4px}input{font-family:inherit}a.gb1,a.gb2,a.gb3,a.gb4{color:#11c !important}body{background:#fff;color:black}a{color:#11c;text-decoration:none}a:hover,a:active{text-decoration:underline}.fl a{color:#36c}a:visited{color:#551a8b}a.gb1,a.gb4{text-decoration:underline}a.gb3:hover{text-decoration:none}#ghead a.gb2:hover{color:#fff !important}.sblc{padding-top:5px}.sblc a{display:block;margin:2px 0;margin-left:13px;font-size:11px}.lsbb{background:#eee;border:solid 1px;border-color:#ccc #999 #999 #ccc;height:30px}.lsbb{display:block}.ftl,#fll a{display:inline-block;margin:0 12px}.lsb{background:url(/images/nav_logo229.png) 0 -261px repeat-x;border:none;color:#000;cursor:pointer;height:30px;margin:0;outline:0;font:15px arial,sans-serif;vertical-align:top}.lsb:active{background:#ccc}.lst:focus{outline:none}</style><script></script><link href="/images/branding/product/ico/googleg_lodp.ico" rel="shortcut icon"></head><body bgcolor="#fff"><script>(function(){var src='/images/nav_logo229.png';var iesg=false;document.body.onload = function(){window.n && window.n();if (document.images){new Image().src=src;}
3
+ if (!iesg){document.f&&document.f.q.focus();document.gbqf&&document.gbqf.q.focus();}
4
+ }
5
+ })();</script><div id="mngb"> <div id=gbar><nobr><b class=gb1>����</b> <a class=gb1 href="https://www.google.co.jp/imghp?hl=ja&tab=wi">�摜</a> <a class=gb1 href="https://maps.google.co.jp/maps?hl=ja&tab=wl">�}�b�v</a> <a class=gb1 href="https://play.google.com/?hl=ja&tab=w8">Play</a> <a class=gb1 href="https://www.youtube.com/?gl=JP&tab=w1">YouTube</a> <a class=gb1 href="https://news.google.co.jp/nwshp?hl=ja&tab=wn">�j���[�X</a> <a class=gb1 href="https://mail.google.com/mail/?tab=wm">Gmail</a> <a class=gb1 href="https://drive.google.com/?tab=wo">�h���C�u</a> <a class=gb1 style="text-decoration:none" href="https://www.google.co.jp/intl/ja/options/"><u>�����ƌ���</u> &raquo;</a></nobr></div><div id=guser width=100%><nobr><span id=gbn class=gbi></span><span id=gbf class=gbf></span><span id=gbe></span><a href="http://www.google.co.jp/history/optout?hl=ja" class=gb4>�E�F�u����</a> | <a href="/preferences?hl=ja" class=gb4>�ݒ�</a> | <a target=_top id=gb_70 href="https://accounts.google.com/ServiceLogin?hl=ja&passive=true&continue=https://www.google.co.jp/" class=gb4>���O�C��</a></nobr></div><div class=gbh style=left:0></div><div class=gbh style=right:0></div> </div><center><br clear="all" id="lgpd"><div id="lga"><div style="padding:28px 0 3px"><div style="height:110px;width:276px;background:url(/images/branding/googlelogo/1x/googlelogo_white_background_color_272x92dp.png) no-repeat" title="Google" align="left" id="hplogo" onload="window.lol&&lol()"><div style="color:#777;font-size:16px;font-weight:bold;position:relative;top:70px;left:218px" nowrap="">���{</div></div></div><br></div><form action="/search" name="f"><table cellpadding="0" cellspacing="0"><tr valign="top"><td width="25%">&nbsp;</td><td align="center" nowrap=""><input name="ie" value="Shift_JIS" type="hidden"><input value="ja" name="hl" type="hidden"><input name="source" type="hidden" value="hp"><input name="biw" type="hidden"><input name="bih" type="hidden"><div class="ds" style="height:32px;margin:4px 0"><input style="color:#000;margin:0;padding:5px 8px 0 6px;vertical-align:top" autocomplete="off" class="lst" value="" title="Google ����" maxlength="2048" name="q" size="57"></div><br style="line-height:0"><span class="ds"><span class="lsbb"><input class="lsb" value="Google ����" name="btnG" type="submit"></span></span><span class="ds"><span class="lsbb"><input class="lsb" value="I'm Feeling Lucky" name="btnI" onclick="if(this.form.q.value)this.checked=1; else top.location='/doodles/'" type="submit"></span></span></td><td class="fl sblc" align="left" nowrap="" width="25%"><a href="/advanced_search?hl=ja&amp;authuser=0">�����I�v�V����</a><a href="/language_tools?hl=ja&amp;authuser=0">����c�[��</a></td></tr></table><input id="gbv" name="gbv" type="hidden" value="1"></form><div id="gac_scont"></div><div style="font-size:83%;min-height:3.5em"><br></div><span id="footer"><div style="font-size:10pt"><div style="margin:19px auto;text-align:center" id="fll"><a href="/intl/ja/ads/">�L���f��</a><a href="http://www.google.co.jp/intl/ja/services/">�r�W�l�X �\�����[�V����</a><a href="https://plus.google.com/115899767381375908215" rel="publisher">+Google</a><a href="/intl/ja/about.html">Google �ɂ‚���</a><a href="https://www.google.co.jp/setprefdomain?prefdom=US&amp;sig=__NSwOcr0nRFmauaxJWrHJmztdkTc%3D" id="fehl">Google.com</a></div></div><p style="color:#767676;font-size:8pt">&copy; 2017 - <a href="/intl/ja/policies/privacy/">�v���C�o�V�[</a> - <a href="/intl/ja/policies/terms/">�K��</a></p></span></center><script>(function(){window.google.cdo={height:0,width:0};(function(){var a=window.innerWidth,b=window.innerHeight;if(!a||!b)var c=window.document,d="CSS1Compat"==c.compatMode?c.documentElement:c.body,a=d.clientWidth,b=d.clientHeight;a&&b&&(a!=google.cdo.width||b!=google.cdo.height)&&google.log("","","/client_204?&atyp=i&biw="+a+"&bih="+b+"&ei="+google.kEI);}).call(this);})();</script><div id="xjsd"></div><div id="xjsi"><script>(function(){function c(b){window.setTimeout(function(){var a=document.createElement("script");a.src=b;document.getElementById("xjsd").appendChild(a)},0)}google.dljp=function(b,a){google.xjsu=b;c(a)};google.dlj=c;}).call(this);(function(){window.google.xjsrm=[];})();if(google.y)google.y.first=[];if(!google.xjs){window._=window._||{};window._._DumpException=function(e){throw e};if(google.timers&&google.timers.load.t){google.timers.load.t.xjsls=new Date().getTime();}google.dljp('/xjs/_/js/k\x3dxjs.hp.en_US.usfcb5N0rIw.O/m\x3dsb_he,d/rt\x3dj/d\x3d1/t\x3dzcms/rs\x3dACT90oH_6o1ZdJ1OdBerX9LppN-xEd11Eg','/xjs/_/js/k\x3dxjs.hp.en_US.usfcb5N0rIw.O/m\x3dsb_he,d/rt\x3dj/d\x3d1/t\x3dzcms/rs\x3dACT90oH_6o1ZdJ1OdBerX9LppN-xEd11Eg');google.xjs=1;}google.pmc={"sb_he":{"agen":true,"cgen":true,"client":"heirloom-hp","dh":true,"dhqt":true,"ds":"","fl":true,"host":"google.co.jp","isbh":28,"jam":0,"jsonp":true,"msgs":{"cibl":"�������N���A","dym":"����������:","lcky":"I\u0026#39;m Feeling Lucky","lml":"�ڍ�","oskt":"���̓c�[��","psrc":"���̌����L�[���[�h��\u003Ca href=\"/history\"\u003E�E�F�u����\u003C/a\u003E����폜����܂���","psrl":"�폜","sbit":"�摜�Ō���","srch":"Google ����"},"nds":true,"ovr":{},"pq":"","refpd":true,"refspre":true,"rfs":[],"scd":10,"sce":5,"stok":"WXDdTX_0YGr0J9JRNcHRvk23BlI"},"d":{}};google.y.first.push(function(){if(google.med){google.med('init');google.initHistory();google.med('history');}});if(google.j&&google.j.en&&google.j.xi){window.setTimeout(google.j.xi,0);}
6
+ </script></div></body></html>
@@ -0,0 +1,6 @@
1
+ <!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="ja"><head><meta content="世界中のあらゆる情報を検索するためのツールを提供しています。さまざまな検索機能を活用して、お探しの情報を見つけてください。" name="description"><meta content="noodp" name="robots"><meta content="text/html; charset=UTF-8" http-equiv="Content-Type"><meta content="/images/branding/googleg/1x/googleg_standard_color_128dp.png" itemprop="image"><title>Google</title><script>(function(){window.google={kEI:'716VWJL3JYq18QWo_qzoAg',kEXPI:'750722,1351903,1352241,1352381,3700253,3700347,4028875,4029815,4032677,4038012,4043492,4045839,4048347,4062666,4065787,4068816,4069773,4069838,4069840,4070138,4072773,4073405,4073726,4073959,4076096,4076931,4076999,4077777,4078438,4079081,4079105,4079894,4081038,4081485,4082194,4082201,4082298,4082619,4083044,4083476,4084343,4084673,4085336,4085412,4085683,4086011,4089003,4089144,4089183,4089427,4089538,4089913,4090414,4090547,4090549,4090598,4090657,4090806,4090893,4091966,4092028,4092182,4092218,4092474,4092478,4092598,4092864,4092867,4092875,4092897,4092934,4093073,4093948,4094169,4094250,4094769,4094987,4094997,4095554,4095771,4095907,4095998,8300096,8300272,8507380,8507419,8507861,8507940,8508624,8510023,10200083,13500022,13500024',authuser:0,kscs:'c9c918f0_24'};google.kHL='ja';})();(function(){google.lc=[];google.li=0;google.getEI=function(a){for(var b;a&&(!a.getAttribute||!(b=a.getAttribute("eid")));)a=a.parentNode;return b||google.kEI};google.getLEI=function(a){for(var b=null;a&&(!a.getAttribute||!(b=a.getAttribute("leid")));)a=a.parentNode;return b};google.https=function(){return"https:"==window.location.protocol};google.ml=function(){return null};google.wl=function(a,b){try{google.ml(Error(a),!1,b)}catch(c){}};google.time=function(){return(new Date).getTime()};google.log=function(a,b,c,d,g){a=google.logUrl(a,b,c,d,g);if(""!=a){b=new Image;var e=google.lc,f=google.li;e[f]=b;b.onerror=b.onload=b.onabort=function(){delete e[f]};window.google&&window.google.vel&&window.google.vel.lu&&window.google.vel.lu(a);b.src=a;google.li=f+1}};google.logUrl=function(a,b,c,d,g){var e="",f=google.ls||"";c||-1!=b.search("&ei=")||(e="&ei="+google.getEI(d),-1==b.search("&lei=")&&(d=google.getLEI(d))&&(e+="&lei="+d));a=c||"/"+(g||"gen_204")+"?atyp=i&ct="+a+"&cad="+b+e+f+"&zx="+google.time();/^http:/i.test(a)&&google.https()&&(google.ml(Error("a"),!1,{src:a,glmm:1}),a="");return a};google.y={};google.x=function(a,b){google.y[a.id]=[a,b];return!1};google.lq=[];google.load=function(a,b,c){google.lq.push([[a],b,c])};google.loadAll=function(a,b){google.lq.push([a,b])};}).call(this);var a=window.location,b=a.href.indexOf("#");if(0<=b){var c=a.href.substring(b+1);/(^|&)q=/.test(c)&&-1==c.indexOf("#")&&a.replace("/search?"+c.replace(/(^|&)fp=[^&]*/g,"")+"&cad=h")};</script><style>#gbar,#guser{font-size:13px;padding-top:1px !important;}#gbar{height:22px}#guser{padding-bottom:7px !important;text-align:right}.gbh,.gbd{border-top:1px solid #c9d7f1;font-size:1px}.gbh{height:0;position:absolute;top:24px;width:100%}@media all{.gb1{height:22px;margin-right:.5em;vertical-align:top}#gbar{float:left}}a.gb1,a.gb4{text-decoration:underline !important}a.gb1,a.gb4{color:#00c !important}.gbi .gb4{color:#dd8e27 !important}.gbf .gb4{color:#900 !important}
2
+ </style><style>body,td,a,p,.h{font-family:arial,sans-serif}body{margin:0;overflow-y:scroll}#gog{padding:3px 8px 0}td{line-height:.8em}.gac_m td{line-height:17px}form{margin-bottom:20px}.h{color:#36c}.q{color:#00c}.ts td{padding:0}.ts{border-collapse:collapse}em{font-weight:bold;font-style:normal}.lst{height:25px;width:496px}.gsfi,.lst{font:18px arial,sans-serif}.gsfs{font:17px arial,sans-serif}.ds{display:inline-box;display:inline-block;margin:3px 0 4px;margin-left:4px}input{font-family:inherit}a.gb1,a.gb2,a.gb3,a.gb4{color:#11c !important}body{background:#fff;color:black}a{color:#11c;text-decoration:none}a:hover,a:active{text-decoration:underline}.fl a{color:#36c}a:visited{color:#551a8b}a.gb1,a.gb4{text-decoration:underline}a.gb3:hover{text-decoration:none}#ghead a.gb2:hover{color:#fff !important}.sblc{padding-top:5px}.sblc a{display:block;margin:2px 0;margin-left:13px;font-size:11px}.lsbb{background:#eee;border:solid 1px;border-color:#ccc #999 #999 #ccc;height:30px}.lsbb{display:block}.ftl,#fll a{display:inline-block;margin:0 12px}.lsb{background:url(/images/nav_logo229.png) 0 -261px repeat-x;border:none;color:#000;cursor:pointer;height:30px;margin:0;outline:0;font:15px arial,sans-serif;vertical-align:top}.lsb:active{background:#ccc}.lst:focus{outline:none}</style><script></script><link href="/images/branding/product/ico/googleg_lodp.ico" rel="shortcut icon"></head><body bgcolor="#fff"><script>(function(){var src='/images/nav_logo229.png';var iesg=false;document.body.onload = function(){window.n && window.n();if (document.images){new Image().src=src;}
3
+ if (!iesg){document.f&&document.f.q.focus();document.gbqf&&document.gbqf.q.focus();}
4
+ }
5
+ })();</script><div id="mngb"> <div id=gbar><nobr><b class=gb1>検索</b> <a class=gb1 href="https://www.google.co.jp/imghp?hl=ja&tab=wi">画像</a> <a class=gb1 href="https://maps.google.co.jp/maps?hl=ja&tab=wl">マップ</a> <a class=gb1 href="https://play.google.com/?hl=ja&tab=w8">Play</a> <a class=gb1 href="https://www.youtube.com/?gl=JP&tab=w1">YouTube</a> <a class=gb1 href="https://news.google.co.jp/nwshp?hl=ja&tab=wn">ニュース</a> <a class=gb1 href="https://mail.google.com/mail/?tab=wm">Gmail</a> <a class=gb1 href="https://drive.google.com/?tab=wo">ドライブ</a> <a class=gb1 style="text-decoration:none" href="https://www.google.co.jp/intl/ja/options/"><u>もっと見る</u> &raquo;</a></nobr></div><div id=guser width=100%><nobr><span id=gbn class=gbi></span><span id=gbf class=gbf></span><span id=gbe></span><a href="http://www.google.co.jp/history/optout?hl=ja" class=gb4>ウェブ履歴</a> | <a href="/preferences?hl=ja" class=gb4>設定</a> | <a target=_top id=gb_70 href="https://accounts.google.com/ServiceLogin?hl=ja&passive=true&continue=https://www.google.co.jp/" class=gb4>ログイン</a></nobr></div><div class=gbh style=left:0></div><div class=gbh style=right:0></div> </div><center><br clear="all" id="lgpd"><div id="lga"><div style="padding:28px 0 3px"><div style="height:110px;width:276px;background:url(/images/branding/googlelogo/1x/googlelogo_white_background_color_272x92dp.png) no-repeat" title="Google" align="left" id="hplogo" onload="window.lol&&lol()"><div style="color:#777;font-size:16px;font-weight:bold;position:relative;top:70px;left:218px" nowrap="">日本</div></div></div><br></div><form action="/search" name="f"><table cellpadding="0" cellspacing="0"><tr valign="top"><td width="25%">&nbsp;</td><td align="center" nowrap=""><input name="ie" value="Shift_JIS" type="hidden"><input value="ja" name="hl" type="hidden"><input name="source" type="hidden" value="hp"><input name="biw" type="hidden"><input name="bih" type="hidden"><div class="ds" style="height:32px;margin:4px 0"><input style="color:#000;margin:0;padding:5px 8px 0 6px;vertical-align:top" autocomplete="off" class="lst" value="" title="Google 検索" maxlength="2048" name="q" size="57"></div><br style="line-height:0"><span class="ds"><span class="lsbb"><input class="lsb" value="Google 検索" name="btnG" type="submit"></span></span><span class="ds"><span class="lsbb"><input class="lsb" value="I'm Feeling Lucky" name="btnI" onclick="if(this.form.q.value)this.checked=1; else top.location='/doodles/'" type="submit"></span></span></td><td class="fl sblc" align="left" nowrap="" width="25%"><a href="/advanced_search?hl=ja&amp;authuser=0">検索オプション</a><a href="/language_tools?hl=ja&amp;authuser=0">言語ツール</a></td></tr></table><input id="gbv" name="gbv" type="hidden" value="1"></form><div id="gac_scont"></div><div style="font-size:83%;min-height:3.5em"><br></div><span id="footer"><div style="font-size:10pt"><div style="margin:19px auto;text-align:center" id="fll"><a href="/intl/ja/ads/">広告掲載</a><a href="http://www.google.co.jp/intl/ja/services/">ビジネス ソリューション</a><a href="https://plus.google.com/115899767381375908215" rel="publisher">+Google</a><a href="/intl/ja/about.html">Google について</a><a href="https://www.google.co.jp/setprefdomain?prefdom=US&amp;sig=__NSwOcr0nRFmauaxJWrHJmztdkTc%3D" id="fehl">Google.com</a></div></div><p style="color:#767676;font-size:8pt">&copy; 2017 - <a href="/intl/ja/policies/privacy/">プライバシー</a> - <a href="/intl/ja/policies/terms/">規約</a></p></span></center><script>(function(){window.google.cdo={height:0,width:0};(function(){var a=window.innerWidth,b=window.innerHeight;if(!a||!b)var c=window.document,d="CSS1Compat"==c.compatMode?c.documentElement:c.body,a=d.clientWidth,b=d.clientHeight;a&&b&&(a!=google.cdo.width||b!=google.cdo.height)&&google.log("","","/client_204?&atyp=i&biw="+a+"&bih="+b+"&ei="+google.kEI);}).call(this);})();</script><div id="xjsd"></div><div id="xjsi"><script>(function(){function c(b){window.setTimeout(function(){var a=document.createElement("script");a.src=b;document.getElementById("xjsd").appendChild(a)},0)}google.dljp=function(b,a){google.xjsu=b;c(a)};google.dlj=c;}).call(this);(function(){window.google.xjsrm=[];})();if(google.y)google.y.first=[];if(!google.xjs){window._=window._||{};window._._DumpException=function(e){throw e};if(google.timers&&google.timers.load.t){google.timers.load.t.xjsls=new Date().getTime();}google.dljp('/xjs/_/js/k\x3dxjs.hp.en_US.usfcb5N0rIw.O/m\x3dsb_he,d/rt\x3dj/d\x3d1/t\x3dzcms/rs\x3dACT90oH_6o1ZdJ1OdBerX9LppN-xEd11Eg','/xjs/_/js/k\x3dxjs.hp.en_US.usfcb5N0rIw.O/m\x3dsb_he,d/rt\x3dj/d\x3d1/t\x3dzcms/rs\x3dACT90oH_6o1ZdJ1OdBerX9LppN-xEd11Eg');google.xjs=1;}google.pmc={"sb_he":{"agen":true,"cgen":true,"client":"heirloom-hp","dh":true,"dhqt":true,"ds":"","fl":true,"host":"google.co.jp","isbh":28,"jam":0,"jsonp":true,"msgs":{"cibl":"検索をクリア","dym":"もしかして:","lcky":"I\u0026#39;m Feeling Lucky","lml":"詳細","oskt":"入力ツール","psrc":"この検索キーワードは\u003Ca href=\"/history\"\u003Eウェブ履歴\u003C/a\u003Eから削除されました","psrl":"削除","sbit":"画像で検索","srch":"Google 検索"},"nds":true,"ovr":{},"pq":"","refpd":true,"refspre":true,"rfs":[],"scd":10,"sce":5,"stok":"WXDdTX_0YGr0J9JRNcHRvk23BlI"},"d":{}};google.y.first.push(function(){if(google.med){google.med('init');google.initHistory();google.med('history');}});if(google.j&&google.j.en&&google.j.xi){window.setTimeout(google.j.xi,0);}
6
+ </script></div></body></html>
data/spec/grader_spec.rb CHANGED
@@ -15,7 +15,7 @@ describe LinkThumbnailer::Grader do
15
15
  let(:action) { instance.call }
16
16
 
17
17
  before do
18
- instance.stub(:graders).and_return(graders)
18
+ allow(instance).to receive(:graders).and_return(graders)
19
19
  end
20
20
 
21
21
  it { expect(action).to eq((0.5 * 0.5) ** weight) }
@@ -12,7 +12,7 @@ describe LinkThumbnailer::Graders::HtmlAttribute do
12
12
  context 'when current node does not match attribute' do
13
13
 
14
14
  before do
15
- instance.stub(:attribute?).and_return(false)
15
+ allow(instance).to receive(:attribute?).and_return(false)
16
16
  end
17
17
 
18
18
  it { expect(action).to eq(1.0) }
@@ -22,9 +22,9 @@ describe LinkThumbnailer::Graders::HtmlAttribute do
22
22
  context 'when current node has a negative attribute' do
23
23
 
24
24
  before do
25
- instance.stub(:attribute?).and_return(true)
26
- instance.stub(:negative?).and_return(true)
27
- instance.stub(:positive?).and_return(false)
25
+ allow(instance).to receive(:attribute?).and_return(true)
26
+ allow(instance).to receive(:negative?).and_return(true)
27
+ allow(instance).to receive(:positive?).and_return(false)
28
28
  end
29
29
 
30
30
  it { expect(action).to eq(0.0) }
@@ -34,9 +34,9 @@ describe LinkThumbnailer::Graders::HtmlAttribute do
34
34
  context 'when current node has a positive attribute' do
35
35
 
36
36
  before do
37
- instance.stub(:attribute?).and_return(true)
38
- instance.stub(:negative?).and_return(false)
39
- instance.stub(:positive?).and_return(true)
37
+ allow(instance).to receive(:attribute?).and_return(true)
38
+ allow(instance).to receive(:negative?).and_return(false)
39
+ allow(instance).to receive(:positive?).and_return(true)
40
40
  end
41
41
 
42
42
  it { expect(action).to eq(1.0) }
@@ -7,7 +7,7 @@ describe LinkThumbnailer::Graders::Length do
7
7
  let(:instance) { described_class.new(description) }
8
8
 
9
9
  before do
10
- instance.stub(:config).and_return(config)
10
+ allow(instance).to receive(:config).and_return(config)
11
11
  end
12
12
 
13
13
  describe '#call' do
@@ -17,7 +17,7 @@ describe LinkThumbnailer::Graders::Length do
17
17
  context 'when text is too short' do
18
18
 
19
19
  before do
20
- instance.stub(:too_short?).and_return(true)
20
+ allow(instance).to receive(:too_short?).and_return(true)
21
21
  end
22
22
 
23
23
  it { expect(action).to eq(0.0) }
@@ -27,8 +27,8 @@ describe LinkThumbnailer::Graders::Length do
27
27
  context 'when text is not too short' do
28
28
 
29
29
  before do
30
- instance.stub(:too_short?).and_return(false)
31
- instance.stub(:text).and_return(text)
30
+ allow(instance).to receive(:too_short?).and_return(false)
31
+ allow(instance).to receive(:text).and_return(text)
32
32
  end
33
33
 
34
34
  context 'when text length is 120' do
@@ -62,10 +62,12 @@ describe LinkThumbnailer::Graders::Length do
62
62
  describe '#too_short?' do
63
63
 
64
64
  let(:action) { instance.send(:too_short?) }
65
+ let(:config) { double }
65
66
 
66
67
  before do
67
- instance.stub_chain(:config, :description_min_length).and_return(10)
68
- instance.stub(:text).and_return(text)
68
+ allow(instance).to receive(:config).and_return(config)
69
+ allow(config).to receive(:description_min_length).and_return(10)
70
+ allow(instance).to receive(:text).and_return(text)
69
71
  end
70
72
 
71
73
  context 'when true' do
@@ -10,8 +10,8 @@ describe LinkThumbnailer::Graders::LinkDensity do
10
10
  let(:action) { instance.call }
11
11
 
12
12
  before do
13
- instance.stub(:text).and_return(text)
14
- instance.stub(:links).and_return(links)
13
+ allow(instance).to receive(:text).and_return(text)
14
+ allow(instance).to receive(:links).and_return(links)
15
15
  end
16
16
 
17
17
  context 'when text length is 0' do
@@ -12,8 +12,8 @@ describe LinkThumbnailer::Graders::Position do
12
12
  context 'when position is 0' do
13
13
 
14
14
  before do
15
- description.stub(:position).and_return(0)
16
- description.stub(:candidates_number).and_return(1)
15
+ allow(description).to receive(:position).and_return(0)
16
+ allow(description).to receive(:candidates_number).and_return(1)
17
17
  end
18
18
 
19
19
  it { expect(action).to eq(1.0) }
@@ -23,8 +23,8 @@ describe LinkThumbnailer::Graders::Position do
23
23
  context 'when position is 1 over 1 candidates' do
24
24
 
25
25
  before do
26
- description.stub(:position).and_return(1)
27
- description.stub(:candidates_number).and_return(1)
26
+ allow(description).to receive(:position).and_return(1)
27
+ allow(description).to receive(:candidates_number).and_return(1)
28
28
  end
29
29
 
30
30
  it { expect(action).to eq(0.0) }
@@ -34,8 +34,8 @@ describe LinkThumbnailer::Graders::Position do
34
34
  context 'when position is 1 over more than 1 candidates' do
35
35
 
36
36
  before do
37
- description.stub(:position).and_return(1)
38
- description.stub(:candidates_number).and_return(2)
37
+ allow(description).to receive(:position).and_return(1)
38
+ allow(description).to receive(:candidates_number).and_return(2)
39
39
  end
40
40
 
41
41
  it { expect(action).to eq(0.5) }
@@ -11,7 +11,7 @@ describe LinkThumbnailer::ImageValidator do
11
11
  let(:action) { instance.call }
12
12
 
13
13
  before do
14
- instance.stub(:blacklist_urls).and_return(blacklist_urls)
14
+ allow(instance).to receive(:blacklist_urls).and_return(blacklist_urls)
15
15
  end
16
16
 
17
17
  context 'when image url is blacklisted' do
@@ -8,7 +8,7 @@ describe LinkThumbnailer::Models::Description do
8
8
  let(:instance) { described_class.new(node, text) }
9
9
 
10
10
  before do
11
- ::LinkThumbnailer::Grader.should_receive(:new).at_least(1).and_return(grader)
11
+ expect(LinkThumbnailer::Grader).to receive(:new).at_least(1).times.and_return(grader)
12
12
  end
13
13
 
14
14
  describe '#to_s' do
@@ -23,7 +23,7 @@ describe LinkThumbnailer::Models::Image do
23
23
  let(:action) { instance <=> other }
24
24
 
25
25
  before do
26
- instance.stub(:size).and_return([20, 20])
26
+ allow(instance).to receive(:size).and_return([20, 20])
27
27
  end
28
28
 
29
29
  context 'when other has a smaller image' do
@@ -58,7 +58,7 @@ describe LinkThumbnailer::Models::Image do
58
58
  let(:action) { instance.valid? }
59
59
 
60
60
  before do
61
- instance.stub(:validator).and_return(validator)
61
+ allow(instance).to receive(:validator).and_return(validator)
62
62
  end
63
63
 
64
64
  it 'calls validator public method' do
@@ -82,8 +82,8 @@ describe LinkThumbnailer::Models::Image do
82
82
  }
83
83
 
84
84
  before do
85
- instance.stub(:size).and_return(size)
86
- instance.stub(:type).and_return(type)
85
+ allow(instance).to receive(:size).and_return(size)
86
+ allow(instance).to receive(:type).and_return(type)
87
87
  end
88
88
 
89
89
  it { expect(action).to eq(result) }
@@ -33,11 +33,11 @@ describe LinkThumbnailer::Models::Video do
33
33
  }
34
34
 
35
35
  before do
36
- instance.stub(:id).and_return(id)
37
- instance.stub(:size).and_return(size)
38
- instance.stub(:duration).and_return(duration)
39
- instance.stub(:provider).and_return(provider)
40
- instance.stub(:embed_code).and_return(embed_code)
36
+ allow(instance).to receive(:id).and_return(id)
37
+ allow(instance).to receive(:size).and_return(size)
38
+ allow(instance).to receive(:duration).and_return(duration)
39
+ allow(instance).to receive(:provider).and_return(provider)
40
+ allow(instance).to receive(:embed_code).and_return(embed_code)
41
41
  end
42
42
 
43
43
  it { expect(action).to eq(result) }
@@ -12,7 +12,7 @@ describe LinkThumbnailer::Models::Website do
12
12
  let(:action) { instance.image = image }
13
13
 
14
14
  before do
15
- image.stub(:valid?).and_return(true)
15
+ allow(image).to receive(:valid?).and_return(true)
16
16
  end
17
17
 
18
18
  it { expect { action }.to change { instance.images.size }.by(1) }
@@ -27,7 +27,7 @@ describe LinkThumbnailer::Models::Website do
27
27
  context 'when image is valid' do
28
28
 
29
29
  before do
30
- image.stub(:valid?).and_return(true)
30
+ allow(image).to receive(:valid?).and_return(true)
31
31
  end
32
32
 
33
33
  it { expect { action }.to change { instance.images.size }.by(1) }
@@ -37,7 +37,7 @@ describe LinkThumbnailer::Models::Website do
37
37
  context 'when image is not valid' do
38
38
 
39
39
  before do
40
- image.stub(:valid?).and_return(false)
40
+ allow(image).to receive(:valid?).and_return(false)
41
41
  end
42
42
 
43
43
  it { expect { action }.to_not change { instance.images.size } }
@@ -7,7 +7,7 @@ describe LinkThumbnailer::Processor do
7
7
  let(:url) { 'http://foo.com' }
8
8
 
9
9
  before do
10
- LinkThumbnailer.stub(:page).and_return(page)
10
+ allow(LinkThumbnailer).to receive(:page).and_return(page)
11
11
  end
12
12
 
13
13
  describe '#call' do
@@ -81,7 +81,7 @@ describe LinkThumbnailer::Processor do
81
81
  context 'when valid' do
82
82
 
83
83
  before do
84
- instance.stub(:valid_url_format?).and_return(true)
84
+ allow(instance).to receive(:valid_url_format?).and_return(true)
85
85
  end
86
86
 
87
87
  it 'yields' do
@@ -94,7 +94,7 @@ describe LinkThumbnailer::Processor do
94
94
  context 'when not valid' do
95
95
 
96
96
  before do
97
- instance.stub(:valid_url_format?).and_return(false)
97
+ allow(instance).to receive(:valid_url_format?).and_return(false)
98
98
  end
99
99
 
100
100
  it { expect { instance.send(:with_valid_url) }.to raise_error(LinkThumbnailer::BadUriFormat) }
@@ -110,7 +110,7 @@ describe LinkThumbnailer::Processor do
110
110
  let(:action) { instance.send(:set_http_headers) }
111
111
 
112
112
  before do
113
- instance.stub(:user_agent).and_return(user_agent)
113
+ allow(instance).to receive(:user_agent).and_return(user_agent)
114
114
  action
115
115
  end
116
116
 
@@ -128,7 +128,7 @@ describe LinkThumbnailer::Processor do
128
128
  context 'when verify_ssl is true' do
129
129
 
130
130
  before do
131
- instance.stub(:ssl_required?).and_return(true)
131
+ allow(instance).to receive(:ssl_required?).and_return(true)
132
132
  action
133
133
  end
134
134
 
@@ -139,7 +139,7 @@ describe LinkThumbnailer::Processor do
139
139
  context 'when verify_ssl is not true' do
140
140
 
141
141
  before do
142
- instance.stub(:ssl_required?).and_return(false)
142
+ allow(instance).to receive(:ssl_required?).and_return(false)
143
143
  action
144
144
  end
145
145
 
@@ -154,7 +154,7 @@ describe LinkThumbnailer::Processor do
154
154
  let(:http_open_timeout) { 1 }
155
155
 
156
156
  before do
157
- instance.stub(:http_open_timeout).and_return(http_open_timeout)
157
+ allow(instance).to receive(:http_open_timeout).and_return(http_open_timeout)
158
158
  action
159
159
  end
160
160
 
@@ -167,7 +167,7 @@ describe LinkThumbnailer::Processor do
167
167
  let(:http_read_timeout) { 1 }
168
168
 
169
169
  before do
170
- instance.stub(:http_read_timeout).and_return(http_read_timeout)
170
+ allow(instance).to receive(:http_read_timeout).and_return(http_read_timeout)
171
171
  action
172
172
  end
173
173
 
@@ -179,9 +179,11 @@ describe LinkThumbnailer::Processor do
179
179
  describe '#perform_request' do
180
180
 
181
181
  let(:action) { instance.send(:perform_request) }
182
+ let(:http) { double }
182
183
 
183
184
  before do
184
- instance.stub_chain(:http, :request).and_return(response)
185
+ allow(instance).to receive(:http).and_return(http)
186
+ allow(http).to receive(:request).and_return(response)
185
187
  end
186
188
 
187
189
  context 'when http success' do
@@ -191,13 +193,40 @@ describe LinkThumbnailer::Processor do
191
193
  let(:response) { ::Net::HTTPSuccess.new('', code, body) }
192
194
 
193
195
  before do
194
- response.stub(:body).and_return(body)
196
+ allow(response).to receive(:body).and_return(body)
195
197
  end
196
198
 
197
199
  it { expect(action).to eq(body) }
198
200
 
199
201
  end
200
202
 
203
+ context 'when access non-utf8-encoding website' do
204
+ let(:code) { 200 }
205
+ let(:body_shift_jis) do
206
+ File.read(File.expand_path('fixtures/google_shift_jis.html', File.dirname(__FILE__)))
207
+ end
208
+ let(:body_utf8) do
209
+ File.read(File.expand_path('fixtures/google_utf8.html', File.dirname(__FILE__)))
210
+ end
211
+ let(:response) do
212
+ r = ::Net::HTTPSuccess.new('', code, body_shift_jis)
213
+ r['Content-Type'] = 'text/html'
214
+ r.body = body_shift_jis
215
+ r.instance_variable_set(:@read, true)
216
+ r
217
+ end
218
+
219
+ context 'when http success with valid charset provided in Content-Type' do
220
+ before { response['Content-Type'] = 'text/html; charset=Shift_JIS' }
221
+ it { expect(action).to eq body_utf8 }
222
+ end
223
+
224
+ context 'when http success with invalid charset provided in Content-Type' do
225
+ before { response['Content-Type'] = 'text/html; charset=Shift-JIS' }
226
+ it { expect(action).to eq body_shift_jis }
227
+ end
228
+ end
229
+
201
230
  context 'when http redirection' do
202
231
 
203
232
  let(:code) { 200 }
@@ -206,8 +235,8 @@ describe LinkThumbnailer::Processor do
206
235
  let(:new_url) { 'http://foo.com/bar' }
207
236
 
208
237
  before do
209
- instance.stub(:redirect_count).and_return(0)
210
- instance.stub(:resolve_relative_url).and_return(new_url)
238
+ allow(instance).to receive(:redirect_count).and_return(0)
239
+ allow(instance).to receive(:resolve_relative_url).and_return(new_url)
211
240
  end
212
241
 
213
242
  it 'calls call method' do
@@ -229,7 +258,7 @@ describe LinkThumbnailer::Processor do
229
258
  let(:action) { instance.send(:build_absolute_url_for, relative_url).to_s }
230
259
 
231
260
  before do
232
- instance.stub(:url).and_return(url)
261
+ allow(instance).to receive(:url).and_return(url)
233
262
  end
234
263
 
235
264
  it { expect(action).to eq("#{scheme}://#{host}#{relative_url}") }
@@ -308,7 +337,7 @@ describe LinkThumbnailer::Processor do
308
337
  context 'when bad format' do
309
338
 
310
339
  before do
311
- instance.stub(:url).and_return("http://foo.com")
340
+ allow(instance).to receive(:url).and_return("http://foo.com")
312
341
  end
313
342
 
314
343
  it { expect(action).to be_falsey }
@@ -318,7 +347,7 @@ describe LinkThumbnailer::Processor do
318
347
  context 'when valid format' do
319
348
 
320
349
  before do
321
- instance.stub(:url).and_return(URI("http://foo.com"))
350
+ allow(instance).to receive(:url).and_return(URI("http://foo.com"))
322
351
  end
323
352
 
324
353
  it { expect(action).to be_truthy }
@@ -334,8 +363,8 @@ describe LinkThumbnailer::Processor do
334
363
  context 'when redirect count is greater than redirect limit' do
335
364
 
336
365
  before do
337
- instance.stub(:redirect_count).and_return(5)
338
- instance.stub(:redirect_limit).and_return(4)
366
+ allow(instance).to receive(:redirect_count).and_return(5)
367
+ allow(instance).to receive(:redirect_limit).and_return(4)
339
368
  end
340
369
 
341
370
  it { expect(action).to be_truthy }
@@ -345,8 +374,8 @@ describe LinkThumbnailer::Processor do
345
374
  context 'when redirect count is less than redirect limit' do
346
375
 
347
376
  before do
348
- instance.stub(:redirect_count).and_return(4)
349
- instance.stub(:redirect_limit).and_return(5)
377
+ allow(instance).to receive(:redirect_count).and_return(4)
378
+ allow(instance).to receive(:redirect_limit).and_return(5)
350
379
  end
351
380
 
352
381
  it { expect(action).to be_falsey }
@@ -356,8 +385,8 @@ describe LinkThumbnailer::Processor do
356
385
  context 'when redirect count is equal to redirect limit' do
357
386
 
358
387
  before do
359
- instance.stub(:redirect_count).and_return(5)
360
- instance.stub(:redirect_limit).and_return(5)
388
+ allow(instance).to receive(:redirect_count).and_return(5)
389
+ allow(instance).to receive(:redirect_limit).and_return(5)
361
390
  end
362
391
 
363
392
  it { expect(action).to be_falsey }
@@ -0,0 +1,60 @@
1
+ require 'spec_helper'
2
+
3
+ describe LinkThumbnailer::Response do
4
+ let(:url) { 'https://www.google.co.jp' }
5
+ let(:page) { ::LinkThumbnailer::Page.new(url, {}) }
6
+
7
+ let(:response) do
8
+ r = ::Net::HTTPSuccess.new('', 200, body_shift_jis)
9
+ r['Content-Type'] = 'text/html'
10
+ r.body = body_shift_jis
11
+ r.instance_variable_set(:@read, true)
12
+ r
13
+ end
14
+
15
+ let(:instance) { described_class.new(response) }
16
+
17
+ let(:body_shift_jis) do
18
+ File.read(File.expand_path('fixtures/google_shift_jis.html', File.dirname(__FILE__)))
19
+ end
20
+
21
+ let(:body_utf8) do
22
+ File.read(File.expand_path('fixtures/google_utf8.html', File.dirname(__FILE__)))
23
+ end
24
+
25
+ before do
26
+ allow(LinkThumbnailer).to receive(:page).and_return(page)
27
+ end
28
+
29
+ describe '#charset' do
30
+ context 'when charset provided in content-type' do
31
+ before do
32
+ response['Content-Type'] = 'text/html; charset=Shift_JIS'
33
+ end
34
+
35
+ it { expect(instance.charset).to eq 'Shift_JIS' }
36
+ end
37
+
38
+ context 'when no charset available in content-type' do
39
+ it { expect(instance.charset).to eq '' }
40
+ end
41
+ end
42
+
43
+ describe '#body' do
44
+ context 'when provide valid charset' do
45
+ before do
46
+ response['Content-Type'] = 'text/html; charset=Shift_JIS'
47
+ end
48
+
49
+ it { expect(instance.body).to eq body_utf8 }
50
+ end
51
+
52
+ context 'when provide invalid charset' do
53
+ before do
54
+ response['Content-Type'] = 'text/html; charset=Shift-JIS'
55
+ end
56
+
57
+ it { expect(instance.body).to eq body_shift_jis }
58
+ end
59
+ end
60
+ end
data/spec/scraper_spec.rb CHANGED
@@ -9,8 +9,8 @@ describe LinkThumbnailer::Scraper do
9
9
  let(:instance) { described_class.new(source, url) }
10
10
 
11
11
  before do
12
- instance.stub(:document).and_return(document)
13
- instance.stub(:website).and_return(website)
12
+ allow(instance).to receive(:document).and_return(document)
13
+ allow(instance).to receive(:website).and_return(website)
14
14
  end
15
15
 
16
16
  describe '#call' do
@@ -22,10 +22,10 @@ describe LinkThumbnailer::Scraper do
22
22
  let(:attributes) { [:bar] }
23
23
  let(:scrapers) { [prefix_1, prefix_2] }
24
24
  let(:action) { instance.call }
25
+ let(:config) { double(attributes: attributes, scrapers: scrapers) }
25
26
 
26
27
  before do
27
- instance.stub_chain(:config, :attributes).and_return(attributes)
28
- instance.stub_chain(:config, :scrapers).and_return(scrapers)
28
+ allow(instance).to receive(:config).and_return(config)
29
29
  end
30
30
 
31
31
  context 'when first one return a result' do
@@ -13,7 +13,7 @@ describe LinkThumbnailer::Scrapers::Base do
13
13
  let(:action) { instance.call(attr) }
14
14
 
15
15
  before do
16
- instance.stub(:value).and_return(value)
16
+ allow(instance).to receive(:value).and_return(value)
17
17
  end
18
18
 
19
19
  it { expect { action }.to change { website.title }.from(nil).to(value) }
@@ -25,7 +25,7 @@ describe LinkThumbnailer::Scrapers::Base do
25
25
  let(:action) { instance.send(:model_class) }
26
26
 
27
27
  before do
28
- instance.stub(:attribute_name).and_return(attr)
28
+ allow(instance).to receive(:attribute_name).and_return(attr)
29
29
  end
30
30
 
31
31
  context 'when internal class exists' do
@@ -40,7 +40,7 @@ describe LinkThumbnailer::Scrapers::Base do
40
40
 
41
41
  let(:attr) { :foo }
42
42
 
43
- it { expect { action }.to raise_exception }
43
+ it { expect { action }.to raise_error(NameError) }
44
44
 
45
45
  end
46
46
 
@@ -54,7 +54,7 @@ describe LinkThumbnailer::Scrapers::Base do
54
54
  let(:action) { instance.send(:modelize, node, text) }
55
55
 
56
56
  before do
57
- instance.stub(:model_class).and_return(model_class)
57
+ allow(instance).to receive(:model_class).and_return(model_class)
58
58
  end
59
59
 
60
60
  it 'instantiates a new model' do
@@ -12,13 +12,13 @@ describe LinkThumbnailer::Scrapers::Opengraph::Base do
12
12
  let(:action) { instance.applicable? }
13
13
 
14
14
  before do
15
- instance.stub(:meta).and_return(meta)
15
+ allow(instance).to receive(:meta).and_return(meta)
16
16
  end
17
17
 
18
18
  context 'when all node is an opengraph' do
19
19
 
20
20
  before do
21
- instance.stub(:opengraph_node?).and_return(true, true)
21
+ allow(instance).to receive(:opengraph_node?).and_return(true, true)
22
22
  end
23
23
 
24
24
  it { expect(action).to be_truthy }
@@ -28,7 +28,7 @@ describe LinkThumbnailer::Scrapers::Opengraph::Base do
28
28
  context 'when any node is an opengraph' do
29
29
 
30
30
  before do
31
- instance.stub(:opengraph_node?).and_return(true, false)
31
+ allow(instance).to receive(:opengraph_node?).and_return(true, false)
32
32
  end
33
33
 
34
34
  it { expect(action).to be_truthy }
@@ -38,7 +38,7 @@ describe LinkThumbnailer::Scrapers::Opengraph::Base do
38
38
  context 'when no node is an opengraph' do
39
39
 
40
40
  before do
41
- instance.stub(:opengraph_node?).and_return(false, false)
41
+ allow(instance).to receive(:opengraph_node?).and_return(false, false)
42
42
  end
43
43
 
44
44
  it { expect(action).to be_falsey }
@@ -52,7 +52,7 @@ describe LinkThumbnailer::Scrapers::Opengraph::Base do
52
52
  let(:action) { instance.send(:opengraph_node?, node) }
53
53
 
54
54
  before do
55
- node.stub(:attribute).with('name').and_return(attribute_from_name)
55
+ allow(node).to receive(:attribute).with('name').and_return(attribute_from_name)
56
56
  end
57
57
 
58
58
  context 'with attribute from name valid' do
@@ -68,7 +68,7 @@ describe LinkThumbnailer::Scrapers::Opengraph::Base do
68
68
  let(:attribute_from_name) { 'foo' }
69
69
 
70
70
  before do
71
- node.stub(:attribute).with('property').and_return(attribute_from_property)
71
+ allow(node).to receive(:attribute).with('property').and_return(attribute_from_property)
72
72
  end
73
73
 
74
74
  context 'and attribute from property valid' do
data/spec/uri_spec.rb CHANGED
@@ -12,7 +12,7 @@ describe LinkThumbnailer::URI do
12
12
  context 'when bad format' do
13
13
 
14
14
  before do
15
- instance.stub(:attribute).and_return("/invalid/path")
15
+ allow(instance).to receive(:attribute).and_return("/invalid/path")
16
16
  end
17
17
 
18
18
  it { expect(action).to be_falsey }
@@ -22,7 +22,7 @@ describe LinkThumbnailer::URI do
22
22
  context 'when valid format' do
23
23
 
24
24
  before do
25
- instance.stub(:attribute).and_return("http://foo.com")
25
+ allow(instance).to receive(:attribute).and_return("http://foo.com")
26
26
  end
27
27
 
28
28
  it { expect(action).to be_truthy }
@@ -8,7 +8,7 @@ describe LinkThumbnailer::VideoParser do
8
8
  let(:instance) { described_class.new(video) }
9
9
 
10
10
  before do
11
- instance.stub(:parser).and_return(parser)
11
+ allow(instance).to receive(:parser).and_return(parser)
12
12
  end
13
13
 
14
14
  describe '#id' do
@@ -18,7 +18,7 @@ describe LinkThumbnailer::VideoParser do
18
18
  context 'when respond to video_id' do
19
19
 
20
20
  before do
21
- parser.stub(:video_id).and_return(1)
21
+ allow(parser).to receive(:video_id).and_return(1)
22
22
  end
23
23
 
24
24
  it { expect(action).to eq(parser.video_id) }
@@ -28,7 +28,7 @@ describe LinkThumbnailer::VideoParser do
28
28
  context 'when do not respond to video_id' do
29
29
 
30
30
  before do
31
- parser.stub(:video_id).and_raise(NoMethodError)
31
+ allow(parser).to receive(:video_id).and_raise(NoMethodError)
32
32
  end
33
33
 
34
34
  it { expect(action).to be_nil }
@@ -44,8 +44,8 @@ describe LinkThumbnailer::VideoParser do
44
44
  context 'when respond to width and height' do
45
45
 
46
46
  before do
47
- parser.stub(:width).and_return(1)
48
- parser.stub(:height).and_return(1)
47
+ allow(parser).to receive(:width).and_return(1)
48
+ allow(parser).to receive(:height).and_return(1)
49
49
  end
50
50
 
51
51
  it { expect(action).to eq([parser.width, parser.height]) }
@@ -55,8 +55,8 @@ describe LinkThumbnailer::VideoParser do
55
55
  context 'when do not respond to width and height' do
56
56
 
57
57
  before do
58
- parser.stub(:width).and_raise(NoMethodError)
59
- parser.stub(:height).and_raise(NoMethodError)
58
+ allow(parser).to receive(:width).and_raise(NoMethodError)
59
+ allow(parser).to receive(:height).and_raise(NoMethodError)
60
60
  end
61
61
 
62
62
  it { expect(action).to be_empty }
@@ -72,7 +72,7 @@ describe LinkThumbnailer::VideoParser do
72
72
  context 'when respond to duration' do
73
73
 
74
74
  before do
75
- parser.stub(:duration).and_return(1)
75
+ allow(parser).to receive(:duration).and_return(1)
76
76
  end
77
77
 
78
78
  it { expect(action).to eq(parser.duration) }
@@ -82,7 +82,7 @@ describe LinkThumbnailer::VideoParser do
82
82
  context 'when do not respond to duration' do
83
83
 
84
84
  before do
85
- parser.stub(:duration).and_raise(NoMethodError)
85
+ allow(parser).to receive(:duration).and_raise(NoMethodError)
86
86
  end
87
87
 
88
88
  it { expect(action).to be_nil }
@@ -98,7 +98,7 @@ describe LinkThumbnailer::VideoParser do
98
98
  context 'when respond to provider' do
99
99
 
100
100
  before do
101
- parser.stub(:provider).and_return(1)
101
+ allow(parser).to receive(:provider).and_return(1)
102
102
  end
103
103
 
104
104
  it { expect(action).to eq(parser.provider) }
@@ -108,7 +108,7 @@ describe LinkThumbnailer::VideoParser do
108
108
  context 'when do not respond to provider' do
109
109
 
110
110
  before do
111
- parser.stub(:provider).and_raise(NoMethodError)
111
+ allow(parser).to receive(:provider).and_raise(NoMethodError)
112
112
  end
113
113
 
114
114
  it { expect(action).to be_nil }
@@ -124,7 +124,7 @@ describe LinkThumbnailer::VideoParser do
124
124
  context 'when respond to embed_code' do
125
125
 
126
126
  before do
127
- parser.stub(:embed_code).and_return('')
127
+ allow(parser).to receive(:embed_code).and_return('')
128
128
  end
129
129
 
130
130
  it { expect(action).to eq(parser.embed_code) }
@@ -134,7 +134,7 @@ describe LinkThumbnailer::VideoParser do
134
134
  context 'when do not respond to embed_code' do
135
135
 
136
136
  before do
137
- parser.stub(:embed_code).and_raise(NoMethodError)
137
+ allow(parser).to receive(:embed_code).and_raise(NoMethodError)
138
138
  end
139
139
 
140
140
  it { expect(action).to be_nil }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: link_thumbnailer
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.3.0
4
+ version: 3.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pierre-Louis Gottfrois
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-27 00:00:00.000000000 Z
11
+ date: 2017-06-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -28,22 +28,16 @@ dependencies:
28
28
  name: json
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: 1.7.7
34
31
  - - "~>"
35
32
  - !ruby/object:Gem::Version
36
- version: '1.8'
33
+ version: '2.1'
37
34
  type: :runtime
38
35
  prerelease: false
39
36
  version_requirements: !ruby/object:Gem::Requirement
40
37
  requirements:
41
- - - ">="
42
- - !ruby/object:Gem::Version
43
- version: 1.7.7
44
38
  - - "~>"
45
39
  - !ruby/object:Gem::Version
46
- version: '1.8'
40
+ version: '2.1'
47
41
  - !ruby/object:Gem::Dependency
48
42
  name: rake
49
43
  requirement: !ruby/object:Gem::Requirement
@@ -64,56 +58,56 @@ dependencies:
64
58
  requirements:
65
59
  - - "~>"
66
60
  - !ruby/object:Gem::Version
67
- version: '1.6'
61
+ version: '1.7'
68
62
  type: :runtime
69
63
  prerelease: false
70
64
  version_requirements: !ruby/object:Gem::Requirement
71
65
  requirements:
72
66
  - - "~>"
73
67
  - !ruby/object:Gem::Version
74
- version: '1.6'
68
+ version: '1.7'
75
69
  - !ruby/object:Gem::Dependency
76
70
  name: net-http-persistent
77
71
  requirement: !ruby/object:Gem::Requirement
78
72
  requirements:
79
73
  - - "~>"
80
74
  - !ruby/object:Gem::Version
81
- version: '2.9'
75
+ version: '3.0'
82
76
  type: :runtime
83
77
  prerelease: false
84
78
  version_requirements: !ruby/object:Gem::Requirement
85
79
  requirements:
86
80
  - - "~>"
87
81
  - !ruby/object:Gem::Version
88
- version: '2.9'
82
+ version: '3.0'
89
83
  - !ruby/object:Gem::Dependency
90
84
  name: video_info
91
85
  requirement: !ruby/object:Gem::Requirement
92
86
  requirements:
93
87
  - - "~>"
94
88
  - !ruby/object:Gem::Version
95
- version: '2.6'
89
+ version: '2.7'
96
90
  type: :runtime
97
91
  prerelease: false
98
92
  version_requirements: !ruby/object:Gem::Requirement
99
93
  requirements:
100
94
  - - "~>"
101
95
  - !ruby/object:Gem::Version
102
- version: '2.6'
96
+ version: '2.7'
103
97
  - !ruby/object:Gem::Dependency
104
98
  name: image_info
105
99
  requirement: !ruby/object:Gem::Requirement
106
100
  requirements:
107
101
  - - "~>"
108
102
  - !ruby/object:Gem::Version
109
- version: '1.0'
103
+ version: '1.1'
110
104
  type: :runtime
111
105
  prerelease: false
112
106
  version_requirements: !ruby/object:Gem::Requirement
113
107
  requirements:
114
108
  - - "~>"
115
109
  - !ruby/object:Gem::Version
116
- version: '1.0'
110
+ version: '1.1'
117
111
  description: Ruby gem generating thumbnail images from a given URL.
118
112
  email:
119
113
  - pierrelouis.gottfrois@gmail.com
@@ -123,6 +117,7 @@ extra_rdoc_files: []
123
117
  files:
124
118
  - ".gitignore"
125
119
  - ".rspec"
120
+ - ".ruby-version"
126
121
  - ".travis.yml"
127
122
  - CHANGELOG.md
128
123
  - Gemfile
@@ -156,6 +151,7 @@ files:
156
151
  - lib/link_thumbnailer/parser.rb
157
152
  - lib/link_thumbnailer/processor.rb
158
153
  - lib/link_thumbnailer/railtie.rb
154
+ - lib/link_thumbnailer/response.rb
159
155
  - lib/link_thumbnailer/scraper.rb
160
156
  - lib/link_thumbnailer/scrapers/base.rb
161
157
  - lib/link_thumbnailer/scrapers/default/base.rb
@@ -182,6 +178,8 @@ files:
182
178
  - spec/fixtures/default_from_body.html
183
179
  - spec/fixtures/default_from_meta.html
184
180
  - spec/fixtures/foo.png
181
+ - spec/fixtures/google_shift_jis.html
182
+ - spec/fixtures/google_utf8.html
185
183
  - spec/fixtures/og_not_valid_example.html
186
184
  - spec/fixtures/og_valid_example.html
187
185
  - spec/fixtures/og_valid_multi_image_example.html
@@ -203,6 +201,7 @@ files:
203
201
  - spec/models/website_spec.rb
204
202
  - spec/page_spec.rb
205
203
  - spec/processor_spec.rb
204
+ - spec/response_spec.rb
206
205
  - spec/scraper_spec.rb
207
206
  - spec/scrapers/base_spec.rb
208
207
  - spec/scrapers/opengraph/base_spec.rb
@@ -228,7 +227,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
228
227
  version: '0'
229
228
  requirements: []
230
229
  rubyforge_project:
231
- rubygems_version: 2.5.1
230
+ rubygems_version: 2.6.10
232
231
  signing_key:
233
232
  specification_version: 4
234
233
  summary: Ruby gem ranking images from a given URL returning an object containing images
@@ -240,6 +239,8 @@ test_files:
240
239
  - spec/fixtures/default_from_body.html
241
240
  - spec/fixtures/default_from_meta.html
242
241
  - spec/fixtures/foo.png
242
+ - spec/fixtures/google_shift_jis.html
243
+ - spec/fixtures/google_utf8.html
243
244
  - spec/fixtures/og_not_valid_example.html
244
245
  - spec/fixtures/og_valid_example.html
245
246
  - spec/fixtures/og_valid_multi_image_example.html
@@ -261,6 +262,7 @@ test_files:
261
262
  - spec/models/website_spec.rb
262
263
  - spec/page_spec.rb
263
264
  - spec/processor_spec.rb
265
+ - spec/response_spec.rb
264
266
  - spec/scraper_spec.rb
265
267
  - spec/scrapers/base_spec.rb
266
268
  - spec/scrapers/opengraph/base_spec.rb