webmock 3.0.1 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +7 -7
- data/CHANGELOG.md +45 -0
- data/README.md +16 -2
- data/lib/webmock.rb +3 -0
- data/lib/webmock/api.rb +8 -0
- data/lib/webmock/http_lib_adapters/curb_adapter.rb +1 -1
- data/lib/webmock/http_lib_adapters/excon_adapter.rb +1 -1
- data/lib/webmock/http_lib_adapters/http_rb/request.rb +7 -1
- data/lib/webmock/http_lib_adapters/http_rb/streamer.rb +4 -0
- data/lib/webmock/http_lib_adapters/http_rb/webmock.rb +1 -1
- data/lib/webmock/http_lib_adapters/httpclient_adapter.rb +5 -3
- data/lib/webmock/http_lib_adapters/net_http.rb +2 -2
- data/lib/webmock/http_lib_adapters/patron_adapter.rb +2 -2
- data/lib/webmock/matchers/any_arg_matcher.rb +13 -0
- data/lib/webmock/matchers/hash_argument_matcher.rb +21 -0
- data/lib/webmock/matchers/hash_excluding_matcher.rb +15 -0
- data/lib/webmock/matchers/hash_including_matcher.rb +4 -23
- data/lib/webmock/rack_response.rb +1 -1
- data/lib/webmock/request_execution_verifier.rb +2 -3
- data/lib/webmock/request_pattern.rb +9 -2
- data/lib/webmock/request_registry.rb +1 -1
- data/lib/webmock/request_signature.rb +1 -1
- data/lib/webmock/request_signature_snippet.rb +4 -4
- data/lib/webmock/stub_request_snippet.rb +2 -2
- data/lib/webmock/util/headers.rb +2 -2
- data/lib/webmock/util/query_mapper.rb +3 -3
- data/lib/webmock/version.rb +1 -1
- data/minitest/webmock_spec.rb +2 -2
- data/spec/acceptance/http_rb/http_rb_spec.rb +9 -0
- data/spec/acceptance/http_rb/http_rb_spec_helper.rb +1 -1
- data/spec/acceptance/httpclient/httpclient_spec.rb +8 -1
- data/spec/acceptance/net_http/net_http_shared.rb +1 -1
- data/spec/acceptance/net_http/net_http_spec.rb +15 -1
- data/spec/acceptance/patron/patron_spec_helper.rb +1 -1
- data/spec/acceptance/shared/request_expectations.rb +7 -0
- data/spec/acceptance/shared/stubbing_requests.rb +5 -0
- data/spec/acceptance/typhoeus/typhoeus_hydra_spec.rb +1 -1
- data/spec/acceptance/typhoeus/typhoeus_hydra_spec_helper.rb +1 -1
- data/spec/unit/api_spec.rb +84 -3
- data/spec/unit/matchers/hash_excluding_matcher_spec.rb +61 -0
- data/spec/unit/request_execution_verifier_spec.rb +12 -12
- data/test/shared_test.rb +15 -2
- metadata +44 -39
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1ba7b559bad31fd1150447c4895e4517a96e5c0b
|
4
|
+
data.tar.gz: 6682c3a0689f7aaf06b11cef43e170d584694187
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f77249e99b5553be7f9afea5de6112c7e63526c4c6ca42124bfa5089061b64eb469d927f903bf37d54245213b66d2217ee8112863848108dc262d995ca64c1d3
|
7
|
+
data.tar.gz: 779df5762aa1d72513d4cae0221b44e1dc92dee9b698db5ae6daf92fe12c29fb29d88af04968baabefe186ca9d51f1c564da89aa4c1e53fb31f55ead0f72d008
|
data/.travis.yml
CHANGED
@@ -1,14 +1,14 @@
|
|
1
|
+
before_install:
|
2
|
+
- gem update bundler
|
3
|
+
|
1
4
|
rvm:
|
2
|
-
- 2.
|
3
|
-
- 2.
|
4
|
-
- 2.2
|
5
|
-
- 2.2.3
|
6
|
-
- 2.3.0
|
7
|
-
- 2.4.0
|
5
|
+
- 2.2.8
|
6
|
+
- 2.3.5
|
7
|
+
- 2.4.2
|
8
8
|
- rbx-2
|
9
9
|
- ruby-head
|
10
10
|
- jruby-9.0.5.0
|
11
|
-
- jruby-9.1.
|
11
|
+
- jruby-9.1.13.0
|
12
12
|
- jruby-head
|
13
13
|
matrix:
|
14
14
|
allow_failures:
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,50 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 3.1.0
|
4
|
+
|
5
|
+
* http.rb 3.0.0 compatibility
|
6
|
+
|
7
|
+
Thanks to [Piotr Boniecki](https://github.com/Bonias)
|
8
|
+
|
9
|
+
* Typhoeus 1.3.0 support
|
10
|
+
|
11
|
+
Thanks to [NARUSE, Yui](https://github.com/nurse)
|
12
|
+
|
13
|
+
* Added support for matching partial query params using hash_excluding
|
14
|
+
|
15
|
+
stub_request(:get, "www.example.com").
|
16
|
+
with(query: hash_excluding({"a" => "b"}))
|
17
|
+
|
18
|
+
RestClient.get("http://www.example.com/?a=b") # ===> Failure
|
19
|
+
RestClient.get("http://www.example.com/?a=c") # ===> Success
|
20
|
+
|
21
|
+
Thanks to [Olexandr Hoshylyk](https://github.com/Warrior109)
|
22
|
+
|
23
|
+
* Added MRI 2.3+ frozen string literal compatibility
|
24
|
+
|
25
|
+
Thanks to [Pat Allan](https://github.com/pat)
|
26
|
+
|
27
|
+
* Ensured that HTTPClient adapter does not yield block on empty response body if a block is provided
|
28
|
+
|
29
|
+
Thanks to [NARUSE, Yui](https://github.com/nurse)
|
30
|
+
|
31
|
+
* Fixed issue with `to_timeout` incorrectly raising `HTTP::ConnectionError` instead of `HTTP::TimeoutError` when using http.rb
|
32
|
+
|
33
|
+
Thanks to [Rick Song](https://github.com/RickCSong)
|
34
|
+
|
35
|
+
* Fixed problem with `response.connection.close` method being undefined when using http.rb
|
36
|
+
|
37
|
+
Thanks to [Janko Marohnić](https://github.com/janko-m)
|
38
|
+
|
39
|
+
* Fixed problem with matching Net::HTTP request header values assigned as numbers.
|
40
|
+
|
41
|
+
Thanks to [Felipe Constantino de Oliveira](https://github.com/felipecdo) for reporting the issue.
|
42
|
+
|
43
|
+
* Fixed problem with Net::HTTP adapter converting empty response body to nil for non 204 responses.
|
44
|
+
|
45
|
+
Thanks to [Jeffrey Charles](https://github.com/jeffcharles) for reporting the issue.
|
46
|
+
|
47
|
+
|
3
48
|
## 3.0.1
|
4
49
|
|
5
50
|
* Suppressed \`warning: \`&' interpreted as argument prefix\`
|
data/README.md
CHANGED
@@ -32,8 +32,6 @@ Supported HTTP libraries
|
|
32
32
|
Supported Ruby Interpreters
|
33
33
|
---------------------------
|
34
34
|
|
35
|
-
* MRI 2.0
|
36
|
-
* MRI 2.1
|
37
35
|
* MRI 2.2
|
38
36
|
* MRI 2.3
|
39
37
|
* MRI 2.4
|
@@ -273,6 +271,16 @@ stub_request(:get, "www.example.com").
|
|
273
271
|
RestClient.get("http://www.example.com/?a[]=b&a[]=c&x=1") # ===> Success
|
274
272
|
```
|
275
273
|
|
274
|
+
### Matching partial query params using hash_excluding
|
275
|
+
|
276
|
+
```ruby
|
277
|
+
stub_request(:get, "www.example.com").
|
278
|
+
with(query: hash_excluding({"a" => "b"}))
|
279
|
+
|
280
|
+
RestClient.get("http://www.example.com/?a=b") # ===> Failure
|
281
|
+
RestClient.get("http://www.example.com/?a=c") # ===> Success
|
282
|
+
```
|
283
|
+
|
276
284
|
### Stubbing with custom response
|
277
285
|
|
278
286
|
```ruby
|
@@ -1035,6 +1043,12 @@ People who submitted patches and new features or suggested improvements. Many th
|
|
1035
1043
|
* George Ulmer
|
1036
1044
|
* Christof Koenig
|
1037
1045
|
* Chung-Yi Chi
|
1046
|
+
* Olexandr Hoshylyk
|
1047
|
+
* Janko Marohnić
|
1048
|
+
* Pat Allan
|
1049
|
+
* Rick Song
|
1050
|
+
* NARUSE, Yui
|
1051
|
+
* Piotr Boniecki
|
1038
1052
|
|
1039
1053
|
For a full list of contributors you can visit the
|
1040
1054
|
[contributors](https://github.com/bblimke/webmock/contributors) page.
|
data/lib/webmock.rb
CHANGED
@@ -18,7 +18,10 @@ require 'webmock/util/json'
|
|
18
18
|
require 'webmock/util/version_checker'
|
19
19
|
require 'webmock/util/hash_validator'
|
20
20
|
|
21
|
+
require 'webmock/matchers/hash_argument_matcher'
|
22
|
+
require 'webmock/matchers/hash_excluding_matcher'
|
21
23
|
require 'webmock/matchers/hash_including_matcher'
|
24
|
+
require 'webmock/matchers/any_arg_matcher'
|
22
25
|
|
23
26
|
require 'webmock/request_pattern'
|
24
27
|
require 'webmock/request_signature'
|
data/lib/webmock/api.rb
CHANGED
@@ -54,6 +54,14 @@ module WebMock
|
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
|
+
def hash_excluding(*args)
|
58
|
+
if defined?(super)
|
59
|
+
super
|
60
|
+
else
|
61
|
+
WebMock::Matchers::HashExcludingMatcher.new(anythingize_lonely_keys(*args))
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
57
65
|
def remove_request_stub(stub)
|
58
66
|
WebMock::StubRegistry.instance.remove_request_stub(stub)
|
59
67
|
end
|
@@ -153,7 +153,7 @@ if defined?(Curl)
|
|
153
153
|
@body_str = webmock_response.body
|
154
154
|
@response_code = webmock_response.status[0]
|
155
155
|
|
156
|
-
@header_str = "HTTP/1.1 #{webmock_response.status[0]} #{webmock_response.status[1]}\r\n"
|
156
|
+
@header_str = "HTTP/1.1 #{webmock_response.status[0]} #{webmock_response.status[1]}\r\n".dup
|
157
157
|
|
158
158
|
@on_debug.call(@header_str, 1) if defined?( @on_debug )
|
159
159
|
|
@@ -1,9 +1,15 @@
|
|
1
1
|
module HTTP
|
2
2
|
class Request
|
3
3
|
def webmock_signature
|
4
|
+
request_body = if defined?(HTTP::Request::Body)
|
5
|
+
''.tap { |string| body.each { |part| string << part } }
|
6
|
+
else
|
7
|
+
body
|
8
|
+
end
|
9
|
+
|
4
10
|
::WebMock::RequestSignature.new(verb, uri.to_s, {
|
5
11
|
headers: headers.to_h,
|
6
|
-
body:
|
12
|
+
body: request_body
|
7
13
|
})
|
8
14
|
end
|
9
15
|
end
|
@@ -43,7 +43,7 @@ module HTTP
|
|
43
43
|
|
44
44
|
def raise_timeout_error
|
45
45
|
raise Errno::ETIMEDOUT if HTTP::VERSION < "1.0.0"
|
46
|
-
raise HTTP::
|
46
|
+
raise HTTP::TimeoutError, "connection error: #{Errno::ETIMEDOUT.new}"
|
47
47
|
end
|
48
48
|
|
49
49
|
def perform
|
@@ -75,8 +75,10 @@ if defined?(::HTTPClient)
|
|
75
75
|
elsif block
|
76
76
|
body = ''
|
77
77
|
do_get_block_without_webmock(req, proxy, conn) do |http_res, chunk|
|
78
|
-
|
79
|
-
|
78
|
+
if chunk && chunk.bytesize > 0
|
79
|
+
body += chunk
|
80
|
+
block.call(http_res, chunk)
|
81
|
+
end
|
80
82
|
end
|
81
83
|
else
|
82
84
|
do_get_block_without_webmock(req, proxy, conn)
|
@@ -117,7 +119,7 @@ if defined?(::HTTPClient)
|
|
117
119
|
raise HTTPClient::TimeoutError if webmock_response.should_timeout
|
118
120
|
webmock_response.raise_error_if_any
|
119
121
|
|
120
|
-
block.call(response, body) if block
|
122
|
+
block.call(response, body) if block && body && body.bytesize > 0
|
121
123
|
|
122
124
|
response
|
123
125
|
end
|
@@ -154,7 +154,7 @@ module WebMock
|
|
154
154
|
def build_net_http_response(webmock_response, &block)
|
155
155
|
response = Net::HTTPResponse.send(:response_class, webmock_response.status[0].to_s).new("1.0", webmock_response.status[0].to_s, webmock_response.status[1])
|
156
156
|
body = webmock_response.body
|
157
|
-
body = nil if
|
157
|
+
body = nil if webmock_response.status[0].to_s == '204'
|
158
158
|
|
159
159
|
response.instance_variable_set(:@body, body)
|
160
160
|
webmock_response.headers.to_a.each do |name, values|
|
@@ -258,7 +258,7 @@ module Net #:nodoc: all
|
|
258
258
|
class WebMockNetBufferedIO < BufferedIO
|
259
259
|
def initialize(io, read_timeout: 60, continue_timeout: nil, debug_output: nil)
|
260
260
|
@read_timeout = read_timeout
|
261
|
-
@rbuf = ''
|
261
|
+
@rbuf = ''.dup
|
262
262
|
@debug_output = debug_output
|
263
263
|
|
264
264
|
@io = case io
|
@@ -106,11 +106,11 @@ if defined?(::Patron)
|
|
106
106
|
header_data = ([status_line] + header_fields).join("\r\n")
|
107
107
|
|
108
108
|
::Patron::Response.new(
|
109
|
-
"",
|
109
|
+
"".dup,
|
110
110
|
webmock_response.status[0],
|
111
111
|
0,
|
112
112
|
header_data,
|
113
|
-
webmock_response.body,
|
113
|
+
webmock_response.body.dup,
|
114
114
|
default_response_charset
|
115
115
|
)
|
116
116
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module WebMock
|
2
|
+
module Matchers
|
3
|
+
# Base class for Hash matchers
|
4
|
+
# https://github.com/rspec/rspec-mocks/blob/master/lib/rspec/mocks/argument_matchers.rb
|
5
|
+
class HashArgumentMatcher
|
6
|
+
def initialize(expected)
|
7
|
+
@expected = Hash[WebMock::Util::HashKeysStringifier.stringify_keys!(expected, deep: true).sort]
|
8
|
+
end
|
9
|
+
|
10
|
+
def ==(_actual, &block)
|
11
|
+
@expected.all?(&block)
|
12
|
+
rescue NoMethodError
|
13
|
+
false
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.from_rspec_matcher(matcher)
|
17
|
+
new(matcher.instance_variable_get(:@expected))
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module WebMock
|
2
|
+
module Matchers
|
3
|
+
# this is a based on RSpec::Mocks::ArgumentMatchers::HashExcludingMatcher
|
4
|
+
# https://github.com/rspec/rspec-mocks/blob/master/lib/rspec/mocks/argument_matchers.rb
|
5
|
+
class HashExcludingMatcher < HashArgumentMatcher
|
6
|
+
def ==(actual)
|
7
|
+
super { |key, value| !actual.key?(key) || value != actual[key] }
|
8
|
+
end
|
9
|
+
|
10
|
+
def inspect
|
11
|
+
"hash_excluding(#{@expected.inspect})"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -1,14 +1,10 @@
|
|
1
1
|
module WebMock
|
2
2
|
module Matchers
|
3
|
-
#this is a based on RSpec::Mocks::ArgumentMatchers::HashIncludingMatcher
|
4
|
-
#https://github.com/rspec/rspec-mocks/blob/master/lib/rspec/mocks/argument_matchers.rb
|
5
|
-
class HashIncludingMatcher
|
6
|
-
def initialize(expected)
|
7
|
-
@expected = Hash[WebMock::Util::HashKeysStringifier.stringify_keys!(expected, deep: true).sort]
|
8
|
-
end
|
9
|
-
|
3
|
+
# this is a based on RSpec::Mocks::ArgumentMatchers::HashIncludingMatcher
|
4
|
+
# https://github.com/rspec/rspec-mocks/blob/master/lib/rspec/mocks/argument_matchers.rb
|
5
|
+
class HashIncludingMatcher < HashArgumentMatcher
|
10
6
|
def ==(actual)
|
11
|
-
|
7
|
+
super { |key, value| actual.key?(key) && value === actual[key] }
|
12
8
|
rescue NoMethodError
|
13
9
|
false
|
14
10
|
end
|
@@ -16,21 +12,6 @@ module WebMock
|
|
16
12
|
def inspect
|
17
13
|
"hash_including(#{@expected.inspect})"
|
18
14
|
end
|
19
|
-
|
20
|
-
def self.from_rspec_matcher(matcher)
|
21
|
-
new(matcher.instance_variable_get(:@expected))
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
#this is a based on RSpec::Mocks::ArgumentMatchers::AnyArgMatcher
|
26
|
-
class AnyArgMatcher
|
27
|
-
def initialize(ignore)
|
28
|
-
end
|
29
|
-
|
30
|
-
def ==(other)
|
31
|
-
true
|
32
|
-
end
|
33
15
|
end
|
34
|
-
|
35
16
|
end
|
36
17
|
end
|
@@ -53,9 +53,8 @@ module WebMock
|
|
53
53
|
|
54
54
|
def failure_message_phrase(is_negated=false)
|
55
55
|
negation = is_negated ? "was not" : "was"
|
56
|
-
|
57
|
-
|
58
|
-
text
|
56
|
+
"The request #{request_pattern} #{negation} expected to execute #{quantity_phrase(is_negated)}but it executed #{times(times_executed)}" +
|
57
|
+
self.class.executed_requests_message
|
59
58
|
end
|
60
59
|
|
61
60
|
def quantity_phrase(is_negated=false)
|
@@ -4,6 +4,10 @@ module WebMock
|
|
4
4
|
def rSpecHashIncludingMatcher?(matcher)
|
5
5
|
matcher.class.name =~ /R?Spec::Mocks::ArgumentMatchers::HashIncludingMatcher/
|
6
6
|
end
|
7
|
+
|
8
|
+
def rSpecHashExcludingMatcher?(matcher)
|
9
|
+
matcher.class.name =~ /R?Spec::Mocks::ArgumentMatchers::HashExcludingMatcher/
|
10
|
+
end
|
7
11
|
end
|
8
12
|
|
9
13
|
class RequestPattern
|
@@ -37,7 +41,7 @@ module WebMock
|
|
37
41
|
end
|
38
42
|
|
39
43
|
def to_s
|
40
|
-
string = "#{@method_pattern.to_s.upcase}"
|
44
|
+
string = "#{@method_pattern.to_s.upcase}".dup
|
41
45
|
string << " #{@uri_pattern.to_s}"
|
42
46
|
string << " with body #{@body_pattern.to_s}" if @body_pattern
|
43
47
|
string << " with headers #{@headers_pattern.to_s}" if @headers_pattern
|
@@ -115,10 +119,13 @@ module WebMock
|
|
115
119
|
def add_query_params(query_params)
|
116
120
|
@query_params = if query_params.is_a?(Hash)
|
117
121
|
query_params
|
118
|
-
elsif query_params.is_a?(WebMock::Matchers::HashIncludingMatcher)
|
122
|
+
elsif query_params.is_a?(WebMock::Matchers::HashIncludingMatcher) \
|
123
|
+
|| query_params.is_a?(WebMock::Matchers::HashExcludingMatcher)
|
119
124
|
query_params
|
120
125
|
elsif rSpecHashIncludingMatcher?(query_params)
|
121
126
|
WebMock::Matchers::HashIncludingMatcher.from_rspec_matcher(query_params)
|
127
|
+
elsif rSpecHashExcludingMatcher?(query_params)
|
128
|
+
WebMock::Matchers::HashExcludingMatcher.from_rspec_matcher(query_params)
|
122
129
|
else
|
123
130
|
WebMock::Util::QueryMapper.query_to_values(query_params, notation: Config.instance.query_values_notation)
|
124
131
|
end
|
@@ -23,7 +23,7 @@ module WebMock
|
|
23
23
|
if requested_signatures.hash.empty?
|
24
24
|
"No requests were made."
|
25
25
|
else
|
26
|
-
text = ""
|
26
|
+
text = "".dup
|
27
27
|
self.requested_signatures.each do |request_signature, times_executed|
|
28
28
|
text << "#{request_signature} was made #{times_executed} time#{times_executed == 1 ? '' : 's' }\n"
|
29
29
|
end
|
@@ -12,7 +12,7 @@ module WebMock
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def to_s
|
15
|
-
string = "#{self.method.to_s.upcase}"
|
15
|
+
string = "#{self.method.to_s.upcase}".dup
|
16
16
|
string << " #{WebMock::Util::URI.strip_default_port_from_uri_string(self.uri.to_s)}"
|
17
17
|
string << " with body '#{body.to_s}'" if body && body.to_s != ''
|
18
18
|
if headers && !headers.empty?
|
@@ -13,14 +13,14 @@ module WebMock
|
|
13
13
|
def stubbing_instructions
|
14
14
|
return unless WebMock.show_stubbing_instructions?
|
15
15
|
|
16
|
-
|
17
|
-
|
16
|
+
"You can stub this request with the following snippet:\n\n" +
|
17
|
+
WebMock::StubRequestSnippet.new(request_stub).to_s
|
18
18
|
end
|
19
19
|
|
20
20
|
def request_stubs
|
21
21
|
return if WebMock::StubRegistry.instance.request_stubs.empty?
|
22
22
|
|
23
|
-
text = "registered request stubs:\n"
|
23
|
+
text = "registered request stubs:\n".dup
|
24
24
|
WebMock::StubRegistry.instance.request_stubs.each do |stub|
|
25
25
|
text << "\n#{WebMock::StubRequestSnippet.new(stub).to_s(false)}"
|
26
26
|
add_body_diff(stub, text) if WebMock.show_body_diff?
|
@@ -50,7 +50,7 @@ module WebMock
|
|
50
50
|
end
|
51
51
|
|
52
52
|
def pretty_print_to_string(string_to_print)
|
53
|
-
StringIO.open("") do |stream|
|
53
|
+
StringIO.open("".dup) do |stream|
|
54
54
|
PP.pp(string_to_print, stream)
|
55
55
|
stream.rewind
|
56
56
|
stream.read
|