pact 1.0.22 → 1.0.23

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.
@@ -2,6 +2,10 @@ Do this to generate your change history
2
2
 
3
3
  git log --date=relative --pretty=format:' * %h - %s (%an, %ad)'
4
4
 
5
+ ### 1.0.23 (29 November 2013)
6
+
7
+ * a978654 - Improving the display of verification errors in the consumer project. (Beth Skurrie, 2 days ago)
8
+
5
9
  ### 1.0.22 (25 November 2013)
6
10
 
7
11
  * f742833 - Updating README (Beth Skurrie, 36 seconds ago)
data/Gemfile CHANGED
@@ -1,5 +1,5 @@
1
1
  source 'https://rubygems.org'
2
-
2
+ source 'http://rea-rubygems'
3
3
  # Specify your gem's dependencies in pact.gemspec
4
4
  gemspec
5
5
 
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- pact (1.0.22)
4
+ pact (1.0.23)
5
5
  awesome_print (~> 1.1.0)
6
6
  find_a_port (~> 1.0.1)
7
7
  json
@@ -13,6 +13,7 @@ PATH
13
13
 
14
14
  GEM
15
15
  remote: https://rubygems.org/
16
+ remote: http://rea-rubygems/
16
17
  specs:
17
18
  activesupport (4.0.0)
18
19
  i18n (~> 0.6, >= 0.6.4)
@@ -4,6 +4,7 @@ module Pact
4
4
 
5
5
  attr_reader :interactions
6
6
  attr_reader :unexpected_requests
7
+ attr_reader :interaction_mismatches
7
8
 
8
9
  def initialize
9
10
  clear
@@ -13,6 +14,7 @@ module Pact
13
14
  def clear
14
15
  @interactions = []
15
16
  @matched_interactions = []
17
+ @interaction_mismatches = []
16
18
  @unexpected_requests = []
17
19
  end
18
20
 
@@ -28,18 +30,35 @@ module Pact
28
30
  @unexpected_requests << request
29
31
  end
30
32
 
33
+ def register_interaction_mismatch interaction_mismatch
34
+ @interaction_mismatches << interaction_mismatch
35
+ end
36
+
31
37
  def all_matched?
32
38
  interaction_diffs.empty?
33
39
  end
34
40
 
35
41
  def missing_interactions
36
- @interactions - @matched_interactions
42
+ @interactions - @matched_interactions - @interaction_mismatches.collect(&:candidate_interactions).flatten
43
+ end
44
+
45
+ def missing_interactions_summaries
46
+ missing_interactions.collect(&:request).collect(&:method_and_path)
47
+ end
48
+
49
+ def interaction_mismatches_summaries
50
+ interaction_mismatches.collect(&:short_summary)
51
+ end
52
+
53
+ def unexpected_requests_summaries
54
+ unexpected_requests.collect(&:method_and_path)
37
55
  end
38
56
 
39
57
  def interaction_diffs
40
58
  {
41
- :missing_interactions => missing_interactions.collect(&:as_json),
42
- :unexpected_requests => unexpected_requests.collect(&:as_json)
59
+ :missing_interactions => missing_interactions_summaries,
60
+ :interaction_mismatches => interaction_mismatches_summaries,
61
+ :unexpected_requests => unexpected_requests_summaries
43
62
  }.inject({}) do | hash, pair |
44
63
  hash[pair.first] = pair.last if pair.last.any?
45
64
  hash
@@ -49,9 +68,9 @@ module Pact
49
68
  def find_candidate_interactions actual_request
50
69
  interactions.select do | interaction |
51
70
  interaction.request.matches_route? actual_request
52
- end
53
- end
71
+ end
72
+ end
54
73
 
55
- end
74
+ end
56
75
  end
57
76
  end
@@ -0,0 +1,51 @@
1
+ module Pact
2
+ module Consumer
3
+ class InteractionMismatch
4
+
5
+ attr_accessor :candidate_interactions, :actual_request
6
+
7
+ # Assumes the method and path matches...
8
+
9
+ def initialize candidate_interactions, actual_request
10
+ @candidate_interactions = candidate_interactions
11
+ @actual_request = actual_request
12
+ @candiate_diffs = candidate_interactions.collect{ | candidate_interaction| CandidateDiff.new(candidate_interaction, actual_request)}
13
+ end
14
+
15
+ def diffs
16
+ candiate_diffs.collect(&:diff_summary)
17
+ end
18
+
19
+ def short_summary
20
+ mismatched_attributes = candiate_diffs.collect(&:mismatched_attributes).flatten.uniq.join(", ").reverse.sub(",", "dna ").reverse #OMG what a hack!
21
+ actual_request.method_and_path + " (#{mismatched_attributes} did not match)"
22
+ end
23
+
24
+ private
25
+
26
+ attr_accessor :candiate_diffs
27
+
28
+ class CandidateDiff
29
+ attr_accessor :candidate_interaction, :actual_request
30
+ def initialize candidate_interaction, actual_request
31
+ @candidate_interaction = candidate_interaction
32
+ @actual_request = actual_request
33
+ end
34
+
35
+ def mismatched_attributes
36
+ diff.keys
37
+ end
38
+
39
+ def diff_summary
40
+ summary = {:description => candidate_interaction.description}
41
+ summary[:provider_state] = candidate_interaction.provider_state if candidate_interaction.provider_state
42
+ summary.merge(diff)
43
+ end
44
+
45
+ def diff
46
+ @diff ||= candidate_interaction.request.difference(actual_request)
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -1,5 +1,6 @@
1
1
  require 'pact/matchers'
