webmock 3.9.1 → 3.10.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 57c2c81fa3eb74334f703d9f92eb11cea8b06f1c70b713fdee1a071a90e99744
4
- data.tar.gz: 96798ebd031599d59d06ff8d2457af877ba6d4a7e9d20ef9e464396c9104bc2c
3
+ metadata.gz: 18f78451e2de5c81e96da75d822f7bb1559f4c9f02e80a383758b9c4ef9be1c3
4
+ data.tar.gz: b245cfea73c1924eaeaad716c487f8548b392d120c28ff0f513da71a63d65944
5
5
  SHA512:
6
- metadata.gz: d6f0e72a1ecc925a006b9f781cb2e873a8dcafef0a6b80be74df2ad34bdb3eba0a9d02571f72fa825321da86d2a0afdbbdfb4b56e7c3b280bc1643b2acd76100
7
- data.tar.gz: 123fdca940fe7ea90b015cb6b085a063a00becef933df84335d1cf762780c12066590ab943c4cd5eba91bba4603f3663d4e8532ca374c036f5c0f306de03e28f
6
+ metadata.gz: 494e56d26e2d83828629de2901e0b1e0234a043261e19bd9080d4326e2812fc699cf7ee3817c8b86b3f99603a1a91918bd1d8474bba10fddefd6cf96565a7869
7
+ data.tar.gz: bb92e415f29748dbb63830bff8231607e599c0082d527513f4c02180dda83930fad830750978be6e59ed206122aeb77f7a48e4603e578fa26aa49f6b143087dd
@@ -1,8 +1,46 @@
1
1
  # Changelog
2
2
 
