webmock 3.8.3 → 3.14.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 +4 -4
- data/.github/workflows/CI.yml +37 -0
- data/CHANGELOG.md +132 -0
- data/Gemfile +1 -1
- data/README.md +70 -30
- data/Rakefile +12 -2
- data/lib/webmock/http_lib_adapters/async_http_client_adapter.rb +7 -5
- data/lib/webmock/http_lib_adapters/em_http_request_adapter.rb +6 -3
- data/lib/webmock/http_lib_adapters/http_rb/client.rb +4 -1
- data/lib/webmock/http_lib_adapters/http_rb/response.rb +13 -2
- data/lib/webmock/http_lib_adapters/http_rb/webmock.rb +1 -1
- data/lib/webmock/http_lib_adapters/httpclient_adapter.rb +23 -6
- data/lib/webmock/http_lib_adapters/manticore_adapter.rb +8 -1
- data/lib/webmock/http_lib_adapters/net_http.rb +17 -3
- data/lib/webmock/request_pattern.rb +77 -46
- data/lib/webmock/response.rb +11 -5
- data/lib/webmock/rspec.rb +2 -1
- data/lib/webmock/stub_registry.rb +26 -11
- data/lib/webmock/test_unit.rb +1 -3
- data/lib/webmock/version.rb +1 -1
- data/lib/webmock/webmock.rb +5 -3
- data/spec/acceptance/async_http_client/async_http_client_spec.rb +27 -1
- data/spec/acceptance/em_http_request/em_http_request_spec.rb +56 -0
- data/spec/acceptance/manticore/manticore_spec.rb +32 -0
- data/spec/acceptance/net_http/net_http_spec.rb +38 -0
- data/spec/acceptance/patron/patron_spec_helper.rb +2 -2
- data/spec/acceptance/shared/stubbing_requests.rb +35 -0
- data/spec/unit/request_pattern_spec.rb +171 -48
- data/spec/unit/response_spec.rb +22 -18
- data/spec/unit/webmock_spec.rb +52 -11
- data/test/test_webmock.rb +6 -0
- data/webmock.gemspec +2 -1
- metadata +25 -11
- data/.travis.yml +0 -19
@@ -252,6 +252,13 @@ class StubSocket #:nodoc:
|
|
252
252
|
def readuntil(*args)
|
253
253
|
end
|
254
254
|
|
255
|
+
def io
|
256
|
+
@io ||= StubIO.new
|
257
|
+
end
|
258
|
+
|
259
|
+
class StubIO
|
260
|
+
def setsockopt(*args); end
|
261
|
+
end
|
255
262
|
end
|
256
263
|
|
257
264
|
module Net #:nodoc: all
|
@@ -306,8 +313,6 @@ module WebMock
|
|
306
313
|
module NetHTTPUtility
|
307
314
|
|
308
315
|
def self.request_signature_from_request(net_http, request, body = nil)
|
309
|
-
protocol = net_http.use_ssl? ? "https" : "http"
|
310
|
-
|
311
316
|
path = request.path
|
312
317
|
|
313
318
|
if path.respond_to?(:request_uri) #https://github.com/bblimke/webmock/issues/288
|
@@ -316,7 +321,7 @@ module WebMock
|
|
316
321
|
|
317
322
|
path = WebMock::Util::URI.heuristic_parse(path).request_uri if path =~ /^http/
|
318
323
|
|
319
|
-
uri =
|
324
|
+
uri = get_uri(net_http, path)
|
320
325
|
method = request.method.downcase.to_sym
|
321
326
|
|
322
327
|
headers = Hash[*request.to_hash.map {|k,v| [k, v]}.inject([]) {|r,x| r + x}]
|
@@ -336,6 +341,15 @@ module WebMock
|
|
336
341
|
WebMock::RequestSignature.new(method, uri, body: request.body, headers: headers)
|
337
342
|
end
|
338
343
|
|
344
|
+
def self.get_uri(net_http, path)
|
345
|
+
protocol = net_http.use_ssl? ? "https" : "http"
|
346
|
+
|
347
|
+
hostname = net_http.address
|
348
|
+
hostname = "[#{hostname}]" if /\A\[.*\]\z/ !~ hostname && /:/ =~ hostname
|
349
|
+
|
350
|
+
"#{protocol}://#{hostname}:#{net_http.port}#{path}"
|
351
|
+
end
|
352
|
+
|
339
353
|
def self.validate_headers(headers)
|
340
354
|
# For Ruby versions < 2.3.0, if you make a request with headers that are symbols
|
341
355
|
# Net::HTTP raises a NoMethodError
|
@@ -80,6 +80,8 @@ module WebMock
|
|
80
80
|
URIRegexpPattern.new(uri)
|
81
81
|
elsif uri.is_a?(Addressable::Template)
|
82
82
|
URIAddressablePattern.new(uri)
|
83
|
+
elsif uri.respond_to?(:call)
|
84
|
+
URICallablePattern.new(uri)
|
83
85
|
else
|
84
86
|
URIStringPattern.new(uri)
|
85
87
|
end
|
@@ -107,11 +109,13 @@ module WebMock
|
|
107
109
|
include RSpecMatcherDetector
|
108
110
|
|
109
111
|
def initialize(pattern)
|
110
|
-
@pattern =
|
111
|
-
|
112
|
+
@pattern = if pattern.is_a?(Addressable::URI) \
|
113
|
+
|| pattern.is_a?(Addressable::Template)
|
114
|
+
pattern
|
115
|
+
elsif pattern.respond_to?(:call)
|
112
116
|
pattern
|
113
117
|
else
|
114
|
-
|
118
|
+
WebMock::Util::URI.normalize_uri(pattern)
|
115
119
|
end
|
116
120
|
@query_params = nil
|
117
121
|
end
|
@@ -131,38 +135,44 @@ module WebMock
|
|
131
135
|
end
|
132
136
|
end
|
133
137
|
|
138
|
+
def matches?(uri)
|
139
|
+
pattern_matches?(uri) && query_params_matches?(uri)
|
140
|
+
end
|
141
|
+
|
134
142
|
def to_s
|
135
|
-
str =
|
143
|
+
str = pattern_inspect
|
136
144
|
str += " with query params #{@query_params.inspect}" if @query_params
|
137
145
|
str
|
138
146
|
end
|
139
|
-
end
|
140
147
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
148
|
+
private
|
149
|
+
|
150
|
+
def pattern_inspect
|
151
|
+
@pattern.inspect
|
145
152
|
end
|
146
153
|
|
147
|
-
def
|
148
|
-
|
149
|
-
str += " with query params #{@query_params.inspect}" if @query_params
|
150
|
-
str
|
154
|
+
def query_params_matches?(uri)
|
155
|
+
@query_params.nil? || @query_params == WebMock::Util::QueryMapper.query_to_values(uri.query, notation: Config.instance.query_values_notation)
|
151
156
|
end
|
152
157
|
end
|
153
158
|
|
154
|
-
class
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
159
|
+
class URICallablePattern < URIPattern
|
160
|
+
private
|
161
|
+
|
162
|
+
def pattern_matches?(uri)
|
163
|
+
@pattern.call(uri)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
class URIRegexpPattern < URIPattern
|
168
|
+
private
|
169
|
+
|
170
|
+
def pattern_matches?(uri)
|
171
|
+
WebMock::Util::URI.variations_of_uri_as_strings(uri).any? { |u| u.match(@pattern) }
|
164
172
|
end
|
173
|
+
end
|
165
174
|
|
175
|
+
class URIAddressablePattern < URIPattern
|
166
176
|
def add_query_params(query_params)
|
167
177
|
@@add_query_params_warned ||= false
|
168
178
|
if not @@add_query_params_warned
|
@@ -172,13 +182,21 @@ module WebMock
|
|
172
182
|
super(query_params)
|
173
183
|
end
|
174
184
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
185
|
+
private
|
186
|
+
|
187
|
+
def pattern_matches?(uri)
|
188
|
+
if @query_params.nil?
|
189
|
+
# Let Addressable check the whole URI
|
190
|
+
matches_with_variations?(uri)
|
191
|
+
else
|
192
|
+
# WebMock checks the query, Addressable checks everything else
|
193
|
+
matches_with_variations?(uri.omit(:query))
|
194
|
+
end
|
179
195
|
end
|
180
196
|
|
181
|
-
|
197
|
+
def pattern_inspect
|
198
|
+
@pattern.pattern.inspect
|
199
|
+
end
|
182
200
|
|
183
201
|
def matches_with_variations?(uri)
|
184
202
|
template =
|
@@ -187,16 +205,34 @@ module WebMock
|
|
187
205
|
rescue Addressable::URI::InvalidURIError
|
188
206
|
Addressable::Template.new(@pattern.pattern)
|
189
207
|
end
|
190
|
-
WebMock::Util::URI.variations_of_uri_as_strings(uri).any? { |u|
|
208
|
+
WebMock::Util::URI.variations_of_uri_as_strings(uri).any? { |u|
|
209
|
+
template_matches_uri?(template, u)
|
210
|
+
}
|
211
|
+
end
|
212
|
+
|
213
|
+
def template_matches_uri?(template, uri)
|
214
|
+
template.match(uri)
|
215
|
+
rescue Addressable::URI::InvalidURIError
|
216
|
+
false
|
191
217
|
end
|
192
218
|
end
|
193
219
|
|
194
220
|
class URIStringPattern < URIPattern
|
195
|
-
def
|
221
|
+
def add_query_params(query_params)
|
222
|
+
super
|
223
|
+
if @query_params.is_a?(Hash) || @query_params.is_a?(String)
|
224
|
+
query_hash = (WebMock::Util::QueryMapper.query_to_values(@pattern.query, notation: Config.instance.query_values_notation) || {}).merge(@query_params)
|
225
|
+
@pattern.query = WebMock::Util::QueryMapper.values_to_query(query_hash, notation: WebMock::Config.instance.query_values_notation)
|
226
|
+
@query_params = nil
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
private
|
231
|
+
|
232
|
+
def pattern_matches?(uri)
|
196
233
|
if @pattern.is_a?(Addressable::URI)
|
197
234
|
if @query_params
|
198
|
-
uri.omit(:query) === @pattern
|
199
|
-
(@query_params.nil? || @query_params == WebMock::Util::QueryMapper.query_to_values(uri.query, notation: Config.instance.query_values_notation))
|
235
|
+
uri.omit(:query) === @pattern
|
200
236
|
else
|
201
237
|
uri === @pattern
|
202
238
|
end
|
@@ -205,19 +241,8 @@ module WebMock
|
|
205
241
|
end
|
206
242
|
end
|
207
243
|
|
208
|
-
def
|
209
|
-
|
210
|
-
if @query_params.is_a?(Hash) || @query_params.is_a?(String)
|
211
|
-
query_hash = (WebMock::Util::QueryMapper.query_to_values(@pattern.query, notation: Config.instance.query_values_notation) || {}).merge(@query_params)
|
212
|
-
@pattern.query = WebMock::Util::QueryMapper.values_to_query(query_hash, notation: WebMock::Config.instance.query_values_notation)
|
213
|
-
@query_params = nil
|
214
|
-
end
|
215
|
-
end
|
216
|
-
|
217
|
-
def to_s
|
218
|
-
str = WebMock::Util::URI.strip_default_port_from_uri_string(@pattern.to_s)
|
219
|
-
str += " with query params #{@query_params.inspect}" if @query_params
|
220
|
-
str
|
244
|
+
def pattern_inspect
|
245
|
+
WebMock::Util::URI.strip_default_port_from_uri_string(@pattern.to_s)
|
221
246
|
end
|
222
247
|
end
|
223
248
|
|
@@ -270,8 +295,9 @@ module WebMock
|
|
270
295
|
end
|
271
296
|
|
272
297
|
private
|
298
|
+
|
273
299
|
def body_as_hash(body, content_type)
|
274
|
-
case
|
300
|
+
case body_format(content_type)
|
275
301
|
when :json then
|
276
302
|
WebMock::Util::JSON.parse(body)
|
277
303
|
when :xml then
|
@@ -281,6 +307,11 @@ module WebMock
|
|
281
307
|
end
|
282
308
|
end
|
283
309
|
|
310
|
+
def body_format(content_type)
|
311
|
+
normalized_content_type = content_type.sub(/\A(application\/)[a-zA-Z0-9.-]+\+(json|xml)\Z/,'\1\2')
|
312
|
+
BODY_FORMATS[normalized_content_type]
|
313
|
+
end
|
314
|
+
|
284
315
|
def assert_non_multipart_body(content_type)
|
285
316
|
if content_type =~ %r{^multipart/form-data}
|
286
317
|
raise ArgumentError.new("WebMock does not support matching body for multipart/form-data requests yet :(")
|
data/lib/webmock/response.rb
CHANGED
@@ -91,10 +91,10 @@ module WebMock
|
|
91
91
|
|
92
92
|
def ==(other)
|
93
93
|
self.body == other.body &&
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
94
|
+
self.headers === other.headers &&
|
95
|
+
self.status == other.status &&
|
96
|
+
self.exception == other.exception &&
|
97
|
+
self.should_timeout == other.should_timeout
|
98
98
|
end
|
99
99
|
|
100
100
|
private
|
@@ -111,7 +111,13 @@ module WebMock
|
|
111
111
|
valid_types = [Proc, IO, Pathname, String, Array]
|
112
112
|
return if @body.nil?
|
113
113
|
return if valid_types.any? { |c| @body.is_a?(c) }
|
114
|
-
|
114
|
+
|
115
|
+
if @body.class.is_a?(Hash)
|
116
|
+
raise InvalidBody, "must be one of: #{valid_types}, but you've used a #{@body.class}' instead." \
|
117
|
+
"\n What shall we encode it to? try calling .to_json .to_xml instead on the hash instead, or otherwise convert it to a string."
|
118
|
+
else
|
119
|
+
raise InvalidBody, "must be one of: #{valid_types}. '#{@body.class}' given"
|
120
|
+
end
|
115
121
|
end
|
116
122
|
|
117
123
|
def read_raw_response(raw_response)
|
data/lib/webmock/rspec.rb
CHANGED
@@ -10,25 +10,39 @@ module WebMock
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def global_stubs
|
13
|
-
@global_stubs ||= []
|
13
|
+
@global_stubs ||= Hash.new { |h, k| h[k] = [] }
|
14
14
|
end
|
15
15
|
|
16
16
|
def reset!
|
17
17
|
self.request_stubs = []
|
18
18
|
end
|
19
19
|
|
20
|
-
def register_global_stub(&block)
|
20
|
+
def register_global_stub(order = :before_local_stubs, &block)
|
21
|
+
unless %i[before_local_stubs after_local_stubs].include?(order)
|
22
|
+
raise ArgumentError.new("Wrong order. Use :before_local_stubs or :after_local_stubs")
|
23
|
+
end
|
24
|
+
|
21
25
|
# This hash contains the responses returned by the block,
|
22
26
|
# keyed by the exact request (using the object_id).
|
23
27
|
# That way, there's no race condition in case #to_return
|
24
28
|
# doesn't run immediately after stub.with.
|
25
29
|
responses = {}
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
30
|
+
response_lock = Mutex.new
|
31
|
+
|
32
|
+
stub = ::WebMock::RequestStub.new(:any, ->(uri) { true }).with { |request|
|
33
|
+
update_response = -> { responses[request.object_id] = yield(request) }
|
34
|
+
|
35
|
+
# The block can recurse, so only lock if we don't already own it
|
36
|
+
if response_lock.owned?
|
37
|
+
update_response.call
|
38
|
+
else
|
39
|
+
response_lock.synchronize(&update_response)
|
40
|
+
end
|
41
|
+
}.to_return(lambda { |request|
|
42
|
+
response_lock.synchronize { responses.delete(request.object_id) }
|
43
|
+
})
|
44
|
+
|
45
|
+
global_stubs[order].push stub
|
32
46
|
end
|
33
47
|
|
34
48
|
def register_request_stub(stub)
|
@@ -54,9 +68,10 @@ module WebMock
|
|
54
68
|
private
|
55
69
|
|
56
70
|
def request_stub_for(request_signature)
|
57
|
-
(global_stubs + request_stubs
|
58
|
-
registered_request_stub
|
59
|
-
|
71
|
+
(global_stubs[:before_local_stubs] + request_stubs + global_stubs[:after_local_stubs])
|
72
|
+
.detect { |registered_request_stub|
|
73
|
+
registered_request_stub.request_pattern.matches?(request_signature)
|
74
|
+
}
|
60
75
|
end
|
61
76
|
|
62
77
|
def evaluate_response_for_request(response, request_signature)
|
data/lib/webmock/test_unit.rb
CHANGED
@@ -8,12 +8,10 @@ module Test
|
|
8
8
|
class TestCase
|
9
9
|
include WebMock::API
|
10
10
|
|
11
|
-
|
11
|
+
teardown
|
12
12
|
def teardown_with_webmock
|
13
|
-
teardown_without_webmock
|
14
13
|
WebMock.reset!
|
15
14
|
end
|
16
|
-
alias_method :teardown, :teardown_with_webmock
|
17
15
|
|
18
16
|
end
|
19
17
|
end
|
data/lib/webmock/version.rb
CHANGED
data/lib/webmock/webmock.rb
CHANGED
@@ -59,11 +59,13 @@ module WebMock
|
|
59
59
|
end
|
60
60
|
|
61
61
|
def self.net_connect_allowed?(uri = nil)
|
62
|
+
return !!Config.instance.allow_net_connect if uri.nil?
|
63
|
+
|
62
64
|
if uri.is_a?(String)
|
63
65
|
uri = WebMock::Util::URI.normalize_uri(uri)
|
64
66
|
end
|
65
67
|
|
66
|
-
Config.instance.allow_net_connect ||
|
68
|
+
!!Config.instance.allow_net_connect ||
|
67
69
|
( Config.instance.allow_localhost && WebMock::Util::URI.is_uri_localhost?(uri) ||
|
68
70
|
Config.instance.allow && net_connect_explicit_allowed?(Config.instance.allow, uri) )
|
69
71
|
end
|
@@ -138,8 +140,8 @@ module WebMock
|
|
138
140
|
puts WebMock::RequestExecutionVerifier.executed_requests_message
|
139
141
|
end
|
140
142
|
|
141
|
-
def self.globally_stub_request(&block)
|
142
|
-
WebMock::StubRegistry.instance.register_global_stub(&block)
|
143
|
+
def self.globally_stub_request(order = :before_local_stubs, &block)
|
144
|
+
WebMock::StubRegistry.instance.register_global_stub(order, &block)
|
143
145
|
end
|
144
146
|
|
145
147
|
%w(
|
@@ -135,7 +135,31 @@ unless RUBY_PLATFORM =~ /java/
|
|
135
135
|
expect { make_request(:get, 'http://www.example.com') }.to raise_error Async::TimeoutError
|
136
136
|
end
|
137
137
|
|
138
|
+
it 'does not invoke "after real request" callbacks for stubbed requests' do
|
139
|
+
WebMock.allow_net_connect!
|
140
|
+
stub_request(:get, 'http://www.example.com').to_return(body: 'abc')
|
141
|
+
|
142
|
+
callback_invoked = false
|
143
|
+
WebMock.after_request(real_requests_only: true) { |_| callback_invoked = true }
|
144
|
+
|
145
|
+
make_request(:get, 'http://www.example.com')
|
146
|
+
expect(callback_invoked).to eq(false)
|
147
|
+
end
|
148
|
+
|
149
|
+
it 'does invoke "after request" callbacks for stubbed requests' do
|
150
|
+
WebMock.allow_net_connect!
|
151
|
+
stub_request(:get, 'http://www.example.com').to_return(body: 'abc')
|
152
|
+
|
153
|
+
callback_invoked = false
|
154
|
+
WebMock.after_request(real_requests_only: false) { |_| callback_invoked = true }
|
155
|
+
|
156
|
+
make_request(:get, 'http://www.example.com')
|
157
|
+
expect(callback_invoked).to eq(true)
|
158
|
+
end
|
159
|
+
|
138
160
|
context 'scheme and protocol' do
|
161
|
+
let(:default_response_headers) { {} }
|
162
|
+
|
139
163
|
before do
|
140
164
|
stub_request(
|
141
165
|
:get, "#{scheme}://www.example.com"
|
@@ -152,7 +176,7 @@ unless RUBY_PLATFORM =~ /java/
|
|
152
176
|
specify do
|
153
177
|
expect(subject).to eq(
|
154
178
|
status: 200,
|
155
|
-
headers:
|
179
|
+
headers: default_response_headers,
|
156
180
|
body: 'BODY'
|
157
181
|
)
|
158
182
|
end
|
@@ -169,6 +193,7 @@ unless RUBY_PLATFORM =~ /java/
|
|
169
193
|
|
170
194
|
context 'HTTP10 protocol' do
|
171
195
|
let(:protocol) { Async::HTTP::Protocol::HTTP10 }
|
196
|
+
let(:default_response_headers) { {"connection"=>["keep-alive"]} }
|
172
197
|
|
173
198
|
include_examples :common
|
174
199
|
end
|
@@ -197,6 +222,7 @@ unless RUBY_PLATFORM =~ /java/
|
|
197
222
|
|
198
223
|
context 'HTTP10 protocol' do
|
199
224
|
let(:protocol) { Async::HTTP::Protocol::HTTP10 }
|
225
|
+
let(:default_response_headers) { {"connection"=>["keep-alive"]} }
|
200
226
|
|
201
227
|
include_examples :common
|
202
228
|
end
|
@@ -71,6 +71,35 @@ unless RUBY_PLATFORM =~ /java/
|
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
|
+
it "only calls request middleware once" do
|
75
|
+
stub_request(:get, "www.example.com")
|
76
|
+
|
77
|
+
middleware = Class.new do
|
78
|
+
def self.called!
|
79
|
+
@called = called + 1
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.called
|
83
|
+
@called || 0
|
84
|
+
end
|
85
|
+
|
86
|
+
def request(client, head, body)
|
87
|
+
self.class.called!
|
88
|
+
[head, body]
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
EM.run do
|
93
|
+
conn = EventMachine::HttpRequest.new('http://www.example.com/')
|
94
|
+
conn.use middleware
|
95
|
+
http = conn.get
|
96
|
+
http.callback do
|
97
|
+
expect(middleware.called).to eq(1)
|
98
|
+
EM.stop
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
74
103
|
let(:response_middleware) do
|
75
104
|
Class.new do
|
76
105
|
def response(resp)
|
@@ -119,6 +148,33 @@ unless RUBY_PLATFORM =~ /java/
|
|
119
148
|
context 'making a real request', net_connect: true do
|
120
149
|
before { WebMock.allow_net_connect! }
|
121
150
|
include_examples "em-http-request middleware/after_request hook integration"
|
151
|
+
|
152
|
+
it "only calls request middleware once" do
|
153
|
+
middleware = Class.new do
|
154
|
+
def self.called!
|
155
|
+
@called = called + 1
|
156
|
+
end
|
157
|
+
|
158
|
+
def self.called
|
159
|
+
@called || 0
|
160
|
+
end
|
161
|
+
|
162
|
+
def request(client, head, body)
|
163
|
+
self.class.called!
|
164
|
+
[head, body]
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
EM.run do
|
169
|
+
conn = EventMachine::HttpRequest.new(webmock_server_url)
|
170
|
+
conn.use middleware
|
171
|
+
http = conn.get
|
172
|
+
http.callback do
|
173
|
+
expect(middleware.called).to eq(1)
|
174
|
+
EM.stop
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
122
178
|
end
|
123
179
|
|
124
180
|
context 'when the request is stubbed' do
|
@@ -70,6 +70,38 @@ if RUBY_PLATFORM =~ /java/
|
|
70
70
|
expect(failure_handler).to have_received(:call)
|
71
71
|
end
|
72
72
|
end
|
73
|
+
|
74
|
+
context 'when used in a streaming mode' do
|
75
|
+
let(:webmock_server_url) {"http://#{WebMockServer.instance.host_with_port}/"}
|
76
|
+
let(:result_chunks) { [] }
|
77
|
+
|
78
|
+
def manticore_streaming_get
|
79
|
+
Manticore.get(webmock_server_url).tap do |req|
|
80
|
+
req.on_success do |response|
|
81
|
+
response.body do |chunk|
|
82
|
+
result_chunks << chunk
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context 'when connections are allowed' do
|
89
|
+
it 'works' do
|
90
|
+
WebMock.allow_net_connect!
|
91
|
+
expect { manticore_streaming_get.call }.to_not raise_error
|
92
|
+
expect(result_chunks).to_not be_empty
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context 'when stubbed' do
|
97
|
+
it 'works' do
|
98
|
+
stub_body = 'hello!'
|
99
|
+
stub_request(:get, webmock_server_url).to_return(body: stub_body)
|
100
|
+
expect { manticore_streaming_get.call }.to_not raise_error
|
101
|
+
expect(result_chunks).to eq [stub_body]
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
73
105
|
end
|
74
106
|
end
|
75
107
|
end
|
@@ -201,6 +201,18 @@ describe "Net:HTTP" do
|
|
201
201
|
expect(Net::HTTP.get_response(Addressable::URI.parse('http://www.example.com/hello?a=1')).body).to eq("abc")
|
202
202
|
end
|
203
203
|
|
204
|
+
it "should support method calls on stubbed socket" do
|
205
|
+
WebMock.allow_net_connect!
|
206
|
+
stub_request(:get, 'www.google.com')#.with(headers: {"My-Header" => 99})
|
207
|
+
req = Net::HTTP::Get.new('/')
|
208
|
+
Net::HTTP.start('www.google.com') do |http|
|
209
|
+
http.request(req, '')
|
210
|
+
socket = http.instance_variable_get(:@socket)
|
211
|
+
expect(socket).to be_a(StubSocket)
|
212
|
+
expect { socket.io.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1) }.to_not raise_error
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
204
216
|
describe "connecting on Net::HTTP.start" do
|
205
217
|
before(:each) do
|
206
218
|
@http = Net::HTTP.new('www.google.com', 443)
|
@@ -328,4 +340,30 @@ describe "Net:HTTP" do
|
|
328
340
|
http.request(req, '')
|
329
341
|
end
|
330
342
|
end
|
343
|
+
|
344
|
+
describe "hostname handling" do
|
345
|
+
it "should set brackets around the hostname if it is an IPv6 address" do
|
346
|
+
net_http = Net::HTTP.new('b2dc:5bdf:4f0d::3014:e0ca', 80)
|
347
|
+
path = '/example.jpg'
|
348
|
+
expect(WebMock::NetHTTPUtility.get_uri(net_http, path)).to eq('http://[b2dc:5bdf:4f0d::3014:e0ca]:80/example.jpg')
|
349
|
+
end
|
350
|
+
|
351
|
+
it "should not set brackets around the hostname if it is already wrapped by brackets" do
|
352
|
+
net_http = Net::HTTP.new('[b2dc:5bdf:4f0d::3014:e0ca]', 80)
|
353
|
+
path = '/example.jpg'
|
354
|
+
expect(WebMock::NetHTTPUtility.get_uri(net_http, path)).to eq('http://[b2dc:5bdf:4f0d::3014:e0ca]:80/example.jpg')
|
355
|
+
end
|
356
|
+
|
357
|
+
it "should not set brackets around the hostname if it is an IPv4 address" do
|
358
|
+
net_http = Net::HTTP.new('181.152.137.168', 80)
|
359
|
+
path = '/example.jpg'
|
360
|
+
expect(WebMock::NetHTTPUtility.get_uri(net_http, path)).to eq('http://181.152.137.168:80/example.jpg')
|
361
|
+
end
|
362
|
+
|
363
|
+
it "should not set brackets around the hostname if it is a domain" do
|
364
|
+
net_http = Net::HTTP.new('www.example.com', 80)
|
365
|
+
path = '/example.jpg'
|
366
|
+
expect(WebMock::NetHTTPUtility.get_uri(net_http, path)).to eq('http://www.example.com:80/example.jpg')
|
367
|
+
end
|
368
|
+
end
|
331
369
|
end
|
@@ -28,8 +28,8 @@ module PatronSpecHelper
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
-
status_line_pattern = %r(\AHTTP/(\d
|
32
|
-
message = response.status_line.match(status_line_pattern)[
|
31
|
+
status_line_pattern = %r(\AHTTP/(\d+(\.\d+)?)\s+(\d\d\d)\s*([^\r\n]+)?)
|
32
|
+
message = response.status_line.match(status_line_pattern)[4] || ""
|
33
33
|
|
34
34
|
OpenStruct.new({
|
35
35
|
body: response.body,
|
@@ -593,6 +593,23 @@ shared_examples_for "stubbing requests" do |*adapter_info|
|
|
593
593
|
end
|
594
594
|
end
|
595
595
|
end
|
596
|
+
|
597
|
+
context "when global stub should be invoked last" do
|
598
|
+
before do
|
599
|
+
WebMock.globally_stub_request(:after_local_stubs) do
|
600
|
+
{ body: "global stub body" }
|
601
|
+
end
|
602
|
+
end
|
603
|
+
|
604
|
+
it "uses global stub when non-global stub is not defined" do
|
605
|
+
expect(http_request(:get, "http://www.example.com/").body).to eq("global stub body")
|
606
|
+
end
|
607
|
+
|
608
|
+
it "uses non-global stub first" do
|
609
|
+
stub_request(:get, "www.example.com").to_return(body: 'non-global stub body')
|
610
|
+
expect(http_request(:get, "http://www.example.com/").body).to eq("non-global stub body")
|
611
|
+
end
|
612
|
+
end
|
596
613
|
end
|
597
614
|
|
598
615
|
describe "when stubbing request with a block evaluated on request" do
|
@@ -640,4 +657,22 @@ shared_examples_for "stubbing requests" do |*adapter_info|
|
|
640
657
|
}.to raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: GET http://www.example.com/))
|
641
658
|
end
|
642
659
|
end
|
660
|
+
|
661
|
+
describe "in Rspec around(:each) hook" do
|
662
|
+
# order goes
|
663
|
+
# around(:each)
|
664
|
+
# before(:each)
|
665
|
+
# after(:each)
|
666
|
+
# anything after example.run in around(:each)
|
667
|
+
around(:each) do |example|
|
668
|
+
example.run
|
669
|
+
expect {
|
670
|
+
http_request(:get, "http://www.example.com/")
|
671
|
+
}.to_not raise_error # WebMock::NetConnectNotAllowedError
|
672
|
+
end
|
673
|
+
|
674
|
+
it "should still allow me to make a mocked request" do
|
675
|
+
stub_request(:get, "www.example.com")
|
676
|
+
end
|
677
|
+
end
|
643
678
|
end
|