webmock 3.16.2 → 3.18.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 438dab0f90920381d01009b8c75892ac83e46043e170c17e1dba5e46ca755c61
4
- data.tar.gz: a760f4b2399f465c62cf03268c13a7ae973900945ed0c4631e146c44f688a97d
3
+ metadata.gz: 70c0ad15601d48c3f413012ced7fde245d03fcc5d5bb7b609fd2ce89084b2589
4
+ data.tar.gz: 4575309d868350685b573d8929ce1836eb044b00fb862c1b9b266a73a1992e9f
5
5
  SHA512:
6
- metadata.gz: c8033597431b3e8ce43e60837d31f18d1ffa52c35079827e122a4616587f29b480b2340786c841bbe9f6b9390c5df08e9b84e933160412c8dc1d5c8a9b214f8b
7
- data.tar.gz: e0580a7b6b712073edf7d6c38fbf7b6df00a294aa9910f1de0e2de61535de67d07315b5d10f141d7e3387bf91aaee7ce6bb204d40190b5357b2120dc0d7d4427
6
+ metadata.gz: acba1ac0ec3d97c5eb244a84d1b8e895f13e9b3cfb1ca5ac4c0d5109eb7fcc508a3d1e51faa426bd31cb2509d61effed7c134119b5c05d128b3466ec3ee397c7
7
+ data.tar.gz: e8eb5385dd3d4fc9f02c541fbec1bc2c825e07445046b3bde50c471925728c08b1bb9aaf963d61fb44f5a38041f54964ab9fa89caef4cd16fd06fe6bb1ceca44
data/CHANGELOG.md CHANGED
@@ -1,14 +1,50 @@
1
1
  # Changelog
2
2
 
