jpmobile 2.0.8 → 2.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,7 +4,8 @@ end
4
4
 
5
5
  module Jpmobile
6
6
  module Emoticon
7
- GETA = 0x3013
7
+ GETA_CODE = 0x3013
8
+ GETA = [GETA_CODE].pack('U')
8
9
 
9
10
  SJIS_TO_UNICODE = {}
10
11
  SJIS_TO_UNICODE.update(DOCOMO_SJIS_TO_UNICODE)
@@ -32,5 +33,20 @@ module Jpmobile
32
33
 
33
34
  SOFTBANK_SJIS_REGEXP = Regexp.union(*SOFTBANK_SJIS_TO_UNICODE.keys.map{|s| Jpmobile::Util.sjis_regexp(s)}).freeze
34
35
  AU_EMAILJIS_REGEXP = Regexp.union(*AU_EMAILJIS_TO_UNICODE.keys.map{|s| Jpmobile::Util.jis_regexp(s)})
36
+
37
+ # for unicode/google emoticons
38
+ UNICODE_EMOTICONS = (UNICODE_TO_DOCOMO_UNICODE.keys|UNICODE_TO_AU_UNICODE.keys|UNICODE_TO_SOFTBANK_UNICODE.keys).uniq
39
+ GOOGLE_EMOTICONS = (GOOGLE_TO_DOCOMO_UNICODE.keys|GOOGLE_TO_AU_UNICODE.keys|GOOGLE_TO_SOFTBANK_UNICODE.keys).uniq
40
+
41
+ UNICODE_EMOTICON_REGEXP = Regexp.union(*UNICODE_EMOTICONS.map{|x| x.kind_of?(Array) ? x.pack('UU') : [x].pack('U')}).freeze
42
+ GOOGLE_EMOTICON_REGEXP = Regexp.union(*GOOGLE_EMOTICONS.map{|x| x.kind_of?(Array) ? x.pack('UU') : [x].pack('U')}).freeze
43
+
44
+ UNICODE_EMOTICON_TO_CARRIER_EMOTICON = UNICODE_TO_DOCOMO_UNICODE.merge(UNICODE_TO_AU_UNICODE.merge(UNICODE_TO_SOFTBANK_UNICODE))
45
+ GOOGLE_EMOTICON_TO_CARRIER_EMOTICON = GOOGLE_TO_SOFTBANK_UNICODE.merge(GOOGLE_TO_AU_UNICODE.merge(GOOGLE_TO_DOCOMO_UNICODE))
46
+
47
+ CONVERSION_TABLE_TO_UNICODE_EMOTICON = Jpmobile::Util.invert_table(UNICODE_TO_DOCOMO_UNICODE).merge(
48
+ Jpmobile::Util.invert_table(UNICODE_TO_AU_UNICODE).merge(Jpmobile::Util.invert_table(UNICODE_TO_SOFTBANK_UNICODE)))
49
+ CONVERSION_TABLE_TO_GOOGLE_EMOTICON = Jpmobile::Util.invert_table(GOOGLE_TO_SOFTBANK_UNICODE).merge(
50
+ Jpmobile::Util.invert_table(GOOGLE_TO_AU_UNICODE).merge(Jpmobile::Util.invert_table(GOOGLE_TO_DOCOMO_UNICODE)))
35
51
  end
36
52
  end
@@ -80,7 +80,7 @@ module Jpmobile::Mobile
80
80
  def variants
81
81
  return @_variants if @_variants
82
82
 
83
- @_variants = self.class.ancestors.select {|c| c.to_s =~ /^Jpmobile/}.map do |klass|
83
+ @_variants = self.class.ancestors.select {|c| c.to_s =~ /^Jpmobile/ && c.to_s !~ /Emoticon/}.map do |klass|
84
84
  klass = klass.to_s.
85
85
  gsub(/Jpmobile::/, '').
86
86
  gsub(/AbstractMobile::/, '').
@@ -6,5 +6,7 @@ module Jpmobile::Mobile
6
6
  class Android < SmartPhone
7
7
  # 対応するUser-Agentの正規表現
8
8
  USER_AGENT_REGEXP = /Android/
9
+
10
+ include Jpmobile::Mobile::GoogleEmoticon
9
11
  end
10
12
  end
@@ -6,5 +6,7 @@ module Jpmobile::Mobile
6
6
  class AndroidTablet < Tablet
7
7
  # 対応するUser-Agentの正規表現
8
8
  USER_AGENT_REGEXP = Regexp.union(/(?!Android.+Mobile)Android/, /Android.+SC-01C/)
9
+
10
+ include Jpmobile::Mobile::GoogleEmoticon
9
11
  end
10
12
  end
@@ -0,0 +1,10 @@
1
+ # -*- coding: utf-8 -*-
2
+ # =BlackBerry
3
+
4
+ module Jpmobile::Mobile
5
+ # ==BlackBerry
6
+ class BlackBerry < SmartPhone
7
+ # 対応するUser-Agentの正規表現
8
+ USER_AGENT_REGEXP = /BlackBerry/
9
+ end
10
+ end
@@ -0,0 +1,29 @@
1
+ # -*- coding: utf-8 -*-
2
+ module Jpmobile::Mobile
3
+ module GoogleEmoticon
4
+ # Jpmobile::Rack::Filter を適用する
5
+ def apply_filter?
6
+ Jpmobile.config.smart_phone_emoticon_compatibility
7
+ end
8
+
9
+ # Jpmobile::Rack::ParamsFilter を適用する
10
+ def apply_params_filter?
11
+ Jpmobile.config.smart_phone_emoticon_compatibility
12
+ end
13
+
14
+ # 文字コード変換
15
+ def to_internal(str)
16
+ # Google絵文字を数値参照に変換
17
+ str = Jpmobile::Emoticon.external_to_unicodecr_google(Jpmobile::Util.utf8(str))
18
+ # 数値参照を UTF-8 に変換
19
+ Jpmobile::Emoticon.unicodecr_to_utf8(str)
20
+ end
21
+ def to_external(str, content_type, charset)
22
+ # UTF-8を数値参照に
23
+ str = Jpmobile::Emoticon.utf8_to_unicodecr(str)
24
+ str = Jpmobile::Emoticon.unicodecr_to_external(str, Jpmobile::Emoticon::CONVERSION_TABLE_TO_GOOGLE_EMOTICON, false)
25
+
26
+ [str, charset]
27
+ end
28
+ end
29
+ end
@@ -6,5 +6,7 @@ module Jpmobile::Mobile
6
6
  class Ipad < Tablet
7
7
  # 対応するUser-Agentの正規表現
8
8
  USER_AGENT_REGEXP = /iPad/
9
+
10
+ include Jpmobile::Mobile::UnicodeEmoticon
9
11
  end
10
12
  end
@@ -7,30 +7,6 @@ module Jpmobile::Mobile
7
7
  # 対応するUser-Agentの正規表現
8
8
  USER_AGENT_REGEXP = /iPhone/
9
9
 
10
- # Jpmobile::Rack::Filter を適用する
11
- def apply_filter?
12
- true
13
- end
14
-
15
- # Jpmobile::Rack::ParamsFilter を適用する
16
- def apply_params_filter?
17
- true
18
- end
19
-
20
- # 文字コード変換
21
- def to_internal(str)
22
- # 絵文字を数値参照に変換
23
- str = Jpmobile::Emoticon.external_to_unicodecr_softbank(Jpmobile::Util.utf8(str))
24
- # 数値参照を UTF-8 に変換
25
- Jpmobile::Emoticon.unicodecr_to_utf8(str)
26
- end
27
- def to_external(str, content_type, charset)
28
- # UTF-8を数値参照に
29
- str = Jpmobile::Emoticon.utf8_to_unicodecr(str)
30
- # 数値参照を絵文字コードに変換
31
- str = Jpmobile::Emoticon.unicodecr_to_external(str, Jpmobile::Emoticon::CONVERSION_TABLE_TO_SOFTBANK, false)
32
-
33
- [str, charset]
34
- end
10
+ include Jpmobile::Mobile::UnicodeEmoticon
35
11
  end
