webmock 3.7.1

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 (142) hide show
  1. checksums.yaml +7 -0
  2. data/.gemtest +0 -0
  3. data/.gitignore +34 -0
  4. data/.rspec-tm +2 -0
  5. data/.travis.yml +19 -0
  6. data/CHANGELOG.md +1698 -0
  7. data/Gemfile +9 -0
  8. data/LICENSE +20 -0
  9. data/README.md +1125 -0
  10. data/Rakefile +28 -0
  11. data/lib/webmock.rb +59 -0
  12. data/lib/webmock/api.rb +109 -0
  13. data/lib/webmock/assertion_failure.rb +11 -0
  14. data/lib/webmock/callback_registry.rb +35 -0
  15. data/lib/webmock/config.rb +18 -0
  16. data/lib/webmock/cucumber.rb +10 -0
  17. data/lib/webmock/deprecation.rb +9 -0
  18. data/lib/webmock/errors.rb +17 -0
  19. data/lib/webmock/http_lib_adapters/async_http_client_adapter.rb +214 -0
  20. data/lib/webmock/http_lib_adapters/curb_adapter.rb +347 -0
  21. data/lib/webmock/http_lib_adapters/em_http_request_adapter.rb +228 -0
  22. data/lib/webmock/http_lib_adapters/excon_adapter.rb +162 -0
  23. data/lib/webmock/http_lib_adapters/http_lib_adapter.rb +7 -0
  24. data/lib/webmock/http_lib_adapters/http_lib_adapter_registry.rb +19 -0
  25. data/lib/webmock/http_lib_adapters/http_rb/client.rb +14 -0
  26. data/lib/webmock/http_lib_adapters/http_rb/request.rb +16 -0
  27. data/lib/webmock/http_lib_adapters/http_rb/response.rb +43 -0
  28. data/lib/webmock/http_lib_adapters/http_rb/streamer.rb +29 -0
  29. data/lib/webmock/http_lib_adapters/http_rb/webmock.rb +68 -0
  30. data/lib/webmock/http_lib_adapters/http_rb_adapter.rb +37 -0
  31. data/lib/webmock/http_lib_adapters/httpclient_adapter.rb +242 -0
  32. data/lib/webmock/http_lib_adapters/manticore_adapter.rb +130 -0
  33. data/lib/webmock/http_lib_adapters/net_http.rb +361 -0
  34. data/lib/webmock/http_lib_adapters/net_http_response.rb +34 -0
  35. data/lib/webmock/http_lib_adapters/patron_adapter.rb +130 -0
  36. data/lib/webmock/http_lib_adapters/typhoeus_hydra_adapter.rb +174 -0
  37. data/lib/webmock/matchers/any_arg_matcher.rb +13 -0
  38. data/lib/webmock/matchers/hash_argument_matcher.rb +21 -0
  39. data/lib/webmock/matchers/hash_excluding_matcher.rb +15 -0
  40. data/lib/webmock/matchers/hash_including_matcher.rb +17 -0
  41. data/lib/webmock/minitest.rb +41 -0
  42. data/lib/webmock/rack_response.rb +69 -0
  43. data/lib/webmock/request_body_diff.rb +64 -0
  44. data/lib/webmock/request_execution_verifier.rb +77 -0
  45. data/lib/webmock/request_pattern.rb +370 -0
  46. data/lib/webmock/request_registry.rb +35 -0
  47. data/lib/webmock/request_signature.rb +54 -0
  48. data/lib/webmock/request_signature_snippet.rb +61 -0
  49. data/lib/webmock/request_stub.rb +100 -0
  50. data/lib/webmock/response.rb +153 -0
  51. data/lib/webmock/responses_sequence.rb +40 -0
  52. data/lib/webmock/rspec.rb +41 -0
  53. data/lib/webmock/rspec/matchers.rb +27 -0
  54. data/lib/webmock/rspec/matchers/request_pattern_matcher.rb +78 -0
  55. data/lib/webmock/rspec/matchers/webmock_matcher.rb +67 -0
  56. data/lib/webmock/stub_registry.rb +67 -0
  57. data/lib/webmock/stub_request_snippet.rb +38 -0
  58. data/lib/webmock/test_unit.rb +22 -0
  59. data/lib/webmock/util/hash_counter.rb +39 -0
  60. data/lib/webmock/util/hash_keys_stringifier.rb +25 -0
  61. data/lib/webmock/util/hash_validator.rb +17 -0
  62. data/lib/webmock/util/headers.rb +64 -0
  63. data/lib/webmock/util/json.rb +67 -0
  64. data/lib/webmock/util/query_mapper.rb +281 -0
  65. data/lib/webmock/util/uri.rb +110 -0
  66. data/lib/webmock/util/values_stringifier.rb +20 -0
  67. data/lib/webmock/util/version_checker.rb +111 -0
  68. data/lib/webmock/version.rb +3 -0
  69. data/lib/webmock/webmock.rb +161 -0
  70. data/minitest/test_helper.rb +34 -0
  71. data/minitest/test_webmock.rb +9 -0
  72. data/minitest/webmock_spec.rb +60 -0
  73. data/spec/acceptance/async_http_client/async_http_client_spec.rb +349 -0
  74. data/spec/acceptance/async_http_client/async_http_client_spec_helper.rb +73 -0
  75. data/spec/acceptance/curb/curb_spec.rb +492 -0
  76. data/spec/acceptance/curb/curb_spec_helper.rb +147 -0
  77. data/spec/acceptance/em_http_request/em_http_request_spec.rb +406 -0
  78. data/spec/acceptance/em_http_request/em_http_request_spec_helper.rb +77 -0
  79. data/spec/acceptance/excon/excon_spec.rb +77 -0
  80. data/spec/acceptance/excon/excon_spec_helper.rb +50 -0
  81. data/spec/acceptance/http_rb/http_rb_spec.rb +82 -0
  82. data/spec/acceptance/http_rb/http_rb_spec_helper.rb +54 -0
  83. data/spec/acceptance/httpclient/httpclient_spec.rb +217 -0
  84. data/spec/acceptance/httpclient/httpclient_spec_helper.rb +57 -0
  85. data/spec/acceptance/manticore/manticore_spec.rb +56 -0
  86. data/spec/acceptance/manticore/manticore_spec_helper.rb +35 -0
  87. data/spec/acceptance/net_http/net_http_shared.rb +153 -0
  88. data/spec/acceptance/net_http/net_http_spec.rb +331 -0
  89. data/spec/acceptance/net_http/net_http_spec_helper.rb +64 -0
  90. data/spec/acceptance/net_http/real_net_http_spec.rb +20 -0
  91. data/spec/acceptance/patron/patron_spec.rb +125 -0
  92. data/spec/acceptance/patron/patron_spec_helper.rb +54 -0
  93. data/spec/acceptance/shared/allowing_and_disabling_net_connect.rb +313 -0
  94. data/spec/acceptance/shared/callbacks.rb +148 -0
  95. data/spec/acceptance/shared/complex_cross_concern_behaviors.rb +36 -0
  96. data/spec/acceptance/shared/enabling_and_disabling_webmock.rb +95 -0
  97. data/spec/acceptance/shared/precedence_of_stubs.rb +15 -0
  98. data/spec/acceptance/shared/request_expectations.rb +930 -0
  99. data/spec/acceptance/shared/returning_declared_responses.rb +409 -0
  100. data/spec/acceptance/shared/stubbing_requests.rb +643 -0
  101. data/spec/acceptance/typhoeus/typhoeus_hydra_spec.rb +135 -0
  102. data/spec/acceptance/typhoeus/typhoeus_hydra_spec_helper.rb +60 -0
  103. data/spec/acceptance/webmock_shared.rb +41 -0
  104. data/spec/fixtures/test.txt +1 -0
  105. data/spec/quality_spec.rb +84 -0
  106. data/spec/spec_helper.rb +48 -0
  107. data/spec/support/example_curl_output.txt +22 -0
  108. data/spec/support/failures.rb +9 -0
  109. data/spec/support/my_rack_app.rb +53 -0
  110. data/spec/support/network_connection.rb +19 -0
  111. data/spec/support/webmock_server.rb +70 -0
  112. data/spec/unit/api_spec.rb +175 -0
  113. data/spec/unit/errors_spec.rb +129 -0
  114. data/spec/unit/http_lib_adapters/http_lib_adapter_registry_spec.rb +17 -0
  115. data/spec/unit/http_lib_adapters/http_lib_adapter_spec.rb +12 -0
  116. data/spec/unit/matchers/hash_excluding_matcher_spec.rb +61 -0
  117. data/spec/unit/matchers/hash_including_matcher_spec.rb +87 -0
  118. data/spec/unit/rack_response_spec.rb +112 -0
  119. data/spec/unit/request_body_diff_spec.rb +90 -0
  120. data/spec/unit/request_execution_verifier_spec.rb +208 -0
  121. data/spec/unit/request_pattern_spec.rb +601 -0
  122. data/spec/unit/request_registry_spec.rb +95 -0
  123. data/spec/unit/request_signature_snippet_spec.rb +89 -0
  124. data/spec/unit/request_signature_spec.rb +155 -0
  125. data/spec/unit/request_stub_spec.rb +199 -0
  126. data/spec/unit/response_spec.rb +282 -0
  127. data/spec/unit/stub_registry_spec.rb +103 -0
  128. data/spec/unit/stub_request_snippet_spec.rb +115 -0
  129. data/spec/unit/util/hash_counter_spec.rb +39 -0
  130. data/spec/unit/util/hash_keys_stringifier_spec.rb +27 -0
  131. data/spec/unit/util/headers_spec.rb +28 -0
  132. data/spec/unit/util/json_spec.rb +33 -0
  133. data/spec/unit/util/query_mapper_spec.rb +157 -0
  134. data/spec/unit/util/uri_spec.rb +361 -0
  135. data/spec/unit/util/version_checker_spec.rb +65 -0
  136. data/spec/unit/webmock_spec.rb +19 -0
  137. data/test/http_request.rb +24 -0
  138. data/test/shared_test.rb +108 -0
  139. data/test/test_helper.rb +23 -0
  140. data/test/test_webmock.rb +6 -0
  141. data/webmock.gemspec +45 -0
  142. metadata +496 -0