2
2
  require 'pact/consumer/mock_service/rack_request_helper'
3
+ require 'pact/consumer/mock_service/interaction_mismatch'
3
4
 
4
5
  module Pact
5
6
  module Consumer
@@ -70,11 +71,8 @@ module Pact
70
71
  multiple_interactions_found_response actual_request, matching_interactions
71
72
  end
72
73
 
73
- def interaction_diffs actual_request, candidate_interactions
74
- candidate_interactions.collect do | candidate_interaction |
75
- diff = candidate_interaction.request.difference(actual_request)
76
- diff_summary_for candidate_interaction, diff
77
- end
74
+ def interaction_mismatch actual_request, candidate_interactions
75
+ InteractionMismatch.new(candidate_interactions, actual_request)
78
76
  end
79
77
 
80
78
  def diff_summary_for interaction, diff
@@ -90,25 +88,29 @@ module Pact
90
88
  summary
91
89
  end
92
90
 
93
- def unrecognised_request_response actual_request, interaction_diffs
91
+ def unrecognised_request_response interaction_mismatch
94
92
  response = {
95
- message: "No interaction found for #{actual_request.method_and_path}",
96
- interaction_diffs: interaction_diffs
93
+ message: "No interaction found for #{interaction_mismatch.actual_request.method_and_path}",
94
+ interaction_diffs: interaction_mismatch.diffs
97
95
  }
98
96
  [500, {'Content-Type' => 'application/json'}, [response.to_json]]
99
97
  end
100
98
 
101
- def log_unrecognised_request_and_interaction_diff actual_request, interaction_diffs, candidate_interactions
102
- logger.error "No interaction found on #{name} for #{actual_request.method_and_path}"
99
+ def log_unrecognised_request_and_interaction_diff interaction_mismatch
100
+ logger.error "No interaction found on #{name} for #{interaction_mismatch.actual_request.method_and_path}"
103
101
  logger.error 'Interaction diffs for that route:'
104
- logger.ap(interaction_diffs, :error)
102
+ logger.ap(interaction_mismatch.diffs, :error)
105
103
  end
106
104
 
107
105
  def handle_unrecognised_request actual_request, candidate_interactions
108
- interaction_list.register_unexpected_request actual_request
109
- interaction_diffs = interaction_diffs(actual_request, candidate_interactions)
110
- log_unrecognised_request_and_interaction_diff actual_request, interaction_diffs, candidate_interactions
111
- unrecognised_request_response actual_request, interaction_diffs
106
+ interaction_mismatch = interaction_mismatch(actual_request, candidate_interactions)
107
+ if candidate_interactions.any?
108
+ interaction_list.register_interaction_mismatch interaction_mismatch
109
+ else
110
+ interaction_list.register_unexpected_request actual_request
111
+ end
112
+ log_unrecognised_request_and_interaction_diff interaction_mismatch
113
+ unrecognised_request_response interaction_mismatch
112
114
  end
113
115
 
114
116
  def response_from response
@@ -26,9 +26,19 @@ module Pact
26
26
  logger.info "Verifying - interactions matched for example \"#{example_description(env)}\""
27
27
  [200, {}, ['Interactions matched']]
28
28
  else
29
- logger.warn "Verifying - actual interactions do not match expected interactions for example \"#{example_description(env)}\". Interaction diffs:"
30
- logger.ap interaction_list.interaction_diffs, :warn
31
- [500, {}, ["Actual interactions do not match expected interactions for mock #{name}. See #{log_description} for details."]]
29
+
30
+ missing_interactions_summaries = interaction_list.missing_interactions_summaries
31
+ interaction_mismatches_summaries = interaction_list.interaction_mismatches_summaries
32
+ unexpected_requests_summaries = interaction_list.unexpected_requests_summaries
33
+ error_message = "Missing requests:
34
+ #{missing_interactions_summaries.join("\n ")}
35
+ Incorrect requests:
36
+ #{interaction_mismatches_summaries.join("\n ")}
37
+ Unexpected requests:
38
+ #{unexpected_requests_summaries.join("\n ")}"
39
+ logger.warn "Verifying - actual interactions do not match expected interactions for example \"#{example_description(env)}\". \n#{error_message}"
40
+ logger.warn error_message
41
+ [500, {}, ["Actual interactions do not match expected interactions for mock #{name}.\n#{error_message}\nSee #{log_description} for details."]]
32
42
  end
