pact 1.3.3 → 1.4.0.rc2
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 +16 -1
- data/Gemfile +5 -0
- data/Gemfile.lock +34 -13
- data/README.md +3 -2
- data/example/animal-service/lib/animal_service/api.rb +1 -0
- data/example/zoo-app/lib/zoo_app/animal_service_client.rb +0 -9
- data/example/zoo-app/lib/zoo_app/models/alligator.rb +2 -0
- data/lib/pact.rb +6 -5
- data/lib/pact/cli.rb +0 -26
- data/lib/pact/consumer/configuration.rb +0 -1
- data/lib/pact/consumer/configuration/configuration_extensions.rb +51 -0
- data/lib/pact/consumer/consumer_contract_builder.rb +1 -2
- data/lib/pact/consumer/interaction_builder.rb +2 -4
- data/lib/pact/doc/interaction_view_model.rb +9 -6
- data/lib/pact/doc/sort_interactions.rb +1 -1
- data/lib/pact/provider/rspec.rb +11 -9
- data/lib/pact/version.rb +1 -1
- data/pact.gemspec +5 -0
- data/spec/lib/pact/consumer/interaction_builder_spec.rb +4 -8
- data/spec/support/case-insensitive-response-header-matching.json +21 -0
- data/spec/support/case-insensitive-response-header-matching.rb +15 -0
- data/tasks/pact-test.rake +5 -0
- metadata +42 -122
- data/lib/pact/configuration.rb +0 -195
- data/lib/pact/consumer/app_manager.rb +0 -158
- data/lib/pact/consumer/interactions_filter.rb +0 -48
- data/lib/pact/consumer/mock_service.rb +0 -2
- data/lib/pact/consumer/mock_service/app.rb +0 -82
- data/lib/pact/consumer/mock_service/interaction_delete.rb +0 -33
- data/lib/pact/consumer/mock_service/interaction_list.rb +0 -76
- data/lib/pact/consumer/mock_service/interaction_mismatch.rb +0 -73
- data/lib/pact/consumer/mock_service/interaction_post.rb +0 -31
- data/lib/pact/consumer/mock_service/interaction_replay.rb +0 -139
- data/lib/pact/consumer/mock_service/log_get.rb +0 -28
- data/lib/pact/consumer/mock_service/missing_interactions_get.rb +0 -30
- data/lib/pact/consumer/mock_service/mock_service_administration_endpoint.rb +0 -31
- data/lib/pact/consumer/mock_service/pact_post.rb +0 -33
- data/lib/pact/consumer/mock_service/rack_request_helper.rb +0 -51
- data/lib/pact/consumer/mock_service/verification_get.rb +0 -68
- data/lib/pact/consumer/mock_service_client.rb +0 -65
- data/lib/pact/consumer/mock_service_interaction_expectation.rb +0 -37
- data/lib/pact/consumer/request.rb +0 -27
- data/lib/pact/consumer/server.rb +0 -90
- data/lib/pact/consumer_contract.rb +0 -1
- data/lib/pact/consumer_contract/consumer_contract.rb +0 -115
- data/lib/pact/consumer_contract/consumer_contract_writer.rb +0 -84
- data/lib/pact/consumer_contract/file_name.rb +0 -19
- data/lib/pact/consumer_contract/headers.rb +0 -51
- data/lib/pact/consumer_contract/interaction.rb +0 -67
- data/lib/pact/consumer_contract/pact_file.rb +0 -24
- data/lib/pact/consumer_contract/request.rb +0 -73
- data/lib/pact/consumer_contract/service_consumer.rb +0 -28
- data/lib/pact/consumer_contract/service_provider.rb +0 -28
- data/lib/pact/logging.rb +0 -14
- data/lib/pact/matchers.rb +0 -1
- data/lib/pact/matchers/actual_type.rb +0 -16
- data/lib/pact/matchers/base_difference.rb +0 -37
- data/lib/pact/matchers/differ.rb +0 -153
- data/lib/pact/matchers/difference.rb +0 -13
- data/lib/pact/matchers/difference_indicator.rb +0 -26
- data/lib/pact/matchers/embedded_diff_formatter.rb +0 -62
- data/lib/pact/matchers/expected_type.rb +0 -35
- data/lib/pact/matchers/index_not_found.rb +0 -15
- data/lib/pact/matchers/list_diff_formatter.rb +0 -101
- data/lib/pact/matchers/matchers.rb +0 -139
- data/lib/pact/matchers/no_diff_indicator.rb +0 -18
- data/lib/pact/matchers/regexp_difference.rb +0 -13
- data/lib/pact/matchers/type_difference.rb +0 -16
- data/lib/pact/matchers/unexpected_index.rb +0 -11
- data/lib/pact/matchers/unexpected_key.rb +0 -11
- data/lib/pact/matchers/unix_diff_formatter.rb +0 -114
- data/lib/pact/reification.rb +0 -28
- data/lib/pact/rspec.rb +0 -53
- data/lib/pact/shared/active_support_support.rb +0 -51
- data/lib/pact/shared/dsl.rb +0 -76
- data/lib/pact/shared/jruby_support.rb +0 -18
- data/lib/pact/shared/json_differ.rb +0 -15
- data/lib/pact/shared/key_not_found.rb +0 -15
- data/lib/pact/shared/null_expectation.rb +0 -31
- data/lib/pact/shared/request.rb +0 -80
- data/lib/pact/shared/text_differ.rb +0 -14
- data/lib/pact/something_like.rb +0 -49
- data/lib/pact/symbolize_keys.rb +0 -12
- data/lib/pact/term.rb +0 -85
- data/spec/lib/pact/consumer/request_spec.rb +0 -24
- data/spec/lib/pact/consumer_contract/active_support_support_spec.rb +0 -58
- data/spec/lib/pact/consumer_contract/consumer_contract_spec.rb +0 -180
- data/spec/lib/pact/consumer_contract/headers_spec.rb +0 -107
- data/spec/lib/pact/consumer_contract/interaction_spec.rb +0 -107
- data/spec/lib/pact/consumer_contract/request_spec.rb +0 -329
- data/spec/lib/pact/matchers/differ_spec.rb +0 -214
- data/spec/lib/pact/matchers/difference_spec.rb +0 -22
- data/spec/lib/pact/matchers/embedded_diff_formatter_spec.rb +0 -90
- data/spec/lib/pact/matchers/index_not_found_spec.rb +0 -21
- data/spec/lib/pact/matchers/list_diff_formatter_spec.rb +0 -114
- data/spec/lib/pact/matchers/matchers_spec.rb +0 -500
- data/spec/lib/pact/matchers/regexp_difference_spec.rb +0 -20
- data/spec/lib/pact/matchers/type_difference_spec.rb +0 -34
- data/spec/lib/pact/matchers/unexpected_index_spec.rb +0 -20
- data/spec/lib/pact/matchers/unexpected_key_spec.rb +0 -20
- data/spec/lib/pact/matchers/unix_diff_formatter_spec.rb +0 -216
- data/spec/lib/pact/reification_spec.rb +0 -67
- data/spec/lib/pact/shared/dsl_spec.rb +0 -86
- data/spec/lib/pact/shared/json_differ_spec.rb +0 -36
- data/spec/lib/pact/shared/key_not_found_spec.rb +0 -20
- data/spec/lib/pact/shared/request_spec.rb +0 -111
- data/spec/lib/pact/shared/text_differ_spec.rb +0 -54
- data/spec/lib/pact/something_like_spec.rb +0 -21
- data/spec/lib/pact/term_spec.rb +0 -89
- data/spec/support/dsl_spec_support.rb +0 -7
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
require 'thwait'
|
|
2
|
-
|
|
3
|
-
require 'net/http'
|
|
4
|
-
require 'uri'
|
|
5
|
-
require 'find_a_port'
|
|
6
|
-
require 'pact/logging'
|
|
7
|
-
require 'pact/consumer/server'
|
|
8
|
-
require 'singleton'
|
|
9
|
-
|
|
10
|
-
module Pact
|
|
11
|
-
module Consumer
|
|
12
|
-
class AppManager
|
|
13
|
-
|
|
14
|
-
include Pact::Logging
|
|
15
|
-
|
|
16
|
-
include Singleton
|
|
17
|
-
|
|
18
|
-
def initialize
|
|
19
|
-
@apps_spawned = false
|
|
20
|
-
@app_registrations = []
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def register_mock_service_for name, url
|
|
24
|
-
uri = URI(url)
|
|
25
|
-
raise "Currently only http is supported" unless uri.scheme == 'http'
|
|
26
|
-
raise "Currently only services on localhost are supported" unless uri.host == 'localhost'
|
|
27
|
-
|
|
28
|
-
register(MockService.new(log_file: create_log_file(name), name: name), uri.port)
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def register(app, port = FindAPort.available_port)
|
|
32
|
-
existing = existing_app_on_port port
|
|
33
|
-
raise "Port #{port} is already being used by #{existing}" if existing and not existing == app
|
|
34
|
-
app_registration = register_app app, port
|
|
35
|
-
app_registration.spawn if @apps_spawned
|
|
36
|
-
port
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def existing_app_on_port port
|
|
40
|
-
app_registration = @app_registrations.find { |app_registration| app_registration.port == port }
|
|
41
|
-
app_registration ? app_registration.app : nil
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def app_registered_on?(port)
|
|
45
|
-
app_registrations.any? { |app_registration| app_registration.port == port }
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
def ports_of_mock_services
|
|
49
|
-
app_registrations.find_all(&:is_a_mock_service?).collect(&:port)
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def kill_all
|
|
53
|
-
app_registrations.find_all(&:spawned?).collect(&:kill)
|
|
54
|
-
@apps_spawned = false
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
def clear_all
|
|
58
|
-
kill_all
|
|
59
|
-
@app_registrations = []
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def spawn_all
|
|
63
|
-
app_registrations.find_all(&:not_spawned?).collect(&:spawn)
|
|
64
|
-
@apps_spawned = true
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
private
|
|
68
|
-
|
|
69
|
-
def create_log_file service_name
|
|
70
|
-
FileUtils::mkdir_p Pact.configuration.log_dir
|
|
71
|
-
log = File.open(log_file_path(service_name), 'w')
|
|
72
|
-
log.sync = true
|
|
73
|
-
log
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def log_file_path service_name
|
|
77
|
-
File.join(Pact.configuration.log_dir, "#{log_file_name(service_name)}.log")
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
def log_file_name service_name
|
|
81
|
-
lower_case_name = service_name.downcase.gsub(/\s+/, '_')
|
|
82
|
-
if lower_case_name.include?('_service')
|
|
83
|
-
lower_case_name.gsub('_service', '_mock_service')
|
|
84
|
-
else
|
|
85
|
-
lower_case_name + '_mock_service'
|
|
86
|
-
end
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
def app_registrations
|
|
90
|
-
@app_registrations
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
def register_app app, port
|
|
94
|
-
app_registration = AppRegistration.new :app => app, :port => port
|
|
95
|
-
app_registrations << app_registration
|
|
96
|
-
app_registration
|
|
97
|
-
end
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
class AppRegistration
|
|
101
|
-
include Pact::Logging
|
|
102
|
-
attr_accessor :port
|
|
103
|
-
attr_accessor :app
|
|
104
|
-
attr_accessor :pid
|
|
105
|
-
|
|
106
|
-
def initialize opts
|
|
107
|
-
@max_wait = 10
|
|
108
|
-
@port = opts[:port]
|
|
109
|
-
@pid = opts[:pid]
|
|
110
|
-
@app = opts[:app]
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
def kill
|
|
114
|
-
# TODO: need to work out how to kill
|
|
115
|
-
# logger.info "Killing #{self}"
|
|
116
|
-
# Process.kill(9, pid)
|
|
117
|
-
# Process.wait(pid)
|
|
118
|
-
# self.pid = nil
|
|
119
|
-
self.pid = nil
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
def not_spawned?
|
|
123
|
-
!spawned?
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
def spawned?
|
|
127
|
-
self.pid != nil
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
def is_a_mock_service?
|
|
131
|
-
app.is_a? MockService
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
def to_s
|
|
135
|
-
"#{app} on port #{port}" + (@pid ? " with pid #{pid}" : "")
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
def spawn
|
|
139
|
-
logger.info "Starting app #{self}..."
|
|
140
|
-
Pact::Server.new(app, port).boot
|
|
141
|
-
self.pid = 'unknown'
|
|
142
|
-
logger.info "Started with pid #{pid}"
|
|
143
|
-
end
|
|
144
|
-
|
|
145
|
-
def wait_until
|
|
146
|
-
waited = 0
|
|
147
|
-
wait_time = 0.1
|
|
148
|
-
while waited < @max_wait do
|
|
149
|
-
break if yield
|
|
150
|
-
sleep wait_time
|
|
151
|
-
waited += wait_time
|
|
152
|
-
raise "Waited longer than #{@max_wait} seconds" if waited >= @max_wait
|
|
153
|
-
end
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
end
|
|
157
|
-
end
|
|
158
|
-
end
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
#
|
|
2
|
-
# When running in pactfile_write_mode :overwrite, all interactions are cleared from the
|
|
3
|
-
# pact file, and all new interactions should be distinct (unique description and provider state).
|
|
4
|
-
# When running in pactfile_write_mode :update, an interaction with the same description
|
|
5
|
-
# and provider state as an existing one will just overwrite that one interaction.
|
|
6
|
-
#
|
|
7
|
-
|
|
8
|
-
module Pact
|
|
9
|
-
module Consumer
|
|
10
|
-
|
|
11
|
-
#TODO: think of a better word than filter
|
|
12
|
-
class InteractionsFilter
|
|
13
|
-
def initialize interactions = []
|
|
14
|
-
@interactions = interactions
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def index_of interaction
|
|
18
|
-
@interactions.find_index{ |i| i.matches_criteria?(description: interaction.description, provider_state: interaction.provider_state)}
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
class UpdatableInteractionsFilter < InteractionsFilter
|
|
23
|
-
|
|
24
|
-
def << interaction
|
|
25
|
-
if (ndx = index_of(interaction))
|
|
26
|
-
@interactions[ndx] = interaction
|
|
27
|
-
else
|
|
28
|
-
@interactions << interaction
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
class DistinctInteractionsFilter < InteractionsFilter
|
|
35
|
-
|
|
36
|
-
def << interaction
|
|
37
|
-
if (ndx = index_of(interaction))
|
|
38
|
-
if @interactions[ndx] != interaction
|
|
39
|
-
raise "Interaction with same description (#{interaction.description}) and provider state (#{interaction.provider_state}) already exists"
|
|
40
|
-
end
|
|
41
|
-
else
|
|
42
|
-
@interactions << interaction
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
end
|
|
48
|
-
end
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
require 'uri'
|
|
2
|
-
require 'json'
|
|
3
|
-
require 'logger'
|
|
4
|
-
require 'awesome_print'
|
|
5
|
-
require 'awesome_print/core_ext/logger' #For some reason we get an error indicating that the method 'ap' is private unless we load this specifically
|
|
6
|
-
require 'pact/consumer/request'
|
|
7
|
-
require 'pact/consumer/mock_service/interaction_list'
|
|
8
|
-
require 'pact/consumer/mock_service/interaction_delete'
|
|
9
|
-
require 'pact/consumer/mock_service/interaction_post'
|
|
10
|
-
require 'pact/consumer/mock_service/interaction_replay'
|
|
11
|
-
require 'pact/consumer/mock_service/missing_interactions_get'
|
|
12
|
-
require 'pact/consumer/mock_service/verification_get'
|
|
13
|
-
require 'pact/consumer/mock_service/log_get'
|
|
14
|
-
require 'pact/consumer/mock_service/pact_post'
|
|
15
|
-
|
|
16
|
-
AwesomePrint.defaults = {
|
|
17
|
-
indent: -2,
|
|
18
|
-
plain: true,
|
|
19
|
-
index: false
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
module Pact
|
|
23
|
-
module Consumer
|
|
24
|
-
|
|
25
|
-
class MockService
|
|
26
|
-
|
|
27
|
-
def initialize options = {}
|
|
28
|
-
log_description = configure_logger options
|
|
29
|
-
interaction_list = InteractionList.new
|
|
30
|
-
|
|
31
|
-
@name = options.fetch(:name, "MockService")
|
|
32
|
-
interactions = []
|
|
33
|
-
@handlers = [
|
|
34
|
-
MissingInteractionsGet.new(@name, @logger, interaction_list),
|
|
35
|
-
VerificationGet.new(@name, @logger, interaction_list, log_description),
|
|
36
|
-
InteractionPost.new(@name, @logger, interaction_list),
|
|
37
|
-
InteractionDelete.new(@name, @logger, interaction_list),
|
|
38
|
-
LogGet.new(@name, @logger),
|
|
39
|
-
PactPost.new(@name, @logger, interactions),
|
|
40
|
-
InteractionReplay.new(@name, @logger, interaction_list, interactions)
|
|
41
|
-
]
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def configure_logger options
|
|
45
|
-
options = {log_file: $stdout}.merge options
|
|
46
|
-
log_stream = options[:log_file]
|
|
47
|
-
@logger = Logger.new log_stream
|
|
48
|
-
@logger.level = Pact.configuration.logger.level
|
|
49
|
-
|
|
50
|
-
if log_stream.is_a? File
|
|
51
|
-
File.absolute_path(log_stream).gsub(Dir.pwd + "/", '')
|
|
52
|
-
else
|
|
53
|
-
"standard out/err"
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
def to_s
|
|
58
|
-
"#{@name} #{super.to_s}"
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def call env
|
|
62
|
-
response = []
|
|
63
|
-
begin
|
|
64
|
-
relevant_handler = @handlers.detect { |handler| handler.match? env }
|
|
65
|
-
response = relevant_handler.respond env
|
|
66
|
-
rescue StandardError => e
|
|
67
|
-
@logger.error 'Error ocurred in mock service:'
|
|
68
|
-
@logger.ap e, :error
|
|
69
|
-
@logger.ap e.backtrace
|
|
70
|
-
response = [500, {'Content-Type' => 'application/json'}, [{message: e.message, backtrace: e.backtrace}.to_json]]
|
|
71
|
-
rescue Exception => e
|
|
72
|
-
@logger.error 'Exception ocurred in mock service:'
|
|
73
|
-
@logger.ap e, :error
|
|
74
|
-
@logger.ap e.backtrace
|
|
75
|
-
raise e
|
|
76
|
-
end
|
|
77
|
-
response
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
end
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
require 'pact/consumer/mock_service/rack_request_helper'
|
|
2
|
-
require 'pact/consumer/mock_service/mock_service_administration_endpoint'
|
|
3
|
-
|
|
4
|
-
module Pact
|
|
5
|
-
module Consumer
|
|
6
|
-
|
|
7
|
-
class InteractionDelete < MockServiceAdministrationEndpoint
|
|
8
|
-
|
|
9
|
-
include RackRequestHelper
|
|
10
|
-
|
|
11
|
-
attr_accessor :interaction_list
|
|
12
|
-
|
|
13
|
-
def initialize name, logger, interaction_list
|
|
14
|
-
super name, logger
|
|
15
|
-
@interaction_list = interaction_list
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def request_path
|
|
19
|
-
'/interactions'
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def request_method
|
|
23
|
-
'DELETE'
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def respond env
|
|
27
|
-
interaction_list.clear
|
|
28
|
-
logger.info "Cleared interactions before example \"#{params_hash(env)['example_description']}\""
|
|
29
|
-
[200, {}, ['Deleted interactions']]
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
end
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
module Pact
|
|
2
|
-
module Consumer
|
|
3
|
-
class InteractionList
|
|
4
|
-
|
|
5
|
-
attr_reader :interactions
|
|
6
|
-
attr_reader :unexpected_requests
|
|
7
|
-
attr_reader :interaction_mismatches
|
|
8
|
-
|
|
9
|
-
def initialize
|
|
10
|
-
clear
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
# For testing, sigh
|
|
14
|
-
def clear
|
|
15
|
-
@interactions = []
|
|
16
|
-
@matched_interactions = []
|
|
17
|
-
@interaction_mismatches = []
|
|
18
|
-
@unexpected_requests = []
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def add interactions
|
|
22
|
-
@interactions << interactions
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def register_matched interaction
|
|
26
|
-
@matched_interactions << interaction
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def register_unexpected_request request
|
|
30
|
-
@unexpected_requests << request
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def register_interaction_mismatch interaction_mismatch
|
|
34
|
-
@interaction_mismatches << interaction_mismatch
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def all_matched?
|
|
38
|
-
interaction_diffs.empty?
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def missing_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)
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
def interaction_diffs
|
|
58
|
-
{
|
|
59
|
-
:missing_interactions => missing_interactions_summaries,
|
|
60
|
-
:interaction_mismatches => interaction_mismatches_summaries,
|
|
61
|
-
:unexpected_requests => unexpected_requests_summaries
|
|
62
|
-
}.inject({}) do | hash, pair |
|
|
63
|
-
hash[pair.first] = pair.last if pair.last.any?
|
|
64
|
-
hash
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def find_candidate_interactions actual_request
|
|
69
|
-
interactions.select do | interaction |
|
|
70
|
-
interaction.request.matches_route? actual_request
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
end
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
module Pact
|
|
2
|
-
module Consumer
|
|
3
|
-
|
|
4
|
-
# Presents the differences between an actual request, and a list of
|
|
5
|
-
# expected interactions where the methods and paths match the actual request.
|
|
6
|
-
# This is used to display a helpful message to the user when a request
|
|
7
|
-
# comes in that doesn't match any of the expected interactions.
|
|
8
|
-
class InteractionMismatch
|
|
9
|
-
|
|
10
|
-
attr_accessor :candidate_interactions, :actual_request
|
|
11
|
-
|
|
12
|
-
# Assumes the method and path matches...
|
|
13
|
-
|
|
14
|
-
def initialize candidate_interactions, actual_request
|
|
15
|
-
@candidate_interactions = candidate_interactions
|
|
16
|
-
@actual_request = actual_request
|
|
17
|
-
@candiate_diffs = candidate_interactions.collect{ | candidate_interaction| CandidateDiff.new(candidate_interaction, actual_request)}
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def to_hash
|
|
21
|
-
candiate_diffs.collect(&:to_hash)
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def to_s
|
|
25
|
-
candiate_diffs.collect(&:to_s).join("\n")
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def short_summary
|
|
29
|
-
mismatched_attributes = candiate_diffs.collect(&:mismatched_attributes).flatten.uniq.join(", ").reverse.sub(",", "dna ").reverse #OMG what a hack!
|
|
30
|
-
actual_request.method_and_path + " (request #{mismatched_attributes} did not match)"
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
private
|
|
34
|
-
|
|
35
|
-
attr_accessor :candiate_diffs
|
|
36
|
-
|
|
37
|
-
class CandidateDiff
|
|
38
|
-
|
|
39
|
-
attr_accessor :candidate_interaction, :actual_request
|
|
40
|
-
|
|
41
|
-
def initialize candidate_interaction, actual_request
|
|
42
|
-
@candidate_interaction = candidate_interaction
|
|
43
|
-
@actual_request = actual_request
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def mismatched_attributes
|
|
47
|
-
diff.keys
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def to_hash
|
|
51
|
-
summary = {:description => candidate_interaction.description}
|
|
52
|
-
summary[:provider_state] = candidate_interaction.provider_state if candidate_interaction.provider_state
|
|
53
|
-
summary.merge(diff)
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def to_s
|
|
57
|
-
[
|
|
58
|
-
"Diff with interaction: #{candidate_interaction.description_with_provider_state_quoted}",
|
|
59
|
-
diff_formatter.call(diff, {colour: false})
|
|
60
|
-
].join("\n")
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
def diff_formatter
|
|
64
|
-
Pact.configuration.diff_formatter_for_content_type(candidate_interaction.request.content_type)
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def diff
|
|
68
|
-
@diff ||= candidate_interaction.request.difference(actual_request)
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
end
|