36
12
  end
@@ -0,0 +1,43 @@
1
+ # -*- coding: utf-8 -*-
2
+ module Jpmobile::Mobile
3
+ module UnicodeEmoticon
4
+ # Jpmobile::Rack::Filter を適用する
5
+ def apply_filter?
6
+ Jpmobile.config.smart_phone_emoticon_compatibility
7
+ end
8
+
9
+ # Jpmobile::Rack::ParamsFilter を適用する
10
+ def apply_params_filter?
11
+ Jpmobile.config.smart_phone_emoticon_compatibility
12
+ end
13
+
14
+ # 文字コード変換
15
+ def to_internal(str)
16
+ if unicode_emoticon?
17
+ # Unicode絵文字を数値参照に変換
18
+ str = Jpmobile::Emoticon.external_to_unicodecr_unicode60(Jpmobile::Util.utf8(str))
19
+ else
20
+ # SoftBank絵文字を数値参照に変換
21
+ str = Jpmobile::Emoticon.external_to_unicodecr_softbank(Jpmobile::Util.utf8(str))
22
+ end
23
+ # 数値参照を UTF-8 に変換
24
+ Jpmobile::Emoticon.unicodecr_to_utf8(str)
25
+ end
26
+ def to_external(str, content_type, charset)
27
+ # UTF-8を数値参照に
28
+ str = Jpmobile::Emoticon.utf8_to_unicodecr(str)
29
+ if unicode_emoticon?
30
+ str = Jpmobile::Emoticon.unicodecr_to_external(str, Jpmobile::Emoticon::CONVERSION_TABLE_TO_UNICODE_EMOTICON, false)
31
+ else
32
+ # 数値参照を絵文字コードに変換
33
+ str = Jpmobile::Emoticon.unicodecr_to_external(str, Jpmobile::Emoticon::CONVERSION_TABLE_TO_SOFTBANK, false)
34
+ end
35
+
36
+ [str, charset]
37
+ end
38
+
39
+ def unicode_emoticon?
40
+ @request.user_agent.match(/ OS 5_/)
41
+ end
42
+ end
43
+ end
data/lib/jpmobile/rack.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  require 'rack/utils'
3
+ require 'singleton'
3
4
 
4
5
  module Jpmobile
5
6
  module Rack
@@ -12,10 +13,14 @@ module Jpmobile
12
13
  end
13
14
 
14
15
  class Configuration
16
+ include Singleton
17
+
15
18
  attr_accessor :form_accept_charset_conversion
19
+ attr_accessor :smart_phone_emoticon_compatibility
16
20
 
17
21
  def initialize
18
- @form_accept_charset_conversion = false
22
+ @form_accept_charset_conversion = false
23
+ @smart_phone_emoticon_compatibility = false
19
24
  end
20
25
 
21
26
  def mobile_filter
@@ -19,7 +19,7 @@ ActiveSupport.on_load(:before_configuration) do
19
19
  class Application
20
20
  class Configuration
21
21
  def jpmobile
22
- @jpmobile ||= ::Jpmobile::Configuration.new
22
+ @jpmobile ||= ::Jpmobile.config
23
23
  end
24
24
  end
25
25
  end
data/lib/jpmobile/util.rb CHANGED
@@ -187,7 +187,7 @@ module Jpmobile
187
187
  end
188
188
 
189
189
  def jis_string_regexp
190
- Regexp.compile(Regexp.escape(ascii_8bit("\x1b\x24\x42")) + "(.+)" + Regexp.escape(ascii_8bit("\x1b\x28\x42")))
190
+ Regexp.compile(Regexp.escape(ascii_8bit("\x1b\x24\x42")) + "(.+?)" + Regexp.escape(ascii_8bit("\x1b\x28\x42")))
191
191
  end
192
192
 
193
193
  def encode(str, charset)
@@ -379,5 +379,19 @@ module Jpmobile
379
379
  end
380
380
 
381
381
  end
