webmock 1.8.6 → 3.14.0

Sign up to get free protection for your applications and to get access to all the features.
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