webmock 1.8.6 → 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.
Files changed (138) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/CI.yml +37 -0
  3. data/.gitignore +6 -0
  4. data/CHANGELOG.md +1198 -0
  5. data/Gemfile +3 -15
  6. data/README.md +761 -305
  7. data/Rakefile +13 -40
  8. data/lib/webmock/api.rb +63 -17
  9. data/lib/webmock/callback_registry.rb +1 -1
  10. data/lib/webmock/config.rb +8 -0
  11. data/lib/webmock/cucumber.rb +2 -0
  12. data/lib/webmock/errors.rb +8 -24
  13. data/lib/webmock/http_lib_adapters/async_http_client_adapter.rb +216 -0
  14. data/lib/webmock/http_lib_adapters/curb_adapter.rb +148 -84
  15. data/lib/webmock/http_lib_adapters/em_http_request_adapter.rb +224 -4
  16. data/lib/webmock/http_lib_adapters/excon_adapter.rb +104 -34
  17. data/lib/webmock/http_lib_adapters/http_rb/client.rb +17 -0
  18. data/lib/webmock/http_lib_adapters/http_rb/request.rb +16 -0
  19. data/lib/webmock/http_lib_adapters/http_rb/response.rb +64 -0
  20. data/lib/webmock/http_lib_adapters/http_rb/streamer.rb +29 -0
  21. data/lib/webmock/http_lib_adapters/http_rb/webmock.rb +68 -0
  22. data/lib/webmock/http_lib_adapters/http_rb_adapter.rb +37 -0
  23. data/lib/webmock/http_lib_adapters/httpclient_adapter.rb +152 -86
  24. data/lib/webmock/http_lib_adapters/manticore_adapter.rb +145 -0
  25. data/lib/webmock/http_lib_adapters/net_http.rb +155 -46
  26. data/lib/webmock/http_lib_adapters/net_http_response.rb +1 -1
  27. data/lib/webmock/http_lib_adapters/patron_adapter.rb +16 -15
  28. data/lib/webmock/http_lib_adapters/typhoeus_hydra_adapter.rb +76 -82
  29. data/lib/webmock/matchers/any_arg_matcher.rb +13 -0
  30. data/lib/webmock/matchers/hash_argument_matcher.rb +21 -0
  31. data/lib/webmock/matchers/hash_excluding_matcher.rb +15 -0
  32. data/lib/webmock/matchers/hash_including_matcher.rb +4 -12
  33. data/lib/webmock/minitest.rb +29 -3
  34. data/lib/webmock/rack_response.rb +14 -7
  35. data/lib/webmock/request_body_diff.rb +64 -0
  36. data/lib/webmock/request_execution_verifier.rb +38 -17
  37. data/lib/webmock/request_pattern.rb +158 -38
  38. data/lib/webmock/request_registry.rb +3 -3
  39. data/lib/webmock/request_signature.rb +7 -3
  40. data/lib/webmock/request_signature_snippet.rb +61 -0
  41. data/lib/webmock/request_stub.rb +9 -6
  42. data/lib/webmock/response.rb +30 -15
  43. data/lib/webmock/rspec/matchers/request_pattern_matcher.rb +38 -2
  44. data/lib/webmock/rspec/matchers/webmock_matcher.rb +23 -2
  45. data/lib/webmock/rspec/matchers.rb +0 -1
  46. data/lib/webmock/rspec.rb +11 -2
  47. data/lib/webmock/stub_registry.rb +31 -10
  48. data/lib/webmock/stub_request_snippet.rb +14 -6
  49. data/lib/webmock/test_unit.rb +4 -4
  50. data/lib/webmock/util/hash_counter.rb +20 -6
  51. data/lib/webmock/util/hash_keys_stringifier.rb +5 -3
  52. data/lib/webmock/util/hash_validator.rb +17 -0
  53. data/lib/webmock/util/headers.rb +23 -2
  54. data/lib/webmock/util/json.rb +20 -7
  55. data/lib/webmock/util/query_mapper.rb +281 -0
  56. data/lib/webmock/util/uri.rb +29 -19
  57. data/lib/webmock/util/values_stringifier.rb +20 -0
  58. data/lib/webmock/util/version_checker.rb +40 -2
  59. data/lib/webmock/version.rb +1 -1
  60. data/lib/webmock/webmock.rb +56 -17
  61. data/lib/webmock.rb +56 -46
  62. data/minitest/test_helper.rb +8 -3
  63. data/minitest/test_webmock.rb +4 -1
  64. data/minitest/webmock_spec.rb +16 -6
  65. data/spec/acceptance/async_http_client/async_http_client_spec.rb +375 -0
  66. data/spec/acceptance/async_http_client/async_http_client_spec_helper.rb +73 -0
  67. data/spec/acceptance/curb/curb_spec.rb +227 -68
  68. data/spec/acceptance/curb/curb_spec_helper.rb +11 -8
  69. data/spec/acceptance/em_http_request/em_http_request_spec.rb +322 -28
  70. data/spec/acceptance/em_http_request/em_http_request_spec_helper.rb +15 -10
  71. data/spec/acceptance/excon/excon_spec.rb +66 -4
  72. data/spec/acceptance/excon/excon_spec_helper.rb +21 -7
  73. data/spec/acceptance/http_rb/http_rb_spec.rb +93 -0
  74. data/spec/acceptance/http_rb/http_rb_spec_helper.rb +54 -0
  75. data/spec/acceptance/httpclient/httpclient_spec.rb +152 -11
  76. data/spec/acceptance/httpclient/httpclient_spec_helper.rb +25 -16
  77. data/spec/acceptance/manticore/manticore_spec.rb +107 -0
  78. data/spec/acceptance/manticore/manticore_spec_helper.rb +35 -0
  79. data/spec/acceptance/net_http/net_http_shared.rb +52 -24
  80. data/spec/acceptance/net_http/net_http_spec.rb +164 -50
  81. data/spec/acceptance/net_http/net_http_spec_helper.rb +19 -10
  82. data/spec/acceptance/net_http/real_net_http_spec.rb +1 -1
  83. data/spec/acceptance/patron/patron_spec.rb +29 -40
  84. data/spec/acceptance/patron/patron_spec_helper.rb +15 -11
  85. data/spec/acceptance/shared/allowing_and_disabling_net_connect.rb +229 -58
  86. data/spec/acceptance/shared/callbacks.rb +32 -30
  87. data/spec/acceptance/shared/complex_cross_concern_behaviors.rb +20 -5
  88. data/spec/acceptance/shared/enabling_and_disabling_webmock.rb +14 -14
  89. data/spec/acceptance/shared/precedence_of_stubs.rb +6 -6
  90. data/spec/acceptance/shared/request_expectations.rb +560 -296
  91. data/spec/acceptance/shared/returning_declared_responses.rb +180 -138
  92. data/spec/acceptance/shared/stubbing_requests.rb +385 -154
  93. data/spec/acceptance/typhoeus/typhoeus_hydra_spec.rb +78 -17
  94. data/spec/acceptance/typhoeus/typhoeus_hydra_spec_helper.rb +19 -15
  95. data/spec/acceptance/webmock_shared.rb +2 -2
  96. data/spec/fixtures/test.txt +1 -0
  97. data/spec/quality_spec.rb +27 -3
  98. data/spec/spec_helper.rb +11 -20
  99. data/spec/support/failures.rb +9 -0
  100. data/spec/support/my_rack_app.rb +8 -3
  101. data/spec/support/network_connection.rb +7 -13
  102. data/spec/support/webmock_server.rb +8 -3
  103. data/spec/unit/api_spec.rb +175 -0
  104. data/spec/unit/errors_spec.rb +116 -19
  105. data/spec/unit/http_lib_adapters/http_lib_adapter_registry_spec.rb +1 -1
  106. data/spec/unit/http_lib_adapters/http_lib_adapter_spec.rb +2 -2
  107. data/spec/unit/matchers/hash_excluding_matcher_spec.rb +61 -0
  108. data/spec/unit/matchers/hash_including_matcher_spec.rb +87 -0
  109. data/spec/unit/rack_response_spec.rb +54 -16
  110. data/spec/unit/request_body_diff_spec.rb +90 -0
  111. data/spec/unit/request_execution_verifier_spec.rb +147 -39
  112. data/spec/unit/request_pattern_spec.rb +462 -198
  113. data/spec/unit/request_registry_spec.rb +29 -9
  114. data/spec/unit/request_signature_snippet_spec.rb +89 -0
  115. data/spec/unit/request_signature_spec.rb +91 -49
  116. data/spec/unit/request_stub_spec.rb +71 -70
  117. data/spec/unit/response_spec.rb +100 -81
  118. data/spec/unit/stub_registry_spec.rb +37 -20
  119. data/spec/unit/stub_request_snippet_spec.rb +51 -31
  120. data/spec/unit/util/hash_counter_spec.rb +6 -6
  121. data/spec/unit/util/hash_keys_stringifier_spec.rb +4 -4
  122. data/spec/unit/util/headers_spec.rb +4 -4
  123. data/spec/unit/util/json_spec.rb +29 -3
  124. data/spec/unit/util/query_mapper_spec.rb +157 -0
  125. data/spec/unit/util/uri_spec.rb +150 -36
  126. data/spec/unit/util/version_checker_spec.rb +15 -9
  127. data/spec/unit/webmock_spec.rb +57 -4
  128. data/test/http_request.rb +3 -3
  129. data/test/shared_test.rb +45 -13
  130. data/test/test_helper.rb +1 -1
  131. data/test/test_webmock.rb +6 -0
  132. data/webmock.gemspec +30 -11
  133. metadata +308 -199
  134. data/.rvmrc +0 -1
  135. data/.travis.yml +0 -11
  136. data/Guardfile +0 -24
  137. data/lib/webmock/http_lib_adapters/em_http_request/em_http_request_0_x.rb +0 -151
  138. data/lib/webmock/http_lib_adapters/em_http_request/em_http_request_1_x.rb +0 -210