@@ -0,0 +1,147 @@
1
+ require 'ostruct'
2
+
3
+ module CurbSpecHelper
4
+ def http_request(method, uri, options = {}, &block)
5
+ uri = Addressable::URI.heuristic_parse(uri)
6
+ body = options[:body]
7
+
8
+ curl = curb_http_request(uri, method, body, options)
9
+
10
+ status, response_headers =
11
+ WebMock::HttpLibAdapters::CurbAdapter.parse_header_string(curl.header_str)
12
+
13
+ # Deal with the fact that the HTTP spec allows multi-values headers
14
+ # to either be a single entry with a comma-separated listed of
15
+ # values, or multiple separate entries
16
+ response_headers.keys.each do |k|
17
+ v = response_headers[k]
18
+ if v.is_a?(Array)
19
+ response_headers[k] = v.join(', ')
20
+ end
21
+ end
22
+
23
+ OpenStruct.new(
24
+ body: curl.body_str,
25
+ headers: WebMock::Util::Headers.normalize_headers(response_headers),
26
+ status: curl.response_code.to_s,
27
+ message: status
28
+ )
29
+ end
30
+
31
+ def setup_request(uri, curl, options={})
32
+ curl ||= Curl::Easy.new
33
+ curl.url = uri.to_s
34
+ if options[:basic_auth]
35
+ curl.http_auth_types = :basic
36
+ curl.username = options[:basic_auth][0]
37
+ curl.password = options[:basic_auth][1]
38
+ end
39
+ curl.timeout = 30
40
+ curl.connect_timeout = 30
41
+
42
+ if headers = options[:headers]
43
+ headers.each {|k,v| curl.headers[k] = v }
44
+ end
45
+
46
+ curl
47
+ end
48
+
49
+ def client_timeout_exception_class
50
+ Curl::Err::TimeoutError
51
+ end
52
+
53
+ def connection_refused_exception_class
54
+ Curl::Err::ConnectionFailedError
55
+ end
56
+
57
+ def http_library
58
+ :curb
59
+ end
60
+
61
+ module DynamicHttp
62
+ def curb_http_request(uri, method, body, options)
63
+ curl = setup_request(uri, nil, options)
64
+
65
+ case method
66
+ when :post
67
+ curl.post_body = body
68
+ when :put
69
+ curl.put_data = body
70
+ end
71
+
72
+ curl.http(method.to_s.upcase)
73
+ curl
74
+ end
75
+ end
76
+
77
+ module NamedHttp
78
+ def curb_http_request(uri, method, body, options)
79
+ curl = setup_request(uri, nil, options)
80
+
81
+ case method
82
+ when :put, :post
83
+ curl.send( "http_#{method}", body )
84
+ else
85
+ curl.send( "http_#{method}" )
86
+ end
87
+ curl
88
+ end
89
+ end
90
+
91
+ module Perform
92
+ def curb_http_request(uri, method, body, options)
93
+ curl = setup_request(uri, nil, options)
94
+
95
+ case method
96
+ when :post
97
+ curl.post_body = body
98
+ when :put
99
+ curl.put_data = body
100
+ when :head
101
+ curl.head = true
102
+ when :delete
103
+ curl.delete = true
104
+ end
105
+
106
+ curl.perform
107
+ curl
108
+ end
109
+ end
110
+
111
+ module ClassNamedHttp
112
+ def curb_http_request(uri, method, body, options)
113
+ args = ["http_#{method}", uri]
114
+ args << body if method == :post || method == :put
115
+
116
+ c = Curl::Easy.send(*args) do |curl|
117
+ setup_request(uri, curl, options)
118
+ end
119
+
120
+ c
121
+ end
122
+ end
123
+
124
+ module ClassPerform
125
+ def curb_http_request(uri, method, body, options)
126
+ args = ["http_#{method}", uri]
127
+ args << body if method == :post || method == :put
128
+
129
+ c = Curl::Easy.send(*args) do |curl|
130
+ setup_request(uri, curl, options)
131
+
132
+ case method
133
+ when :post
134
+ curl.post_body = body
135
+ when :put
136
+ curl.put_data = body
137
+ when :head
138
+ curl.head = true
139
+ when :delete
140
+ curl.delete = true
141
+ end
142
+ end
143
+
144
+ c
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,406 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+ require 'acceptance/webmock_shared'
4
+ require 'ostruct'
5
+
6
+ unless RUBY_PLATFORM =~ /java/
7
+ require 'acceptance/em_http_request/em_http_request_spec_helper'
8
+
9
+ describe "EM::HttpRequest" do
10
+ include EMHttpRequestSpecHelper
11
+
12
+ include_context "with WebMock", :no_status_message
13
+
14
+ #functionality only supported for em-http-request 1.x
15
+ if defined?(EventMachine::HttpConnection)
16
+ context 'when a real request is made and redirects are followed', net_connect: true do
17
+ before { WebMock.allow_net_connect! }
18
+
19
+ # This url redirects to the https URL.
20
+ let(:http_url) { "http://raw.github.com:80/gist/fb555cb593f3349d53af/6921dd638337d3f6a51b0e02e7f30e3c414f70d6/vcr_gist" }
21
+ let(:https_url) { http_url.gsub('http', 'https').gsub('80', '443') }
22
+
23
+ def make_request
24
+ EM.run do
25
+ request = EM::HttpRequest.new(http_url).get(redirects: 1)
26
+ request.callback { EM.stop }
27
+ end
28
+ end
29
+
30
+ it "invokes the globally_stub_request hook with both requests" do
31
+ urls = []
32
+ WebMock.globally_stub_request { |r| urls << r.uri.to_s; nil }
33
+
34
+ make_request
35
+
36
+ expect(urls).to eq([http_url, https_url])
37
+ end
38
+
39
+ it 'invokes the after_request hook with both requests' do
40
+ urls = []
41
+ WebMock.after_request { |req, res| urls << req.uri.to_s }
42
+
43
+ make_request
44
+
45
+ expect(urls).to eq([http_url, https_url])
46
+ end
47
+ end
48
+
49
+ describe "with middleware" do
50
+
51
+ it "should work with request middleware" do
52
+ stub_request(:get, "www.example.com").with(body: 'bar')
53
+
54
+ middleware = Class.new do
55
+ def request(client, head, body)
56
+ [{}, 'bar']
57
+ end
58
+ end
59
+
60
+ EM.run do
61
+ conn = EventMachine::HttpRequest.new('http://www.example.com/')
62
+
63
+ conn.use middleware
64
+
65
+ http = conn.get(body: 'foo')
66
+
67
+ http.callback do
68
+ expect(WebMock).to have_requested(:get, "www.example.com").with(body: 'bar')
69
+ EM.stop
70
+ end
71
+ end
72
+ end
73
+
74
+ let(:response_middleware) do
75
+ Class.new do
76
+ def response(resp)
77
+ resp.response = 'bar'
78
+ end
79
+ end
80
+ end
81
+
82
+ it "should work with response middleware" do
83
+ stub_request(:get, "www.example.com").to_return(body: 'foo')
84
+
85
+ EM.run do
86
+ conn = EventMachine::HttpRequest.new('http://www.example.com/')
87
+
88
+ conn.use response_middleware
89
+
90
+ http = conn.get
91
+
92
+ http.callback do
93
+ expect(http.response).to eq('bar')
94
+ EM.stop
95
+ end
96
+ end
97
+ end
98
+
99
+ let(:webmock_server_url) { "http://#{WebMockServer.instance.host_with_port}/" }
100
+
101
+ shared_examples_for "em-http-request middleware/after_request hook integration" do
102
+ it 'yields the original raw body to the after_request hook even if a response middleware modifies the body' do
103
+ yielded_response_body = nil
104
+ ::WebMock.after_request do |request, response|
105
+ yielded_response_body = response.body
106
+ end
107
+
108
+ EM::HttpRequest.use response_middleware
109
+
110
+ EM.run do
111
+ http = EventMachine::HttpRequest.new(webmock_server_url).get
112
+ http.callback { EM.stop }
113
+ end
114
+
115
+ expect(yielded_response_body).to eq("hello world")
116
+ end
117
+ end
118
+
119
+ context 'making a real request', net_connect: true do
120
+ before { WebMock.allow_net_connect! }
121
+ include_examples "em-http-request middleware/after_request hook integration"
122
+ end
123
+
124
+ context 'when the request is stubbed' do
125
+ before { stub_request(:get, webmock_server_url).to_return(body: 'hello world') }
126
+ include_examples "em-http-request middleware/after_request hook integration"
127
+ end
128
+ end
129
+
130
+ it 'should trigger error callbacks asynchronously' do
131
+ stub_request(:get, 'www.example.com').to_timeout
132
+ called = false
133
+
134
+ EM.run do
135
+ conn = EventMachine::HttpRequest.new('http://www.example.com/')
136
+ http = conn.get
137
+ http.errback do
138
+ called = true
139
+ EM.stop
140
+ end
141
+ expect(called).to eq(false)
142
+ end
143
+
144
+ expect(called).to eq(true)
145
+ end
146
+
147
+ # not pretty, but it works
148
+ if defined?(EventMachine::Synchrony)
149
+ describe "with synchrony" do
150
+ let(:webmock_em_http) { File.expand_path(File.join(File.dirname(__FILE__), "../lib/webmock/http_lib_adapters/em_http_request/em_http_request_1_x.rb")) }
151
+
152
+ before(:each) do
153
+ # need to reload the webmock em-http adapter after we require synchrony
154
+ WebMock::HttpLibAdapters::EmHttpRequestAdapter.disable!
155
+ $".delete webmock_em_http
156
+ $".delete File.expand_path(File.join(File.dirname(__FILE__), "../../../lib/webmock/http_lib_adapters/em_http_request_adapter.rb"))
157
+ require 'em-synchrony'
158
+ require 'em-synchrony/em-http'
159
+ require File.expand_path(File.join(File.dirname(__FILE__), "../../../lib/webmock/http_lib_adapters/em_http_request_adapter.rb"))
160
+ end
161
+
162
+ it "should work" do
163
+ stub_request(:post, /.*.testserver.com*/).to_return(status: 200, body: 'ok')
164
+ expect {
165
+ EM.run do
166
+ fiber = Fiber.new do
167
+ EM::HttpRequest.new("http://www.testserver.com").post body: "foo=bar&baz=bang", timeout: 60
168
+ EM.stop
169
+ end
170
+ fiber.resume
171
+ end
172
+ }.not_to raise_error
173
+ end
174
+
175
+ after(:each) do
176
+ EM.send(:remove_const, :Synchrony)
177
+ EM.send(:remove_const, :HTTPMethods)
178
+ WebMock::HttpLibAdapters::EmHttpRequestAdapter.disable!
179
+ $".reject! {|path| path.include? "em-http-request"}
180
+ $".delete webmock_em_http
181
+ $".delete File.expand_path(File.join(File.dirname(__FILE__), "../../../lib/webmock/http_lib_adapters/em_http_request_adapter.rb"))
182
+ require 'em-http-request'
183
+ require File.expand_path(File.join(File.dirname(__FILE__), "../../../lib/webmock/http_lib_adapters/em_http_request_adapter.rb"))
184
+ end
185
+ end
186
+ end
187
+ end
188
+
189
+ it "should work with streaming" do
190
+ stub_request(:get, "www.example.com").to_return(body: "abc")
191
+ response = ""
192
+ EM.run {
193
+ http = EventMachine::HttpRequest.new('http://www.example.com/').get
194
+ http.stream { |chunk| response = chunk; EM.stop }
195
+ }
196
+ expect(response).to eq("abc")
197
+ end
198
+
199
+ it "should work with responses that use chunked transfer encoding" do
200
+ stub_request(:get, "www.example.com").to_return(body: "abc", headers: { 'Transfer-Encoding' => 'chunked' })
201
+ expect(http_request(:get, "http://www.example.com").body).to eq("abc")
202
+ end
203
+
204
+ it "should work with optional query params" do
205
+ stub_request(:get, "www.example.com/?x=3&a[]=b&a[]=c").to_return(body: "abc")
206
+ expect(http_request(:get, "http://www.example.com/?x=3", query: {"a" => ["b", "c"]}).body).to eq("abc")
207
+ end
208
+
209
+ it "should work with optional query params declared as string" do
210
+ stub_request(:get, "www.example.com/?x=3&a[]=b&a[]=c").to_return(body: "abc")
211
+ expect(http_request(:get, "http://www.example.com/?x=3", query: "a[]=b&a[]=c").body).to eq("abc")
212
+ end
213
+
214
+ it "should work when the body is passed as a Hash" do
215
+ stub_request(:post, "www.example.com").with(body: {a: "1", b: "2"}).to_return(body: "ok")
216
+ expect(http_request(:post, "http://www.example.com", body: {a: "1", b: "2"}).body).to eq("ok")
217
+ end
218
+
219
+ if defined?(EventMachine::HttpConnection)
220
+ it "should work when a file is passed as body" do
221
+ stub_request(:post, "www.example.com").with(body: File.read(__FILE__)).to_return(body: "ok")
222
+ expect(http_request(:post, "http://www.example.com", file: __FILE__).body).to eq("ok")
223
+ end
224
+ end
225
+
226
+ it "should work with UTF-8 strings" do
227
+ body = "Привет, Мир!"
228
+ stub_request(:post, "www.example.com").to_return(body: body)
229
+ expect(http_request(:post, "http://www.example.com").body.bytesize).to eq(body.bytesize)
230
+ end
231
+
232
+ it "should work with multiple requests to the same connection" do
233
+ stub_request(:get, "www.example.com/foo").to_return(body: "bar")
234
+ stub_request(:get, "www.example.com/baz").to_return(body: "wombat")
235
+ err1 = nil
236
+ err2 = nil
237
+ body1 = nil
238
+ body2 = nil
239
+ i = 0
240
+
241
+ EM.run do
242
+ conn = EM::HttpRequest.new("http://www.example.com")
243
+ conn.get(path: "/foo").callback do |resp|
244
+ body1 = resp.response
245
+ i += 1; EM.stop if i == 2
246
+ end.errback do |resp|
247
+ err1 = resp.error
248
+ i += 1; EM.stop if i == 2
249
+ end
250
+
251
+ conn.get(path: "/baz").callback do |resp|
252
+ body2 = resp.response
253
+ i += 1; EM.stop if i == 2
254
+ end.errback do |resp|
255
+ err2 = resp.error
256
+ i += 1; EM.stop if i == 2
257
+ end
258
+ end
259
+
260
+ expect(err1).to be(nil)
261
+ expect(err2).to be(nil)
262
+ expect(body1).to eq("bar")
263
+ expect(body2).to eq("wombat")
264
+ end
265
+
266
+ it "should work with multiple requests to the same connection when the first request times out" do
267
+ stub_request(:get, "www.example.com/foo").to_timeout.then.to_return(status: 200, body: "wombat")
268
+ err = nil
269
+ body = nil
270
+
271
+ EM.run do
272
+ conn = EM::HttpRequest.new("http://www.example.com")
273
+ conn.get(path: "/foo").callback do |resp|
274
+ err = :success_from_timeout
275
+ EM.stop
276
+ end.errback do |resp|
277
+ conn.get(path: "/foo").callback do |retry_resp|
278
+ expect(retry_resp.response_header.status).to eq(200)
279
+ body = retry_resp.response
280
+ EM.stop
281
+ end.errback do |retry_resp|
282
+ err = retry_resp.error
283
+ EM.stop
284
+ end
285
+ end
286
+ end
287
+
288
+ expect(err).to be(nil)
289
+ expect(body).to eq("wombat")
290
+ end
291
+
292
+ describe "mocking EM::HttpClient API" do
293
+ let(:uri) { "http://www.example.com/" }
294
+
295
+ before do
296
+ stub_request(:get, uri)
297
+ WebMock::HttpLibAdapters::EmHttpRequestAdapter.enable!
298
+ end
299
+
300
+ def client(uri, options = {})
301
+ client = nil
302
+ EM.run do
303
+ client = EventMachine::HttpRequest.new(uri).get(options)
304
+ client.callback { EM.stop }
305
+ client.errback { failed }
306
+ end
307
+ client
308
+ end
309
+
310
+ subject { client(uri) }
311
+
312
+ it 'should support #uri' do
313
+ expect(subject.uri).to eq(Addressable::URI.parse(uri))
314
+ end
315
+
316
+ it 'should support #last_effective_url' do
317
+ expect(subject.last_effective_url).to eq(Addressable::URI.parse(uri))
318
+ end
319
+
320
+ context "with a query" do
321
+ let(:uri) { "http://www.example.com/?a=1&b=2" }
322
+ subject { client("http://www.example.com/?a=1", query: { 'b' => 2 }) }
323
+
324
+ it "#request_signature doesn't mutate the original uri" do
325
+ expect(subject.uri).to eq(Addressable::URI.parse("http://www.example.com/?a=1"))
326
+ signature = WebMock::RequestRegistry.instance.requested_signatures.hash.keys.first
327
+ expect(signature.uri).to eq(Addressable::URI.parse(uri))
328
+ end
329
+ end
330
+
331
+ describe 'get_response_cookie' do
332
+
333
+ before(:each) do
334
+ stub_request(:get, "http://example.org/").
335
+ to_return(
336
+ status: 200,
337
+ body: "",
338
+ headers: { 'Set-Cookie' => cookie_string }
339
+ )
340
+ end
341
+
342
+ describe 'success' do
343
+
344
+ context 'with only one cookie' do
345
+
346
+ let(:cookie_name) { 'name_of_the_cookie' }
347
+ let(:cookie_value) { 'value_of_the_cookie' }
348
+ let(:cookie_string) { "#{cookie_name}=#{cookie_value}" }
349
+
350
+ it 'successfully gets the cookie' do
351
+ EM.run {
352
+ http = EventMachine::HttpRequest.new('http://example.org').get
353
+
354
+ http.errback { fail(http.error) }
355
+ http.callback {
356
+ expect(http.get_response_cookie(cookie_name)).to eq(cookie_value)
357
+ EM.stop
358
+ }
359
+ }
360
+ end
361
+ end
362
+
363
+ context 'with several cookies' do
364
+
365
+ let(:cookie_name) { 'name_of_the_cookie' }
366
+ let(:cookie_value) { 'value_of_the_cookie' }
367
+ let(:cookie_2_name) { 'name_of_the_2nd_cookie' }
368
+ let(:cookie_2_value) { 'value_of_the_2nd_cookie' }
369
+ let(:cookie_string) { %W(#{cookie_name}=#{cookie_value} #{cookie_2_name}=#{cookie_2_value}) }
370
+
371
+ it 'successfully gets both cookies' do
372
+ EM.run {
373
+ http = EventMachine::HttpRequest.new('http://example.org').get
374
+
375
+ http.errback { fail(http.error) }
376
+ http.callback {
377
+ expect(http.get_response_cookie(cookie_name)).to eq(cookie_value)
378
+ expect(http.get_response_cookie(cookie_2_name)).to eq(cookie_2_value)
379
+ EM.stop
380
+ }
381
+ }
382
+ end
383
+ end
384
+ end
385
+
386
+ describe 'failure' do
387
+
388
+ let(:cookie_string) { 'a=b' }
389
+
390
+ it 'returns nil when no cookie is found' do
391
+ EM.run {
392
+ http = EventMachine::HttpRequest.new('http://example.org').get
393
+
394
+ http.errback { fail(http.error) }
395
+ http.callback {
396
+ expect(http.get_response_cookie('not_found_cookie')).to eq(nil)
397
+ EM.stop
398
+ }
399
+ }
400
+ end
401
+ end
402
+ end
403
+ end
404
+
405
+ end
406
+ end