webmock 3.0.0 → 3.14.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/CI.yml +37 -0
  3. data/CHANGELOG.md +416 -0
  4. data/Gemfile +1 -1
  5. data/README.md +157 -31
  6. data/Rakefile +12 -4
  7. data/lib/webmock/api.rb +12 -0
  8. data/lib/webmock/http_lib_adapters/async_http_client_adapter.rb +216 -0
  9. data/lib/webmock/http_lib_adapters/curb_adapter.rb +17 -3
  10. data/lib/webmock/http_lib_adapters/em_http_request_adapter.rb +7 -4
  11. data/lib/webmock/http_lib_adapters/excon_adapter.rb +5 -2
  12. data/lib/webmock/http_lib_adapters/http_rb/client.rb +4 -1
  13. data/lib/webmock/http_lib_adapters/http_rb/request.rb +7 -1
  14. data/lib/webmock/http_lib_adapters/http_rb/response.rb +24 -3
  15. data/lib/webmock/http_lib_adapters/http_rb/streamer.rb +6 -2
  16. data/lib/webmock/http_lib_adapters/http_rb/webmock.rb +2 -2
  17. data/lib/webmock/http_lib_adapters/httpclient_adapter.rb +28 -9
  18. data/lib/webmock/http_lib_adapters/manticore_adapter.rb +33 -15
  19. data/lib/webmock/http_lib_adapters/net_http.rb +54 -14
  20. data/lib/webmock/http_lib_adapters/net_http_response.rb +1 -1
  21. data/lib/webmock/http_lib_adapters/patron_adapter.rb +4 -4
  22. data/lib/webmock/matchers/any_arg_matcher.rb +13 -0
  23. data/lib/webmock/matchers/hash_argument_matcher.rb +21 -0
  24. data/lib/webmock/matchers/hash_excluding_matcher.rb +15 -0
  25. data/lib/webmock/matchers/hash_including_matcher.rb +4 -23
  26. data/lib/webmock/rack_response.rb +1 -1
  27. data/lib/webmock/request_body_diff.rb +1 -1
  28. data/lib/webmock/request_execution_verifier.rb +2 -3
  29. data/lib/webmock/request_pattern.rb +108 -46
  30. data/lib/webmock/request_registry.rb +1 -1
  31. data/lib/webmock/request_signature.rb +1 -1
  32. data/lib/webmock/request_signature_snippet.rb +4 -4
  33. data/lib/webmock/response.rb +11 -5
  34. data/lib/webmock/rspec.rb +10 -3
  35. data/lib/webmock/stub_registry.rb +26 -11
  36. data/lib/webmock/stub_request_snippet.rb +10 -6
  37. data/lib/webmock/test_unit.rb +1 -3
  38. data/lib/webmock/util/hash_counter.rb +4 -4
  39. data/lib/webmock/util/headers.rb +17 -2
  40. data/lib/webmock/util/json.rb +1 -2
  41. data/lib/webmock/util/query_mapper.rb +9 -7
  42. data/lib/webmock/util/uri.rb +10 -10
  43. data/lib/webmock/util/values_stringifier.rb +20 -0
  44. data/lib/webmock/version.rb +1 -1
  45. data/lib/webmock/webmock.rb +10 -3
  46. data/lib/webmock.rb +53 -48
  47. data/minitest/webmock_spec.rb +2 -2
  48. data/spec/acceptance/async_http_client/async_http_client_spec.rb +375 -0
  49. data/spec/acceptance/async_http_client/async_http_client_spec_helper.rb +73 -0
  50. data/spec/acceptance/curb/curb_spec.rb +33 -0
  51. data/spec/acceptance/em_http_request/em_http_request_spec.rb +56 -0
  52. data/spec/acceptance/em_http_request/em_http_request_spec_helper.rb +1 -1
  53. data/spec/acceptance/excon/excon_spec.rb +4 -2
  54. data/spec/acceptance/excon/excon_spec_helper.rb +2 -0
  55. data/spec/acceptance/http_rb/http_rb_spec.rb +20 -0
  56. data/spec/acceptance/http_rb/http_rb_spec_helper.rb +5 -2
  57. data/spec/acceptance/httpclient/httpclient_spec.rb +8 -1
  58. data/spec/acceptance/manticore/manticore_spec.rb +51 -0
  59. data/spec/acceptance/net_http/net_http_shared.rb +1 -1
  60. data/spec/acceptance/net_http/net_http_spec.rb +53 -1
  61. data/spec/acceptance/patron/patron_spec.rb +7 -0
  62. data/spec/acceptance/patron/patron_spec_helper.rb +3 -3
  63. data/spec/acceptance/shared/callbacks.rb +3 -2
  64. data/spec/acceptance/shared/request_expectations.rb +14 -0
  65. data/spec/acceptance/shared/returning_declared_responses.rb +36 -15
  66. data/spec/acceptance/shared/stubbing_requests.rb +95 -0
  67. data/spec/acceptance/typhoeus/typhoeus_hydra_spec.rb +1 -1
  68. data/spec/acceptance/typhoeus/typhoeus_hydra_spec_helper.rb +1 -1
  69. data/spec/support/webmock_server.rb +1 -0
  70. data/spec/unit/api_spec.rb +103 -3
  71. data/spec/unit/matchers/hash_excluding_matcher_spec.rb +61 -0
  72. data/spec/unit/request_execution_verifier_spec.rb +12 -12
  73. data/spec/unit/request_pattern_spec.rb +195 -49
  74. data/spec/unit/request_signature_snippet_spec.rb +2 -2
  75. data/spec/unit/response_spec.rb +22 -18
  76. data/spec/unit/stub_request_snippet_spec.rb +30 -10
  77. data/spec/unit/util/query_mapper_spec.rb +13 -0
  78. data/spec/unit/util/uri_spec.rb +74 -2
  79. data/spec/unit/webmock_spec.rb +54 -5
  80. data/test/shared_test.rb +15 -2
  81. data/test/test_webmock.rb +6 -0
  82. data/webmock.gemspec +11 -3
  83. metadata +66 -17
  84. data/.travis.yml +0 -20