data/Guardfile DELETED
@@ -1,24 +0,0 @@
1
- # A sample Guardfile
2
- # More info at https://github.com/guard/guard#readme
3
-
4
- # rubies = %w[
5
- # 1.8.6
6
- # 1.8.7
7
- # 1.9.2
8
- # ree
9
- # jruby
10
- # ].map { |ruby| "#{ruby}@webmock" }
11
-
12
- rspec_options = {
13
- # :rvm => rubies,
14
- :all_on_start => false,
15
- :notification => false,
16
- :cli => '--color',
17
- :version => 2
18
- }
19
-
20
- guard 'rspec', rspec_options do
21
- watch(%r{^spec/.+_spec\.rb})
22
- watch(%r{^lib/(.+)\.rb}) { |m| "spec/lib/#{m[1]}_spec.rb" }
23
- watch('spec/spec_helper.rb') { "spec" }
24
- end
@@ -1,151 +0,0 @@
1
- if defined?(EventMachine::HttpRequest)
2
- module WebMock
3
- module HttpLibAdapters
4
- class EmHttpRequestAdapter < HttpLibAdapter
5
- adapter_for :em_http_request
6
-
7
- OriginalHttpRequest = EventMachine::HttpRequest unless const_defined?(:OriginalHttpRequest)
8
-
9
- def self.enable!
10
- EventMachine.send(:remove_const, :HttpRequest)
11
- EventMachine.send(:const_set, :HttpRequest, EventMachine::WebMockHttpRequest)
12
- end
13
-
14
- def self.disable!
15
- EventMachine.send(:remove_const, :HttpRequest)
16
- EventMachine.send(:const_set, :HttpRequest, OriginalHttpRequest)
17
- end
18
- end
19
- end
20
- end
21
-
22
-
23
- module EventMachine
24
- class WebMockHttpRequest < EventMachine::HttpRequest
25
-
26
- include HttpEncoding
27
-
28
- class WebMockHttpClient < EventMachine::HttpClient
29
-
30
- def setup(response, uri, error = nil)
31
- @last_effective_url = @uri = uri
32
- if error
33
- on_error(error)
34
- fail(self)
35
- else
36
- EM.next_tick do
37
- receive_data(response)
38
- succeed(self)
39
- end
40
- end
41
- end
42
-
43
- def unbind
44
- end
45
-
46
- def close_connection
47
- end
48
- end
49
-
50
- def send_request_with_webmock(&block)
51
- request_signature = build_request_signature
52
-
53
- WebMock::RequestRegistry.instance.requested_signatures.put(request_signature)
54
-
55
- if webmock_response = WebMock::StubRegistry.instance.response_for_request(request_signature)
56
- WebMock::CallbackRegistry.invoke_callbacks(
57
- {:lib => :em_http_request}, request_signature, webmock_response)
58
- client = WebMockHttpClient.new(nil)
59
- client.on_error("WebMock timeout error") if webmock_response.should_timeout
60
- client.setup(make_raw_response(webmock_response), @uri,
61
- webmock_response.should_timeout ? "WebMock timeout error" : nil)
62
- client
63
- elsif WebMock.net_connect_allowed?(request_signature.uri)
64
- http = send_request_without_webmock(&block)
65
- http.callback {
66
- if WebMock::CallbackRegistry.any_callbacks?
67
- webmock_response = build_webmock_response(http)
68
- WebMock::CallbackRegistry.invoke_callbacks(
69
- {:lib => :em_http_request, :real_request => true}, request_signature,
70
- webmock_response)
71
- end
72
- }
73
- http
74
- else
75
- raise WebMock::NetConnectNotAllowedError.new(request_signature)
76
- end
77
- end
78
-
79
- alias_method :send_request_without_webmock, :send_request
80
- alias_method :send_request, :send_request_with_webmock
81
-
82
-
83
- private
84
-
85
- def build_webmock_response(http)
86
- webmock_response = WebMock::Response.new
87
- webmock_response.status = [http.response_header.status, http.response_header.http_reason]
88
- webmock_response.headers = http.response_header
89
- webmock_response.body = http.response
90
- webmock_response
91
- end
92
-
93
- def build_request_signature
94
- if @req
95
- options = @req.options
96
- method = @req.method
97
- uri = @req.uri
98
- else
99
- options = @options
100
- method = @method
101
- uri = @uri
102
- end
103
-
104
- if options[:authorization] || options['authorization']
105
- auth = (options[:authorization] || options['authorization'])
106
- userinfo = auth.join(':')
107
- userinfo = WebMock::Util::URI.encode_unsafe_chars_in_userinfo(userinfo)
108
- options.reject! {|k,v| k.to_s == 'authorization' } #we added it to url userinfo
109
- uri.userinfo = userinfo
110
- end
111
-
112
- uri.query = encode_query(@req.uri, options[:query]).slice(/\?(.*)/, 1)
113
-
114
- body = options[:body] || options['body']
115
- body = form_encode_body(body) if body.is_a?(Hash)
116
-
117
- WebMock::RequestSignature.new(
118
- method.downcase.to_sym,
119
- uri.to_s,
120
- :body => body,
121
- :headers => (options[:head] || options['head'])
122
- )
123
- end
124
-
125
-
126
- def make_raw_response(response)
127
- response.raise_error_if_any
128
-
129
- status, headers, body = response.status, response.headers, response.body
130
-
131
- response_string = []
132
- response_string << "HTTP/1.1 #{status[0]} #{status[1]}"
133
-
134
- headers.each do |header, value|
135
- value = value.join(", ") if value.is_a?(Array)
136
-
137
- # WebMock's internal processing will not handle the body
138
- # correctly if the header indicates that it is chunked, unless
139
- # we also create all the chunks.
140
- # It's far easier just to remove the header.
141
- next if header =~ /transfer-encoding/i && value =~/chunked/i
142
-
143
- response_string << "#{header}: #{value}"
144
- end if headers
145
-
146
- response_string << "" << body
147
- response_string.join("\n")
148
- end
149
- end
150
- end
151
- end
@@ -1,210 +0,0 @@
1
- if defined?(EventMachine::HttpClient)
2
- module WebMock
3
- module HttpLibAdapters
4
- class EmHttpRequestAdapter < HttpLibAdapter
5
- adapter_for :em_http_request
6
-
7
- OriginalHttpClient = EventMachine::HttpClient unless const_defined?(:OriginalHttpClient)
8
- OriginalHttpConnection = EventMachine::HttpConnection unless const_defined?(:OriginalHttpConnection)
9
-
10
-
11
- def self.enable!
12
- EventMachine.send(:remove_const, :HttpConnection)
13
- EventMachine.send(:const_set, :HttpConnection, EventMachine::WebMockHttpConnection)
14
- EventMachine.send(:remove_const, :HttpClient)
15
- EventMachine.send(:const_set, :HttpClient, EventMachine::WebMockHttpClient)
16
- end
17
-
18
- def self.disable!
19
- EventMachine.send(:remove_const, :HttpConnection)
20
- EventMachine.send(:const_set, :HttpConnection, OriginalHttpConnection)
21
- EventMachine.send(:remove_const, :HttpClient)
22
- EventMachine.send(:const_set, :HttpClient, OriginalHttpClient)
23
- end
24
- end
25
- end
26
- end
27
-
28
- module EventMachine
29
-
30
- if defined?(Synchrony) && HTTPMethods.instance_methods.include?(:aget)
31
- # have to make the callbacks fire on the next tick in order
32
- # to avoid the dreaded "double resume" exception
33
- module HTTPMethods
34
- %w[get head post delete put].each do |type|
35
- class_eval %[
36
- def #{type}(options = {}, &blk)
37
- f = Fiber.current
38
-
39
- conn = setup_request(:#{type}, options, &blk)
40
- conn.callback { EM.next_tick { f.resume(conn) } }
41
- conn.errback { EM.next_tick { f.resume(conn) } }
42
-
43
- Fiber.yield
44
- end
45
- ]
46
- end
47
- end
48
- end
49
-
50
- class WebMockHttpConnection < HttpConnection
51
- def webmock_activate_connection(client)
52
- request_signature = client.request_signature
53
-
54
- if client.stubbed_webmock_response
55
- conn = HttpStubConnection.new rand(10000)
56
- post_init
57
-
58
- @deferred = false
59
- @conn = conn
60
-
61
- conn.parent = self
62
- conn.pending_connect_timeout = @connopts.connect_timeout
63
- conn.comm_inactivity_timeout = @connopts.inactivity_timeout
64
-
65
- finalize_request(client)
66
- @conn.set_deferred_status :succeeded
67
- elsif WebMock.net_connect_allowed?(request_signature.uri)
68
- real_activate_connection(client)
69
- else
70
- raise WebMock::NetConnectNotAllowedError.new(request_signature)
71
- end
72
- end
73
- alias_method :real_activate_connection, :activate_connection
74
- alias_method :activate_connection, :webmock_activate_connection
75
- end
76
-
77
- class WebMockHttpClient < EventMachine::HttpClient
78
- include HttpEncoding
79
-
80
- def uri
81
- @req.uri
82
- end
83
-
84
- def setup(response, uri, error = nil)
85
- @last_effective_url = @uri = uri
86
- if error
87
- on_error(error)
88
- fail(self)
89
- else
90
- @conn.receive_data(response)
91
- succeed(self)
92
- end
93
- end
94
-
95
- def send_request_with_webmock(head, body)
96
- WebMock::RequestRegistry.instance.requested_signatures.put(request_signature)
97
-
98
- if stubbed_webmock_response
99
- on_error("WebMock timeout error") if stubbed_webmock_response.should_timeout
100
- WebMock::CallbackRegistry.invoke_callbacks({:lib => :em_http_request}, request_signature, stubbed_webmock_response)
101
- EM.next_tick {
102
- setup(make_raw_response(stubbed_webmock_response), @uri,
103
- stubbed_webmock_response.should_timeout ? "WebMock timeout error" : nil)
104
- }
105
- self
106
- elsif WebMock.net_connect_allowed?(request_signature.uri)
107
- send_request_without_webmock(head, body)
108
- callback {
109
- if WebMock::CallbackRegistry.any_callbacks?
110
- webmock_response = build_webmock_response
111
- WebMock::CallbackRegistry.invoke_callbacks(
112
- {:lib => :em_http_request, :real_request => true},
113
- request_signature,
114
- webmock_response)
115
- end
116
- }
117
- self
118
- else
119
- raise WebMock::NetConnectNotAllowedError.new(request_signature)
120
- end
121
- end
122
-
123
- alias_method :send_request_without_webmock, :send_request
124
- alias_method :send_request, :send_request_with_webmock
125
-
126
- def request_signature
127
- @request_signature ||= build_request_signature
128
- end
129
-
130
- def stubbed_webmock_response
131
- unless defined?(@stubbed_webmock_response)
132
- @stubbed_webmock_response = WebMock::StubRegistry.instance.response_for_request(request_signature)
133
- end
134
-
135
- @stubbed_webmock_response
136
- end
137
-
138
- private
139
-
140
- def build_webmock_response
141
- webmock_response = WebMock::Response.new
142
- webmock_response.status = [response_header.status, response_header.http_reason]
143
- webmock_response.headers = response_header
144
- webmock_response.body = response
145
- webmock_response
146
- end
147
-
148
- def build_request_signature
149
- headers, body = @req.headers, @req.body
150
-
151
- @conn.middleware.select {|m| m.respond_to?(:request) }.each do |m|
152
- headers, body = m.request(self, headers, body)
153
- end
154
-
155
- method = @req.method
156
- uri = @req.uri
157
- auth = @req.proxy[:authorization] if @req.proxy
158
- query = @req.query
159
-
160
- if auth
161
- userinfo = auth.join(':')
162
- userinfo = WebMock::Util::URI.encode_unsafe_chars_in_userinfo(userinfo)
163
- if @req
164
- @req.proxy.reject! {|k,v| t.to_s == 'authorization' }
165
- else
166
- options.reject! {|k,v| k.to_s == 'authorization' } #we added it to url userinfo
167
- end
168
- uri.userinfo = userinfo
169
- end
170
-
171
- uri.query = encode_query(@req.uri, query).slice(/\?(.*)/, 1)
172
-
173
- body = form_encode_body(body) if body.is_a?(Hash)
174
-
175
- WebMock::RequestSignature.new(
176
- method.downcase.to_sym,
177
- uri.to_s,
178
- :body => body,
179
- :headers => headers
180
- )
181
- end
182
-
183
- def make_raw_response(response)
184
- response.raise_error_if_any
185
-
186
- status, headers, body = response.status, response.headers, response.body
187
- headers ||= {}
188
-
189
- response_string = []
190
- response_string << "HTTP/1.1 #{status[0]} #{status[1]}"
191
-
192
- headers["Content-Length"] = body.bytesize unless headers["Content-Length"]
193
- headers.each do |header, value|
194
- value = value.join(", ") if value.is_a?(Array)
195
-
196
- # WebMock's internal processing will not handle the body
197
- # correctly if the header indicates that it is chunked, unless
198
- # we also create all the chunks.
199
- # It's far easier just to remove the header.
200
- next if header =~ /transfer-encoding/i && value =~/chunked/i
201
-
202
- response_string << "#{header}: #{value}"
203
- end if headers
204
-
205
- response_string << "" << body
206
- response_string.join("\n")
207
- end
208
- end
209
- end
210
- end