pact 0.1.28

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 (72) hide show
  1. data/.gitignore +28 -0
  2. data/.rspec +2 -0
  3. data/Gemfile +5 -0
  4. data/Gemfile.lock +83 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +238 -0
  7. data/Rakefile +33 -0
  8. data/bin/pact +4 -0
  9. data/lib/pact/app.rb +32 -0
  10. data/lib/pact/configuration.rb +54 -0
  11. data/lib/pact/consumer/app_manager.rb +177 -0
  12. data/lib/pact/consumer/configuration_dsl.rb +71 -0
  13. data/lib/pact/consumer/consumer_contract_builder.rb +79 -0
  14. data/lib/pact/consumer/consumer_contract_builders.rb +10 -0
  15. data/lib/pact/consumer/dsl.rb +98 -0
  16. data/lib/pact/consumer/interaction.rb +70 -0
  17. data/lib/pact/consumer/mock_service.rb +340 -0
  18. data/lib/pact/consumer/rspec.rb +43 -0
  19. data/lib/pact/consumer/run_condor.rb +4 -0
  20. data/lib/pact/consumer/run_mock_contract_service.rb +13 -0
  21. data/lib/pact/consumer/service_consumer.rb +22 -0
  22. data/lib/pact/consumer/service_producer.rb +23 -0
  23. data/lib/pact/consumer.rb +7 -0
  24. data/lib/pact/consumer_contract.rb +110 -0
  25. data/lib/pact/json_warning.rb +23 -0
  26. data/lib/pact/logging.rb +14 -0
  27. data/lib/pact/matchers/matchers.rb +85 -0
  28. data/lib/pact/matchers.rb +1 -0
  29. data/lib/pact/producer/configuration_dsl.rb +62 -0
  30. data/lib/pact/producer/matchers.rb +22 -0
  31. data/lib/pact/producer/pact_spec_runner.rb +57 -0
  32. data/lib/pact/producer/producer_state.rb +81 -0
  33. data/lib/pact/producer/rspec.rb +127 -0
  34. data/lib/pact/producer/test_methods.rb +89 -0
  35. data/lib/pact/producer.rb +1 -0
  36. data/lib/pact/rake_task.rb +64 -0
  37. data/lib/pact/reification.rb +26 -0
  38. data/lib/pact/request.rb +109 -0
  39. data/lib/pact/term.rb +40 -0
  40. data/lib/pact/verification_task.rb +57 -0
  41. data/lib/pact/version.rb +3 -0
  42. data/lib/pact.rb +5 -0
  43. data/lib/tasks/pact.rake +6 -0
  44. data/pact.gemspec +36 -0
  45. data/scratchpad.txt +36 -0
  46. data/spec/features/consumption_spec.rb +146 -0
  47. data/spec/features/producer_states/zebras.rb +28 -0
  48. data/spec/features/production_spec.rb +160 -0
  49. data/spec/integration/pact/configuration_spec.rb +65 -0
  50. data/spec/lib/pact/configuration_spec.rb +35 -0
  51. data/spec/lib/pact/consumer/app_manager_spec.rb +41 -0
  52. data/spec/lib/pact/consumer/consumer_contract_builder_spec.rb +87 -0
  53. data/spec/lib/pact/consumer/dsl_spec.rb +52 -0
  54. data/spec/lib/pact/consumer/interaction_spec.rb +108 -0
  55. data/spec/lib/pact/consumer/mock_service_spec.rb +147 -0
  56. data/spec/lib/pact/consumer/service_consumer_spec.rb +11 -0
  57. data/spec/lib/pact/consumer_contract_spec.rb +125 -0
  58. data/spec/lib/pact/matchers/matchers_spec.rb +354 -0
  59. data/spec/lib/pact/producer/configuration_dsl_spec.rb +101 -0
  60. data/spec/lib/pact/producer/producer_state_spec.rb +103 -0
  61. data/spec/lib/pact/producer/rspec_spec.rb +48 -0
  62. data/spec/lib/pact/reification_spec.rb +43 -0
  63. data/spec/lib/pact/request_spec.rb +316 -0
  64. data/spec/lib/pact/term_spec.rb +36 -0
  65. data/spec/lib/pact/verification_task_spec.rb +64 -0
  66. data/spec/spec_helper.rb +5 -0
  67. data/spec/support/a_consumer-a_producer.json +34 -0
  68. data/spec/support/pact_rake_support.rb +41 -0
  69. data/spec/support/test_app_fail.json +22 -0
  70. data/spec/support/test_app_pass.json +21 -0
  71. data/tasks/pact-test.rake +19 -0
  72. metadata +381 -0