@@ -36,6 +36,7 @@ class WebMockServer
36
36
  end
37
37
  end
38
38
  server.start do |socket|
39
+ socket.read(1)
39
40
  socket.puts <<-EOT.gsub(/^\s+\|/, '')
40
41
  |HTTP/1.1 200 OK\r
41
42
  |Date: Fri, 31 Dec 1999 23:59:59 GMT\r
@@ -2,9 +2,8 @@ require 'spec_helper'
2
2
 
3
3
  describe WebMock::API do
4
4
  describe '#hash_including' do
5
-
6
5
  subject { klass.new.hash_including(args) }
7
- let(:args) { {data: :one} }
6
+ let(:args) { { data: :one } }
8
7
 
9
8
  context 'when mixed into a class that does not define `hash_including`' do
10
9
  let(:klass) do
@@ -54,7 +53,7 @@ describe WebMock::API do
54
53
 
55
54
 
56
55
  context 'when mixed into a class with a parent that defines `hash_including`' do
57
- subject {klass.new.hash_including(*args)}
56
+ subject { klass.new.hash_including(*args) }
58
57
  let(:args) { %w(:foo, :bar, {:data => :one}) }
59
58
  let(:klass) do
60
59
  Class.new(
@@ -70,6 +69,107 @@ describe WebMock::API do
70
69
  expect(subject).to eq(args)
71
70
  end
72
71
  end
72
+ end
73
+
74
+ describe '#hash_excluding' do
75
+ subject { klass.new.hash_excluding(args) }
76
+ let(:args) { { data: :one } }
77
+
78
+ context 'when mixed into a class that does not define `hash_including`' do
79
+ let(:klass) do
80
+ Class.new do
81
+ include WebMock::API
82
+ end
83
+ end
84
+
85
+ it 'uses WebMock::Matchers::HashIncludingMatcher' do
86
+ expect(subject).to be_a(WebMock::Matchers::HashExcludingMatcher)
87
+ end
88
+
89
+ # by testing equality for HashIncludingMatcher (which stringifies the passed hash) we are
90
+ # testing HashIncludingMatcher.initialize behavior as well
91
+ context 'when args correspond to an hash' do
92
+ context 'creates "HashExcludingMatcher"' do
93
+ it 'equals hash with similar key but different value' do
94
+ expect(subject).to eq('data' => :two)
95
+ end
96
+
97
+ it 'equals hash with similar value but different key' do
98
+ expect(subject).to eq('data2' => :one)
99
+ end
100
+
101
+ it 'equals hash with defferent value and key' do
102
+ expect(subject).to eq('data2' => :two)
103
+ end
104
+
105
+ it 'not equals with similar value and key' do
106
+ expect(subject).not_to eq('data' => :one)
107
+ end
108
+ end
109
+ end
110
+
111
+ context 'when args are one or many keys' do
112
+ subject { klass.new.hash_excluding(:foo, :bar) }
113
+ let(:anything) { WebMock::Matchers::AnyArgMatcher.new(nil) }
114
+
115
+ it "creates 'HashExcludingMatcher' with keys anythingized" do
116
+ expect(subject).not_to eq('foo' => anything, 'bar' => anything )
117
+ end
118
+ end
119
+
120
+ context 'when args are both keys and key/value pairs' do
121
+ subject { klass.new.hash_excluding(:foo, :bar, data: :one) }
122
+ let(:anything) { WebMock::Matchers::AnyArgMatcher.new(nil) }
123
+
124
+ it 'creates "HashExcludingMatcher" with keys anythingized' do
125
+ expect(subject).not_to eq('foo' => anything, 'bar' => anything, 'data' => :one)
126
+ end
127
+ end
128
+
129
+ context 'when args are an empty hash' do
130
+ subject { klass.new.hash_excluding({}) }
131
+
132
+ it 'creates "HashExcludingMatcher" with an empty hash' do
133
+ expect(subject).to eq({})
134
+ end
135
+ end
136
+ end
137
+
138
+ context 'when mixed into a class with a parent that defines `hash_excluding`' do
139
+ subject { klass.new.hash_excluding(*args) }
140
+ let(:args) { %w(:foo, :bar, {:data => :one}) }
141
+ let(:klass) do
142
+ Class.new(
143
+ Class.new do
144
+ def hash_excluding(*args)
145
+ args
146
+ end
147
+ end
148
+ ) { include WebMock::API }
149
+ end
150
+
151
+ it 'uses super and passes the args untampered' do
152
+ expect(subject).to eq(args)
153
+ end
154
+ end
155
+ end
156
+
157
+ describe '#reset_executed_requests!' do
158
+ subject { WebMock::API.reset_executed_requests! }
159
+
160
+ let(:request_signature) { WebMock::RequestSignature.new(:get, "www.example.com") }
161
+ let(:request_pattern) { WebMock::RequestPattern.new(:get, "www.example.com") }
73
162
 
163
+ before do
164
+ WebMock::RequestRegistry.instance.requested_signatures.put(request_signature)
165
+ end
166
+
167
+ it 'resets request registry counter' do
168
+ expect{
169
+ subject
170
+ }.to change{
171
+ WebMock::RequestRegistry.instance.times_executed(request_pattern)
172
+ }.from(1).to(0)
173
+ end
74
174
  end
75
175
  end
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ module WebMock
4
+ module Matchers
5
+ describe HashExcludingMatcher do
6
+ it 'stringifies the given hash keys' do
7
+ expect(HashExcludingMatcher.new(a: 1, b: 2)).not_to eq('a' => 1, 'b' => 2)
8
+ end
9
+
10
+ it 'sorts elements in the hash' do
11
+ expect(HashExcludingMatcher.new(b: 2, a: 1)).not_to eq('a' => 1, 'b' => 2)
12
+ end
13
+
14
+ it 'describes itself properly' do
15
+ expect(HashExcludingMatcher.new(a: 1).inspect).to eq 'hash_excluding({"a"=>1})'
16
+ end
17
+
18
+ describe 'success' do
19
+ it 'match with hash with a missing key' do
20
+ expect(HashExcludingMatcher.new(a: 1)).to eq('b' => 2)
21
+ end
22
+
23
+ it 'match an empty hash with a given key' do
24
+ expect(HashExcludingMatcher.new(a: 1)).to eq({})
25
+ end
26
+
27
+ it 'match when values are nil but keys are different' do
28
+ expect(HashExcludingMatcher.new(a: nil)).to eq('b' => nil)
29
+ end
30
+
31
+ describe 'when matching an empty hash' do
32
+ it 'does not matches against any hash' do
33
+ expect(HashExcludingMatcher.new({})).to eq(a: 1, b: 2, c: 3)
34
+ end
35
+ end
36
+ end
37
+
38
+ describe 'failing' do
39
+ it 'does not match a hash with a one missing key when one pair is matching' do
40
+ expect(HashExcludingMatcher.new(a: 1, b: 2)).not_to eq('b' => 2)
41
+ end
42
+
43
+ it 'match a hash with an incorrect value' do
44
+ expect(HashExcludingMatcher.new(a: 1, b: 2)).not_to eq('a' => 1, 'b' => 3)
45
+ end
46
+
47
+ it 'does not matches the same hash' do
48
+ expect(HashExcludingMatcher.new('a' => 1, 'b' => 2)).not_to eq('a' => 1, 'b' => 2)
49
+ end
50
+
51
+ it 'does not matches a hash with extra stuff' do
52
+ expect(HashExcludingMatcher.new(a: 1)).not_to eq('a' => 1, 'b' => 2)
53
+ end
54
+
55
+ it 'does not match a non-hash' do
56
+ expect(HashExcludingMatcher.new(a: 1)).not_to eq 1
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -53,7 +53,7 @@ describe WebMock::RequestExecutionVerifier do
53
53
  @verifier.times_executed = 0
54
54
  @verifier.expected_times_executed = 2
55
55
  expected_text = "The request www.example.com was expected to execute 2 times but it executed 0 times"
56
- expected_text << @executed_requests_info
56
+ expected_text += @executed_requests_info
57
57
  expect(@verifier.failure_message).to eq(expected_text)
58
58
  end
59
59
 
@@ -61,7 +61,7 @@ describe WebMock::RequestExecutionVerifier do
61
61
  @verifier.times_executed = 1
62
62
  @verifier.expected_times_executed = 1
63
63
  expected_text = "The request www.example.com was expected to execute 1 time but it executed 1 time"
64
- expected_text << @executed_requests_info
64
+ expected_text += @executed_requests_info
65
65
  expect(@verifier.failure_message).to eq(expected_text)
66
66
  end
67
67
 
@@ -70,7 +70,7 @@ describe WebMock::RequestExecutionVerifier do
70
70
  @verifier.times_executed = 1
71
71
  @verifier.at_least_times_executed = 2
72
72
  expected_text = "The request www.example.com was expected to execute at least 2 times but it executed 1 time"
73
- expected_text << @executed_requests_info
73
+ expected_text += @executed_requests_info
74
74
  expect(@verifier.failure_message).to eq(expected_text)
75
75
  end
76
76
 
@@ -78,7 +78,7 @@ describe WebMock::RequestExecutionVerifier do
78
78
  @verifier.times_executed = 2
79
79
  @verifier.at_least_times_executed = 3
80
80
  expected_text = "The request www.example.com was expected to execute at least 3 times but it executed 2 times"
81
- expected_text << @executed_requests_info
81
+ expected_text += @executed_requests_info
82
82
  expect(@verifier.failure_message).to eq(expected_text)
83
83
  end
84
84
  end
@@ -88,7 +88,7 @@ describe WebMock::RequestExecutionVerifier do
88
88
  @verifier.times_executed = 3
89
89
  @verifier.at_most_times_executed = 2
90
90
  expected_text = "The request www.example.com was expected to execute at most 2 times but it executed 3 times"
91
- expected_text << @executed_requests_info
91
+ expected_text += @executed_requests_info
92
92
  expect(@verifier.failure_message).to eq(expected_text)
93
93
  end
94
94
 
@@ -96,7 +96,7 @@ describe WebMock::RequestExecutionVerifier do
96
96
  @verifier.times_executed = 2
97
97
  @verifier.at_most_times_executed = 1
98
98
  expected_text = "The request www.example.com was expected to execute at most 1 time but it executed 2 times"
99
- expected_text << @executed_requests_info
99
+ expected_text += @executed_requests_info
100
100
  expect(@verifier.failure_message).to eq(expected_text)
101
101
  end
102
102
  end
@@ -108,14 +108,14 @@ describe WebMock::RequestExecutionVerifier do
108
108
  @verifier.times_executed = 2
109
109
  @verifier.expected_times_executed = 2
110
110
  expected_text = "The request www.example.com was not expected to execute 2 times but it executed 2 times"
111
- expected_text << @executed_requests_info
111
+ expected_text += @executed_requests_info
112
112
  expect(@verifier.failure_message_when_negated).to eq(expected_text)
113
113
  end
114
114
 
115
115
  it "reports failure message when not expected request but it executed" do
116
116
  @verifier.times_executed = 1
117
117
  expected_text = "The request www.example.com was not expected to execute but it executed 1 time"
118
- expected_text << @executed_requests_info
118
+ expected_text += @executed_requests_info
119
119
  expect(@verifier.failure_message_when_negated).to eq(expected_text)
120
120
  end
121
121
 
@@ -124,7 +124,7 @@ describe WebMock::RequestExecutionVerifier do
124
124
  @verifier.times_executed = 3
125
125
  @verifier.at_least_times_executed = 2
126
126
  expected_text = "The request www.example.com was not expected to execute at least 2 times but it executed 3 times"
127
- expected_text << @executed_requests_info
127
+ expected_text += @executed_requests_info
128
128
  expect(@verifier.failure_message_when_negated).to eq(expected_text)
129
129
  end
130
130
 
@@ -132,7 +132,7 @@ describe WebMock::RequestExecutionVerifier do
132
132
  @verifier.times_executed = 2
133
133
  @verifier.at_least_times_executed = 2
134
134
  expected_text = "The request www.example.com was not expected to execute at least 2 times but it executed 2 times"
135
- expected_text << @executed_requests_info
135
+ expected_text += @executed_requests_info
136
136
  expect(@verifier.failure_message_when_negated).to eq(expected_text)
137
137
  end
138
138
  end
@@ -142,7 +142,7 @@ describe WebMock::RequestExecutionVerifier do
142
142
  @verifier.times_executed = 2
143
143
  @verifier.at_most_times_executed = 3
144
144
  expected_text = "The request www.example.com was not expected to execute at most 3 times but it executed 2 times"
145
- expected_text << @executed_requests_info
145
+ expected_text += @executed_requests_info
146
146
  expect(@verifier.failure_message_when_negated).to eq(expected_text)
147
147
  end
148
148
 
@@ -150,7 +150,7 @@ describe WebMock::RequestExecutionVerifier do
150
150
  @verifier.times_executed = 1
151
151
  @verifier.at_most_times_executed = 2
152
152
  expected_text = "The request www.example.com was not expected to execute at most 2 times but it executed 1 time"
153
- expected_text << @executed_requests_info
153
+ expected_text += @executed_requests_info
154
154
  expect(@verifier.failure_message_when_negated).to eq(expected_text)
155
155
  end
156
156
  end
@@ -58,7 +58,7 @@ describe WebMock::RequestPattern do
58
58
  end
59
59
 
60
60
  it "should raise an error if neither options or block is provided" do
61
- expect { @request_pattern.with() }.to raise_error('#with method invoked with no arguments. Either options hash or block must be specified.')
61
+ expect { @request_pattern.with() }.to raise_error('#with method invoked with no arguments. Either options hash or block must be specified. Created a block with do..end? Try creating it with curly braces {} instead.')
62
62
  end
63
63
  end
64
64
 
@@ -111,6 +111,21 @@ describe WebMock::RequestPattern do
111
111
  to match(WebMock::RequestSignature.new(:get, "www.example.com"))
112
112
  end
113
113
 
114
+ it "should match if uri matches requesst uri as URI object" do
115
+ expect(WebMock::RequestPattern.new(:get, URI.parse("www.example.com"))).
116
+ to match(WebMock::RequestSignature.new(:get, "www.example.com"))
117
+ end
118
+
119
+ it "should match if uri proc pattern returning true" do
120
+ expect(WebMock::RequestPattern.new(:get, ->(uri) { true })).
121
+ to match(WebMock::RequestSignature.new(:get, "www.example.com"))
122
+ end
123
+
124
+ it "should not match if uri proc pattern returns false" do
125
+ expect(WebMock::RequestPattern.new(:get, ->(uri) { false })).
126
+ not_to match(WebMock::RequestSignature.new(:get, "www.example.com"))
127
+ end
128
+
114
129
  it "should match if uri Addressable::Template pattern matches unescaped form of request uri" do
115
130
  expect(WebMock::RequestPattern.new(:get, Addressable::Template.new("www.example.com/{any_path}"))).
116
131
  to match(WebMock::RequestSignature.new(:get, "www.example.com/my%20path"))
@@ -121,6 +136,41 @@ describe WebMock::RequestPattern do
121
136
  to match(WebMock::RequestSignature.new(:get, "www.example.com"))
122
137
  end
123
138
 
139
+ it "should match if uri Addressable::Template pattern matches request uri without TLD" do
140
+ expect(WebMock::RequestPattern.new(:get, Addressable::Template.new("localhost"))).
141
+ to match(WebMock::RequestSignature.new(:get, "localhost"))
142
+ end
143
+
144
+ it "should match if Addressable::Template pattern that has ip address host matches request uri" do
145
+ signature = WebMock::RequestSignature.new(:get, "127.0.0.1:3000/1234")
146
+ uri = Addressable::Template.new("127.0.0.1:3000/{id}")
147
+ expect(WebMock::RequestPattern.new(:get, uri)).to match(signature)
148
+ end
149
+
150
+ it "should match if Addressable::Template pattern that has ip address host without port matches request uri" do
151
+ signature = WebMock::RequestSignature.new(:get, "127.0.0.1/1234")
152
+ uri = Addressable::Template.new("127.0.0.1/{id}")
153
+ expect(WebMock::RequestPattern.new(:get, uri)).to match(signature)
154
+ end
155
+
156
+ it "should match if Addressable::Template pattern host matches request uri" do
157
+ signature = WebMock::RequestSignature.new(:get, "www.example.com")
158
+ uri = Addressable::Template.new("{subdomain}.example.com")
159
+ expect(WebMock::RequestPattern.new(:get, uri)).to match(signature)
160
+ end
161
+
162
+ it "should not match if Addressable::Template pattern host does not match request uri" do
163
+ signature = WebMock::RequestSignature.new(:get, "www.bad-example.com")
164
+ uri = Addressable::Template.new("{subdomain}.example.com")
165
+ expect(WebMock::RequestPattern.new(:get, uri)).not_to match(signature)
166
+ end
167
+
168
+ it "should match if uri Addressable::Template pattern matches request uri without a schema and a path " do
169
+ signature = WebMock::RequestSignature.new(:get, "127.0.0.1:3000")
170
+ uri = Addressable::Template.new("127.0.0.1:3000")
171
+ expect(WebMock::RequestPattern.new(:get, uri)).to match(signature)
172
+ end
173
+
124
174
  it "should match for uris with same parameters as pattern" do
125
175
  expect(WebMock::RequestPattern.new(:get, "www.example.com?a=1&b=2")).
126
176
  to match(WebMock::RequestSignature.new(:get, "www.example.com?a=1&b=2"))
@@ -188,7 +238,7 @@ describe WebMock::RequestPattern do
188
238
  to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c"))
189
239
  end
190
240
 
191
- it "should match request query params if params don't match" do
241
+ it "should not match request query params if params don't match" do
192
242
  expect(WebMock::RequestPattern.new(:get, /.*example.*/, query: {"x" => ["b", "c"]})).
193
243
  not_to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c"))
194
244
  end
@@ -218,13 +268,85 @@ describe WebMock::RequestPattern do
218
268
  end
219
269
  end
220
270
 
271
+ describe "when uri is described as URI" do
272
+ it "should match request query params" do
273
+ expect(WebMock::RequestPattern.new(:get, URI.parse("www.example.com"), query: {"a" => ["b", "c"]})).
274
+ to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c"))
275
+ end
276
+
277
+ it "should not match request query params if params don't match" do
278
+ expect(WebMock::RequestPattern.new(:get, URI.parse("www.example.com"), query: {"x" => ["b", "c"]})).
279
+ not_to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c"))
280
+ end
281
+
282
+ it "should match when query params are declared as HashIncluding matcher matching params" do
283
+ expect(WebMock::RequestPattern.new(:get, URI.parse("www.example.com"),
284
+ query: WebMock::Matchers::HashIncludingMatcher.new({"a" => ["b", "c"]}))).
285
+ to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c&b=1"))
286
+ end
287
+
288
+ it "should not match when query params are declared as HashIncluding matcher not matching params" do
289
+ expect(WebMock::RequestPattern.new(:get, URI.parse("www.example.com"),
290
+ query: WebMock::Matchers::HashIncludingMatcher.new({"x" => ["b", "c"]}))).
291
+ not_to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c&b=1"))
292
+ end
293
+
294
+ it "should match when query params are declared as RSpec HashIncluding matcher matching params" do
295
+ expect(WebMock::RequestPattern.new(:get, URI.parse("www.example.com"),
296
+ query: RSpec::Mocks::ArgumentMatchers::HashIncludingMatcher.new({"a" => ["b", "c"]}))).
297
+ to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c&b=1"))
298
+ end
299
+
300
+ it "should not match when query params are declared as RSpec HashIncluding matcher not matching params" do
301
+ expect(WebMock::RequestPattern.new(:get, URI.parse("www.example.com"),
302
+ query: RSpec::Mocks::ArgumentMatchers::HashIncludingMatcher.new({"a" => ["b", "d"]}))).
303
+ not_to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c&b=1"))
304
+ end
305
+ end
306
+
307
+ describe "when uri is described as a proc" do
308
+ it "should match request query params" do
309
+ expect(WebMock::RequestPattern.new(:get, ->(uri) { true }, query: {"a" => ["b", "c"]})).
310
+ to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c"))
311
+ end
312
+
313
+ it "should not match request query params if params don't match" do
314
+ expect(WebMock::RequestPattern.new(:get, ->(uri) { true }, query: {"x" => ["b", "c"]})).
315
+ not_to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c"))
316
+ end
317
+
318
+ it "should match when query params are declared as HashIncluding matcher matching params" do
319
+ expect(WebMock::RequestPattern.new(:get, ->(uri) { true },
320
+ query: WebMock::Matchers::HashIncludingMatcher.new({"a" => ["b", "c"]}))).
321
+ to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c&b=1"))
322
+ end
323
+
324
+ it "should not match when query params are declared as HashIncluding matcher not matching params" do
325
+ expect(WebMock::RequestPattern.new(:get, ->(uri) { true },
326
+ query: WebMock::Matchers::HashIncludingMatcher.new({"x" => ["b", "c"]}))).
327
+ not_to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c&b=1"))
328
+ end
329
+
330
+ it "should match when query params are declared as RSpec HashIncluding matcher matching params" do
331
+ expect(WebMock::RequestPattern.new(:get, ->(uri) { true },
332
+ query: RSpec::Mocks::ArgumentMatchers::HashIncludingMatcher.new({"a" => ["b", "c"]}))).
333
+ to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c&b=1"))
334
+ end
335
+
336
+ it "should not match when query params are declared as RSpec HashIncluding matcher not matching params" do
337
+ expect(WebMock::RequestPattern.new(:get, ->(uri) { true },
338
+ query: RSpec::Mocks::ArgumentMatchers::HashIncludingMatcher.new({"a" => ["b", "d"]}))).
339
+ not_to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c&b=1"))
340
+ end
341
+ end
342
+
221
343
  describe "when uri is described as Addressable::Template" do
222
344
  it "should raise error if query params are specified" do
223
345
  expect(WebMock::RequestPattern.new(:get, Addressable::Template.new("www.example.com"), query: {"a" => ["b", "c"]})).
224
346
  to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c"))
225
347
  end
226
348
 
227
- it "should match request query params if params don't match" do
349
+ it "should not match request query params if params don't match" do
228
350
  expect(WebMock::RequestPattern.new(:get, Addressable::Template.new("www.example.com"), query: {"x" => ["b", "c"]})).
229
351
  not_to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c"))
230
352
  end
@@ -412,69 +534,93 @@ describe WebMock::RequestPattern do
412
534
  end
413
535
 
414
536
  describe "for request with json body and content type is set to json" do
415
- it "should match when hash matches body" do
416
- expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: body_hash)).
417
- to match(WebMock::RequestSignature.new(:post, "www.example.com", headers: {content_type: 'application/json'},
418
- body: "{\"a\":\"1\",\"c\":{\"d\":[\"e\",\"f\"]},\"b\":\"five\"}"))
419
- end
537
+ shared_examples "a json body" do
538
+ it "should match when hash matches body" do
539
+ expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: body_hash)).
540
+ to match(WebMock::RequestSignature.new(:post, "www.example.com", headers: {content_type: content_type},
541
+ body: "{\"a\":\"1\",\"c\":{\"d\":[\"e\",\"f\"]},\"b\":\"five\"}"))
542
+ end
420
543
 
