agiley-faraday_middleware 0.8.3.2 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/.gitignore +2 -2
  2. data/.rspec +2 -1
  3. data/.travis.yml +6 -3
  4. data/Gemfile +5 -1
  5. data/Rakefile +16 -4
  6. data/faraday_middleware.gemspec +1 -1
  7. data/lib/faraday_middleware.rb +17 -13
  8. data/lib/faraday_middleware/instrumentation.rb +2 -2
  9. data/lib/faraday_middleware/rack_compatible.rb +14 -9
  10. data/lib/faraday_middleware/request/encode_json.rb +4 -2
  11. data/lib/faraday_middleware/request/method_override.rb +51 -0
  12. data/lib/faraday_middleware/request/oauth.rb +28 -5
  13. data/lib/faraday_middleware/response/caching.rb +7 -2
  14. data/lib/faraday_middleware/response/chunked.rb +29 -0
  15. data/lib/faraday_middleware/response/follow_redirects.rb +100 -11
  16. data/lib/faraday_middleware/response/mashify.rb +11 -2
  17. data/lib/faraday_middleware/response/parse_dates.rb +39 -0
  18. data/lib/faraday_middleware/response/parse_json.rb +17 -5
  19. data/lib/faraday_middleware/response/parse_marshal.rb +2 -2
  20. data/lib/faraday_middleware/response/parse_xml.rb +3 -2
  21. data/lib/faraday_middleware/response/parse_yaml.rb +3 -1
  22. data/lib/faraday_middleware/response/rashify.rb +2 -0
  23. data/lib/faraday_middleware/response_middleware.rb +2 -2
  24. data/lib/faraday_middleware/version.rb +1 -1
  25. data/spec/caching_test.rb +37 -4
  26. data/spec/chunked_spec.rb +78 -0
  27. data/spec/encode_json_spec.rb +13 -13
  28. data/spec/follow_redirects_spec.rb +203 -18
  29. data/spec/helper.rb +15 -1
  30. data/spec/mashify_spec.rb +46 -26
  31. data/spec/method_override_spec.rb +92 -0
  32. data/spec/oauth2_spec.rb +18 -18
  33. data/spec/oauth_spec.rb +67 -17
  34. data/spec/parse_dates_spec.rb +39 -0
  35. data/spec/parse_json_spec.rb +37 -19
  36. data/spec/parse_marshal_spec.rb +3 -3
  37. data/spec/parse_xml_spec.rb +13 -13
  38. data/spec/parse_yaml_spec.rb +10 -10
  39. data/spec/rashify_spec.rb +26 -23
  40. metadata +78 -21
@@ -1,5 +1,15 @@
1
1
  if ENV['COVERAGE']
2
2
  require 'simplecov'
3
+
4
+ SimpleCov.formatter = Class.new do
5
+ def format(result)
6
+ SimpleCov::Formatter::HTMLFormatter.new.format(result) unless ENV['CI']
7
+ File.open('coverage/covered_percent', 'w') do |f|
8
+ f.puts result.source_files.covered_percent.to_i
9
+ end
10
+ end
11
+ end
12
+
3
13
  SimpleCov.start do
4
14
  # add_filter 'faraday_middleware.rb'
5
15
  add_filter 'backwards_compatibility.rb'
@@ -11,6 +21,7 @@ require 'rspec'
11
21
  module ResponseMiddlewareExampleGroup
12
22
  def self.included(base)
13
23
  base.let(:options) { Hash.new }
