faraday 0.9.1 → 2.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (135) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +554 -0
  3. data/LICENSE.md +1 -1
  4. data/README.md +32 -197
  5. data/Rakefile +4 -68
  6. data/examples/client_spec.rb +119 -0
  7. data/examples/client_test.rb +144 -0
  8. data/lib/faraday/adapter/test.rb +194 -58
  9. data/lib/faraday/adapter.rb +76 -20
  10. data/lib/faraday/adapter_registry.rb +30 -0
  11. data/lib/faraday/connection.rb +341 -212
  12. data/lib/faraday/encoders/flat_params_encoder.rb +105 -0
  13. data/lib/faraday/encoders/nested_params_encoder.rb +183 -0
  14. data/lib/faraday/error.rb +123 -29
  15. data/lib/faraday/logging/formatter.rb +106 -0
  16. data/lib/faraday/methods.rb +6 -0
  17. data/lib/faraday/middleware.rb +18 -25
  18. data/lib/faraday/middleware_registry.rb +83 -0
  19. data/lib/faraday/options/connection_options.rb +22 -0
  20. data/lib/faraday/options/env.rb +199 -0
  21. data/lib/faraday/options/proxy_options.rb +32 -0
  22. data/lib/faraday/options/request_options.rb +22 -0
  23. data/lib/faraday/options/ssl_options.rb +69 -0
  24. data/lib/faraday/options.rb +63 -195
  25. data/lib/faraday/parameters.rb +4 -180
  26. data/lib/faraday/rack_builder.rb +99 -59
  27. data/lib/faraday/request/authorization.rb +37 -30
  28. data/lib/faraday/request/instrumentation.rb +47 -27
  29. data/lib/faraday/request/json.rb +55 -0
  30. data/lib/faraday/request/url_encoded.rb +48 -24
  31. data/lib/faraday/request.rb +76 -32
  32. data/lib/faraday/response/json.rb +54 -0
  33. data/lib/faraday/response/logger.rb +22 -48
  34. data/lib/faraday/response/raise_error.rb +57 -14
  35. data/lib/faraday/response.rb +32 -35
  36. data/lib/faraday/utils/headers.rb +139 -0
  37. data/lib/faraday/utils/params_hash.rb +61 -0
  38. data/lib/faraday/utils.rb +47 -222
  39. data/lib/faraday/version.rb +5 -0
  40. data/lib/faraday.rb +111 -222
  41. data/spec/external_adapters/faraday_specs_setup.rb +14 -0
  42. data/spec/faraday/adapter/test_spec.rb +413 -0
  43. data/spec/faraday/adapter_registry_spec.rb +28 -0
  44. data/spec/faraday/adapter_spec.rb +55 -0
  45. data/spec/faraday/connection_spec.rb +793 -0
  46. data/spec/faraday/error_spec.rb +60 -0
  47. data/spec/faraday/middleware_registry_spec.rb +31 -0
  48. data/spec/faraday/middleware_spec.rb +52 -0
  49. data/spec/faraday/options/env_spec.rb +76 -0
  50. data/spec/faraday/options/options_spec.rb +297 -0
  51. data/spec/faraday/options/proxy_options_spec.rb +44 -0
  52. data/spec/faraday/options/request_options_spec.rb +19 -0
  53. data/spec/faraday/params_encoders/flat_spec.rb +42 -0
  54. data/spec/faraday/params_encoders/nested_spec.rb +150 -0
  55. data/spec/faraday/rack_builder_spec.rb +317 -0
  56. data/spec/faraday/request/authorization_spec.rb +83 -0
  57. data/spec/faraday/request/instrumentation_spec.rb +74 -0
  58. data/spec/faraday/request/json_spec.rb +111 -0
  59. data/spec/faraday/request/url_encoded_spec.rb +93 -0
  60. data/spec/faraday/request_spec.rb +110 -0
  61. data/spec/faraday/response/json_spec.rb +117 -0
  62. data/spec/faraday/response/logger_spec.rb +220 -0
  63. data/spec/faraday/response/raise_error_spec.rb +172 -0
  64. data/spec/faraday/response_spec.rb +75 -0
  65. data/spec/faraday/utils/headers_spec.rb +82 -0
  66. data/spec/faraday/utils_spec.rb +118 -0
  67. data/spec/faraday_spec.rb +37 -0
  68. data/spec/spec_helper.rb +132 -0
  69. data/spec/support/disabling_stub.rb +14 -0
  70. data/spec/support/fake_safe_buffer.rb +15 -0
  71. data/spec/support/helper_methods.rb +96 -0
  72. data/spec/support/shared_examples/adapter.rb +105 -0
  73. data/spec/support/shared_examples/params_encoder.rb +18 -0
  74. data/spec/support/shared_examples/request_method.rb +263 -0
  75. data/spec/support/streaming_response_checker.rb +35 -0
  76. metadata +81 -109
  77. data/.document +0 -6
  78. data/CONTRIBUTING.md +0 -36
  79. data/Gemfile +0 -25
  80. data/faraday.gemspec +0 -34
  81. data/lib/faraday/adapter/em_http.rb +0 -237
  82. data/lib/faraday/adapter/em_http_ssl_patch.rb +0 -56
  83. data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +0 -66
  84. data/lib/faraday/adapter/em_synchrony.rb +0 -92
  85. data/lib/faraday/adapter/excon.rb +0 -80
  86. data/lib/faraday/adapter/httpclient.rb +0 -106
  87. data/lib/faraday/adapter/net_http.rb +0 -130
  88. data/lib/faraday/adapter/net_http_persistent.rb +0 -48
  89. data/lib/faraday/adapter/patron.rb +0 -72
  90. data/lib/faraday/adapter/rack.rb +0 -58
  91. data/lib/faraday/adapter/typhoeus.rb +0 -123
  92. data/lib/faraday/autoload.rb +0 -84
  93. data/lib/faraday/request/basic_authentication.rb +0 -13
  94. data/lib/faraday/request/multipart.rb +0 -63
  95. data/lib/faraday/request/retry.rb +0 -148
  96. data/lib/faraday/request/token_authentication.rb +0 -15
  97. data/lib/faraday/upload_io.rb +0 -67
  98. data/script/cached-bundle +0 -46
  99. data/script/console +0 -7
  100. data/script/generate_certs +0 -42
  101. data/script/package +0 -7
  102. data/script/proxy-server +0 -42
  103. data/script/release +0 -17
  104. data/script/s3-put +0 -71
  105. data/script/server +0 -36
  106. data/script/test +0 -172
  107. data/test/adapters/default_test.rb +0 -14
  108. data/test/adapters/em_http_test.rb +0 -20
  109. data/test/adapters/em_synchrony_test.rb +0 -20
  110. data/test/adapters/excon_test.rb +0 -20
  111. data/test/adapters/httpclient_test.rb +0 -21
  112. data/test/adapters/integration.rb +0 -254
  113. data/test/adapters/logger_test.rb +0 -82
  114. data/test/adapters/net_http_persistent_test.rb +0 -20
  115. data/test/adapters/net_http_test.rb +0 -14
  116. data/test/adapters/patron_test.rb +0 -20
  117. data/test/adapters/rack_test.rb +0 -31
  118. data/test/adapters/test_middleware_test.rb +0 -114
  119. data/test/adapters/typhoeus_test.rb +0 -28
  120. data/test/authentication_middleware_test.rb +0 -65
  121. data/test/composite_read_io_test.rb +0 -111
  122. data/test/connection_test.rb +0 -522
  123. data/test/env_test.rb +0 -218
  124. data/test/helper.rb +0 -81
  125. data/test/live_server.rb +0 -67
  126. data/test/middleware/instrumentation_test.rb +0 -88
  127. data/test/middleware/retry_test.rb +0 -177
  128. data/test/middleware_stack_test.rb +0 -173
  129. data/test/multibyte.txt +0 -1
  130. data/test/options_test.rb +0 -252
  131. data/test/parameters_test.rb +0 -64
  132. data/test/request_middleware_test.rb +0 -142
  133. data/test/response_middleware_test.rb +0 -72
  134. data/test/strawberry.rb +0 -2
  135. data/test/utils_test.rb +0 -58