421
- it "should match if hash matches body in different form" do
422
- expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: body_hash)).
423
- to match(WebMock::RequestSignature.new(:post, "www.example.com", headers: {content_type: 'application/json'},
424
- body: "{\"a\":\"1\",\"b\":\"five\",\"c\":{\"d\":[\"e\",\"f\"]}}"))
425
- end
544
+ it "should match if hash matches body in different form" do
545
+ expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: body_hash)).
546
+ to match(WebMock::RequestSignature.new(:post, "www.example.com", headers: {content_type: content_type},
547
+ body: "{\"a\":\"1\",\"b\":\"five\",\"c\":{\"d\":[\"e\",\"f\"]}}"))
548
+ end
426
549
 
427
- it "should not match when body is not json" do
428
- expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: body_hash)).
429
- not_to match(WebMock::RequestSignature.new(:post, "www.example.com",
430
- headers: {content_type: 'application/json'}, body: "foo bar"))
431
- end
550
+ it "should not match when body is not json" do
551
+ expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: body_hash)).
552
+ not_to match(WebMock::RequestSignature.new(:post, "www.example.com",
553
+ headers: {content_type: content_type}, body: "foo bar"))
554
+ end
432
555
 
433
- it "should not match if request body is different" do
434
- expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: {a: 1, b: 2})).
435
- not_to match(WebMock::RequestSignature.new(:post, "www.example.com",
436
- headers: {content_type: 'application/json'}, body: "{\"a\":1,\"c\":null}"))
556
+ it "should not match if request body is different" do
557
+ expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: {a: 1, b: 2})).
558
+ not_to match(WebMock::RequestSignature.new(:post, "www.example.com",
559
+ headers: {content_type: content_type}, body: "{\"a\":1,\"c\":null}"))
560
+ end
561
+
562
+ it "should not match if request body is has less params than pattern" do
563
+ expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: {a: 1, b: 2})).
564
+ not_to match(WebMock::RequestSignature.new(:post, "www.example.com",
565
+ headers: {content_type: content_type}, body: "{\"a\":1}"))
566
+ end
567
+
568
+ it "should not match if request body is has more params than pattern" do
569
+ expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: {a: 1})).
570
+ not_to match(WebMock::RequestSignature.new(:post, "www.example.com",
571
+ headers: {content_type: content_type}, body: "{\"a\":1,\"c\":1}"))
572
+ end
437
573
  end