24
+ base.let(:headers) { Hash.new }
14
25
  base.let(:middleware) {
15
26
  described_class.new(lambda {|env|
16
27
  Faraday::Response.new(env)
@@ -21,7 +32,7 @@ module ResponseMiddlewareExampleGroup
21
32
  def process(body, content_type = nil, options = {})
22
33
  env = {
23
34
  :body => body, :request => options,
24
- :response_headers => Faraday::Utils::Headers.new
35
+ :response_headers => Faraday::Utils::Headers.new(headers)
25
36
  }
26
37
  env[:response_headers]['content-type'] = content_type if content_type
27
38
  middleware.call(env)
@@ -30,4 +41,7 @@ end
30
41
 
31
42
  RSpec.configure do |config|
32
43
  config.include ResponseMiddlewareExampleGroup, :type => :response
44
+ config.expect_with :rspec do |c|
45
+ c.syntax = :expect
46
+ end
33
47
  end
@@ -2,63 +2,80 @@ require 'helper'
2
2
  require 'faraday_middleware/response/mashify'
3
3
 
4
4
  describe FaradayMiddleware::Mashify do
5
- context 'during configuration' do
6
- it 'should allow for a custom Mash class to be set' do
7
- described_class.should respond_to(:mash_class)
8
- described_class.should respond_to(:mash_class=)
5
+ context "during configuration" do
6
+ it "allows for a custom Mash class to be set" do
7
+ expect(described_class).to respond_to(:mash_class)
8
+ expect(described_class).to respond_to(:mash_class=)
9
9
  end
10
10
  end
11
11
 
12
- context 'when used' do
12
+ context "when used" do
13
13
  before(:each) { described_class.mash_class = ::Hashie::Mash }
14
14
  let(:mashify) { described_class.new }
15
15
 
16
- it 'should create a Hashie::Mash from the body' do
16
+ it "creates a Hashie::Mash from the body" do
17
17
  env = { :body => { "name" => "Erik Michaels-Ober", "username" => "sferik" } }
18
18
  me = mashify.on_complete(env)
19
- me.class.should == Hashie::Mash
19
+ expect(me.class).to eq(Hashie::Mash)
20
20
  end
21
21
 
22
- it 'should handle strings' do
22
+ it "handles strings" do
23
23
  env = { :body => "Most amazing string EVER" }
24
24
  me = mashify.on_complete(env)
25
- me.should == "Most amazing string EVER"
25
+ expect(me).to eq("Most amazing string EVER")
26
26
  end
27
27
 
28
- it 'should handle arrays' do
28
+ it "handles arrays" do
29
29
  env = { :body => [123, 456] }
30
30
  values = mashify.on_complete(env)
31
- values.first.should == 123
32
- values.last.should == 456
31
+ expect(values.first).to eq(123)
32
+ expect(values.last).to eq(456)
33
33
  end
34
34
 
35
- it 'should handle arrays of hashes' do
35
+ it "handles arrays of hashes" do
36
36
  env = { :body => [{ "username" => "sferik" }, { "username" => "pengwynn" }] }
37
37
  us = mashify.on_complete(env)
38
- us.first.username.should == 'sferik'
39
- us.last.username.should == 'pengwynn'
38
+ expect(us.first.username).to eq('sferik')
39
+ expect(us.last.username).to eq('pengwynn')
40
40
  end
41
41
 
42
- it 'should handle mixed arrays' do
42
+ it "handles nested arrays of hashes" do
43
+ env = { :body => [[{ "username" => "sferik" }, { "username" => "pengwynn" }]] }
44
+ us = mashify.on_complete(env)
45
+ expect(us.first.first.username).to eq('sferik')
46
+ expect(us.first.last.username).to eq('pengwynn')
47
+ end
48
+
49
+ it "handles mixed arrays" do
43
50
  env = { :body => [123, { "username" => "sferik" }, 456] }
44
51
  values = mashify.on_complete(env)
45
- values.first.should == 123
46
- values.last.should == 456
47
- values[1].username.should == 'sferik'
52
+ expect(values.first).to eq(123)
53
+ expect(values.last).to eq(456)
54
+ expect(values[1].username).to eq('sferik')
48
55
  end
49
56
 
50
- it 'should allow for use of custom Mash subclasses' do
57
+ it "allows for use of custom Mash subclasses at the class level" do
51
58
  class MyMash < ::Hashie::Mash; end
52
59
  described_class.mash_class = MyMash
53
60
 
54
61
  env = { :body => { "name" => "Erik Michaels-Ober", "username" => "sferik" } }
55
62
  me = mashify.on_complete(env)
56
63
 
57
- me.class.should == MyMash
64
+ expect(me.class).to eq(MyMash)
65
+ end
66
+
67
+ it "allows for use of custom Mash subclasses at the instance level" do
68
+ class MyMash < ::Hashie::Mash; end
69
+ mashify = described_class.new(nil, :mash_class => MyMash)
70
+
71
+ env = { :body => { "name" => "Erik Michaels-Ober", "username" => "sferik" } }
72
+ me = mashify.on_complete(env)
73
+
74
+ expect(me.class).to eq(MyMash)
58
75
  end
59
76
  end
60
77
 
61
- context 'integration test' do
78
+ context "integration test" do
62
79
  let(:stubs) { Faraday::Adapter::Test::Stubs.new }
63
80
  let(:connection) do
64
81
  Faraday::Connection.new do |builder|
@@ -69,11 +86,14 @@ describe FaradayMiddleware::Mashify do
69
86
 
70
87
  # although it is not good practice to pass a hash as the body, if we add ParseJson
71
88
  # to the middleware stack we end up testing two middlewares instead of one
72
- it 'should create a Hash from the body' do
73
- stubs.get('/hash') {[200, {'content-type' => 'application/json; charset=utf-8'}, { "name" => "Erik Michaels-Ober", "username" => "sferik" }]}
89
+ it "creates a Hash from the body" do
90
+ stubs.get('/hash') {
91
+ data = { 'name' => 'Erik Michaels-Ober', 'username' => 'sferik' }
92
+ [200, {'content-type' => 'application/json; charset=utf-8'}, data]
93
+ }
74
94
  me = connection.get('/hash').body
75
- me.name.should == 'Erik Michaels-Ober'
76
- me.username.should == 'sferik'
95
+ expect(me.name).to eq('Erik Michaels-Ober')
96
+ expect(me.username).to eq('sferik')
77
97
  end
78
98
  end
79
99
  end
@@ -0,0 +1,92 @@
1
+ require 'helper'
2
+ require 'faraday_middleware/request/method_override'
3
+
4
+ describe FaradayMiddleware::MethodOverride do
5
+
6
+ let(:middleware) { described_class.new(lambda {|env| env }, *options) }
7
+ let(:env) { middleware.call request_env(request_method) }
8
+
9
+ def request_env(method)
10
+ { :method => method,
11
+ :request_headers => Faraday::Utils::Headers.new
12
+ }
13
+ end
14
+
15
+ shared_examples "overrides method" do |method|
16
+ it "sets physical method to POST" do
17
+ expect(env[:method]).to eq(:post)
18
+ end
19
+
20
+ it "sets header to #{method}" do
21
+ expect(env[:request_headers]['X-Http-Method-Override']).to eq(method)
22
+ end
23
+ end
24
+
25
+ shared_examples "doesn't override method" do |method|
26
+ it "keeps original method" do
27
+ expect(env[:method]).to eq(method)
28
+ end
29
+
30
+ it "doesn't set header value" do
31
+ expect(env[:request_headers]).not_to have_key('X-Http-Method-Override')
32
+ end
33
+
34
+ end
35
+
36
+ context "with default options" do
37
+ let(:options) { nil }
38
+
39
+ context "GET" do
40
+ let(:request_method) { :get }
41
+ include_examples "doesn't override method", :get
42
+ end
43
+
44
+ context "POST" do
45
+ let(:request_method) { :post }
46
+ include_examples "doesn't override method", :post
47
+ end
48
+
49
+ context "PUT" do
50
+ let(:request_method) { :put }
51
+ include_examples "overrides method", 'PUT'
52
+ end
53
+ end
54
+
55
+ context "configured to rewrite [:patch, :delete]" do
56
+ let(:options) { [{ :rewrite => [:patch, :delete] }] }
57
+
58
+ context "PUT" do
59
+ let(:request_method) { :put }
60
+ include_examples "doesn't override method", :put
61
+ end
62
+
63
+ context "PATCH" do
64
+ let(:request_method) { :patch }
65
+ include_examples "overrides method", 'PATCH'
66
+ end
67
+
68
+ context "DELETE" do
69
+ let(:request_method) { :delete }
70
+ include_examples "overrides method", 'DELETE'
71
+ end
72
+ end
73
+
74
+ context "configured to rewrite ['PATCH']" do
75
+ let(:options) { [{ :rewrite => %w[PATCH] }] }
76
+
77
+ context "PATCH" do
78
+ let(:request_method) { :patch }
79
+ include_examples "overrides method", 'PATCH'
80
+ end
81
+ end
82
+
83
+ context "with invalid option" do
84
+ let(:options) { [{ :hello => 'world' }] }
85
+ let(:request_method) { :get }
86
+
87
+ it "raises key error" do
88
+ expect{ env }.to raise_error(IndexError, /key not found/)
89
+ end
90
+ end
91
+
92
+ end
@@ -31,17 +31,17 @@ describe FaradayMiddleware::OAuth2 do
31
31
 
32
32
  it "doesn't add params" do
33
33
  request = perform(:q => 'hello')
34
- query_params(request).should eq('q' => 'hello')
34
+ expect(query_params(request)).to eq('q' => 'hello')
35
35
  end
36
36
 
37
37
  it "doesn't add headers" do
38
- auth_header(perform).should be_nil
38
+ expect(auth_header(perform)).to be_nil
39
39
  end
40
40
 
41
41
  it "creates header for explicit token" do
42
42
  request = perform(:q => 'hello', :access_token => 'abc123')
43
- query_params(request).should eq('q' => 'hello', 'access_token' => 'abc123')
44
- auth_header(request).should eq(%(Token token="abc123"))
43
+ expect(query_params(request)).to eq('q' => 'hello', 'access_token' => 'abc123')
44
+ expect(auth_header(request)).to eq(%(Token token="abc123"))
45
45
  end
46
46
  end
47
47
 
@@ -49,23 +49,23 @@ describe FaradayMiddleware::OAuth2 do
49
49
  let(:options) { 'XYZ' }
50
50
 
51
51
  it "adds token param" do
52
- query_params(perform(:q => 'hello')).should eq('q' => 'hello', 'access_token' => 'XYZ')
52
+ expect(query_params(perform(:q => 'hello'))).to eq('q' => 'hello', 'access_token' => 'XYZ')
53
53
  end
54
54
 
55
55
  it "adds token header" do
56
- auth_header(perform).should eq(%(Token token="XYZ"))
56
+ expect(auth_header(perform)).to eq(%(Token token="XYZ"))
57
57
  end
58
58
 
59
59
  it "overrides default with explicit token" do
60
60
  request = perform(:q => 'hello', :access_token => 'abc123')
61
- query_params(request).should eq('q' => 'hello', 'access_token' => 'abc123')
62
- auth_header(request).should eq(%(Token token="abc123"))
61
+ expect(query_params(request)).to eq('q' => 'hello', 'access_token' => 'abc123')
62
+ expect(auth_header(request)).to eq(%(Token token="abc123"))
63
63
  end
64
64
 
65
65
  it "clears default with empty explicit token" do
66
66
  request = perform(:q => 'hello', :access_token => nil)
67
- query_params(request).should eq('q' => 'hello', 'access_token' => nil)
68
- auth_header(request).should be_nil
67
+ expect(query_params(request)).to eq('q' => 'hello', 'access_token' => nil)
68
+ expect(auth_header(request)).to be_nil
69
69
  end
70
70
  end
71
71
 
@@ -74,11 +74,11 @@ describe FaradayMiddleware::OAuth2 do
74
74
  subject { perform({:q => 'hello'}, 'Authorization' => 'custom') }
75
75
 
76
76
  it "adds token param" do
77
- query_params(subject).should eq('q' => 'hello', 'access_token' => 'XYZ')
77
+ expect(query_params(subject)).to eq('q' => 'hello', 'access_token' => 'XYZ')
78
78
  end
79
79
 
80
80
  it "doesn't override existing header" do
81
- auth_header(subject).should eq('custom')
81
+ expect(auth_header(subject)).to eq('custom')
82
82
  end
83
83
  end
84
84
 
@@ -86,13 +86,13 @@ describe FaradayMiddleware::OAuth2 do
86
86
  let(:options) { ['XYZ', {:param_name => :oauth}] }
87
87
 
88
88
  it "adds token param" do
89
- query_params(perform).should eq('oauth' => 'XYZ')
89
+ expect(query_params(perform)).to eq('oauth' => 'XYZ')
90
90
  end
91
91
 
92
92
  it "overrides default with explicit token" do
93
93
  request = perform(:oauth => 'abc123')
94
- query_params(request).should eq('oauth' => 'abc123')
95
- auth_header(request).should eq(%(Token token="abc123"))
94
+ expect(query_params(request)).to eq('oauth' => 'abc123')
95
+ expect(auth_header(request)).to eq(%(Token token="abc123"))
96
96
  end
97
97
  end
98
98
 
@@ -100,11 +100,11 @@ describe FaradayMiddleware::OAuth2 do
100
100
  let(:options) { [{:param_name => :oauth}] }
101
101
 
102
102
  it "doesn't add param" do
103
- query_params(perform).should be_empty
103
+ expect(query_params(perform)).to be_empty
104
104
  end
105
105
 
106
106
  it "overrides default with explicit token" do
107
- query_params(perform(:oauth => 'abc123')).should eq('oauth' => 'abc123')
107
+ expect(query_params(perform(:oauth => 'abc123'))).to eq('oauth' => 'abc123')
108
108
  end
109
109
  end
110
110
 
@@ -112,7 +112,7 @@ describe FaradayMiddleware::OAuth2 do
112
112
  let(:options) { ['XYZ', {:param_name => nil}] }
113
113
 
114
114
  it "raises error" do
115
- expect { make_app }.to raise_error(ArgumentError, ":param_name can't be blank")
115
+ expect{ make_app }.to raise_error(ArgumentError, ":param_name can't be blank")
116
116
  end
117
117
  end
118
118
  end
@@ -1,6 +1,7 @@
1
1
  require 'helper'
2
2
  require 'faraday_middleware/request/oauth'
3
3
  require 'uri'
4
+ require 'forwardable'
4
5
 
5
6
  describe FaradayMiddleware::OAuth do
6
7
  def auth_header(env)
@@ -14,11 +15,12 @@ describe FaradayMiddleware::OAuth do
14
15
  end
15
16
  end
16
17
 
17
- def perform(oauth_options = {}, headers = {})
18
+ def perform(oauth_options = {}, headers = {}, params = {})
18
19
  env = {
19
20
  :url => URI('http://example.com/'),
20
21
  :request_headers => Faraday::Utils::Headers.new.update(headers),
21
- :request => {}
22
+ :request => {},
23
+ :body => params
22
24
  }
23
25
  unless oauth_options.is_a? Hash and oauth_options.empty?
24
26
  env[:request][:oauth] = oauth_options
@@ -34,21 +36,21 @@ describe FaradayMiddleware::OAuth do
34
36
  context "invalid options" do
35
37
  let(:options) { nil }
36
38
 
37
- it "should error out" do
38
- expect { make_app }.to raise_error(ArgumentError)
39
+ it "errors out" do
40
+ expect{ make_app }.to raise_error(ArgumentError)
39
41
  end
40
42
  end
41
43
 
42
44
  context "empty options" do
43
45
  let(:options) { [{}] }
44
46
 
45
- it "should sign request" do
47
+ it "signs request" do
46
48
  auth = auth_values(perform)
47
49
  expected_keys = %w[ oauth_nonce
48
50
  oauth_signature oauth_signature_method
49
51
  oauth_timestamp oauth_version ]
50
52
 
51
- auth.keys.should =~ expected_keys
53
+ expect(auth.keys).to match_array expected_keys
52
54
  end
53
55
  end
54
56
 
@@ -65,27 +67,27 @@ describe FaradayMiddleware::OAuth do
65
67
  oauth_signature oauth_signature_method
66
68
  oauth_timestamp oauth_token oauth_version ]
67
69
 
68
- auth.keys.should =~ expected_keys
69
- auth['oauth_version'].should eq(%("1.0"))
70
- auth['oauth_signature_method'].should eq(%("HMAC-SHA1"))
71
- auth['oauth_consumer_key'].should eq(%("CKEY"))
72
- auth['oauth_token'].should eq(%("TOKEN"))
70
+ expect(auth.keys).to match_array expected_keys
71
+ expect(auth['oauth_version']).to eq(%("1.0"))
72
+ expect(auth['oauth_signature_method']).to eq(%("HMAC-SHA1"))
73
+ expect(auth['oauth_consumer_key']).to eq(%("CKEY"))
74
+ expect(auth['oauth_token']).to eq(%("TOKEN"))
73
75
  end
74
76
 
75
77
  it "doesn't override existing header" do
76
78
  request = perform({}, "Authorization" => "iz me!")
77
- auth_header(request).should eq("iz me!")
79
+ expect(auth_header(request)).to eq("iz me!")
78
80
  end
79
81
 
80
82
  it "can override oauth options per-request" do
81
83
  auth = auth_values(perform(:consumer_key => 'CKEY2'))
82
84
 
83
- auth['oauth_consumer_key'].should eq(%("CKEY2"))
84
- auth['oauth_token'].should eq(%("TOKEN"))
85
+ expect(auth['oauth_consumer_key']).to eq(%("CKEY2"))
86
+ expect(auth['oauth_token']).to eq(%("TOKEN"))
85
87
  end
86
88
 
87
89
  it "can turn off oauth signing per-request" do
88
- auth_header(perform(false)).should be_nil
90
+ expect(auth_header(perform(false))).to be_nil
89
91
  end
90
92
  end
91
93
 
@@ -94,8 +96,56 @@ describe FaradayMiddleware::OAuth do
94
96
 
95
97
  it "adds auth info to the header" do
96
98
  auth = auth_values(perform)
97
- auth.should include('oauth_consumer_key')
98
- auth.should_not include('oauth_token')
99
+ expect(auth).to include('oauth_consumer_key')
100
+ expect(auth).not_to include('oauth_token')
99
101
  end
100
102
  end
103
+
104
+ context "handling body parameters" do
105
+ let(:options) { [{ :consumer_key => 'CKEY',
106
+ :consumer_secret => 'CSECRET',
107
+ :nonce => '547fed103e122eecf84c080843eedfe6',
108
+ :timestamp => '1286830180'}] }
109
+
110
+ let(:value) { {'foo' => 'bar'} }
111
+
112
+ let(:type_json) { {'Content-Type' => 'application/json'} }
113
+ let(:type_form) { {'Content-Type' => 'application/x-www-form-urlencoded'} }
114
+
115
+ extend Forwardable
116
+ query_method = :build_nested_query
117
+ query_module = ::Faraday::Utils.respond_to?(query_method) ? 'Faraday::Utils' : 'Rack::Utils'
118
+ def_delegator query_module, query_method
119
+
120
+ it "does not include the body for JSON" do
121
+ auth_header_with = auth_header(perform({}, type_json, '{"foo":"bar"}'))
122
+ auth_header_without = auth_header(perform({}, type_json, {}))
123
+
124
+ expect(auth_header_with).to eq(auth_header_without)
125
+ end
126
+
127
+ it "includes the body parameters with form Content-Type" do
128
+ auth_header_with = auth_header(perform({}, type_form, {}))
129
+ auth_header_without = auth_header(perform({}, type_form, value))
130
+
131
+ expect(auth_header_with).not_to eq(auth_header_without)
132
+ end
133
+
134
+ it "includes the body parameters with an unspecified Content-Type" do
135
+ auth_header_with = auth_header(perform({}, {}, value))
136
+ auth_header_without = auth_header(perform({}, type_form, value))
137
+
138
+ expect(auth_header_with).to eq(auth_header_without)
139
+ end
140
+
141
+ it "includes the body parameters for form type with string body" do
142
+ # simulates the behavior of Faraday::MiddleWare::UrlEncoded
143
+ value = { 'foo' => ['bar', 'baz', 'wat'] }
144
+ auth_header_hash = auth_header(perform({}, type_form, value))
145
+ auth_header_string = auth_header(perform({}, type_form, build_nested_query(value)))
146
+ expect(auth_header_string).to eq(auth_header_hash)
147
+ end
148
+
149
+ end
150
+
101
151
  end