382
+
383
+ def invert_table(hash)
384
+ result = {}
385
+ hash.keys.each do |key|
386
+ if result[hash[key]]
387
+ if !key.kind_of?(Array) and !result[hash[key]].kind_of?(Array) and result[hash[key]] > key
388
+ result[hash[key]] = key
389
+ end
390
+ else
391
+ result[hash[key]] = key
392
+ end
393
+ end
394
+ result
395
+ end
382
396
  end
383
397
  end
@@ -0,0 +1,20 @@
1
+ # -*- coding: utf-8 -*-
2
+ require File.join(File.expand_path(File.dirname(__FILE__)), '../../rack_helper.rb')
3
+
4
+ describe Jpmobile::Rack::MobileCarrier, "Windows Phone" do
5
+ include Rack::Test::Methods
6
+
7
+ context "端末種別で" do
8
+ it "BlackBerryを判別できること" do
9
+ res = Rack::MockRequest.env_for(
10
+ 'http://jpmobile-rails.org/',
11
+ 'HTTP_USER_AGENT' => 'BlackBerry9000/4.6.0.224 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/220')
12
+ env = Jpmobile::Rack::MobileCarrier.new(UnitApplication.new).call(res)[1]
13
+
14
+ env['rack.jpmobile'].class.should == Jpmobile::Mobile::BlackBerry
15
+ env['rack.jpmobile'].position.should be_nil
16
+ env['rack.jpmobile'].smart_phone?.should be_true
17
+ env['rack.jpmobile'].supports_cookie?.should be_true
18
+ end
19
+ end
20
+ end
@@ -7,6 +7,8 @@ describe "絵文字が" do
7
7
  include Jpmobile::Util
8
8
 
9
9
  before(:each) do
10
+ Jpmobile.config.smart_phone_emoticon_compatibility = true
11
+
10
12
  @docomo_cr = "&#xE63E;";
11
13
  @docomo_utf8 = [0xe63e].pack("U")
12
14
  @docomo_docomopoint = "&#xE6D5;"
@@ -271,4 +273,169 @@ describe "絵文字が" do
271
273
  response_body(res).should == [0xe04a].pack('U')
272
274
  end
273
275
  end