438
574
 
439
- it "should not match if request body is has less params than pattern" do
440
- expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: {a: 1, b: 2})).
441
- not_to match(WebMock::RequestSignature.new(:post, "www.example.com",
442
- headers: {content_type: 'application/json'}, body: "{\"a\":1}"))
575
+ context "standard application/json" do
576
+ let(:content_type) { 'application/json' }
577
+ it_behaves_like "a json body"
443
578
  end
444
579
 
445
- it "should not match if request body is has more params than pattern" do
446
- expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: {a: 1})).
447
- not_to match(WebMock::RequestSignature.new(:post, "www.example.com",
448
- headers: {content_type: 'application/json'}, body: "{\"a\":1,\"c\":1}"))
580
+ context "custom json content type" do
581
+ let(:content_type) { 'application/vnd.api+json' }
582
+ it_behaves_like "a json body"
449
583
  end
450
584
  end
451
585
 
452
586
  describe "for request with xml body and content type is set to xml" do
453
587
  let(:body_hash) { {"opt" => {:a => '1', :b => 'five', 'c' => {'d' => ['e', 'f']}}} }
454
588
 
455
- it "should match when hash matches body" do
456
- expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: body_hash)).
457
- to match(WebMock::RequestSignature.new(:post, "www.example.com", headers: {content_type: 'application/xml'},
458
- body: "<opt a=\"1\" b=\"five\">\n <c>\n <d>e</d>\n <d>f</d>\n </c>\n</opt>\n"))
459
- end
589
+ shared_examples "a xml body" do
590
+ it "should match when hash matches body" do
591
+ expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: body_hash)).
592
+ to match(WebMock::RequestSignature.new(:post, "www.example.com", headers: {content_type: content_type},
593
+ body: "<opt a=\"1\" b=\"five\">\n <c>\n <d>e</d>\n <d>f</d>\n </c>\n</opt>\n"))
594
+ end
460
595
 