33
43
  end
34
44
 
@@ -12,7 +12,7 @@ module Pact
12
12
 
13
13
  def verify example_description
14
14
  response = http.request_get("/verify?example_description=#{URI.encode(example_description)}", MOCK_SERVICE_ADMINISTRATON_HEADERS)
15
- raise response.body unless response.is_a? Net::HTTPSuccess
15
+ raise "\e[31m#{response.body}\e[m" unless response.is_a? Net::HTTPSuccess
16
16
  end
17
17
 
18
18
  def log msg
@@ -20,8 +20,8 @@ module Pact
20
20
 
21
21
  def self.key_not_found
22
22
  nil
23
- end
24
- end
23
+ end
24
+ end
25
25
  end
26
26
  end
27
27
  end
@@ -1,3 +1,3 @@
1
1
  module Pact
2
- VERSION = "1.0.22"
2
+ VERSION = "1.0.23"
3
3
  end
@@ -6,18 +6,21 @@ module Pact::Consumer
6
6
  describe InteractionList do
7
7
  shared_context "unexpected requests and missed interactions" do
8
8
  let(:expected_interaction) { InteractionFactory.create }
9
- let(:unexpected_request) { RequestFactory.create_actual }
9
+ let(:unexpected_request) { RequestFactory.create_actual method: 'put' }
10
+ let(:candidate_interaction) { double("Pact::Interaction") }
11
+ let(:candidate_interactions) { [candidate_interaction] }
12
+ let(:interaction_mismatch) { instance_double("Pact::Consumer::InteractionMismatch", :short_summary => 'blah', :candidate_interactions => candidate_interactions)}
10
13
  subject {
11
14
  interactionList = InteractionList.new
12
15
  interactionList.add expected_interaction
13
16
  interactionList.register_unexpected_request unexpected_request
17
+ interactionList.register_interaction_mismatch interaction_mismatch
14
18
  interactionList
15
19
  }
16
20
  end
17
21
 
18
22
  shared_context "no unexpected requests or missed interactions exist" do
19
23
  let(:expected_interaction) { InteractionFactory.create }
