pact 1.3.3 → 1.4.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|