461
- it "should match if hash matches body in different form" do
462
- expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: body_hash)).
463
- to match(WebMock::RequestSignature.new(:post, "www.example.com", headers: {content_type: 'application/xml'},
464
- body: "<opt b=\"five\" a=\"1\">\n <c>\n <d>e</d>\n <d>f</d>\n </c>\n</opt>\n"))
465
- end
596
+ it "should match if hash matches body in different form" do
597
+ expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: body_hash)).
598
+ to match(WebMock::RequestSignature.new(:post, "www.example.com", headers: {content_type: content_type},
599
+ body: "<opt b=\"five\" a=\"1\">\n <c>\n <d>e</d>\n <d>f</d>\n </c>\n</opt>\n"))
600
+ end
466
601
 
467
- it "should not match when body is not xml" do
468
- expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: body_hash)).
469
- not_to match(WebMock::RequestSignature.new(:post, "www.example.com",
470
- headers: {content_type: 'application/xml'}, body: "foo bar"))
471
- end
602
+ it "should not match when body is not xml" do
603
+ expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: body_hash)).
604
+ not_to match(WebMock::RequestSignature.new(:post, "www.example.com",
605
+ headers: {content_type: content_type}, body: "foo bar"))
606
+ end
472
607
 
473
- it "matches when the content type include a charset" do
474
- expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: body_hash)).
475
- to match(WebMock::RequestSignature.new(:post, "www.example.com", headers: {content_type: 'application/xml;charset=UTF-8'},
476
- body: "<opt a=\"1\" b=\"five\">\n <c>\n <d>e</d>\n <d>f</d>\n </c>\n</opt>\n"))
608
+ it "matches when the content type include a charset" do
609
+ expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: body_hash)).
610
+ to match(WebMock::RequestSignature.new(:post, "www.example.com", headers: {content_type: "#{content_type};charset=UTF-8"},
611
+ body: "<opt a=\"1\" b=\"five\">\n <c>\n <d>e</d>\n <d>f</d>\n </c>\n</opt>\n"))
612
+
613
+ end
614
+ end
615
+
616
+ context "standard application/xml" do
617
+ let(:content_type) { 'application/xml' }
618
+ it_behaves_like "a xml body"
619
+ end
477
620
 