276
+
277
+ context 'for iPhone' do
278
+ context 'lower iOS 4' do
279
+ before(:each) do
280
+ @res = Rack::MockRequest.env_for(
281
+ "/",
282
+ 'HTTP_USER_AGENT' => "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0_1 like Mac OS X; ja-jp) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A306 Safari/6531.22.7",
283
+ 'Content-Type' => 'text/html; charset=utf-8')
284
+ end
285
+
286
+ it 'should convert Softbank emoticon' do
287
+ response = Jpmobile::Rack::MobileCarrier.new(Jpmobile::Rack::Filter.new(UnitApplication.new(@softbank_cr))).call(@res)[2]
288
+ response_body(response).should == [0xe04a].pack('U')
289
+ response = Jpmobile::Rack::MobileCarrier.new(Jpmobile::Rack::Filter.new(UnitApplication.new(@softbank_utf8))).call(@res)[2]
290
+ response_body(response).should == [0xe04a].pack('U')
291
+ end
292
+
293
+ it "converts query parameters" do
294
+ query_string = "q=" + URI.encode([0xe04A].pack("U"))
295
+
296
+ res = Rack::MockRequest.env_for(
297
+ "/?#{query_string}",
298
+ "REQUEST_METHOD" => "GET",
299
+ 'HTTP_USER_AGENT' => "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0_1 like Mac OS X; ja-jp) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A306 Safari/6531.22.7",
300
+ 'Content-Type' => 'text/html; charset=utf-8')
301
+ res = Jpmobile::Rack::MobileCarrier.new(Jpmobile::Rack::ParamsFilter.new(Jpmobile::Rack::Filter.new(RenderParamApp.new))).call(res)
302
+ req = Rack::Request.new(res[1])
303
+ req.params['q'].should == [0xf04a].pack("U")
304
+ response_body(res).should == [0xe04a].pack('U')
305
+ end
306
+
307
+ it 'should not convert 〓' do
308
+ response = Jpmobile::Rack::MobileCarrier.new(Jpmobile::Rack::Filter.new(UnitApplication.new('〓'))).call(@res)[2]
309
+ response_body(response).should == '〓'
310
+ end
311
+ end
312
+
313
+ context 'upper iOS 5' do
314
+ before(:each) do
315
+ @res = Rack::MockRequest.env_for(
316
+ "/",
317
+ 'HTTP_USER_AGENT' => "Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Mobile/9A334 Safari/7534.48.3",
318
+ 'Content-Type' => 'text/html; charset=utf-8')
319
+ @unicode_single = "\342\230\200"
320
+ @unicode_multi = "\342\233\205"
321
+ end
322
+
323
+ it "should convert Unicode emoticon" do
324
+ response = Jpmobile::Rack::MobileCarrier.new(Jpmobile::Rack::Filter.new(UnitApplication.new(@unicode_single))).call(@res)[2]
325
+ response_body(response).should == [0x2600].pack('U*')
326
+ response = Jpmobile::Rack::MobileCarrier.new(Jpmobile::Rack::Filter.new(UnitApplication.new(@unicode_multi))).call(@res)[2]
327
+ response_body(response).should == [0x26C5].pack('U*')
328
+ end
329
+
330
+ it "converts query parameters" do
331
+ query_string = "q=" + URI.encode(@unicode_multi)
332
+
333
+ res = Rack::MockRequest.env_for(
334
+ "/?#{query_string}",
335
+ "REQUEST_METHOD" => "GET",
336
+ 'HTTP_USER_AGENT' => "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0_1 like Mac OS X; ja-jp) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A306 Safari/6531.22.7",
337
+ 'Content-Type' => 'text/html; charset=utf-8')
338
+ res = Jpmobile::Rack::MobileCarrier.new(Jpmobile::Rack::ParamsFilter.new(Jpmobile::Rack::Filter.new(RenderParamApp.new))).call(res)
339
+ req = Rack::Request.new(res[1])
340
+ req.params['q'].should == [0x26C5].pack("U")
341
+ response_body(res).should == [0x26C5].pack('U')
342
+ end
343
+
344
+ it 'should not convert 〓' do
345
+ response = Jpmobile::Rack::MobileCarrier.new(Jpmobile::Rack::Filter.new(UnitApplication.new('〓'))).call(@res)[2]
346
+ response_body(response).should == '〓'
347
+ end
348
+ end
349
+ end
350
+
351
+ context 'for Android' do
352
+ before(:each) do
353
+ @google_single = "\363\276\200\200"
354
+ @google_multi = "\363\276\200\217"
355
+ end
356
+
357
+ context 'mobile' do
358
+ before(:each) do
359
+ @res = Rack::MockRequest.env_for(
360
+ "/",
361
+ 'HTTP_USER_AGENT' => 'Mozilla/5.0 (Linux; U; Android 1.6; ja-jp; SonyEriccsonSO-01B Build/R1EA018) AppleWebKit/528.5+ (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1',
362
+ 'Content-Type' => 'text/html; charset=utf-8')
363
+ end
364
+
365
+ it "should convert Google emoticon" do
366
+ response = Jpmobile::Rack::MobileCarrier.new(Jpmobile::Rack::Filter.new(UnitApplication.new(@google_single))).call(@res)[2]
367
+ response_body(response).should == [0xFE000].pack('U*')
368
+ response = Jpmobile::Rack::MobileCarrier.new(Jpmobile::Rack::Filter.new(UnitApplication.new(@google_multi))).call(@res)[2]
369
+ response_body(response).should == [0xFE00F].pack('U*')
370
+ end
371
+
372
+ it "converts query parameters irreversibly" do
373
+ query_string = "q=" + URI.encode(@google_multi)
374
+
375
+ res = Rack::MockRequest.env_for(
376
+ "/?#{query_string}",
377
+ "REQUEST_METHOD" => "GET",
378
+ 'HTTP_USER_AGENT' => 'Mozilla/5.0 (Linux; U; Android 1.6; ja-jp; SonyEriccsonSO-01B Build/R1EA018) AppleWebKit/528.5+ (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1',
379
+ 'Content-Type' => 'text/html; charset=utf-8')
380
+ res = Jpmobile::Rack::MobileCarrier.new(Jpmobile::Rack::ParamsFilter.new(Jpmobile::Rack::Filter.new(RenderParamApp.new))).call(res)
381
+ req = Rack::Request.new(res[1])
382
+ req.params['q'].should == [0xe63e, 0xe63f].pack("U*")
383
+ response_body(res).should == [0xfe000, 0xfe001].pack("U*")
384
+ end
385
+
386
+ it 'should not convert 〓' do
387
+ response = Jpmobile::Rack::MobileCarrier.new(Jpmobile::Rack::Filter.new(UnitApplication.new('〓'))).call(@res)[2]
388
+ response_body(response).should == '〓'
389
+ end
390
+ end
391
+
392
+ context 'tablet' do
393
+ before(:each) do
394
+ @res = Rack::MockRequest.env_for(
395
+ "/",
396
+ 'HTTP_USER_AGENT' => 'Mozilla/5.0 (Linux; U; Android 2.2; ja-jp; SC-01C Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1',
397
+ 'Content-Type' => 'text/html; charset=utf-8')
398
+ end
399
+
400
+ it "should convert Google emoticon" do
401
+ response = Jpmobile::Rack::MobileCarrier.new(Jpmobile::Rack::Filter.new(UnitApplication.new(@google_single))).call(@res)[2]
402
+ response_body(response).should == [0xFE000].pack('U*')
403
+ response = Jpmobile::Rack::MobileCarrier.new(Jpmobile::Rack::Filter.new(UnitApplication.new(@google_multi))).call(@res)[2]
404
+ response_body(response).should == [0xFE00F].pack('U*')
405
+ end
406
+
407
+ it "converts query parameters irreversibly" do
408
+ query_string = "q=" + URI.encode(@google_multi)
409
+
410
+ res = Rack::MockRequest.env_for(
411
+ "/?#{query_string}",
412
+ "REQUEST_METHOD" => "GET",
413
+ 'HTTP_USER_AGENT' => 'Mozilla/5.0 (Linux; U; Android 2.2; ja-jp; SC-01C Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1',
414
+ 'Content-Type' => 'text/html; charset=utf-8')
415
+ res = Jpmobile::Rack::MobileCarrier.new(Jpmobile::Rack::ParamsFilter.new(Jpmobile::Rack::Filter.new(RenderParamApp.new))).call(res)
416
+ req = Rack::Request.new(res[1])
417
+ req.params['q'].should == [0xe63e, 0xe63f].pack("U*")
418
+ response_body(res).should == [0xfe000, 0xfe001].pack("U*")
419
+ end
420
+
421
+ it 'should not convert 〓' do
422
+ response = Jpmobile::Rack::MobileCarrier.new(Jpmobile::Rack::Filter.new(UnitApplication.new('〓'))).call(@res)[2]
423
+ response_body(response).should == '〓'
424
+ end
425
+
426
+ it 'should convert unsupported emoticon to "〓"' do
427
+ query_string = "q=" + URI.encode("\xF3\xBE\x93\xA4")
428
+
429
+ res = Rack::MockRequest.env_for(
430
+ "/?#{query_string}",
431
+ "REQUEST_METHOD" => "GET",
432
+ 'HTTP_USER_AGENT' => 'Mozilla/5.0 (Linux; U; Android 2.2; ja-jp; SC-01C Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1',
433
+ 'Content-Type' => 'text/html; charset=utf-8')
434
+ res = Jpmobile::Rack::MobileCarrier.new(Jpmobile::Rack::ParamsFilter.new(Jpmobile::Rack::Filter.new(RenderParamApp.new))).call(res)
435
+ req = Rack::Request.new(res[1])
436
+ req.params['q'].should == '〓'
437
+ response_body(res).should == '〓'
438
+ end
439
+ end
440
+ end
274
441
  end