data/README.md CHANGED
@@ -1,200 +1,31 @@
1
- # Faraday
1
+ # [![Faraday](./docs/assets/img/repo-card-slim.png)][website]
2
2
 
3
- Faraday is an HTTP client lib that provides a common interface over many
4
- adapters (such as Net::HTTP) and embraces the concept of Rack middleware when
5
- processing the request/response cycle.
3
+ [![Gem Version](https://badge.fury.io/rb/faraday.svg)](https://rubygems.org/gems/faraday)
4
+ [![GitHub Actions CI](https://github.com/lostisland/faraday/workflows/CI/badge.svg)](https://github.com/lostisland/faraday/actions?query=workflow%3ACI)
5
+ [![GitHub Discussions](https://img.shields.io/github/discussions/lostisland/faraday?logo=github)](https://github.com/lostisland/faraday/discussions)
6
6
 
7
- Faraday supports these adapters:
8
7
 
9
- * Net::HTTP
10
- * [Excon][]
11
- * [Typhoeus][]
12
- * [Patron][]
13
- * [EventMachine][]
14
- * [HTTPClient][]
8
+ Faraday is an HTTP client library abstraction layer that provides a common interface over many
9
+ adapters (such as Net::HTTP) and embraces the concept of Rack middleware when processing the request/response cycle.
10
+ You probably don't want to use Faraday directly in your project, as it will lack an actual client library to perform
11
+ requests. Instead, you probably want to have a look at [Awesome Faraday][awesome] for a list of available adapters.
15
12
 
16
- It also includes a Rack adapter for hitting loaded Rack applications through
17
- Rack::Test, and a Test adapter for stubbing requests by hand.
13
+ ## Getting Started
18
14
 
19
- ## Usage
20
-
21
- ```ruby
22
- conn = Faraday.new(:url => 'http://sushi.com') do |faraday|
23
- faraday.request :url_encoded # form-encode POST params
24
- faraday.response :logger # log requests to STDOUT
25
- faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
26
- end
27
-
28
- ## GET ##
29
-
30
- response = conn.get '/nigiri/sake.json' # GET http://sushi.com/nigiri/sake.json
31
- response.body
32
-
33
- conn.get '/nigiri', { :name => 'Maguro' } # GET http://sushi.com/nigiri?name=Maguro
34
-
35
- conn.get do |req| # GET http://sushi.com/search?page=2&limit=100
36
- req.url '/search', :page => 2
37
- req.params['limit'] = 100
38
- end
39
-
40
- ## POST ##
41
-
42
- conn.post '/nigiri', { :name => 'Maguro' } # POST "name=maguro" to http://sushi.com/nigiri
43
-
44
- # post payload as JSON instead of "www-form-urlencoded" encoding:
45
- conn.post do |req|
46
- req.url '/nigiri'
47
- req.headers['Content-Type'] = 'application/json'
48
- req.body = '{ "name": "Unagi" }'
49
- end
50
-
51
- ## Per-request options ##
52
-
53
- conn.get do |req|
54
- req.url '/search'
55
- req.options.timeout = 5 # open/read timeout in seconds
56
- req.options.open_timeout = 2 # connection open timeout in seconds
57
- end
58
- ```
59
-
60
- If you don't need to set up anything, you can roll with just the default middleware
61
- stack and default adapter (see [Faraday::RackBuilder#initialize](https://github.com/lostisland/faraday/blob/master/lib/faraday/rack_builder.rb)):
62
-
63
- ```ruby
64
- response = Faraday.get 'http://sushi.com/nigiri/sake.json'
65
- ```
66
-
67
- ## Advanced middleware usage
68
-
69
- The order in which middleware is stacked is important. Like with Rack, the
70
- first middleware on the list wraps all others, while the last middleware is the
71
- innermost one, so that must be the adapter.
72
-
73
- ```ruby
74
- Faraday.new(...) do |conn|
75
- # POST/PUT params encoders:
76
- conn.request :multipart
77
- conn.request :url_encoded
78
-
79
- conn.adapter :net_http
80
- end
81
- ```
82
-
83
- This request middleware setup affects POST/PUT requests in the following way:
84
-
85
- 1. `Request::Multipart` checks for files in the payload, otherwise leaves
86
- everything untouched;
87
- 2. `Request::UrlEncoded` encodes as "application/x-www-form-urlencoded" if not
88
- already encoded or of another type
89
-
90
- Swapping middleware means giving the other priority. Specifying the
91
- "Content-Type" for the request is explicitly stating which middleware should
92
- process it.
93
-
94
- Examples:
95
-
96
- ```ruby
97
- # uploading a file:
98
- payload[:profile_pic] = Faraday::UploadIO.new('/path/to/avatar.jpg', 'image/jpeg')
99
-
100
- # "Multipart" middleware detects files and encodes with "multipart/form-data":
101
- conn.put '/profile', payload
102
- ```
103
-
104
- ## Writing middleware
105
-
106
- Middleware are classes that implement a `call` instance method. They hook into
107
- the request/response cycle.
108
-
109
- ```ruby
110
- def call(request_env)
111
- # do something with the request
112
- # request_env[:request_headers].merge!(...)
113
-
114
- @app.call(request_env).on_complete do |response_env|
115
- # do something with the response
116
- # response_env[:response_headers].merge!(...)
117
- end
118
- end
119
- ```
120
-
121
- It's important to do all processing of the response only in the `on_complete`
122
- block. This enables middleware to work in parallel mode where requests are
123
- asynchronous.
124
-
125
- The `env` is a hash with symbol keys that contains info about the request and,
126
- later, response. Some keys are:
127
-
128
- ```
129
- # request phase
130
- :method - :get, :post, ...
131
- :url - URI for the current request; also contains GET parameters
132
- :body - POST parameters for :post/:put requests
133
- :request_headers
134
-
135
- # response phase
136
- :status - HTTP response status code, such as 200
137
- :body - the response body
138
- :response_headers
139
- ```
140
-
141
- ## Using Faraday for testing
142
-
143
- ```ruby
144
- # It's possible to define stubbed request outside a test adapter block.
145
- stubs = Faraday::Adapter::Test::Stubs.new do |stub|
146
- stub.get('/tamago') { |env| [200, {}, 'egg'] }
147
- end
148
-
149
- # You can pass stubbed request to the test adapter or define them in a block
150
- # or a combination of the two.
151
- test = Faraday.new do |builder|
152
- builder.adapter :test, stubs do |stub|
153
- stub.get('/ebi') { |env| [ 200, {}, 'shrimp' ]}
154
- end
155
- end
156
-
157
- # It's also possible to stub additional requests after the connection has
158
- # been initialized. This is useful for testing.
159
- stubs.get('/uni') { |env| [ 200, {}, 'urchin' ]}
160
-
161
- resp = test.get '/tamago'
162
- resp.body # => 'egg'
163
- resp = test.get '/ebi'
164
- resp.body # => 'shrimp'
165
- resp = test.get '/uni'
166
- resp.body # => 'urchin'
167
- resp = test.get '/else' #=> raises "no such stub" error
168
-
169
- # If you like, you can treat your stubs as mocks by verifying that all of
170
- # the stubbed calls were made. NOTE that this feature is still fairly
171
- # experimental: It will not verify the order or count of any stub, only that
172
- # it was called once during the course of the test.
173
- stubs.verify_stubbed_calls
174
- ```
175
-
176
- ## TODO
177
-
178
- * support streaming requests/responses
179
- * better stubbing API
15
+ The best starting point is the [Faraday Website][website], with its introduction and explanation.
16
+ Need more details? See the [Faraday API Documentation][apidoc] to see how it works internally.
180
17
 
181
18
  ## Supported Ruby versions
182
19
 
183
- This library aims to support and is [tested against][travis] the following Ruby
184
- implementations:
185
-
186
- * MRI 1.8.7
187
- * MRI 1.9.2
188
- * MRI 1.9.3
189
- * MRI 2.0.0
190
- * MRI 2.1.0
191
- * [JRuby][]
192
- * [Rubinius][]
20
+ This library aims to support and is [tested against][actions] the currently officially supported Ruby
21
+ implementations. This means that, even without a major release, we could add or drop support for Ruby versions,
22
+ following their [EOL](https://endoflife.date/ruby).
23
+ Currently that means we support Ruby 2.6+
193
24
 
194
25
  If something doesn't work on one of these Ruby versions, it's a bug.
195
26
 
196
27
  This library may inadvertently work (or seem to work) on other Ruby
197
- implementations, however support will only be provided for the versions listed
28
+ implementations and versions, however support will only be provided for the versions listed
198
29
  above.
199
30
 
200
31
  If you would like this library to support another Ruby version, you may
@@ -204,17 +35,21 @@ implementation, you will be responsible for providing patches in a timely
204
35
  fashion. If critical issues for a particular implementation exist at the time
205
36
  of a major release, support for that Ruby version may be dropped.
206
37
 
207
- ## Copyright
38
+ ## Contribute
208
39
 
209
- Copyright (c) 2009-2013 [Rick Olson](mailto:technoweenie@gmail.com), Zack Hobson.
210
- See [LICENSE][] for details.
40
+ Do you want to contribute to Faraday?
41
+ Open the issues page and check for the `help wanted` label!
42
+ But before you start coding, please read our [Contributing Guide][contributing]
211
43
 
212
- [travis]: http://travis-ci.org/lostisland/faraday
213
- [excon]: https://github.com/geemus/excon#readme
214
- [typhoeus]: https://github.com/typhoeus/typhoeus#readme
215
- [patron]: http://toland.github.com/patron/
216
- [eventmachine]: https://github.com/igrigorik/em-http-request#readme
217
- [httpclient]: https://github.com/nahi/httpclient
218
- [jruby]: http://jruby.org/
219
- [rubinius]: http://rubini.us/
220
- [license]: LICENSE.md
44
+ ## Copyright
45
+ © 2009 - 2022, the [Faraday Team][faraday_team]. Website and branding design by [Elena Lo Piccolo](https://elelopic.design).
46
+
47
+ [awesome]: https://github.com/lostisland/awesome-faraday/#adapters
48
+ [website]: https://lostisland.github.io/faraday
49
+ [faraday_team]: https://lostisland.github.io/faraday/team
50
+ [contributing]: https://github.com/lostisland/faraday/blob/master/.github/CONTRIBUTING.md
51
+ [apidoc]: https://www.rubydoc.info/github/lostisland/faraday
52
+ [actions]: https://github.com/lostisland/faraday/actions
53
+ [jruby]: http://jruby.org/
54
+ [rubinius]: http://rubini.us/
55
+ [license]: LICENSE.md
data/Rakefile CHANGED
@@ -1,71 +1,7 @@
1
- require 'date'
2
- require 'fileutils'
3
- require 'openssl'
4
- require 'rake/testtask'
5
- require 'bundler'
6
- Bundler::GemHelper.install_tasks
1
+ # frozen_string_literal: true
7
2
 
8
- task :default => :test
3
+ require 'rspec/core/rake_task'
9
4
 
10
- ## helper functions
5
+ RSpec::Core::RakeTask.new(:spec)
11
6
 
12
- def name
13
- @name ||= Dir['*.gemspec'].first.split('.').first
14
- end
15
-
16
- def version
17
- line = File.read("lib/#{name}.rb")[/^\s*VERSION\s*=\s*.*/]
18
- line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
19
- end
20
-
21
- def gemspec_file
22
- "#{name}.gemspec"
23
- end
24
-
25
- def gem_file
26
- "#{name}-#{version}.gem"
27
- end
28
-
29
- def replace_header(head, header_name)
30
- head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"}
31
- end
32
-
33
- # Adapted from WEBrick::Utils. Skips cert extensions so it
34
- # can be used as a CA bundle
35
- def create_self_signed_cert(bits, cn, comment)
36
- rsa = OpenSSL::PKey::RSA.new(bits)
37
- cert = OpenSSL::X509::Certificate.new
38
- cert.version = 2
39
- cert.serial = 1
40
- name = OpenSSL::X509::Name.new(cn)
41
- cert.subject = name
42
- cert.issuer = name
43
- cert.not_before = Time.now
44
- cert.not_after = Time.now + (365*24*60*60)
45
- cert.public_key = rsa.public_key
46
- cert.sign(rsa, OpenSSL::Digest::SHA1.new)
47
- return [cert, rsa]
48
- end
49
-
50
- ## standard tasks
51
-
52
- desc "Run all tests"
53
- task :test do
54
- exec 'script/test'
55
- end
56
-
57
- desc "Generate certificates for SSL tests"
58
- task :'test:generate_certs' do
59
- cert, key = create_self_signed_cert(1024, [['CN', 'localhost']], 'Faraday Test CA')
60
- FileUtils.mkdir_p 'tmp'
61
- File.open('tmp/faraday-cert.key', 'w') {|f| f.puts(key) }
62
- File.open('tmp/faraday-cert.crt', 'w') {|f| f.puts(cert.to_s) }
63
- end
64
-
65
- file 'tmp/faraday-cert.key' => :'test:generate_certs'
66
- file 'tmp/faraday-cert.crt' => :'test:generate_certs'
67
-
68
- desc "Open an irb session preloaded with this library"
69
- task :console do
70
- sh "irb -rubygems -r ./lib/#{name}.rb"
71
- end
7
+ task default: :spec
@@ -0,0 +1,119 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Requires Ruby with rspec and faraday gems.
4
+ # rspec client_spec.rb
5
+
6
+ require 'faraday'
7
+ require 'json'
8
+
9
+ # Example API client
10
+ class Client
11
+ def initialize(conn)
12
+ @conn = conn
13
+ end
14
+
15
+ def httpbingo(jname, params: {})
16
+ res = @conn.get("/#{jname}", params)
17
+ data = JSON.parse(res.body)
18
+ data['origin']
19
+ end
20
+
21
+ def foo(params)
22
+ res = @conn.post('/foo', JSON.dump(params))
23
+ res.status
24
+ end
25
+ end
26
+
27
+ RSpec.describe Client do
28
+ let(:stubs) { Faraday::Adapter::Test::Stubs.new }
29
+ let(:conn) { Faraday.new { |b| b.adapter(:test, stubs) } }
30
+ let(:client) { Client.new(conn) }
31
+
32
+ it 'parses origin' do
33
+ stubs.get('/ip') do |env|
34
+ # optional: you can inspect the Faraday::Env
35
+ expect(env.url.path).to eq('/ip')
36
+ [
37
+ 200,
38
+ { 'Content-Type': 'application/javascript' },
39
+ '{"origin": "127.0.0.1"}'
40
+ ]
41
+ end
42
+
43
+ # uncomment to trigger stubs.verify_stubbed_calls failure
44
+ # stubs.get('/unused') { [404, {}, ''] }
45
+
46
+ expect(client.httpbingo('ip')).to eq('127.0.0.1')
47
+ stubs.verify_stubbed_calls
48
+ end
49
+
50
+ it 'handles 404' do
51
+ stubs.get('/api') do
52
+ [
53
+ 404,
54
+ { 'Content-Type': 'application/javascript' },
55
+ '{}'
56
+ ]
57
+ end
58
+ expect(client.httpbingo('api')).to be_nil
59
+ stubs.verify_stubbed_calls
60
+ end
61
+
62
+ it 'handles exception' do
63
+ stubs.get('/api') do
64
+ raise Faraday::ConnectionFailed
65
+ end
66
+
67
+ expect { client.httpbingo('api') }.to raise_error(Faraday::ConnectionFailed)
68
+ stubs.verify_stubbed_calls
69
+ end
70
+
71
+ context 'When the test stub is run in strict_mode' do
72
+ let(:stubs) { Faraday::Adapter::Test::Stubs.new(strict_mode: true) }
73
+
74
+ it 'verifies the all parameter values are identical' do
75
+ stubs.get('/api?abc=123') do
76
+ [
77
+ 200,
78
+ { 'Content-Type': 'application/javascript' },
79
+ '{"origin": "127.0.0.1"}'
80
+ ]
81
+ end
82
+
83
+ # uncomment to raise Stubs::NotFound
84
+ # expect(client.httpbingo('api', params: { abc: 123, foo: 'Kappa' })).to eq('127.0.0.1')
85
+ expect(client.httpbingo('api', params: { abc: 123 })).to eq('127.0.0.1')
86
+ stubs.verify_stubbed_calls
87
+ end
88
+ end
89
+
90
+ context 'When the Faraday connection is configured with FlatParamsEncoder' do
91
+ let(:conn) { Faraday.new(request: { params_encoder: Faraday::FlatParamsEncoder }) { |b| b.adapter(:test, stubs) } }
92
+
93
+ it 'handles the same multiple URL parameters' do
94
+ stubs.get('/api?a=x&a=y&a=z') { [200, { 'Content-Type' => 'application/json' }, '{"origin": "127.0.0.1"}'] }
95
+
96
+ # uncomment to raise Stubs::NotFound
97
+ # expect(client.httpbingo('api', params: { a: %w[x y] })).to eq('127.0.0.1')
98
+ expect(client.httpbingo('api', params: { a: %w[x y z] })).to eq('127.0.0.1')
99
+ stubs.verify_stubbed_calls
100
+ end
101
+ end
102
+
103
+ context 'When you want to test the body, you can use a proc as well as string' do
104
+ it 'tests with a string' do
105
+ stubs.post('/foo', '{"name":"YK"}') { [200, {}, ''] }
106
+
107
+ expect(client.foo(name: 'YK')).to eq 200
108
+ stubs.verify_stubbed_calls
109
+ end
110
+
111
+ it 'tests with a proc' do
112
+ check = ->(request_body) { JSON.parse(request_body).slice('name') == { 'name' => 'YK' } }
113
+ stubs.post('/foo', check) { [200, {}, ''] }
114
+
115
+ expect(client.foo(name: 'YK', created_at: Time.now)).to eq 200
116
+ stubs.verify_stubbed_calls
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,144 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Requires Ruby with test-unit and faraday gems.
4
+ # ruby client_test.rb
5
+
6
+ require 'faraday'
7
+ require 'json'
8
+ require 'test/unit'
9
+
10
+ # Example API client
11
+ class Client
12
+ def initialize(conn)
13
+ @conn = conn
14
+ end
15
+
16
+ def httpbingo(jname, params: {})
17
+ res = @conn.get("/#{jname}", params)
18
+ data = JSON.parse(res.body)
19
+ data['origin']
20
+ end
21
+
22
+ def foo(params)
23
+ res = @conn.post('/foo', JSON.dump(params))
24
+ res.status
25
+ end
26
+ end
27
+
28
+ # Example API client test
29
+ class ClientTest < Test::Unit::TestCase
30
+ def test_httpbingo_name
31
+ stubs = Faraday::Adapter::Test::Stubs.new
32
+ stubs.get('/api') do |env|
33
+ # optional: you can inspect the Faraday::Env
34
+ assert_equal '/api', env.url.path
35
+ [
36
+ 200,
37
+ { 'Content-Type': 'application/javascript' },
38
+ '{"origin": "127.0.0.1"}'
39
+ ]
40
+ end
41
+
42
+ # uncomment to trigger stubs.verify_stubbed_calls failure
43
+ # stubs.get('/unused') { [404, {}, ''] }
44
+
45
+ cli = client(stubs)
46
+ assert_equal '127.0.0.1', cli.httpbingo('api')
47
+ stubs.verify_stubbed_calls
48
+ end
49
+
50
+ def test_httpbingo_not_found
51
+ stubs = Faraday::Adapter::Test::Stubs.new
52
+ stubs.get('/api') do
53
+ [
54
+ 404,
55
+ { 'Content-Type': 'application/javascript' },
56
+ '{}'
57
+ ]
58
+ end
59
+
60
+ cli = client(stubs)
61
+ assert_nil cli.httpbingo('api')
62
+ stubs.verify_stubbed_calls
63
+ end
64
+
65
+ def test_httpbingo_exception
66
+ stubs = Faraday::Adapter::Test::Stubs.new
67
+ stubs.get('/api') do
68
+ raise Faraday::ConnectionFailed
69
+ end
70
+
71
+ cli = client(stubs)
72
+ assert_raise Faraday::ConnectionFailed do
73
+ cli.httpbingo('api')
74
+ end
75
+ stubs.verify_stubbed_calls
76
+ end
77
+
78
+ def test_strict_mode
79
+ stubs = Faraday::Adapter::Test::Stubs.new(strict_mode: true)
80
+ stubs.get('/api?abc=123') do
81
+ [
82
+ 200,
83
+ { 'Content-Type': 'application/javascript' },
84
+ '{"origin": "127.0.0.1"}'
85
+ ]
86
+ end
87
+
88
+ cli = client(stubs)
89
+ assert_equal '127.0.0.1', cli.httpbingo('api', params: { abc: 123 })
90
+
91
+ # uncomment to raise Stubs::NotFound
92
+ # assert_equal '127.0.0.1', cli.httpbingo('api', params: { abc: 123, foo: 'Kappa' })
93
+ stubs.verify_stubbed_calls
94
+ end
95
+
96
+ def test_non_default_params_encoder
97
+ stubs = Faraday::Adapter::Test::Stubs.new(strict_mode: true)
98
+ stubs.get('/api?a=x&a=y&a=z') do
99
+ [
100
+ 200,
101
+ { 'Content-Type': 'application/javascript' },
102
+ '{"origin": "127.0.0.1"}'
103
+ ]
104
+ end
105
+ conn = Faraday.new(request: { params_encoder: Faraday::FlatParamsEncoder }) do |builder|
106
+ builder.adapter :test, stubs
107
+ end
108
+
109
+ cli = Client.new(conn)
110
+ assert_equal '127.0.0.1', cli.httpbingo('api', params: { a: %w[x y z] })
111
+
112
+ # uncomment to raise Stubs::NotFound
113
+ # assert_equal '127.0.0.1', cli.httpbingo('api', params: { a: %w[x y] })
114
+ stubs.verify_stubbed_calls
115
+ end
116
+
117
+ def test_with_string_body
118
+ stubs = Faraday::Adapter::Test::Stubs.new do |stub|
119
+ stub.post('/foo', '{"name":"YK"}') { [200, {}, ''] }
120
+ end
121
+ cli = client(stubs)
122
+ assert_equal 200, cli.foo(name: 'YK')
123
+
124
+ stubs.verify_stubbed_calls
125
+ end
126
+
127
+ def test_with_proc_body
128
+ stubs = Faraday::Adapter::Test::Stubs.new do |stub|
129
+ check = ->(request_body) { JSON.parse(request_body).slice('name') == { 'name' => 'YK' } }
130
+ stub.post('/foo', check) { [200, {}, ''] }
131
+ end
132
+ cli = client(stubs)
133
+ assert_equal 200, cli.foo(name: 'YK', created_at: Time.now)
134
+
135
+ stubs.verify_stubbed_calls
136
+ end
137
+
138
+ def client(stubs)
139
+ conn = Faraday.new do |builder|
140
+ builder.adapter :test, stubs
141
+ end
142
+ Client.new(conn)
143
+ end
144
+ end