webmock 3.14.0 → 3.18.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/CI.yml +1 -0
- data/CHANGELOG.md +86 -2
- data/README.md +12 -3
- data/lib/webmock/http_lib_adapters/async_http_client_adapter.rb +6 -1
- data/lib/webmock/http_lib_adapters/curb_adapter.rb +2 -2
- data/lib/webmock/http_lib_adapters/http_rb/client.rb +1 -3
- data/lib/webmock/http_lib_adapters/http_rb/response.rb +4 -1
- data/lib/webmock/http_lib_adapters/http_rb/streamer.rb +4 -2
- data/lib/webmock/http_lib_adapters/http_rb/webmock.rb +6 -2
- data/lib/webmock/http_lib_adapters/net_http.rb +22 -115
- data/lib/webmock/request_pattern.rb +23 -7
- data/lib/webmock/request_signature.rb +2 -2
- data/lib/webmock/request_stub.rb +15 -0
- data/lib/webmock/response.rb +8 -8
- data/lib/webmock/version.rb +1 -1
- data/lib/webmock/webmock.rb +10 -0
- data/minitest/webmock_spec.rb +1 -1
- data/spec/acceptance/async_http_client/async_http_client_spec.rb +5 -5
- data/spec/acceptance/curb/curb_spec.rb +11 -0
- data/spec/acceptance/em_http_request/em_http_request_spec.rb +1 -1
- data/spec/acceptance/em_http_request/em_http_request_spec_helper.rb +1 -1
- data/spec/acceptance/excon/excon_spec.rb +2 -2
- data/spec/acceptance/net_http/net_http_shared.rb +46 -9
- data/spec/acceptance/net_http/net_http_spec.rb +49 -23
- data/spec/acceptance/net_http/real_net_http_spec.rb +1 -1
- data/spec/acceptance/patron/patron_spec.rb +19 -21
- data/spec/acceptance/shared/allowing_and_disabling_net_connect.rb +14 -14
- data/spec/acceptance/shared/callbacks.rb +2 -2
- data/spec/acceptance/shared/complex_cross_concern_behaviors.rb +1 -1
- data/spec/unit/request_pattern_spec.rb +12 -0
- data/spec/unit/request_signature_spec.rb +21 -1
- data/spec/unit/request_stub_spec.rb +35 -0
- data/spec/unit/response_spec.rb +29 -1
- data/spec/unit/webmock_spec.rb +54 -0
- data/webmock.gemspec +4 -4
- metadata +29 -29
@@ -248,7 +248,7 @@ unless RUBY_PLATFORM =~ /java/
|
|
248
248
|
end
|
249
249
|
|
250
250
|
context 'multiple requests' do
|
251
|
-
let(:endpoint) { Async::HTTP::Endpoint.parse('http://www.example.com') }
|
251
|
+
let!(:endpoint) { Async::HTTP::Endpoint.parse('http://www.example.com') }
|
252
252
|
let(:requests_count) { 3 }
|
253
253
|
|
254
254
|
shared_examples :common do
|
@@ -300,13 +300,13 @@ unless RUBY_PLATFORM =~ /java/
|
|
300
300
|
end
|
301
301
|
|
302
302
|
context 'HTTP1 protocol' do
|
303
|
-
let(:protocol) { Async::HTTP::Protocol::HTTP1 }
|
303
|
+
let!(:protocol) { Async::HTTP::Protocol::HTTP1 }
|
304
304
|
|
305
305
|
include_examples :common
|
306
306
|
end
|
307
307
|
|
308
308
|
context 'HTTP2 protocol' do
|
309
|
-
let(:protocol) { Async::HTTP::Protocol::HTTP2 }
|
309
|
+
let!(:protocol) { Async::HTTP::Protocol::HTTP2 }
|
310
310
|
|
311
311
|
include_examples :common
|
312
312
|
end
|
@@ -331,13 +331,13 @@ unless RUBY_PLATFORM =~ /java/
|
|
331
331
|
end
|
332
332
|
|
333
333
|
context 'HTTP1 protocol' do
|
334
|
-
let(:protocol) { Async::HTTP::Protocol::HTTP1 }
|
334
|
+
let!(:protocol) { Async::HTTP::Protocol::HTTP1 }
|
335
335
|
|
336
336
|
include_examples :common
|
337
337
|
end
|
338
338
|
|
339
339
|
context 'HTTP2 protocol' do
|
340
|
-
let(:protocol) { Async::HTTP::Protocol::HTTP2 }
|
340
|
+
let!(:protocol) { Async::HTTP::Protocol::HTTP2 }
|
341
341
|
|
342
342
|
include_examples :common
|
343
343
|
end
|
@@ -383,6 +383,17 @@ unless RUBY_PLATFORM =~ /java/
|
|
383
383
|
expect(c.body).to eq("abc")
|
384
384
|
end
|
385
385
|
|
386
|
+
it "supports headers containing the ':' character" do
|
387
|
+
stub_request(:get, "www.example.com").with(headers: {'Referer'=>'http://www.example.com'}).to_return(body: "abc")
|
388
|
+
|
389
|
+
c = Curl::Easy.new
|
390
|
+
c.url = "http://www.example.com"
|
391
|
+
c.headers = ["Referer: http://www.example.com"]
|
392
|
+
c.http(:GET)
|
393
|
+
expect(c.body).to eq("abc")
|
394
|
+
expect(c.headers).to eq(["Referer: http://www.example.com"])
|
395
|
+
end
|
396
|
+
|
386
397
|
describe 'match request body' do
|
387
398
|
it 'for post' do
|
388
399
|
stub_request(:post, "www.example.com").with(body: 'foo=nhe').to_return(body: "abc")
|
@@ -22,7 +22,7 @@ unless RUBY_PLATFORM =~ /java/
|
|
22
22
|
|
23
23
|
def make_request
|
24
24
|
EM.run do
|
25
|
-
request = EM::HttpRequest.new(http_url).get(redirects: 1)
|
25
|
+
request = EM::HttpRequest.new(http_url, ssl: {verify_peer: true}).get(redirects: 1)
|
26
26
|
request.callback { EM.stop }
|
27
27
|
end
|
28
28
|
end
|
@@ -16,7 +16,7 @@ module EMHttpRequestSpecHelper
|
|
16
16
|
error_set = false
|
17
17
|
uri = Addressable::URI.heuristic_parse(uri)
|
18
18
|
EventMachine.run {
|
19
|
-
request = EventMachine::HttpRequest.new("#{uri.normalize.to_s}")
|
19
|
+
request = EventMachine::HttpRequest.new("#{uri.normalize.to_s}", ssl: {verify_peer: true})
|
20
20
|
http = request.send(method, {
|
21
21
|
timeout: 30,
|
22
22
|
body: options[:body],
|
@@ -20,7 +20,7 @@ describe "Excon" do
|
|
20
20
|
it "should support excon response_block for real requests", net_connect: true do
|
21
21
|
a = []
|
22
22
|
WebMock.allow_net_connect!
|
23
|
-
r = Excon.new('
|
23
|
+
r = Excon.new('https://httpstat.us/200', headers: { "Accept" => "*" }).
|
24
24
|
get(response_block: lambda {|e, remaining, total| a << e}, chunk_size: 1)
|
25
25
|
expect(a).to eq(["2", "0", "0", " ", "O", "K"])
|
26
26
|
expect(r.body).to eq("")
|
@@ -41,7 +41,7 @@ describe "Excon" do
|
|
41
41
|
WebMock.after_request { |_, res|
|
42
42
|
response = res
|
43
43
|
}
|
44
|
-
r = Excon.new('
|
44
|
+
r = Excon.new('https://httpstat.us/200', headers: { "Accept" => "*" }).
|
45
45
|
get(response_block: lambda {|e, remaining, total| a << e}, chunk_size: 1)
|
46
46
|
expect(response.body).to eq("200 OK")
|
47
47
|
expect(a).to eq(["2", "0", "0", " ", "O", "K"])
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
1
3
|
shared_examples_for "Net::HTTP" do
|
2
4
|
describe "when making real requests", net_connect: true do
|
3
5
|
let(:port){ WebMockServer.instance.port }
|
@@ -26,21 +28,56 @@ shared_examples_for "Net::HTTP" do
|
|
26
28
|
|
27
29
|
it "should connect only once when connected on start", net_connect: true do
|
28
30
|
@http = Net::HTTP.new('localhost', port)
|
29
|
-
|
31
|
+
socket_before_request = socket_after_request = nil
|
30
32
|
@http.start {|conn|
|
31
|
-
|
33
|
+
socket_before_request = conn.instance_variable_get(:@socket)
|
32
34
|
conn.request(Net::HTTP::Get.new("/"))
|
33
|
-
|
35
|
+
socket_after_request = conn.instance_variable_get(:@socket)
|
34
36
|
}
|
35
37
|
|
36
|
-
if !defined?(WebMock::
|
37
|
-
expect(
|
38
|
-
expect(
|
39
|
-
expect(
|
38
|
+
if !defined?(WebMock::NetHTTPUtility) || WebMock::Config.instance.net_http_connect_on_start
|
39
|
+
expect(socket_before_request).to be_a(Net::BufferedIO)
|
40
|
+
expect(socket_after_request).to be_a(Net::BufferedIO)
|
41
|
+
expect(socket_after_request).to be(socket_before_request)
|
42
|
+
else
|
43
|
+
expect(socket_before_request).to be_a(StubSocket)
|
44
|
+
expect(socket_after_request).to be_a(Net::BufferedIO)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should allow sending multiple requests when persisted", net_connect: true do
|
49
|
+
@http = Net::HTTP.new('example.org')
|
50
|
+
@http.start
|
51
|
+
expect(@http.get("/")).to be_a(Net::HTTPSuccess)
|
52
|
+
expect(@http.get("/")).to be_a(Net::HTTPSuccess)
|
53
|
+
expect(@http.get("/")).to be_a(Net::HTTPSuccess)
|
54
|
+
@http.finish
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should not leak file descriptors", net_connect: true do
|
58
|
+
sockets = Set.new
|
59
|
+
|
60
|
+
@http = Net::HTTP.new('example.org')
|
61
|
+
@http.start
|
62
|
+
sockets << @http.instance_variable_get(:@socket)
|
63
|
+
@http.get("/")
|
64
|
+
sockets << @http.instance_variable_get(:@socket)
|
65
|
+
@http.get("/")
|
66
|
+
sockets << @http.instance_variable_get(:@socket)
|
67
|
+
@http.get("/")
|
68
|
+
sockets << @http.instance_variable_get(:@socket)
|
69
|
+
@http.finish
|
70
|
+
|
71
|
+
if !defined?(WebMock::NetHTTPUtility) || WebMock.net_http_connect_on_start?(Addressable::URI.parse("http://example.com/"))
|
72
|
+
expect(sockets.length).to eq(1)
|
73
|
+
expect(sockets.to_a[0]).to be_a(Net::BufferedIO)
|
40
74
|
else
|
41
|
-
expect(
|
42
|
-
expect(
|
75
|
+
expect(sockets.length).to eq(2)
|
76
|
+
expect(sockets.to_a[0]).to be_a(StubSocket)
|
77
|
+
expect(sockets.to_a[1]).to be_a(Net::BufferedIO)
|
43
78
|
end
|
79
|
+
|
80
|
+
expect(sockets.all?(&:closed?)).to be(true)
|
44
81
|
end
|
45
82
|
|
46
83
|
it "should pass the read_timeout value on", net_connect: true do
|
@@ -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
|
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
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
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("http://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("http://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)
|
@@ -254,6 +253,21 @@ describe "Net:HTTP" do
|
|
254
253
|
}
|
255
254
|
end
|
256
255
|
|
256
|
+
it "should connect to the server on start when allowlisted", net_connect: true do
|
257
|
+
WebMock.disable_net_connect!(allow: "www.google.com", net_http_connect_on_start: "www.google.com")
|
258
|
+
@http.start {|conn|
|
259
|
+
cert = OpenSSL::X509::Certificate.new conn.peer_cert
|
260
|
+
expect(cert).to be_a(OpenSSL::X509::Certificate)
|
261
|
+
}
|
262
|
+
end
|
263
|
+
|
264
|
+
it "should not connect to the server on start when not allowlisted", net_connect: true do
|
265
|
+
WebMock.disable_net_connect!(allow: "www.google.com", net_http_connect_on_start: "www.yahoo.com")
|
266
|
+
@http.start {|conn|
|
267
|
+
expect(conn.peer_cert).to be_nil
|
268
|
+
}
|
269
|
+
end
|
270
|
+
|
257
271
|
it "should connect to the server if the URI matches an regex", net_connect: true do
|
258
272
|
WebMock.disable_net_connect!(allow: /google.com/)
|
259
273
|
Net::HTTP.get('www.google.com','/')
|
@@ -282,6 +296,13 @@ describe "Net:HTTP" do
|
|
282
296
|
it_should_behave_like "Net::HTTP"
|
283
297
|
end
|
284
298
|
|
299
|
+
describe "when net_http_connect_on_start is a specific host" do
|
300
|
+
before(:each) do
|
301
|
+
WebMock.allow_net_connect!(net_http_connect_on_start: "localhost")
|
302
|
+
end
|
303
|
+
it_should_behave_like "Net::HTTP"
|
304
|
+
end
|
305
|
+
|
285
306
|
describe 'after_request callback support', net_connect: true do
|
286
307
|
let(:expected_body_regex) { /hello world/ }
|
287
308
|
|
@@ -365,5 +386,10 @@ describe "Net:HTTP" do
|
|
365
386
|
path = '/example.jpg'
|
366
387
|
expect(WebMock::NetHTTPUtility.get_uri(net_http, path)).to eq('http://www.example.com:80/example.jpg')
|
367
388
|
end
|
389
|
+
|
390
|
+
it "does not require a path" do
|
391
|
+
net_http = Net::HTTP.new('www.example.com', 80)
|
392
|
+
expect(WebMock::NetHTTPUtility.get_uri(net_http)).to eq('http://www.example.com:80')
|
393
|
+
end
|
368
394
|
end
|
369
395
|
end
|
@@ -93,31 +93,29 @@ unless RUBY_PLATFORM =~ /java/
|
|
93
93
|
@sess.copy("/abc", "/def")
|
94
94
|
end
|
95
95
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
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
|
-
|
106
|
-
|
107
|
-
|
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
|
-
|
110
|
-
|
111
|
-
|
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
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
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
|
-
|
119
|
-
|
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
|
@@ -91,7 +91,7 @@ shared_context "allowing and disabling net connect" do |*adapter_info|
|
|
91
91
|
describe "is not allowed, with exceptions" do
|
92
92
|
describe "allowing by host string" do
|
93
93
|
before :each do
|
94
|
-
WebMock.disable_net_connect!(allow: 'httpstat.us')
|
94
|
+
WebMock.disable_net_connect!(allow: 'https://httpstat.us')
|
95
95
|
end
|
96
96
|
|
97
97
|
context "when the host is not allowed" do
|
@@ -109,13 +109,13 @@ shared_context "allowing and disabling net connect" do |*adapter_info|
|
|
109
109
|
|
110
110
|
context "when the host is allowed" do
|
111
111
|
it "should return stubbed response if request was stubbed" do
|
112
|
-
stub_request(:get, 'httpstat.us/200').to_return(body: "abc")
|
113
|
-
expect(http_request(:get, "
|
112
|
+
stub_request(:get, 'https://httpstat.us/200').to_return(body: "abc")
|
113
|
+
expect(http_request(:get, "https://httpstat.us/200").body).to eq("abc")
|
114
114
|
end
|
115
115
|
|
116
116
|
# WARNING: this makes a real HTTP request!
|
117
117
|
it "should make a real request to allowed host", net_connect: true do
|
118
|
-
expect(http_request(:get, "
|
118
|
+
expect(http_request(:get, "https://httpstat.us/200").status).to eq('200')
|
119
119
|
end
|
120
120
|
end
|
121
121
|
end
|
@@ -229,13 +229,13 @@ shared_context "allowing and disabling net connect" do |*adapter_info|
|
|
229
229
|
|
230
230
|
context "when the host is allowed" do
|
231
231
|
it "should return stubbed response if request was stubbed" do
|
232
|
-
stub_request(:get, 'httpstat.us/200').to_return(body: "abc")
|
233
|
-
expect(http_request(:get, "
|
232
|
+
stub_request(:get, 'https://httpstat.us/200').to_return(body: "abc")
|
233
|
+
expect(http_request(:get, "https://httpstat.us/200").body).to eq("abc")
|
234
234
|
end
|
235
235
|
|
236
236
|
# WARNING: this makes a real HTTP request!
|
237
237
|
it "should make a real request to allowed host", net_connect: true do
|
238
|
-
expect(http_request(:get, "
|
238
|
+
expect(http_request(:get, "https://httpstat.us/200").status).to eq('200')
|
239
239
|
end
|
240
240
|
|
241
241
|
it "should make a real request if request is allowed by path regexp and url contains default port", net_connect: true do
|
@@ -266,20 +266,20 @@ shared_context "allowing and disabling net connect" do |*adapter_info|
|
|
266
266
|
|
267
267
|
context "when the host is allowed" do
|
268
268
|
it "should return stubbed response if request was stubbed" do
|
269
|
-
stub_request(:get, 'httpstat.us/200').to_return(body: "abc")
|
270
|
-
expect(http_request(:get, "
|
269
|
+
stub_request(:get, 'https://httpstat.us/200').to_return(body: "abc")
|
270
|
+
expect(http_request(:get, "https://httpstat.us/200").body).to eq("abc")
|
271
271
|
end
|
272
272
|
|
273
273
|
# WARNING: this makes a real HTTP request!
|
274
274
|
it "should make a real request to allowed host", net_connect: true do
|
275
|
-
expect(http_request(:get, "
|
275
|
+
expect(http_request(:get, "https://httpstat.us/200").status).to eq('200')
|
276
276
|
end
|
277
277
|
end
|
278
278
|
end
|
279
279
|
|
280
280
|
describe "allowing by a list of the above" do
|
281
281
|
before :each do
|
282
|
-
WebMock.disable_net_connect!(allow: [lambda{|_| false }, %r{foobar}, 'httpstat.us'])
|
282
|
+
WebMock.disable_net_connect!(allow: [lambda{|_| false }, %r{foobar}, 'https://httpstat.us'])
|
283
283
|
end
|
284
284
|
|
285
285
|
context "when the host is not allowed" do
|
@@ -297,13 +297,13 @@ shared_context "allowing and disabling net connect" do |*adapter_info|
|
|
297
297
|
|
298
298
|
context "when the host is allowed" do
|
299
299
|
it "should return stubbed response if request was stubbed" do
|
300
|
-
stub_request(:get, 'httpstat.us/200').to_return(body: "abc")
|
301
|
-
expect(http_request(:get, "
|
300
|
+
stub_request(:get, 'https://httpstat.us/200').to_return(body: "abc")
|
301
|
+
expect(http_request(:get, "https://httpstat.us/200").body).to eq("abc")
|
302
302
|
end
|
303
303
|
|
304
304
|
# WARNING: this makes a real HTTP request!
|
305
305
|
it "should make a real request to allowed host", net_connect: true do
|
306
|
-
expect(http_request(:get, "
|
306
|
+
expect(http_request(:get, "https://httpstat.us/200").status).to eq('200')
|
307
307
|
end
|
308
308
|
end
|
309
309
|
end
|
@@ -102,7 +102,7 @@ shared_context "callbacks" do |*adapter_info|
|
|
102
102
|
WebMock.after_request(except: [:other_lib]) do |_, response|
|
103
103
|
@response = response
|
104
104
|
end
|
105
|
-
http_request(:get, "
|
105
|
+
http_request(:get, "https://httpstat.us/201", headers: { "Accept" => "*" })
|
106
106
|
end
|
107
107
|
|
108
108
|
it "should pass real response to callback with status and message" do
|
@@ -111,7 +111,7 @@ shared_context "callbacks" do |*adapter_info|
|
|
111
111
|
end
|
112
112
|
|
113
113
|
it "should pass real response to callback with headers" do
|
114
|
-
expect(@response.headers["
|
114
|
+
expect(@response.headers["Server"]).to eq( "Kestrel")
|
115
115
|
expect(@response.headers["Content-Length"]).to eq("11") unless adapter_info.include?(:no_content_length_header)
|
116
116
|
end
|
117
117
|
|
@@ -18,7 +18,7 @@ shared_context "complex cross-concern behaviors" do |*adapter_info|
|
|
18
18
|
expect(played_back_response).to eq(real_response)
|
19
19
|
end
|
20
20
|
|
21
|
-
let(:no_content_url) { '
|
21
|
+
let(:no_content_url) { 'https://httpstat.us/204' }
|
22
22
|
[nil, ''].each do |stub_val|
|
23
23
|
it "returns the same value (nil or "") for a request stubbed as #{stub_val.inspect} that a real empty response has", net_connect: true do
|
24
24
|
unless http_library == :curb
|
@@ -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",
|
@@ -18,7 +18,7 @@ describe WebMock::RequestSignature do
|
|
18
18
|
end
|
19
19
|
|
20
20
|
it "assigns normalized headers" do
|
21
|
-
|
21
|
+
allow(WebMock::Util::Headers).to receive(:normalize_headers).with({'A' => 'a'}.freeze).and_return('B' => 'b')
|
22
22
|
expect(
|
23
23
|
WebMock::RequestSignature.new(:get, "www.example.com", headers: {'A' => 'a'}).headers
|
24
24
|
).to eq({'B' => 'b'})
|
@@ -125,11 +125,21 @@ describe WebMock::RequestSignature do
|
|
125
125
|
expect(subject.url_encoded?).to be true
|
126
126
|
end
|
127
127
|
|
128
|
+
it "returns true if the headers are urlencoded with a specified charset" do
|
129
|
+
subject.headers = { "Content-Type" => "application/x-www-form-urlencoded; charset=UTF-8" }
|
130
|
+
expect(subject.url_encoded?).to be true
|
131
|
+
end
|
132
|
+
|
128
133
|
it "returns false if the headers are NOT urlencoded" do
|
129
134
|
subject.headers = { "Content-Type" => "application/made-up-format" }
|
130
135
|
expect(subject.url_encoded?).to be false
|
131
136
|
end
|
132
137
|
|
138
|
+
it "returns false when no content type header is present" do
|
139
|
+
subject.headers = { "Some-Header" => "some-value" }
|
140
|
+
expect(subject.url_encoded?).to be false
|
141
|
+
end
|
142
|
+
|
133
143
|
it "returns false when no headers are set" do
|
134
144
|
subject.headers = nil
|
135
145
|
expect(subject.url_encoded?).to be false
|
@@ -142,11 +152,21 @@ describe WebMock::RequestSignature do
|
|
142
152
|
expect(subject.json_headers?).to be true
|
143
153
|
end
|
144
154
|
|
155
|
+
it "returns true if the headers are json with a specified charset" do
|
156
|
+
subject.headers = { "Content-Type" => "application/json; charset=UTF-8" }
|
157
|
+
expect(subject.json_headers?).to be true
|
158
|
+
end
|
159
|
+
|
145
160
|
it "returns false if the headers are NOT json" do
|
146
161
|
subject.headers = { "Content-Type" => "application/made-up-format" }
|
147
162
|
expect(subject.json_headers?).to be false
|
148
163
|
end
|
149
164
|
|
165
|
+
it "returns false when no content type header is present" do
|
166
|
+
subject.headers = { "Some-Header" => "some-value" }
|
167
|
+
expect(subject.json_headers?).to be false
|
168
|
+
end
|
169
|
+
|
150
170
|
it "returns false when no headers are set" do
|
151
171
|
subject.headers = nil
|
152
172
|
expect(subject.json_headers?).to be false
|
@@ -50,6 +50,41 @@ describe WebMock::RequestStub do
|
|
50
50
|
|
51
51
|
end
|
52
52
|
|
53
|
+
describe "to_return_json" do
|
54
|
+
|
55
|
+
it "should raise if a block is given" do
|
56
|
+
expect {
|
57
|
+
@request_stub.to_return_json(body: "abc", status: 500) { puts "don't call me" }
|
58
|
+
}.to raise_error(ArgumentError, '#to_return_json does not support passing a block')
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should assign responses normally" do
|
62
|
+
@request_stub.to_return_json([{body: "abc"}, {body: "def"}])
|
63
|
+
expect([@request_stub.response.body, @request_stub.response.body]).to eq(["abc", "def"])
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should json-ify a Hash body" do
|
67
|
+
@request_stub.to_return_json(body: {abc: "def"}, status: 500)
|
68
|
+
expect(@request_stub.response.body).to eq({abc: "def"}.to_json)
|
69
|
+
expect(@request_stub.response.status).to eq([500, ""])
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should apply the content_type header" do
|
73
|
+
@request_stub.to_return_json(body: {abc: "def"}, status: 500)
|
74
|
+
expect(@request_stub.response.headers).to eq({"Content-Type"=>"application/json"})
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should preserve existing headers" do
|
78
|
+
@request_stub.to_return_json(headers: {"A" => "a"}, body: "")
|
79
|
+
expect(@request_stub.response.headers).to eq({"A"=>"a", "Content-Type"=>"application/json"})
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should allow callsites to override content_type header" do
|
83
|
+
@request_stub.to_return_json(headers: {content_type: 'application/super-special-json'})
|
84
|
+
expect(@request_stub.response.headers).to eq({"Content-Type"=>"application/super-special-json"})
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
53
88
|
describe "then" do
|
54
89
|
it "should return stub without any modifications, acting as syntactic sugar" do
|
55
90
|
expect(@request_stub.then).to eq(@request_stub)
|
data/spec/unit/response_spec.rb
CHANGED
@@ -31,7 +31,7 @@ describe WebMock::Response do
|
|
31
31
|
end
|
32
32
|
|
33
33
|
it "should report normalized headers" do
|
34
|
-
|
34
|
+
allow(WebMock::Util::Headers).to receive(:normalize_headers).with({'A' => 'a'}.freeze).and_return('B' => 'b')
|
35
35
|
@response = WebMock::Response.new(headers: {'A' => 'a'})
|
36
36
|
expect(@response.headers).to eq({'B' => 'b'})
|
37
37
|
end
|
@@ -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
|