3
- # 3.16.2
3
+ # 3.18.0
4
+
5
+ * Net::BufferedIO is not replaced anymore.
6
+
7
+ Thanks to [Ray Zane](https://github.com/rzane)
8
+
9
+ * Simplified connection handing in Net::HTTP adapter.
10
+
11
+ Thanks to [Ray Zane](https://github.com/rzane)
4
12
 
5
- * Minimum required Ruby version is 2.0 again.
13
+ # 3.17.1
6
14
 
7
- # 3.16.1
15
+ * Fixed Syntax Error
16
+
17
+ Thanks to [Mark Spangler](https://github.com/mspangler)
18
+
19
+ # 3.17.0
8
20
 
9
21
  * Minimum required Ruby version is 2.3
10
22
 
11
- # 3.16.0
23
+ Thanks to [Go Sueyoshi](https://github.com/sue445)
24
+
25
+ * When using Net::HTTP, stubbed socket StubSocket#close and StubSocket#closed? behave more like the real sockets.
26
+
27
+ Thanks to [Ray Zane](https://github.com/rzane)
28
+
29
+ * Added `peeraddr`, `ssl_version` and `cipher` methods to stubbed sockets used by Net::HTTP.
30
+
31
+ Thanks to [Ray Zane](https://github.com/rzane)
32
+
33
+ * Added support for matching top-level array in JSON request body.
34
+
35
+ E.g.
36
+
37
+ ````
38
+ stub_request(:post, 'www.example.com').with(body: [{a: 1}])
39
+ ````
40
+
41
+ Thanks to [Cedric Sohrauer](https://github.com/cedrics)
42
+
43
+ # 3.16.2
44
+
45
+ * Minimum required Ruby version is 2.0.
46
+
47
+ # 3.16.0 (yanked)
12
48
 
13
49
  * Fix leaky file descriptors and reuse socket for persistent connections.
14
50
 
@@ -18,7 +54,11 @@
18
54
 
19
55
  Thanks to [Ray Zane](https://github.com/rzane)
20
56
 
21
- # 3.15.0
57
+ # 3.15.2
58
+
59
+ * Minimum required Ruby version is 2.0.
60
+
61
+ # 3.15.0 (yanked)
22
62
 
23
63
  * fixed async-http adapter on Windows
24
64
 
data/README.md CHANGED
@@ -1166,13 +1166,17 @@ People who submitted patches and new features or suggested improvements. Many th
1166
1166
  * Timmitry
1167
1167
  * Michael Fairley
1168
1168
  * Ray Zane
1169
+ * Go Sueyoshi
1170
+ * Cedric Sohrauer
1171
+ * Akira Matsuda
1172
+ * Mark Spangler
1169
1173
 
1170
1174
  For a full list of contributors you can visit the
1171
1175
  [contributors](https://github.com/bblimke/webmock/contributors) page.
1172
1176
 
1173
1177
  ## Background
1174
1178
 
1175
- Thank you Fakeweb! This library was inspired by [FakeWeb](http://fakeweb.rubyforge.org).
1179
+ Thank you Fakeweb! This library was inspired by [FakeWeb](https://github.com/chrisk/fakeweb).
1176
1180
  I imported some solutions from that project to WebMock. I also copied some code i.e Net:HTTP adapter.
1177
1181
  Fakeweb architecture unfortunately didn't allow me to extend it easily with the features I needed.
1178
1182
  I also preferred some things to work differently i.e request stub precedence.
@@ -10,24 +10,19 @@ module WebMock
10
10
  adapter_for :net_http
11
11
 
12
12
  OriginalNetHTTP = Net::HTTP unless const_defined?(:OriginalNetHTTP)
13
- OriginalNetBufferedIO = Net::BufferedIO unless const_defined?(:OriginalNetBufferedIO)
14
13
 
15
14
  def self.enable!
16
- Net.send(:remove_const, :BufferedIO)
17
15
  Net.send(:remove_const, :HTTP)
18
16
  Net.send(:remove_const, :HTTPSession)
19
17
  Net.send(:const_set, :HTTP, @webMockNetHTTP)
20
18
  Net.send(:const_set, :HTTPSession, @webMockNetHTTP)
21
- Net.send(:const_set, :BufferedIO, Net::WebMockNetBufferedIO)
22
19
  end
23
20
 
24
21
  def self.disable!
25
- Net.send(:remove_const, :BufferedIO)
26
22
  Net.send(:remove_const, :HTTP)
27
23
  Net.send(:remove_const, :HTTPSession)
28
24
  Net.send(:const_set, :HTTP, OriginalNetHTTP)
29
25
  Net.send(:const_set, :HTTPSession, OriginalNetHTTP)
30
- Net.send(:const_set, :BufferedIO, OriginalNetBufferedIO)
31
26
 
32
27
  #copy all constants from @webMockNetHTTP to original Net::HTTP
33
28
  #in case any constants were added to @webMockNetHTTP instead of Net::HTTP
@@ -72,74 +67,57 @@ module WebMock
72
67
  end
73
68
 
74
69
  def request(request, body = nil, &block)
70
+ return super unless started?
71
+
75
72
  request_signature = WebMock::NetHTTPUtility.request_signature_from_request(self, request, body)
76
73
 
77
74
  WebMock::RequestRegistry.instance.requested_signatures.put(request_signature)
78
75
 
79
76
  if webmock_response = WebMock::StubRegistry.instance.response_for_request(request_signature)
80
- @socket = Net::HTTP.socket_type.new
81
77
  WebMock::CallbackRegistry.invoke_callbacks(
82
78
  {lib: :net_http}, request_signature, webmock_response)
83
79
  build_net_http_response(webmock_response, &block)
84
80
  elsif WebMock.net_connect_allowed?(request_signature.uri)
85
81
  check_right_http_connection
86
- after_request = lambda do |response|
87
- if WebMock::CallbackRegistry.any_callbacks?
88
- webmock_response = build_webmock_response(response)
89
- WebMock::CallbackRegistry.invoke_callbacks(
90
- {lib: :net_http, real_request: true}, request_signature, webmock_response)
91
- end
92
- response.extend Net::WebMockHTTPResponse
93
- block.call response if block
94
- response
95
- end
96
- super_with_after_request = lambda {
97
- response = super(request, nil, &nil)
98
- after_request.call(response)
99
- }
100
- if started?
101
- ensure_actual_connection
102
- super_with_after_request.call
103
- else
104
- start_with_connect {
105
- super_with_after_request.call
106
- }
82
+ ensure_actually_connected
83
+
84
+ response = super(request, nil, &nil)
85
+
86
+ if WebMock::CallbackRegistry.any_callbacks?
87
+ WebMock::CallbackRegistry.invoke_callbacks(
88
+ {lib: :net_http, real_request: true},
89
+ request_signature,
90
+ build_webmock_response(response)
91
+ )
107
92
  end
93
+
94
+ response.extend Net::WebMockHTTPResponse
95
+ block.call response if block
96
+ response
108
97
  else
109
98
  raise WebMock::NetConnectNotAllowedError.new(request_signature)
110
99
  end
111
100
  end
112
101
 
113
- def start_without_connect
114
- raise IOError, 'HTTP session already opened' if @started
115
- if block_given?
116
- begin
117
- @socket = Net::HTTP.socket_type.new
118
- @started = true
119
- return yield(self)
120
- ensure
121
- do_finish
122
- end
123
- end
124
- @socket = Net::HTTP.socket_type.new
125
- @started = true
126
- self
127
- end
128
-
129
-
130
- def ensure_actual_connection
131
- do_start if @socket.is_a?(StubSocket)
132
- end
102
+ private
133
103
 
134
- alias_method :start_with_connect, :start
104
+ alias_method :actually_connect, :connect
135
105
 
136
- def start(&block)
106
+ def connect
137
107
  uri = Addressable::URI.parse(WebMock::NetHTTPUtility.get_uri(self))
138
108
 
139
109
  if WebMock.net_http_connect_on_start?(uri)
140
- super(&block)
110
+ super
141
111
  else
142
- start_without_connect(&block)
112
+ @socket = StubSocket.new
113
+ end
114
+ end
115
+
116
+ def ensure_actually_connected
117
+ if @socket.is_a?(StubSocket)
118
+ @socket&.close
119
+ @socket = nil
120
+ actually_connect
143
121
  end
144
122
  end
145
123
 
@@ -161,7 +139,7 @@ module WebMock
161
139
  response.extend Net::WebMockHTTPResponse
162
140
 
163
141
  if webmock_response.should_timeout
164
- raise timeout_exception, "execution expired"
142
+ raise Net::OpenTimeout, "execution expired"
165
143
  end
166
144
 
167
145
  webmock_response.raise_error_if_any
@@ -171,16 +149,6 @@ module WebMock
171
149
  response
172
150
  end
173
151
 
174
- def timeout_exception
175
- if defined?(Net::OpenTimeout)
176
- # Ruby 2.x
177
- Net::OpenTimeout
178
- else
179
- # Fallback, if things change
180
- Timeout::Error
181
- end
182
- end
183
-
184
152
  def build_webmock_response(net_http_response)
185
153
  webmock_response = WebMock::Response.new
186
154
  webmock_response.status = [
@@ -214,31 +182,21 @@ module WebMock
214
182
  end
215
183
  end
216
184
 
217
- # patch for StringIO behavior in Ruby 2.2.3
218
- # https://github.com/bblimke/webmock/issues/558
219
- class PatchedStringIO < StringIO #:nodoc:
220
-
221
- alias_method :orig_read_nonblock, :read_nonblock
222
-
223
- def read_nonblock(size, *args, **kwargs)
224
- args.reject! {|arg| !arg.is_a?(Hash)}
225
- orig_read_nonblock(size, *args, **kwargs)
226
- end
227
-
228
- end
229
-
230
185
  class StubSocket #:nodoc:
231
186
 
232
187
  attr_accessor :read_timeout, :continue_timeout, :write_timeout
233
188
 
234
189
  def initialize(*args)
190
+ @closed = false
235
191
  end
236
192
 
237
193
  def closed?
238
- @closed ||= true
194
+ @closed
239
195
  end
240
196
 
241
197
  def close
198
+ @closed = true
199
+ nil
242
200
  end
243
201
 
244
202
  def readuntil(*args)
@@ -251,57 +209,12 @@ class StubSocket #:nodoc:
251
209
  class StubIO
252
210
  def setsockopt(*args); end
253
211
  def peer_cert; end
212
+ def peeraddr; ["AF_INET", 443, "127.0.0.1", "127.0.0.1"] end
213
+ def ssl_version; "TLSv1.3" end
214
+ def cipher; ["TLS_AES_128_GCM_SHA256", "TLSv1.3", 128, 128] end
254
215
  end
255
216
  end
256
217
 
257
- module Net #:nodoc: all
258
-
259
- class WebMockNetBufferedIO < BufferedIO
260
- def initialize(io, *args, **kwargs)
261
- io = case io
262
- when Socket, OpenSSL::SSL::SSLSocket, IO
263
- io
264
- when StringIO
265
- PatchedStringIO.new(io.string)
266
- when String
267
- PatchedStringIO.new(io)
268
- end
269
- raise "Unable to create local socket" unless io
270
-
271
- # Prior to 2.4.0 `BufferedIO` only takes a single argument (`io`) with no
272
- # options. Here we pass through our full set of arguments only if we're
273
- # on 2.4.0 or later, and use a simplified invocation otherwise.
274
- if RUBY_VERSION >= '2.4.0'
275
- super
276
- else
277
- super(io)
278
- end
279
- end
280
-
281
- if RUBY_VERSION >= '2.6.0'
282
- # https://github.com/ruby/ruby/blob/7d02441f0d6e5c9d0a73a024519eba4f69e36dce/lib/net/protocol.rb#L208
283
- # Modified version of method from ruby, so that nil is always passed into orig_read_nonblock to avoid timeout
284
- def rbuf_fill
285
- case rv = @io.read_nonblock(BUFSIZE, nil, exception: false)
286
- when String
287
- return if rv.nil?
288
- @rbuf << rv
289
- rv.clear
290
- return
291
- when :wait_readable
292
- @io.to_io.wait_readable(@read_timeout) or raise Net::ReadTimeout
293
- when :wait_writable
294
- @io.to_io.wait_writable(@read_timeout) or raise Net::ReadTimeout
295
- when nil
296
- raise EOFError, 'end of file reached'
297
- end while true
298
- end
299
- end
300
- end
301
-
302
- end
303
-
304
-
305
218
  module WebMock
306
219
  module NetHTTPUtility
307
220
 
@@ -318,7 +231,6 @@ module WebMock
318
231
  method = request.method.downcase.to_sym
319
232
 
320
233
  headers = Hash[*request.to_hash.map {|k,v| [k, v]}.inject([]) {|r,x| r + x}]
321
- validate_headers(headers)
322
234
 
323
235
  if request.body_stream
324
236
  body = request.body_stream.read
@@ -343,25 +255,6 @@ module WebMock
343
255
  "#{protocol}://#{hostname}:#{net_http.port}#{path}"
344
256
  end
345
257
 
346
- def self.validate_headers(headers)
347
- # For Ruby versions < 2.3.0, if you make a request with headers that are symbols
348
- # Net::HTTP raises a NoMethodError
349
- #
350
- # WebMock normalizes headers when creating a RequestSignature,
351
- # and will update all headers from symbols to strings.
352
- #
353
- # This could create a false positive in a test suite with WebMock.
354
- #
355
- # So before this point, WebMock raises an ArgumentError if any of the headers are symbols
356
- # instead of the cryptic NoMethodError "undefined method `split' ...` from Net::HTTP
357
- if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.3.0')
358
- header_as_symbol = headers.keys.find {|header| header.is_a? Symbol}
359
- if header_as_symbol
360
- raise ArgumentError.new("Net:HTTP does not accept headers as symbols")
361
- end
362
- end
363
- end
364
-
365
258
  def self.check_right_http_connection
366
259
  @was_right_http_connection_loaded = defined?(RightHttpConnection)
367
260
  end
@@ -281,6 +281,8 @@ module WebMock
281
281
  if (@pattern).is_a?(Hash)
282
282
  return true if @pattern.empty?
283
283
  matching_body_hashes?(body_as_hash(body, content_type), @pattern, content_type)
284
+ elsif (@pattern).is_a?(Array)
285
+ matching_body_array?(body_as_hash(body, content_type), @pattern, content_type)
284
286
  elsif (@pattern).is_a?(WebMock::Matchers::HashIncludingMatcher)
285
287
  @pattern == body_as_hash(body, content_type)
286
288
  else
@@ -344,19 +346,33 @@ module WebMock
344
346
  def matching_body_hashes?(query_parameters, pattern, content_type)
345
347
  return false unless query_parameters.is_a?(Hash)
346
348
  return false unless query_parameters.keys.sort == pattern.keys.sort
347
- query_parameters.each do |key, actual|
349
+
350
+ query_parameters.all? do |key, actual|
348
351
  expected = pattern[key]
352
+ matching_values(actual, expected, content_type)
353
+ end
354
+ end
349
355
 
350
- if actual.is_a?(Hash) && expected.is_a?(Hash)
351
- return false unless matching_body_hashes?(actual, expected, content_type)
352
- else
353
- expected = WebMock::Util::ValuesStringifier.stringify_values(expected) if url_encoded_body?(content_type)
354
- return false unless expected === actual
355
- end
356
+ def matching_body_array?(query_parameters, pattern, content_type)
357
+ return false unless query_parameters.is_a?(Array)
358
+ return false unless query_parameters.length == pattern.length
359
+
360
+ query_parameters.each_with_index do |actual, index|
361
+ expected = pattern[index]
362
+ return false unless matching_values(actual, expected, content_type)
356
363
  end
364
+
357
365
  true
358
366
  end
359
367
 
368
+ def matching_values(actual, expected, content_type)
369
+ return matching_body_hashes?(actual, expected, content_type) if actual.is_a?(Hash) && expected.is_a?(Hash)
370
+ return matching_body_array?(actual, expected, content_type) if actual.is_a?(Array) && expected.is_a?(Array)
371
+
372
+ expected = WebMock::Util::ValuesStringifier.stringify_values(expected) if url_encoded_body?(content_type)
373
+ expected === actual
374
+ end
375
+
360
376
  def empty_string?(string)
361
377
  string.nil? || string == ""
362
378
  end
@@ -35,11 +35,11 @@ module WebMock
35
35
  alias == eql?
36
36
 
37
37
  def url_encoded?
38
- !!(headers && headers.fetch('Content-Type', "").start_with?('application/x-www-form-urlencoded'))
38
+ !!(headers&.fetch('Content-Type', nil)&.start_with?('application/x-www-form-urlencoded'))
39
39
  end
40
40
 
41
41
  def json_headers?
42
- !!(headers && headers.fetch('Content-Type', "").start_with?('application/json'))
42
+ !!(headers&.fetch('Content-Type', nil)&.start_with?('application/json'))
43
43
  end
44
44
 
45
45
  private
@@ -14,8 +14,11 @@ module WebMock
14
14
 
15
15
  class Response
16
16
  def initialize(options = {})
17
- if options.is_a?(IO) || options.is_a?(String)
17
+ case options
18
+ when IO, StringIO
18
19
  self.options = read_raw_response(options)
20
+ when String
21
+ self.options = read_raw_response(StringIO.new(options))
19
22
  else
20
23
  self.options = options
21
24
  end
@@ -120,13 +123,8 @@ module WebMock
120
123
  end
121
124
  end
122
125
 
123
- def read_raw_response(raw_response)
124
- if raw_response.is_a?(IO)
125
- string = raw_response.read
126
- raw_response.close
127
- raw_response = string
128
- end
129
- socket = ::Net::BufferedIO.new(raw_response)
126
+ def read_raw_response(io)
127
+ socket = ::Net::BufferedIO.new(io)
130
128
  response = ::Net::HTTPResponse.read_new(socket)
131
129
  transfer_encoding = response.delete('transfer-encoding') #chunks were already read by curl
132
130
  response.reading_body(socket, true) {}
@@ -138,6 +136,8 @@ module WebMock
138
136
  options[:body] = response.read_body
139
137
  options[:status] = [response.code.to_i, response.message]
140
138
  options
139
+ ensure
140
+ socket.close
141
141
  end
142
142
 
143
143
  InvalidBody = Class.new(StandardError)
@@ -1,3 +1,3 @@
1
1
  module WebMock
2
- VERSION = '3.16.2' unless defined?(::WebMock::VERSION)
2
+ VERSION = '3.18.0' unless defined?(::WebMock::VERSION)
3
3
  end
@@ -115,33 +115,16 @@ describe "Net:HTTP" do
115
115
  expect(Net::HTTP.start("www.example.com") { |http| http.request(req)}.body).to eq("abc")
116
116
  end
117
117
 
118
- it "raises an ArgumentError if passed headers as symbols if RUBY_VERSION < 2.3.0" do
118
+ it "raises an ArgumentError if passed headers as symbols" do
119
119
  uri = URI.parse("http://google.com/")
120
120
  http = Net::HTTP.new(uri.host, uri.port)
121
121
  request = Net::HTTP::Get.new(uri.request_uri)
122
+ request[:InvalidHeaderSinceItsASymbol] = "this will not be valid"
122
123
 
123
- # Net::HTTP calls downcase on header keys assigned with []=
124
- # In Ruby 1.8.7 symbols do not respond to downcase
125
- #
126
- # Meaning you can not assign header keys as symbols in ruby 1.8.7 using []=
127
- if :symbol.respond_to?(:downcase)
128
- request[:InvalidHeaderSinceItsASymbol] = "this will not be valid"
129
- else
130
- request.instance_eval do
131
- @header = request.to_hash.merge({InvalidHeaderSinceItsASymbol: "this will not be valid"})
132
- end
133
- end
134
-
135
- if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.3.0')
136
- expect do
137
- http.request(request)
138
- end.to raise_error ArgumentError, "Net:HTTP does not accept headers as symbols"
139
- else
140
- stub_http_request(:get, "google.com").with(headers: { InvalidHeaderSinceItsASymbol: "this will not be valid" })
141
- expect do
142
- http.request(request)
143
- end.not_to raise_error
144
- end
124
+ stub_http_request(:get, "google.com").with(headers: { InvalidHeaderSinceItsASymbol: "this will not be valid" })
125
+ expect do
126
+ http.request(request)
127
+ end.not_to raise_error
145
128
  end
146
129
 
147
130
  it "should handle multiple values for the same response header" do
@@ -213,6 +196,22 @@ describe "Net:HTTP" do
213
196
  end
214
197
  end
215
198
 
199
+ if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.7.0')
200
+ it "uses the StubSocket to provide IP address" do
201
+ Net::HTTP.start("example.com") do |http|
202
+ expect(http.ipaddr).to eq("127.0.0.1")
203
+ end
204
+ end
205
+ end
206
+
207
+ it "defines common socket methods" do
208
+ Net::HTTP.start("example.com") do |http|
209
+ socket = http.instance_variable_get(:@socket)
210
+ expect(socket.io.ssl_version).to eq("TLSv1.3")
211
+ expect(socket.io.cipher).to eq(["TLS_AES_128_GCM_SHA256", "TLSv1.3", 128, 128])
212
+ end
213
+ end
214
+
216
215
  describe "connecting on Net::HTTP.start" do
217
216
  before(:each) do
218
217
  @http = Net::HTTP.new('www.google.com', 443)
@@ -93,31 +93,29 @@ unless RUBY_PLATFORM =~ /java/
93
93
  @sess.copy("/abc", "/def")
94
94
  end
95
95
 
96
- if /^1\.9/ === RUBY_VERSION
97
- describe "handling encoding same way as patron" do
98
- around(:each) do |example|
99
- @encoding = Encoding.default_internal
100
- Encoding.default_internal = "UTF-8"
101
- example.run
102
- Encoding.default_internal = @encoding
103
- end
96
+ describe "handling encoding same way as patron" do
97
+ around(:each) do |example|
98
+ @encoding = Encoding.default_internal
99
+ Encoding.default_internal = "UTF-8"
100
+ example.run
101
+ Encoding.default_internal = @encoding
102
+ end
104
103
 
105
- it "should not encode body with default encoding" do
106
- stub_request(:get, "www.example.com").
107
- to_return(body: "Øl")
104
+ it "should not encode body with default encoding" do
105
+ stub_request(:get, "www.example.com").
106
+ to_return(body: "Øl")
108
107
 
109
- expect(@sess.get("").body.encoding).to eq(Encoding::ASCII_8BIT)
110
- expect(@sess.get("").inspectable_body.encoding).to eq(Encoding::UTF_8)
111
- end
108
+ expect(@sess.get("").body.encoding).to eq(Encoding::ASCII_8BIT)
109
+ expect(@sess.get("").inspectable_body.encoding).to eq(Encoding::UTF_8)
110
+ end
112
111
 
113
- it "should not encode body to default internal" do
114
- stub_request(:get, "www.example.com").
115
- to_return(headers: {'Content-Type' => 'text/html; charset=iso-8859-1'},
116
- body: "Øl".encode("iso-8859-1"))
112
+ it "should not encode body to default internal" do
113
+ stub_request(:get, "www.example.com").
114
+ to_return(headers: {'Content-Type' => 'text/html; charset=iso-8859-1'},
115
+ body: "Øl".encode("iso-8859-1"))
117
116
 
118
- expect(@sess.get("").body.encoding).to eq(Encoding::ASCII_8BIT)
119
- expect(@sess.get("").decoded_body.encoding).to eq(Encoding.default_internal)
120
- end
117
+ expect(@sess.get("").body.encoding).to eq(Encoding::ASCII_8BIT)
118
+ expect(@sess.get("").decoded_body.encoding).to eq(Encoding.default_internal)
121
119
  end
122
120
  end
123
121
  end
@@ -547,6 +547,18 @@ describe WebMock::RequestPattern do
547
547
  body: "{\"a\":\"1\",\"b\":\"five\",\"c\":{\"d\":[\"e\",\"f\"]}}"))
548
548
  end
549
549
 
550
+ it "should match if the request body has a top level array" do
551
+ expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: [{a: 1}])).
552
+ to match(WebMock::RequestSignature.new(:post, "www.example.com",
553
+ headers: {content_type: content_type}, body: "[{\"a\":1}]"))
554
+ end
555
+
556
+ it "should not match if the request body has a different top level array" do
557
+ expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: ["a", "b"])).
558
+ not_to match(WebMock::RequestSignature.new(:post, "www.example.com",
559
+ headers: {content_type: content_type}, body: "[\"a\", \"c\"]"))
560
+ end
561
+
550
562
  it "should not match when body is not json" do
551
563
  expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: body_hash)).
552
564
  not_to match(WebMock::RequestSignature.new(:post, "www.example.com",
@@ -142,6 +142,34 @@ describe WebMock::Response do
142
142
  end
143
143
 
144
144
  describe "from raw response" do
145
+ describe "when input is a StringIO" do
146
+ before(:each) do
147
+ @io = StringIO.new(File.read(CURL_EXAMPLE_OUTPUT_PATH))
148
+ @response = WebMock::Response.new(@io)
149
+ end
150
+
151
+ it "should read status" do
152
+ expect(@response.status).to eq([202, "OK"])
153
+ end
154
+
155
+ it "should read headers" do
156
+ expect(@response.headers).to eq(
157
+ "Date"=>"Sat, 23 Jan 2010 01:01:05 GMT",
158
+ "Content-Type"=>"text/html; charset=UTF-8",
159
+ "Content-Length"=>"419",
160
+ "Connection"=>"Keep-Alive",
161
+ "Accept"=>"image/jpeg, image/png"
162
+ )
163
+ end
164
+
165
+ it "should read body" do
166
+ expect(@response.body.size).to eq(419)
167
+ end
168
+
169
+ it "should close IO" do
170
+ expect(@io).to be_closed
171
+ end
172
+ end
145
173
 
146
174
  describe "when input is IO" do
147
175
  before(:each) do
data/webmock.gemspec CHANGED
@@ -8,7 +8,7 @@ Gem::Specification.new do |s|
8
8
  s.platform = Gem::Platform::RUBY
9
9
  s.authors = ['Bartosz Blimke']
10
10
  s.email = ['bartosz.blimke@gmail.com']
11
- s.homepage = 'http://github.com/bblimke/webmock'
11
+ s.homepage = 'https://github.com/bblimke/webmock'
12
12
  s.summary = %q{Library for stubbing HTTP requests in Ruby.}
13
13
  s.description = %q{WebMock allows stubbing HTTP requests and setting expectations on HTTP requests.}
14
14
  s.license = "MIT"
@@ -21,7 +21,7 @@ Gem::Specification.new do |s|
21
21
  'wiki_uri' => 'https://github.com/bblimke/webmock/wiki'
22
22
  }
23
23
 
24
- s.required_ruby_version = '>= 2.0'
24
+ s.required_ruby_version = '>= 2.3'
25
25
 
26
26
  s.add_dependency 'addressable', '>= 2.8.0'
27
27
  s.add_dependency 'crack', '>= 0.3.2'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: webmock
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.16.2
4
+ version: 3.18.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bartosz Blimke
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-08-10 00:00:00.000000000 Z
11
+ date: 2022-08-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -416,14 +416,14 @@ files:
416
416
  - test/test_helper.rb
417
417
  - test/test_webmock.rb
418
418
  - webmock.gemspec
419
- homepage: http://github.com/bblimke/webmock
419
+ homepage: https://github.com/bblimke/webmock
420
420
  licenses:
421
421
  - MIT
422
422
  metadata:
423
423
  bug_tracker_uri: https://github.com/bblimke/webmock/issues
424
- changelog_uri: https://github.com/bblimke/webmock/blob/v3.16.2/CHANGELOG.md
425
- documentation_uri: https://www.rubydoc.info/gems/webmock/3.16.2
426
- source_code_uri: https://github.com/bblimke/webmock/tree/v3.16.2
424
+ changelog_uri: https://github.com/bblimke/webmock/blob/v3.18.0/CHANGELOG.md
425
+ documentation_uri: https://www.rubydoc.info/gems/webmock/3.18.0
426
+ source_code_uri: https://github.com/bblimke/webmock/tree/v3.18.0
427
427
  wiki_uri: https://github.com/bblimke/webmock/wiki
428
428
  post_install_message:
429
429
  rdoc_options: []
@@ -433,14 +433,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
433
433
  requirements:
434
434
  - - ">="
435
435
  - !ruby/object:Gem::Version
436
- version: '2.0'
436
+ version: '2.3'
437
437
  required_rubygems_version: !ruby/object:Gem::Requirement
438
438
  requirements:
439
439
  - - ">="
440
440
  - !ruby/object:Gem::Version
441
441
  version: '0'
442
442
  requirements: []
443
- rubygems_version: 3.1.2
443
+ rubygems_version: 3.0.3
444
444
  signing_key:
445
445
  specification_version: 4
446
446
  summary: Library for stubbing HTTP requests in Ruby.