20
- let(:unexpected_request) { RequestFactory.create_actual }
21
24
  subject {
22
25
  interactionList = InteractionList.new
23
26
  interactionList.add expected_interaction
@@ -30,7 +33,9 @@ module Pact::Consumer
30
33
  context "when unexpected requests and missed interactions exist" do
31
34
  include_context "unexpected requests and missed interactions"
32
35
  let(:expected_diff) {
33
- {:missing_interactions=>[expected_interaction.as_json], :unexpected_requests=>[unexpected_request.as_json]}
36
+ {:missing_interactions=>["GET /path"],
37
+ :unexpected_requests=>["PUT /path"],
38
+ :interaction_mismatches => ['blah']}
34
39
  }
35
40
  it "returns the unexpected requests and missed interactions" do
36
41
  expect(subject.interaction_diffs).to eq expected_diff
@@ -62,5 +67,12 @@ module Pact::Consumer
62
67
  end
63
68
  end
64
69
  end
70
+
71
+ describe "missing_interactions_summaries" do
72
+ include_context "unexpected requests and missed interactions"
73
+ it "returns a list of the method and paths for each missing interaction" do
74
+ expect(subject.missing_interactions_summaries).to eq ["GET /path"]
75
+ end
76
+ end
65
77
  end
66
78
  end
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+ require 'pact/consumer/mock_service/interaction_mismatch'
3
+
4
+ module Pact
5
+ module Consumer
6
+ describe InteractionMismatch do
7
+ let(:actual_request) { instance_double('Pact::Consumer::Request::Actual', :method_and_path => 'GET /path') }
8
+ let(:expected_request_1) { instance_double('Pact::Request::Expected') }
9
+ let(:expected_request_2) { instance_double('Pact::Request::Expected') }
10
+ let(:candidate_1) { instance_double('Pact::Interaction', request: expected_request_1) }
11
+ let(:candidate_2) { instance_double('Pact::Interaction', request: expected_request_2) }
12
+ let(:candidate_interactions) { [candidate_1, candidate_2] }
13
+ subject { InteractionMismatch.new(candidate_interactions, actual_request) }
14
+ let(:diff_1) { {body: nil} }
15
+ let(:diff_2) { {} }
16
+
17
+ before do
18
+ expected_request_1.stub(:difference).with(actual_request).and_return(diff_1)
19
+ expected_request_2.stub(:difference).with(actual_request).and_return(diff_2)
20
+ end
21
+
22
+ describe "short_summary" do
23
+ it "includes the method and path" do
24
+ expect(subject.short_summary).to match /GET \/path \(.*\)/
25
+ end
26
+ context "when the body does not match" do
27
+ let(:diff_1) { {body: nil} }
28
+
29
+ it "returns a message indicating that the body does not match" do
30
+ expect(subject.short_summary).to include "(body did not match)"
31
+ end
32
+ end
33
+ context "when the headers do not match" do
34
+ let(:diff_1) { {headers: nil} }
35
+ it "returns a message indicating that the body does not match" do
36
+ expect(subject.short_summary).to include "(headers did not match)"
37
+ end
38
+ end
39
+ context "when the headers and body do not match" do
40
+ let(:diff_1) { {body: nil, headers: nil} }
41
+ let(:diff_2) { {body: nil, headers: nil} }
42
+ it "returns a message indicating that the headers and body do not match" do
43
+ expect(subject.short_summary).to include "(body and headers did not match)"
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -76,7 +76,7 @@ class RequestFactory
76
76
  deep_merge(DEFAULTS, overrides)
77
77
  end
78
78
 
79
- def self.create_actual
80
- Pact::Consumer::Request::Actual.from_hash(create_hash)
79
+ def self.create_actual overrides = {}
80
+ Pact::Consumer::Request::Actual.from_hash(create_hash(overrides))
81
81
  end
82
82
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pact
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.22
4
+ version: 1.0.23
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ authors:
13
13
  autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
- date: 2013-11-25 00:00:00.000000000 Z
16
+ date: 2013-11-28 00:00:00.000000000 Z
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
19
19
  name: randexp
@@ -307,6 +307,7 @@ files:
307
307
  - lib/pact/consumer/mock_service/app.rb
308
308
  - lib/pact/consumer/mock_service/interaction_delete.rb
309
309
  - lib/pact/consumer/mock_service/interaction_list.rb
310
+ - lib/pact/consumer/mock_service/interaction_mismatch.rb
310
311
  - lib/pact/consumer/mock_service/interaction_post.rb
311
312
  - lib/pact/consumer/mock_service/interaction_replay.rb
312
313
  - lib/pact/consumer/mock_service/log_get.rb
@@ -372,6 +373,8 @@ files:
372
373
  - spec/lib/pact/consumer/interaction_builder_spec.rb
373
374
  - spec/lib/pact/consumer/interactions_spec.rb
374
375
  - spec/lib/pact/consumer/mock_service/interaction_list_spec.rb
376
+ - spec/lib/pact/consumer/mock_service/interaction_mismatch_spec.rb
377
+ - spec/lib/pact/consumer/mock_service/interaction_replay_spec.rb
375
378
  - spec/lib/pact/consumer/mock_service/rack_request_helper_spec.rb
376
379
  - spec/lib/pact/consumer/mock_service_interaction_expectation_spec.rb
377
380
  - spec/lib/pact/consumer/request_spec.rb
@@ -421,7 +424,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
421
424
  version: '0'
422
425
  segments:
423
426
  - 0
424
- hash: 1182047425998304532
427
+ hash: -1054460629994905299
425
428
  required_rubygems_version: !ruby/object:Gem::Requirement
426
429
  none: false
427
430
  requirements:
@@ -430,7 +433,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
430
433
  version: '0'
431
434
  segments:
432
435
  - 0
433
- hash: 1182047425998304532
436
+ hash: -1054460629994905299
434
437
  requirements: []
435
438
  rubyforge_project:
436
439
  rubygems_version: 1.8.23
@@ -453,6 +456,8 @@ test_files:
453
456
  - spec/lib/pact/consumer/interaction_builder_spec.rb
454
457
  - spec/lib/pact/consumer/interactions_spec.rb
455
458
  - spec/lib/pact/consumer/mock_service/interaction_list_spec.rb
459
+ - spec/lib/pact/consumer/mock_service/interaction_mismatch_spec.rb
460
+ - spec/lib/pact/consumer/mock_service/interaction_replay_spec.rb
456
461
  - spec/lib/pact/consumer/mock_service/rack_request_helper_spec.rb
457
462
  - spec/lib/pact/consumer/mock_service_interaction_expectation_spec.rb
458
463
  - spec/lib/pact/consumer/request_spec.rb