621
+ context "custom xml content type" do
622
+ let(:content_type) { 'application/atom+xml' }
623
+ it_behaves_like "a xml body"
478
624
  end
479
625
  end
480
626
  end
@@ -60,7 +60,7 @@ RSpec.describe WebMock::RequestSignatureSnippet do
60
60
  result = subject.request_stubs
61
61
  result.sub!("registered request stubs:\n\n", "")
62
62
  expect(result).to eq(
63
- "stub_request(:get, \"https://www.example.com/\").\n with(body: {\"a\"=>\"b\"})"
63
+ "stub_request(:get, \"https://www.example.com/\").\n with(\n body: {\"a\"=>\"b\"})"
64
64
  )
65
65
  end
66
66
 
@@ -74,7 +74,7 @@ RSpec.describe WebMock::RequestSignatureSnippet do
74
74
  result = subject.request_stubs
75
75
  result.sub!("registered request stubs:\n\n", "")
76
76
  expect(result).to eq(
77
- "stub_request(:get, \"https://www.example.com/\").\n with(body: {\"a\"=>\"b\"})\n\nBody diff:\n [[\"-\", \"key\", \"different value\"], [\"+\", \"a\", \"b\"]]\n"
77
+ "stub_request(:get, \"https://www.example.com/\").\n with(\n body: {\"a\"=>\"b\"})\n\nBody diff:\n [[\"-\", \"key\", \"different value\"], [\"+\", \"a\", \"b\"]]\n"
78
78
  )
79
79
  end
80
80
  end