3
+ # 3.10.0
4
+
5
+ * Added option to global stubs to have lower priority than local stubs.
6
+
7
+ WebMock.globally_stub_request(:after_local_stubs) do
8
+ { body: "global stub body" }
9
+ end
10
+
11
+ stub_request(:get, "www.example.com").to_return(body: 'non-global stub body')
12
+
13
+ expect(http_request(:get, "http://www.example.com/").body).to eq("non-global stub body")
14
+
15
+ Thanks to [Marek Kasztelnik](https://github.com/mkasztelnik)
16
+
17
+ # 3.9.5
18
+
19
+ * Prevent overwriting `teardown` method in Test::Unit
20
+
21
+ Thanks to [Jesse Bowes](https://github.com/jessebs)
22
+
23
+ # 3.9.4
24
+
25
+ * More intuitive error message when stubbed response body was provided as Hash
26
+
27
+ Thanks to [Ben Koshy](https://github.com/BKSpurgeon)
28
+
29
+ # 3.9.3
30
+
31
+ * Make httpclient_adapter thread-safe
32
+
33
+ Thanks to [Adam Harwood](https://github.com/adam-harwood)
34
+
35
+ # 3.9.2
36
+
37
+ * Made global stubs thread-safe
38
+
39
+ Thanks to [Adam Harwood](https://github.com/adam-harwood)
40
+
3
41
  # 3.9.1
4
42
 
5
- Fixed support for passing `URI` objects as second argument of `stub_request`
43
+ * Fixed support for passing `URI` objects as second argument of `stub_request`
6
44
 
7
45
  Thanks to [Ryan Kerr](https://github.com/leboshi)
8
46
 
@@ -28,11 +66,11 @@
28
66
 
29
67
  * Fixed async-http adapter which caused Async::HTTP::Client or Async::HTTP::Internet to hang and never return a response.
30
68
 
31
- Thanks to (Bruno Sutic)[https://github.com/bruno-] and [Samuel Williams](https://github.com/ioquatix)
69
+ Thanks to [Bruno Sutic](https://github.com/bruno-) and [Samuel Williams](https://github.com/ioquatix)
32
70
 
33
71
  * Fixed warning when using async-http adapter
34
72
 
35
- Thanks to (Bruno Sutic)[https://github.com/bruno-]
73
+ Thanks to [Bruno Sutic](https://github.com/bruno-)
36
74
 
37
75
  * Dropped support for Ruby 2.3 - EOL date: 2019-03-31
38
76
 
@@ -40,7 +78,7 @@
40
78
 
41
79
  * Handling matching of Addressable::Template patterns that have an ip address without port and patterns that have ip address and don’t have schema and path.
42
80
 
43
- Thanks to (Rafael França)[https://github.com/rafaelfranca] and (guppy0356)[https://github.com/guppy0356]
81
+ Thanks to [Rafael França](https://github.com/rafaelfranca) and [guppy0356](https://github.com/guppy0356)
44
82
 
45
83
  ## 3.8.3
46
84
 
data/README.md CHANGED
@@ -24,16 +24,19 @@ Features
24
24
  Supported HTTP libraries
25
25
  ------------------------
26
26
 
27
- * Net::HTTP and libraries based on Net::HTTP (i.e RightHttpConnection, REST Client, HTTParty)
28
- * HTTPClient
29
- * Patron
30
- * EM-HTTP-Request
27
+ * Async::HTTP::Client
31
28
  * Curb (currently only Curb::Easy)
32
- * Typhoeus (currently only Typhoeus::Hydra)
29
+ * EM-HTTP-Request
33
30
  * Excon
34
- * HTTP Gem
31
+ * HTTPClient
32
+ * [HTTP Gem (also known as http.rb)](https://github.com/httprb/http)
35
33
  * Manticore
36
- * Async::HTTP::Client
34
+ * Net::HTTP and other libraries based on Net::HTTP, e.g.:
35
+ * HTTParty
36
+ * REST Client
37
+ * RightHttpConnection
38
+ * Patron
39
+ * Typhoeus (currently only Typhoeus::Hydra)
37
40
 
38
41
  Supported Ruby Interpreters
39
42
  ---------------------------
@@ -46,7 +49,17 @@ Supported Ruby Interpreters
46
49
 
47
50
  ## Installation
48
51
 
52
+ ```bash
49
53
  gem install webmock
54
+ ```
55
+ or alternatively:
56
+
57
+ ```ruby
58
+ # add to your Gemfile
59
+ group :test do
60
+ gem "webmock"
61
+ end
62
+ ```
50
63
 
51
64
  ### or to install the latest development version from github master
52
65
 
@@ -58,36 +71,36 @@ Supported Ruby Interpreters
58
71
 
59
72
  WebMock 2.x has changed somewhat since version 1.x. Changes are listed in [CHANGELOG.md](CHANGELOG.md)
60
73
 
61
- ### Test::Unit
74
+ ### Cucumber
62
75
 
63
- Add the following code to `test/test_helper.rb`
76
+ Create a file `features/support/webmock.rb` with the following contents:
64
77
 
65
78
  ```ruby
66
- require 'webmock/test_unit'
79
+ require 'webmock/cucumber'
67
80
  ```
68
81
 
69
- ### RSpec
82
+ ### MiniTest
70
83
 
71
- Add the following code to `spec/spec_helper`:
84
+ Add the following code to `test/test_helper`:
72
85
 
73
86
  ```ruby
74
- require 'webmock/rspec'
87
+ require 'webmock/minitest'
75
88
  ```
76
89
 
77
- ### MiniTest
90
+ ### RSpec
78
91
 
79
- Add the following code to `test/test_helper`:
92
+ Add the following code to `spec/spec_helper`:
80
93
 
81
94
  ```ruby
82
- require 'webmock/minitest'
95
+ require 'webmock/rspec'
83
96
  ```
84
97
 
85
- ### Cucumber
98
+ ### Test::Unit
86
99
 
87
- Create a file `features/support/webmock.rb` with the following contents:
100
+ Add the following code to `test/test_helper.rb`
88
101
 
89
102
  ```ruby
90
- require 'webmock/cucumber'
103
+ require 'webmock/test_unit'
91
104
  ```
92
105
 
93
106
  ### Outside a test framework
@@ -101,13 +114,10 @@ include WebMock::API
101
114
  WebMock.enable!
102
115
  ```
103
116
 
104
- ## Examples
105
-
106
-
117
+ # Examples
107
118
 
108
119
  ## Stubbing
109
120
 
110
-
111
121
  ### Stubbed request based on uri only and with the default response
112
122
 
113
123
  ```ruby
@@ -1137,6 +1147,10 @@ People who submitted patches and new features or suggested improvements. Many th
1137
1147
  * Lucas Uyezu
1138
1148
  * Bruno Sutic
1139
1149
  * Ryan Kerr
1150
+ * Adam Harwood
1151
+ * Ben Koshy
1152
+ * Jesse Bowes
1153
+ * Marek Kasztelnik
1140
1154
 
1141
1155
  For a full list of contributors you can visit the
1142
1156
  [contributors](https://github.com/bblimke/webmock/contributors) page.
@@ -43,6 +43,9 @@ if defined?(::HTTPClient)
43
43
  end
44
44
 
45
45
  module WebMockHTTPClients
46
+
47
+ REQUEST_RESPONSE_LOCK = Mutex.new
48
+
46
49
  def do_get_block(req, proxy, conn, &block)
47
50
  do_get(req, proxy, conn, false, &block)
48
51
  end
@@ -57,7 +60,7 @@ if defined?(::HTTPClient)
57
60
  WebMock::RequestRegistry.instance.requested_signatures.put(request_signature)
58
61
 
59
62
  if webmock_responses[request_signature]
60
- webmock_response = webmock_responses.delete(request_signature)
63
+ webmock_response = synchronize_request_response { webmock_responses.delete(request_signature) }
61
64
  response = build_httpclient_response(webmock_response, stream, req.header, &block)
62
65
  @request_filter.each do |filter|
63
66
  filter.filter_response(req, response)
@@ -68,7 +71,7 @@ if defined?(::HTTPClient)
68
71
  res
69
72
  elsif WebMock.net_connect_allowed?(request_signature.uri)
70
73
  # in case there is a nil entry in the hash...
71
- webmock_responses.delete(request_signature)
74
+ synchronize_request_response { webmock_responses.delete(request_signature) }
72
75
 
73
76
  res = if stream
74
77
  do_get_stream_without_webmock(req, proxy, conn, &block)
@@ -100,7 +103,7 @@ if defined?(::HTTPClient)
100
103
  def do_request_async(method, uri, query, body, extheader)
101
104
  req = create_request(method, uri, query, body, extheader)
102
105
  request_signature = build_request_signature(req)
103
- webmock_request_signatures << request_signature
106
+ synchronize_request_response { webmock_request_signatures << request_signature }
104
107
 
105
108
  if webmock_responses[request_signature] || WebMock.net_connect_allowed?(request_signature.uri)
106
109
  super
@@ -184,7 +187,9 @@ if defined?(::HTTPClient)
184
187
 
185
188
  def webmock_responses
186
189
  @webmock_responses ||= Hash.new do |hash, request_signature|
187
- hash[request_signature] = WebMock::StubRegistry.instance.response_for_request(request_signature)
190
+ synchronize_request_response do
191
+ hash[request_signature] = WebMock::StubRegistry.instance.response_for_request(request_signature)
192
+ end
188
193
  end
189
194
  end
190
195
 
@@ -193,8 +198,10 @@ if defined?(::HTTPClient)
193
198
  end
194
199
 
195
200
  def previous_signature_for(signature)
196
- return nil unless index = webmock_request_signatures.index(signature)
197
- webmock_request_signatures.delete_at(index)
201
+ synchronize_request_response do
202
+ return nil unless index = webmock_request_signatures.index(signature)
203
+ webmock_request_signatures.delete_at(index)
204
+ end
198
205
  end
199
206
 
200
207
  private
@@ -209,6 +216,16 @@ if defined?(::HTTPClient)
209
216
  hdrs
210
217
  end
211
218
  end
219
+
220
+ def synchronize_request_response
221
+ if REQUEST_RESPONSE_LOCK.owned?
222
+ yield
223
+ else
224
+ REQUEST_RESPONSE_LOCK.synchronize do
225
+ yield
226
+ end
227
+ end
228
+ end
212
229
  end
213
230
 
214
231
  class WebMockHTTPClient < HTTPClient
@@ -91,10 +91,10 @@ module WebMock
91
91
 
92
92
  def ==(other)
93
93
  self.body == other.body &&
94
- self.headers === other.headers &&
95
- self.status == other.status &&
96
- self.exception == other.exception &&
97
- self.should_timeout == other.should_timeout
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
- raise InvalidBody, "must be one of: #{valid_types}. '#{@body.class}' given"
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)
@@ -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 = {}
30
+ response_lock = Mutex.new
26
31
 
27
32
  stub = ::WebMock::RequestStub.new(:any, ->(uri) { true }).with { |request|
28
- responses[request.object_id] = yield(request)
29
- }.to_return(lambda { |request| responses.delete(request.object_id) })
30
-
31
- global_stubs.push stub
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).detect { |registered_request_stub|
58
- registered_request_stub.request_pattern.matches?(request_signature)
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)
@@ -8,12 +8,10 @@ module Test
8
8
  class TestCase
9
9
  include WebMock::API
10
10
 
11
- alias_method :teardown_without_webmock, :teardown
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
@@ -1,3 +1,3 @@
1
1
  module WebMock
2
- VERSION = '3.9.1' unless defined?(::WebMock::VERSION)
2
+ VERSION = '3.10.0' unless defined?(::WebMock::VERSION)
3
3
  end
@@ -140,8 +140,8 @@ module WebMock
140
140
  puts WebMock::RequestExecutionVerifier.executed_requests_message
141
141
  end
142
142
 
143
- def self.globally_stub_request(&block)
144
- 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)
145
145
  end
146
146
 
147
147
  %w(
@@ -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
@@ -130,11 +130,15 @@ describe WebMock::Response do
130
130
  # Users of webmock commonly make the mistake of stubbing the response
131
131
  # body to return a hash, to prevent this:
132
132
  #
133
- it "should error if not given one of the allowed types" do
133
+ it "should error if given a non-allowed type: a hash" do
134
134
  expect { WebMock::Response.new(body: Hash.new) }.to \
135
135
  raise_error(WebMock::Response::InvalidBody)
136
136
  end
137
137
 
138
+ it "should error if given a non-allowed type: something that is not a hash" do
139
+ expect { WebMock::Response.new(body: 123) }.to \
140
+ raise_error(WebMock::Response::InvalidBody)
141
+ end
138
142
  end
139
143
 
140
144
  describe "from raw response" do
@@ -152,12 +156,12 @@ describe WebMock::Response do
152
156
 
153
157
  it "should read headers" do
154
158
  expect(@response.headers).to eq({
155
- "Date"=>"Sat, 23 Jan 2010 01:01:05 GMT",
156
- "Content-Type"=>"text/html; charset=UTF-8",
157
- "Content-Length"=>"419",
158
- "Connection"=>"Keep-Alive",
159
- "Accept"=>"image/jpeg, image/png"
160
- })
159
+ "Date"=>"Sat, 23 Jan 2010 01:01:05 GMT",
160
+ "Content-Type"=>"text/html; charset=UTF-8",
161
+ "Content-Length"=>"419",
162
+ "Connection"=>"Keep-Alive",
163
+ "Accept"=>"image/jpeg, image/png"
164
+ })
161
165
  end
162
166
 
163
167
  it "should read body" do
@@ -182,12 +186,12 @@ describe WebMock::Response do
182
186
 
183
187
  it "should read headers" do
184
188
  expect(@response.headers).to eq({
185
- "Date"=>"Sat, 23 Jan 2010 01:01:05 GMT",
186
- "Content-Type"=>"text/html; charset=UTF-8",
187
- "Content-Length"=>"419",
188
- "Connection"=>"Keep-Alive",
189
- "Accept"=>"image/jpeg, image/png"
190
- })
189
+ "Date"=>"Sat, 23 Jan 2010 01:01:05 GMT",
190
+ "Content-Type"=>"text/html; charset=UTF-8",
191
+ "Content-Length"=>"419",
192
+ "Connection"=>"Keep-Alive",
193
+ "Accept"=>"image/jpeg, image/png"
194
+ })
191
195
  end
192
196
 
193
197
  it "should read body" do
@@ -234,11 +238,11 @@ describe WebMock::Response do
234
238
  it "should evaluate new response with evaluated options" do
235
239
  request_signature = WebMock::RequestSignature.new(:post, "www.example.com", body: "abc", headers: {'A' => 'a'})
236
240
  response = WebMock::DynamicResponse.new(lambda {|request|
237
- {
238
- body: request.body,
239
- headers: request.headers,
240
- status: 302
241
- }
241
+ {
242
+ body: request.body,
243
+ headers: request.headers,
244
+ status: 302
245
+ }
242
246
  })
243
247
  evaluated_response = response.evaluate(request_signature)
244
248
  expect(evaluated_response.body).to eq("abc")
@@ -3,4 +3,10 @@ require File.expand_path(File.dirname(__FILE__) + '/shared_test')
3
3
 
4
4
  class TestWebMock < Test::Unit::TestCase
5
5
  include SharedTest
6
+
7
+ def teardown
8
+ # Ensure global Test::Unit teardown was called
9
+ assert_empty WebMock::RequestRegistry.instance.requested_signatures.hash
10
+ assert_empty WebMock::StubRegistry.instance.request_stubs
11
+ end
6
12
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: webmock
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.9.1
4
+ version: 3.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bartosz Blimke
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-09-14 00:00:00.000000000 Z
11
+ date: 2020-11-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -407,11 +407,11 @@ licenses:
407
407
  - MIT
408
408
  metadata:
409
409
  bug_tracker_uri: https://github.com/bblimke/webmock/issues
410
- changelog_uri: https://github.com/bblimke/webmock/blob/v3.9.1/CHANGELOG.md
411
- documentation_uri: https://www.rubydoc.info/gems/webmock/3.9.1
412
- source_code_uri: https://github.com/bblimke/webmock/tree/v3.9.1
410
+ changelog_uri: https://github.com/bblimke/webmock/blob/v3.10.0/CHANGELOG.md
411
+ documentation_uri: https://www.rubydoc.info/gems/webmock/3.10.0
412
+ source_code_uri: https://github.com/bblimke/webmock/tree/v3.10.0
413
413
  wiki_uri: https://github.com/bblimke/webmock/wiki
414
- post_install_message:
414
+ post_install_message:
415
415
  rdoc_options: []
416
416
  require_paths:
417
417
  - lib
@@ -427,7 +427,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
427
427
  version: '0'
428
428
  requirements: []
429
429
  rubygems_version: 3.1.2
430
- signing_key:
430
+ signing_key:
431
431
  specification_version: 4
432
432
  summary: Library for stubbing HTTP requests in Ruby.
433
433
  test_files: