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.
- data/CHANGELOG.md +4 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +2 -1
- data/lib/pact/consumer/mock_service/interaction_list.rb +25 -6
- data/lib/pact/consumer/mock_service/interaction_mismatch.rb +51 -0
- data/lib/pact/consumer/mock_service/interaction_replay.rb +17 -15
- data/lib/pact/consumer/mock_service/verification_get.rb +13 -3
- data/lib/pact/consumer/mock_service_client.rb +1 -1
- data/lib/pact/consumer/request.rb +2 -2
- data/lib/pact/version.rb +1 -1
- data/spec/lib/pact/consumer/mock_service/interaction_list_spec.rb +15 -3
- data/spec/lib/pact/consumer/mock_service/interaction_mismatch_spec.rb +49 -0
- data/spec/lib/pact/consumer/mock_service/interaction_replay_spec.rb +0 -0
- data/spec/support/factories.rb +2 -2
- metadata +9 -4
data/CHANGELOG.md
CHANGED
@@ -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
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
pact (1.0.
|
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 =>
|
42
|
-
:
|
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
|
74
|
-
candidate_interactions
|
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
|
91
|
+
def unrecognised_request_response interaction_mismatch
|
94
92
|
response = {
|
95
|
-
message: "No interaction found for #{actual_request.method_and_path}",
|
96
|
-
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
|
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(
|
102
|
+
logger.ap(interaction_mismatch.diffs, :error)
|
105
103
|
end
|
106
104
|
|
107
105
|
def handle_unrecognised_request actual_request, candidate_interactions
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
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
|
-
|
30
|
-
|
31
|
-
|
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
|
data/lib/pact/version.rb
CHANGED
@@ -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=>[
|
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
|
File without changes
|
data/spec/support/factories.rb
CHANGED
@@ -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.
|
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-
|
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:
|
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:
|
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
|