@@ -0,0 +1,354 @@
1
+ require 'spec_helper'
2
+ require 'pact/term'
3
+ require 'pact/matchers'
4
+
5
+ describe Pact::Matchers do
6
+ include Pact::Matchers
7
+
8
+ describe 'structure_diff' do
9
+ let(:expected) {
10
+ {a: 'a string', b: 1, c: nil, d: [{e: 'thing'}], f: {g: 10}}
11
+ }
12
+
13
+ context "when the classes match" do
14
+ let(:actual) { {a: 'another string', b: 2, c: nil, d: [{e: 'something'}], f: {g: 100}} }
15
+ it "returns an empty hash" do
16
+ expect(structure_diff(expected, actual)).to be_empty
17
+ end
18
+ end
19
+
20
+ context "when a number is expected" do
21
+ let(:expected) { {a: 1} }
22
+ #let(:difference) { {a: {expected: 'Fixnum (eg. 1)', actual: 'String ("a string")'}} }
23
+ let(:difference) { {a: {expected: {:class => Fixnum, eg: 1 } , actual: {:class => String, :value => 'a string'}}} }
24
+
25
+ context "and a string is found" do
26
+ let(:actual) { {a: 'a string'}}
27
+ it "returns the diff" do
28
+ expect(structure_diff(expected, actual)).to eq difference
29
+ end
30
+ end
31
+ context "and nil is found" do
32
+ let(:actual) { {a: nil}}
33
+ let(:difference ) { {a: {:expected => {:class => Fixnum, eg: 1}, :actual => nil} } }
34
+ it "returns the diff" do
35
+ expect(structure_diff(expected, actual)).to eq difference
36
+ end
37
+ end
38
+ context "and a hash is found" do
39
+ let(:actual) { {a: {b: 1}} }
40
+ let(:difference) { {:a=>{:expected=>{:class=>Fixnum, :eg=>1}, :actual=>{:class=>Hash, :value=>{:b=>1}}}} }
41
+ it "returns the diff" do
42
+ expect(structure_diff(expected, actual)).to eq difference
43
+ end
44
+ end
45
+ context "and an array is found" do
46
+ let(:actual) { {a: [1] } }
47
+ let(:difference) { {:a=>{:expected=>{:class=>Fixnum, :eg=>1}, :actual=>{:class=>Array, :value=>[1]}}} }
48
+ it "returns the diff" do
49
+ expect(structure_diff(expected, actual)).to eq difference
50
+ end
51
+ end
52
+ end
53
+
54
+ context "when an array is expected" do
55
+ let(:expected) { [{name: 'Fred'}, {name: 'Mary'}] }
56
+ context "when an item with differing class values is found" do
57
+ let(:actual) { [{name: 'Fred'}, {name: 1}] }
58
+ let(:difference) { [
59
+ Pact::Matchers::NO_DIFF_INDICATOR,
60
+ {:name => {
61
+ :expected=> { :class=>String, :eg=>"Mary" },
62
+ :actual=> { :class=>Fixnum, :value=>1} }
63
+ }
64
+ ]
65
+ }
66
+ it "returns the diff" do
67
+ expect(structure_diff(expected, actual)).to eq difference
68
+ end
69
+ end
70
+ end
71
+
72
+
73
+ context "when nil is expected" do
74
+ let(:expected) { {a: nil} }
75
+ context "and a string is found" do
76
+ let(:actual) { {a: 'a string'} }
77
+ let(:difference) { {:a=>{:expected=>nil, :actual=>{:class=>String, :value=>"a string"}}} }
78
+ it "returns the diff" do
79
+ expect(structure_diff(expected, actual)).to eq difference
80
+ end
81
+ end
82
+ end
83
+
84
+ context "when a term is expected" do
85
+ let(:expected) { {a: Pact::Term.new(:matcher => /p/, :generate => 'apple')} }
86
+ context "and a non matching string is found" do
87
+ let(:actual) { {a: 'banana'} }
88
+ let(:difference) { {:a=>{:expected=>/p/, :actual=>"banana"}} }
89
+ it "returns the diff" do
90
+ expect(structure_diff(expected, actual)).to eq difference
91
+ end
92
+ end
93
+ end
94
+ end
95
+
96
+ describe 'diffing' do
97
+
98
+ context 'where an expected value is a non-empty string' do
99
+
100
+ subject { {:a => 'a', :b => 'b'} }
101
+
102
+ context 'and the actual value is an empty string' do
103
+
104
+ let(:actual) { {:a => 'a', :b => ''} }
105
+
106
+ it 'includes this in the diff' do
107
+ expect(diff(subject, actual)).to eql({:b => {:expected => 'b', :actual => ''}})
108
+ end
109
+
110
+ end
111
+
112
+ end
113
+
114
+ context "when the expected value is a hash" do
115
+ subject { {a: 'b'} }
116
+ context "when the actual value is an array" do
117
+ let(:actual) { [1] }
118
+ let(:difference) { {expected: subject, actual: actual} }
119
+ it "should return the diff" do
120
+ expect(diff(subject, actual)).to eql(difference)
121
+ end
122
+ end
123
+ context "when the actual value is an hash" do
124
+ let(:actual) { {b: 'c'} }
125
+ let(:difference) { { a: {expected:"b", actual: nil}} }
126
+ it "should return the diff" do
127
+ expect(diff(subject, actual)).to eql(difference)
128
+ end
129
+ end
130
+ context "when the actual value is an number" do
131
+ let(:actual) { 1 }
132
+ let(:difference) { {expected: {a: "b"}, actual: 1} }
133
+ it "should return the diff" do
134
+ expect(diff(subject, actual)).to eql(difference)
135
+ end
136
+ end
137
+ context "when the actual value is a string" do
138
+ let(:actual) { "Thing" }
139
+ let(:difference) { {expected: subject, actual: actual} }
140
+ it "should return the diff" do
141
+ expect(diff(subject, actual)).to eql(difference)
142
+ end
143
+ end
144
+ context "when the actual value is the same" do
145
+ let (:actual) { {a: 'b'} }
146
+ it "should return an empty hash" do
147
+ expect(diff(subject, actual)).to eql({})
148
+ end
149
+ end
150
+ end
151
+
152
+ context "when the expected value is an array" do
153
+ subject { [1] }
154
+ context "when the actual value is an array" do
155
+ let(:actual) { [2] }
156
+ let(:difference) { {expected: subject, actual: actual} }
157
+ it "should return the diff" do
158
+ expect(diff(subject, actual)).to eql([{expected: 1, actual: 2}])
159
+ end
160
+ end
161
+ context "when the actual value is an hash" do
162
+ let(:actual) { {b: 'c'} }
163
+ let(:difference) { {expected: subject, actual: actual} }
164
+ it "should return the diff" do
165
+ expect(diff(subject, actual)).to eql(difference)
166
+ end
167
+ end
168
+ context "when the actual value is an number" do
169
+ let(:actual) { 1 }
170
+ let(:difference) { {expected: subject, actual: actual} }
171
+ it "should return the diff" do
172
+ expect(diff(subject, actual)).to eql(difference)
173
+ end
174
+ end
175
+ context "when the actual value is a string" do
176
+ let(:actual) { "Thing" }
177
+ let(:difference) { {expected: subject, actual: actual} }
178
+ it "should return the diff" do
179
+ expect(diff(subject, actual)).to eql(difference)
180
+ end
181
+ end
182
+ context "when the actual value is the same" do
183
+ let (:actual) { [1] }
184
+ it "should return an empty hash" do
185
+ expect(diff(subject, actual)).to eql({})
186
+ end
187
+ end
188
+ end
189
+
190
+ context "when the expected value is a string" do
191
+ subject { "Thing"}
192
+ context "when the actual value is an array" do
193
+ let(:actual) { [2] }
194
+ let(:difference) { {expected: subject, actual: actual} }
195
+ it "should return the diff" do
196
+ expect(diff(subject, actual)).to eql(difference)
197
+ end
198
+ end
199
+ context "when the actual value is an hash" do
200
+ let(:actual) { {b: 'c'} }
201
+ let(:difference) { {expected: subject, actual: actual} }
202
+ it "should return the diff" do
203
+ expect(diff(subject, actual)).to eql(difference)
204
+ end
205
+ end
206
+ context "when the actual value is an number" do
207
+ let(:actual) { 1 }
208
+ let(:difference) { {expected: subject, actual: actual} }
209
+ it "should return the diff" do
210
+ expect(diff(subject, actual)).to eql(difference)
211
+ end
212
+ end
213
+ context "when the actual value is a string" do
214
+ let(:actual) { "Another Thing" }
215
+ let(:difference) { {expected: subject, actual: actual} }
216
+ it "should return the diff" do
217
+ expect(diff(subject, actual)).to eql(difference)
218
+ end
219
+ end
220
+ context "when the actual value is the same" do
221
+ let (:actual) { "Thing" }
222
+ it "should return an empty hash" do
223
+ expect(diff(subject, actual)).to eql({})
224
+ end
225
+ end
226
+ end
227
+
228
+ context "when the expected value is a number" do
229
+ subject { 1 }
230
+ let(:difference) { {expected: subject, actual: actual} }
231
+ context "when the actual value is an array" do
232
+ let(:actual) { [2] }
233
+ it "should return the diff" do
234
+ expect(diff(subject, actual)).to eql(difference)
235
+ end
236
+ end
237
+ context "when the actual value is an hash" do
238
+ let(:actual) { {b: 'c'} }
239
+ it "should return the diff" do
240
+ expect(diff(subject, actual)).to eql(difference)
241
+ end
242
+ end
243
+ context "when the actual value is an number" do
244
+ let(:actual) { 2 }
245
+ it "should return the diff" do
246
+ expect(diff(subject, actual)).to eql(difference)
247
+ end
248
+ end
249
+ context "when the actual value is a string" do
250
+ let(:actual) { "Another Thing" }
251
+ it "should return the diff" do
252
+ expect(diff(subject, actual)).to eql(difference)
253
+ end
254
+ end
255
+ context "when the actual value is the same" do
256
+ let (:actual) { 1 }
257
+ it "should return an empty hash" do
258
+ expect(diff(subject, actual)).to eql({})
259
+ end
260
+ end
261
+ end
262
+
263
+ context "when the expected value is a String matcher" do
264
+
265
+ end
266
+
267
+ context "when the expected value is a Number matcher" do
268
+
269
+ end
270
+ context "when the expected value is an array with a matcher" do
271
+
272
+ end
273
+ context "when the expected value is a hash with a matcher" do
274
+
275
+ end
276
+
277
+ context "when an expected value is nil but not nil is found" do
278
+ subject { {a: nil} }
279
+ let(:actual) { {a: 'blah'} }
280
+ let(:difference) { {:a=>{:expected=>nil, :actual=>"blah"}} }
281
+ it "should return the diff" do
282
+ expect(diff(subject, actual)).to eql(difference)
283
+ end
284
+ end
285
+
286
+ context "a deep mismatch" do
287
+ subject { {a: {b: { c: [1,2]}, d: { e: Pact::Term.new(matcher: /a/)}}, f: 1, g: {h: 99}} }
288
+ let(:actual) { {a: {b: { c: [1,2]}, d: { e: 'food'}}, f: "thing"} }
289
+ let(:difference) { {:a=>{:d=>{:e=>{:expected=>/a/, :actual=>"food"}}}, :f=>{:expected=>1, :actual=>"thing"}, :g=>{:expected=>{:h=>99}, :actual=>nil}} }
290
+
291
+ it 'should return the diff' do
292
+ expect(diff(subject, actual)).to eql(difference)
293
+ end
294
+ end
295
+
296
+
297
+ context "where a Pact::Term is found that matches the actual value" do
298
+ subject { {:a => Pact::Term.new(:matcher => /a/)} }
299
+ let(:actual) { {:a => "apple" } }
300
+
301
+ it 'does not include this in the diff' do
302
+ expect(diff(subject, actual)).to eql({})
303
+ end
304
+ end
305
+
306
+ context "where an array is expected at a key inside a hash, but a hash is found" do
307
+ subject { {:a => [1,2,3]} }
308
+ let(:actual) { {:a => {:b => 1} } }
309
+
310
+ it 'includes this in the diff' do
311
+ expect(diff(subject, actual)).to eql({:a => {:expected => [1,2,3], :actual => {:b => 1}}})
312
+ end
313
+ end
314
+
315
+ context "where an array is expected, but a hash is found" do
316
+ subject { {:a => :b} }
317
+ let(:actual) { [4,5,6] }
318
+
319
+ it 'includes this in the diff' do
320
+ expect(diff(subject, actual)).to eql({:expected => {:a => :b}, :actual => [4,5,6] })
321
+ end
322
+ end
323
+
324
+ context "where a hash is expected, but array is found" do
325
+ subject { [4,5,6] }
326
+ let(:actual) { {:a => :b} }
327
+
328
+ it 'includes this in the diff' do
329
+ expect(diff(subject, actual)).to eql({:expected => [4,5,6], :actual => {:a => :b} })
330
+ end
331
+ end
332
+
333
+ context "when two different arrays are found" do
334
+ subject { [4,5,6] }
335
+ let(:actual) { [4,6,7] }
336
+ let(:difference) { [Pact::Matchers::NO_DIFF_INDICATOR, {:expected=>5, :actual=>6}, {:expected=>6, :actual=>7}] }
337
+
338
+ it 'includes this in the diff' do
339
+ expect(diff(subject, actual)).to eql(difference)
340
+ end
341
+ end
342
+
343
+ context "when an array that matches the Pact::Term is found" do
344
+ subject { [Pact::Term.new(:matcher => /4/),"5","6"] }
345
+ let(:actual) { ["4","5","6"] }
346
+
347
+ it 'includes this in the diff' do
348
+ expect(diff(subject, actual)).to eql({})
349
+ end
350
+ end
351
+
352
+ end
353
+
354
+ end
@@ -0,0 +1,101 @@
1
+ require 'spec_helper'
2
+ require 'pact/producer/configuration_dsl'
3
+
4
+ module Pact::Producer
5
+ describe ConfigurationDSL do
6
+
7
+ class MockConfig
8
+ include ConfigurationDSL
9
+ end
10
+
11
+ describe "producer" do
12
+ let(:mock_config) { MockConfig.new }
13
+ context "when a producer is configured" do
14
+ before do
15
+ mock_config.producer do
16
+ name "Fred"
17
+ app { "An app" }
18
+ end
19
+ end
20
+ it "should allow configuration of the name" do
21
+ expect(mock_config.producer.name).to eql "Fred"
22
+ end
23
+ it "should allow configuration of the test app" do
24
+ expect(mock_config.producer.app).to eql "An app"
25
+ end
26
+ end
27
+ context "when a producer is not configured" do
28
+ it "raises an error" do
29
+ expect{ mock_config.producer }.to raise_error(/Please configure your producer/)
30
+ end
31
+ end
32
+ end
33
+
34
+
35
+ module ConfigurationDSL
36
+
37
+ describe ProducerDSL do
38
+
39
+ describe "initialize" do
40
+
41
+ context "with an object instead of a block" do
42
+ subject do
43
+ ProducerDSL.new do
44
+ name nil
45
+ app 'blah'
46
+ end
47
+ end
48
+ it "raises an error" do
49
+ expect{ subject }.to raise_error
50
+ end
51
+ end
52
+
53
+
54
+ end
55
+ describe "validate" do
56
+ context "when no name is provided" do
57
+ subject do
58
+ ProducerDSL.new do
59
+ app { Object.new }
60
+ end
61
+ end
62
+ it "raises an error" do
63
+ expect{ subject.validate}.to raise_error("Please provide a name for the Producer")
64
+ end
65
+ end
66
+ context "when nil name is provided" do
67
+ subject do
68
+ ProducerDSL.new do
69
+ name nil
70
+ app { Object.new }
71
+ end
72
+ end
73
+ it "raises an error" do
74
+ expect{ subject.validate}.to raise_error("Please provide a name for the Producer")
75
+ end
76
+ end
77
+ context "when no app is provided" do
78
+ subject do
79
+ ProducerDSL.new do
80
+ name 'Blah'
81
+ end
82
+ end
83
+ it "raises an error" do
84
+ expect{ subject.validate }.to raise_error("Please configure an app for the Producer")
85
+ end
86
+ end
87
+ end
88
+ end
89
+
90
+ describe ProducerConfig do
91
+ describe "app" do
92
+ subject { ProducerConfig.new("blah") { Object.new } }
93
+ it "should execute the app_block each time" do
94
+ expect(subject.app.object_id).to_not equal(subject.app.object_id)
95
+ end
96
+ end
97
+ end
98
+
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,103 @@
1
+ require 'spec_helper'
2
+ require 'pact/producer/producer_state'
3
+
4
+ module Pact
5
+ module Producer
6
+
7
+ describe 'global ProducerState' do
8
+
9
+ MESSAGES = []
10
+
11
+ Pact.producer_state :no_alligators do
12
+ set_up do
13
+ MESSAGES << 'set_up'
14
+ end
15
+ tear_down do
16
+ MESSAGES << 'tear_down'
17
+ end
18
+ end
19
+
20
+ Pact.producer_state 'some alligators' do
21
+ end
22
+
23
+ before do
24
+ MESSAGES.clear
25
+ end
26
+
27
+ subject { ProducerState.get('no_alligators') }
28
+
29
+ describe 'set_up' do
30
+ it 'should call the block passed to set_up' do
31
+ subject.set_up
32
+ MESSAGES.should eq ['set_up']
33
+ end
34
+ end
35
+
36
+ describe 'tear_down' do
37
+ it 'should call the block passed to set_up' do
38
+ subject.tear_down
39
+ MESSAGES.should eq ['tear_down']
40
+ end
41
+ end
42
+
43
+ describe '.get' do
44
+ context 'when the name is a matching symbol' do
45
+ it 'will return the ProducerState' do
46
+ ProducerState.get('no_alligators').should_not be_nil
47
+ end
48
+ end
49
+ context 'when the name is a matching string' do
50
+ it 'will return the ProducerState' do
51
+ ProducerState.get('some alligators').should_not be_nil
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+
58
+ describe 'namespaced ProducerStates' do
59
+
60
+ NAMESPACED_MESSAGES = []
61
+
62
+ Pact.with_consumer 'a consumer' do
63
+ producer_state 'the weather is sunny' do
64
+ set_up do
65
+ NAMESPACED_MESSAGES << 'sunny!'
66
+ end
67
+ end
68
+ end
69
+
70
+ Pact.producer_state 'the weather is cloudy' do
71
+ set_up do
72
+ NAMESPACED_MESSAGES << 'cloudy :('
73
+ end
74
+ end
75
+
76
+ before do
77
+ NAMESPACED_MESSAGES.clear
78
+ end
79
+
80
+ describe '.get' do
81
+ context 'for a consumer' do
82
+ it 'has a namespaced name' do
83
+ ProducerState.get('the weather is sunny', :for => 'a consumer').should_not be_nil
84
+ end
85
+
86
+ it 'falls back to a global state of the same name if one is not found for the specified consumer' do
87
+ ProducerState.get('the weather is cloudy', :for => 'a consumer').should_not be_nil
88
+ end
89
+ end
90
+
91
+ end
92
+
93
+ describe 'set_up' do
94
+ context 'for a consumer' do
95
+ it 'runs its own setup' do
96
+ ProducerState.get('the weather is sunny', :for => 'a consumer').set_up
97
+ NAMESPACED_MESSAGES.should eq ['sunny!']
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,48 @@
1
+ require 'pact/producer/rspec'
2
+
3
+ describe "the match_term matcher" do
4
+
5
+ it 'does not match a hash to an array' do
6
+ expect({}).to_not match_term([])
7
+ end
8
+
9
+ it 'does not match an array to a hash' do
10
+ expect([]).to_not match_term({})
11
+ end
12
+
13
+ it 'matches regular expressions' do
14
+ expect('blah').to match_term(/[a-z]*/)
15
+ end
16
+
17
+ it 'matches pact terms' do
18
+ expect('wootle').to match_term Pact::Term.new(generate:'wootle', matcher:/woot../)
19
+ end
20
+
21
+ it 'matches all elements of arrays' do
22
+ expect(['one', 'two', ['three']]).to match_term [/one/, 'two', [Pact::Term.new(generate:'three', matcher:/thr../)]]
23
+ end
24
+
25
+ it 'matches all values of hashes' do
26
+ expect({1 => 'one', 2 => 2, 3 => 'three'}).to match_term({1 => /one/, 2 => 2, 3 => Pact::Term.new(generate:'three', matcher:/thr../)})
27
+ end
28
+
29
+ it 'matches all other objects using ==' do
30
+ expect('wootle').to match_term 'wootle'
31
+ end
32
+
33
+ # Note: because a consumer specifies only the keys it cares about, the pact ignores keys that are returned
34
+ # by the producer, but not are not specified in the pact. This means that any hash will match an
35
+ # expected empty hash, because there is currently no way for a consumer to expect an absence of keys.
36
+ it 'is confused by an empty hash' do
37
+ expect({:hello => 'everyone'}).to match_term({})
38
+ end
39
+
40
+ it 'should not be confused by an empty array' do
41
+ expect(['blah']).to_not match_term([])
42
+ end
43
+
44
+ it "should allow matches on an array where each item in the array only contains a subset of the actual" do
45
+ expect([{name: 'Fred', age: 12}, {name: 'John', age: 13}]).to match_term([{name: 'Fred'}, {name: 'John'}])
46
+ end
47
+
48
+ end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ module Pact
4
+ describe Reification do
5
+
6
+ let(:response_spec) do
7
+ {
8
+ woot: /x/,
9
+ britney: 'britney',
10
+ nested: { foo: /bar/, baz: 'qux' },
11
+ my_term: Term.new(generate: 'wiffle', matcher: /^wif/),
12
+ array: ['first', /second/]
13
+ }
14
+ end
15
+
16
+ describe "from term" do
17
+
18
+ subject { Reification.from_term(response_spec) }
19
+
20
+ it "converts regexes into real data" do
21
+ expect(subject[:woot]).to eql 'x'
22
+ end
23
+
24
+ it "converts terms into real data" do
25
+ expect(subject[:my_term]).to eql 'wiffle'
26
+ end
27
+
28
+ it "passes strings through" do
29
+ expect(subject[:britney]).to eql 'britney'
30
+ end
31
+
32
+ it "handles nested hashes" do
33
+ expect(subject[:nested]).to eql({ foo: 'bar', baz: 'qux' })
34
+ end
35
+
36
+ it "handles arrays" do
37
+ expect(subject[:array]).to eql ['first', 'second']
38
+ end
39
+
40
+ end
41
+
42
+ end
43
+ end