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,31 +0,0 @@
|
|
|
1
|
-
require 'pact/consumer/mock_service/mock_service_administration_endpoint'
|
|
2
|
-
|
|
3
|
-
module Pact
|
|
4
|
-
module Consumer
|
|
5
|
-
class InteractionPost < MockServiceAdministrationEndpoint
|
|
6
|
-
|
|
7
|
-
attr_accessor :interaction_list
|
|
8
|
-
|
|
9
|
-
def initialize name, logger, interaction_list
|
|
10
|
-
super name, logger
|
|
11
|
-
@interaction_list = interaction_list
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def request_path
|
|
15
|
-
'/interactions'
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def request_method
|
|
19
|
-
'POST'
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def respond env
|
|
23
|
-
interaction = Interaction.from_hash(JSON.load(env['rack.input'].string))
|
|
24
|
-
interaction_list.add interaction
|
|
25
|
-
logger.info "Registered expected interaction #{interaction.request.method_and_path}"
|
|
26
|
-
logger.debug JSON.pretty_generate JSON.parse(interaction.to_json)
|
|
27
|
-
[200, {}, ['Added interaction']]
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
end
|
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
require 'pact/matchers'
|
|
2
|
-
require 'pact/consumer/mock_service/rack_request_helper'
|
|
3
|
-
require 'pact/consumer/mock_service/interaction_mismatch'
|
|
4
|
-
require 'pact/consumer_contract'
|
|
5
|
-
require 'pact/consumer/interactions_filter'
|
|
6
|
-
|
|
7
|
-
module Pact
|
|
8
|
-
module Consumer
|
|
9
|
-
|
|
10
|
-
class InteractionReplay
|
|
11
|
-
include Pact::Matchers
|
|
12
|
-
include RackRequestHelper
|
|
13
|
-
|
|
14
|
-
attr_accessor :name, :logger, :interaction_list, :interactions
|
|
15
|
-
|
|
16
|
-
def initialize name, logger, interaction_list, interactions
|
|
17
|
-
@name = name
|
|
18
|
-
@logger = logger
|
|
19
|
-
@interaction_list = interaction_list
|
|
20
|
-
@interactions = DistinctInteractionsFilter.new(interactions)
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def match? env
|
|
24
|
-
true # default handler
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def respond env
|
|
28
|
-
find_response request_as_hash_from(env)
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
private
|
|
32
|
-
|
|
33
|
-
def add_verified_interaction interaction
|
|
34
|
-
interactions << interaction
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def find_response request_hash
|
|
38
|
-
actual_request = Request::Actual.from_hash(request_hash)
|
|
39
|
-
logger.info "Received request #{actual_request.method_and_path}"
|
|
40
|
-
logger.debug pretty_generate actual_request
|
|
41
|
-
candidate_interactions = interaction_list.find_candidate_interactions actual_request
|
|
42
|
-
matching_interactions = find_matching_interactions actual_request, from: candidate_interactions
|
|
43
|
-
|
|
44
|
-
case matching_interactions.size
|
|
45
|
-
when 0 then handle_unrecognised_request actual_request, candidate_interactions
|
|
46
|
-
when 1 then handle_matched_interaction matching_interactions.first
|
|
47
|
-
else
|
|
48
|
-
handle_more_than_one_matching_interaction actual_request, matching_interactions
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def find_matching_interactions actual_request, opts
|
|
53
|
-
candidate_interactions = opts.fetch(:from)
|
|
54
|
-
candidate_interactions.select do | candidate_interaction |
|
|
55
|
-
candidate_interaction.request.matches? actual_request
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def handle_matched_interaction interaction
|
|
60
|
-
interaction_list.register_matched interaction
|
|
61
|
-
add_verified_interaction interaction
|
|
62
|
-
response = response_from(interaction.response)
|
|
63
|
-
logger.info "Found matching response for #{interaction.request.method_and_path}"
|
|
64
|
-
logger.debug pretty_generate(interaction.response)
|
|
65
|
-
response
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def multiple_interactions_found_response actual_request, matching_interactions
|
|
69
|
-
response = {
|
|
70
|
-
message: "Multiple interaction found for #{actual_request.method_and_path}",
|
|
71
|
-
matching_interactions: matching_interactions.collect{ | interaction | request_summary_for(interaction) }
|
|
72
|
-
}
|
|
73
|
-
[500, {'Content-Type' => 'application/json'}, [response.to_json]]
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def handle_more_than_one_matching_interaction actual_request, matching_interactions
|
|
77
|
-
logger.error "Multiple interactions found for #{actual_request.method_and_path}:"
|
|
78
|
-
matching_interactions.each do | interaction |
|
|
79
|
-
logger.debug pretty_generate(interaction)
|
|
80
|
-
end
|
|
81
|
-
multiple_interactions_found_response actual_request, matching_interactions
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
def interaction_mismatch actual_request, candidate_interactions
|
|
85
|
-
InteractionMismatch.new(candidate_interactions, actual_request)
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
def request_summary_for interaction
|
|
89
|
-
summary = {:description => interaction.description}
|
|
90
|
-
summary[:provider_state] if interaction.provider_state
|
|
91
|
-
summary[:request] = interaction.request
|
|
92
|
-
summary
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
def unrecognised_request_response interaction_mismatch
|
|
96
|
-
response = {
|
|
97
|
-
message: "No interaction found for #{interaction_mismatch.actual_request.method_and_path}",
|
|
98
|
-
interaction_diffs: interaction_mismatch.to_hash
|
|
99
|
-
}
|
|
100
|
-
[500, {'Content-Type' => 'application/json'}, [response.to_json]]
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
def log_unrecognised_request_and_interaction_diff interaction_mismatch
|
|
104
|
-
logger.error "No matching interaction found on #{name} for #{interaction_mismatch.actual_request.method_and_path}"
|
|
105
|
-
logger.error 'Interaction diffs for that route:'
|
|
106
|
-
logger.error(interaction_mismatch.to_s)
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
def handle_unrecognised_request actual_request, candidate_interactions
|
|
110
|
-
interaction_mismatch = interaction_mismatch(actual_request, candidate_interactions)
|
|
111
|
-
if candidate_interactions.any?
|
|
112
|
-
interaction_list.register_interaction_mismatch interaction_mismatch
|
|
113
|
-
else
|
|
114
|
-
interaction_list.register_unexpected_request actual_request
|
|
115
|
-
end
|
|
116
|
-
log_unrecognised_request_and_interaction_diff interaction_mismatch
|
|
117
|
-
unrecognised_request_response interaction_mismatch
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
def response_from response
|
|
121
|
-
[response['status'], (response['headers'] || {}).to_hash, [render_body(Pact::Reification.from_term(response['body']))]]
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
def render_body body
|
|
125
|
-
return '' unless body
|
|
126
|
-
body.kind_of?(String) ? body.force_encoding('utf-8') : body.to_json
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
def logger_info_ap msg
|
|
130
|
-
logger.info msg
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
#Doesn't seem to reliably pretty generate unless we go to JSON and back again :(
|
|
134
|
-
def pretty_generate object
|
|
135
|
-
JSON.pretty_generate(JSON.parse(object.to_json))
|
|
136
|
-
end
|
|
137
|
-
end
|
|
138
|
-
end
|
|
139
|
-
end
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
require 'pact/consumer/mock_service/mock_service_administration_endpoint'
|
|
2
|
-
|
|
3
|
-
module Pact
|
|
4
|
-
module Consumer
|
|
5
|
-
class LogGet < MockServiceAdministrationEndpoint
|
|
6
|
-
|
|
7
|
-
include RackRequestHelper
|
|
8
|
-
|
|
9
|
-
def request_path
|
|
10
|
-
'/log'
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def request_method
|
|
14
|
-
'GET'
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
def respond env
|
|
19
|
-
logger.info "Debug message from client - #{message(env)}"
|
|
20
|
-
[200, {}, []]
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def message env
|
|
24
|
-
params_hash(env)['msg']
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
require 'pact/consumer/mock_service/mock_service_administration_endpoint'
|
|
2
|
-
|
|
3
|
-
module Pact
|
|
4
|
-
module Consumer
|
|
5
|
-
|
|
6
|
-
class MissingInteractionsGet < MockServiceAdministrationEndpoint
|
|
7
|
-
include RackRequestHelper
|
|
8
|
-
|
|
9
|
-
def initialize name, logger, interaction_list
|
|
10
|
-
super name, logger
|
|
11
|
-
@interaction_list = interaction_list
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def request_path
|
|
15
|
-
'/interactions/missing'
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def request_method
|
|
19
|
-
'GET'
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def respond env
|
|
23
|
-
number_of_missing_interactions = @interaction_list.missing_interactions.size
|
|
24
|
-
logger.info "Number of missing interactions for mock \"#{name}\" = #{number_of_missing_interactions}"
|
|
25
|
-
[200, {}, [{size: number_of_missing_interactions}.to_json]]
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
end
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
require 'pact/consumer/mock_service/rack_request_helper'
|
|
2
|
-
module Pact
|
|
3
|
-
module Consumer
|
|
4
|
-
class MockServiceAdministrationEndpoint
|
|
5
|
-
|
|
6
|
-
attr_accessor :logger, :name
|
|
7
|
-
|
|
8
|
-
def initialize name, logger
|
|
9
|
-
@name = name
|
|
10
|
-
@logger = logger
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
include RackRequestHelper
|
|
14
|
-
|
|
15
|
-
def match? env
|
|
16
|
-
headers_from(env)['X-Pact-Mock-Service'] &&
|
|
17
|
-
env['REQUEST_PATH'] == request_path &&
|
|
18
|
-
env['REQUEST_METHOD'] == request_method
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def request_path
|
|
22
|
-
raise NotImplementedError
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def request_method
|
|
26
|
-
raise NotImplementedError
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
end
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
require 'pact/consumer/mock_service/mock_service_administration_endpoint'
|
|
2
|
-
require 'pact/consumer_contract/consumer_contract_writer'
|
|
3
|
-
|
|
4
|
-
module Pact
|
|
5
|
-
module Consumer
|
|
6
|
-
class PactPost < MockServiceAdministrationEndpoint
|
|
7
|
-
|
|
8
|
-
attr_accessor :consumer_contract, :interactions
|
|
9
|
-
|
|
10
|
-
def initialize name, logger, interactions
|
|
11
|
-
super name, logger
|
|
12
|
-
@interactions = interactions
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def request_path
|
|
16
|
-
'/pact'
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def request_method
|
|
20
|
-
'POST'
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def respond env
|
|
24
|
-
consumer_contract_details = JSON.parse(env['rack.input'].string, symbolize_names: true)
|
|
25
|
-
logger.info "Writing pact with details #{consumer_contract_details}"
|
|
26
|
-
consumer_contract_writer = ConsumerContractWriter.new(consumer_contract_details.merge(interactions: interactions), logger)
|
|
27
|
-
json = consumer_contract_writer.write
|
|
28
|
-
|
|
29
|
-
[200, {'Content-Type' =>'application/json'}, [json]]
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
end
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
module Pact
|
|
2
|
-
module Consumer
|
|
3
|
-
|
|
4
|
-
module RackRequestHelper
|
|
5
|
-
REQUEST_KEYS = {
|
|
6
|
-
'REQUEST_METHOD' => :method,
|
|
7
|
-
'PATH_INFO' => :path,
|
|
8
|
-
'QUERY_STRING' => :query,
|
|
9
|
-
'rack.input' => :body
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
def params_hash env
|
|
13
|
-
env["QUERY_STRING"].split("&").collect{| param| param.split("=")}.inject({}){|params, param| params[param.first] = URI.decode(param.last); params }
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def request_as_hash_from env
|
|
17
|
-
request = env.inject({}) do |memo, (k, v)|
|
|
18
|
-
request_key = REQUEST_KEYS[k]
|
|
19
|
-
memo[request_key] = v if request_key
|
|
20
|
-
memo
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
request[:headers] = headers_from env
|
|
24
|
-
body_string = request[:body].read
|
|
25
|
-
|
|
26
|
-
if body_string.empty?
|
|
27
|
-
request.delete :body
|
|
28
|
-
else
|
|
29
|
-
body_is_json = request[:headers]['Content-Type'] =~ /json/
|
|
30
|
-
request[:body] = body_is_json ? JSON.parse(body_string) : body_string
|
|
31
|
-
end
|
|
32
|
-
request[:method] = request[:method].downcase
|
|
33
|
-
request
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
private
|
|
37
|
-
|
|
38
|
-
def headers_from env
|
|
39
|
-
headers = env.reject{ |key, value| !(key.start_with?("HTTP") || key == 'CONTENT_TYPE' || key == 'CONTENT_LENGTH')}
|
|
40
|
-
headers.inject({}) do | hash, header |
|
|
41
|
-
hash[standardise_header(header.first)] = header.last
|
|
42
|
-
hash
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def standardise_header header
|
|
47
|
-
header.gsub(/^HTTP_/, '').split("_").collect{|word| word[0] + word[1..-1].downcase}.join("-")
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
end
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
require 'pact/consumer/mock_service/mock_service_administration_endpoint'
|
|
2
|
-
|
|
3
|
-
module Pact
|
|
4
|
-
module Consumer
|
|
5
|
-
class VerificationGet < MockServiceAdministrationEndpoint
|
|
6
|
-
|
|
7
|
-
include RackRequestHelper
|
|
8
|
-
attr_accessor :interaction_list, :log_description
|
|
9
|
-
|
|
10
|
-
def initialize name, logger, interaction_list, log_description
|
|
11
|
-
super name, logger
|
|
12
|
-
@interaction_list = interaction_list
|
|
13
|
-
@log_description = log_description
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def request_path
|
|
17
|
-
'/interactions/verification'
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def request_method
|
|
21
|
-
'GET'
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def respond env
|
|
25
|
-
if interaction_list.all_matched?
|
|
26
|
-
logger.info "Verifying - interactions matched for example \"#{example_description(env)}\""
|
|
27
|
-
[200, {'Content-Type' => 'text/plain'}, ['Interactions matched']]
|
|
28
|
-
else
|
|
29
|
-
error_message = FailureMessage.new(interaction_list).to_s
|
|
30
|
-
logger.warn "Verifying - actual interactions do not match expected interactions for example \"#{example_description(env)}\". \n#{error_message}"
|
|
31
|
-
logger.warn error_message
|
|
32
|
-
[500, {'Content-Type' => 'text/plain'}, ["Actual interactions do not match expected interactions for mock #{name}.\n\n#{error_message}See #{log_description} for details."]]
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def example_description env
|
|
37
|
-
params_hash(env)['example_description']
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
class FailureMessage
|
|
41
|
-
|
|
42
|
-
def initialize interaction_list
|
|
43
|
-
@interaction_list = interaction_list
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def to_s
|
|
47
|
-
titles_and_summaries.collect do | title, summaries |
|
|
48
|
-
"#{title}:\n\t#{summaries.join("\n\t")}\n\n" if summaries.any?
|
|
49
|
-
end.compact.join
|
|
50
|
-
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
private
|
|
54
|
-
|
|
55
|
-
attr_reader :interaction_list
|
|
56
|
-
|
|
57
|
-
def titles_and_summaries
|
|
58
|
-
{
|
|
59
|
-
"Incorrect requests" => interaction_list.interaction_mismatches_summaries,
|
|
60
|
-
"Missing requests" => interaction_list.missing_interactions_summaries,
|
|
61
|
-
"Unexpected requests" => interaction_list.unexpected_requests_summaries,
|
|
62
|
-
}
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
end
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
require 'net/http'
|
|
2
|
-
require 'pact/consumer/mock_service_interaction_expectation'
|
|
3
|
-
|
|
4
|
-
module Pact
|
|
5
|
-
module Consumer
|
|
6
|
-
class MockServiceClient
|
|
7
|
-
|
|
8
|
-
MOCK_SERVICE_ADMINISTRATON_HEADERS = {'X-Pact-Mock-Service' => 'true'}
|
|
9
|
-
|
|
10
|
-
def initialize port
|
|
11
|
-
@http = Net::HTTP.new('localhost', port)
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def verify example_description
|
|
15
|
-
response = http.request_get("/interactions/verification?example_description=#{URI.encode(example_description)}", MOCK_SERVICE_ADMINISTRATON_HEADERS)
|
|
16
|
-
raise "\e[31m#{response.body}\e[m" unless response.is_a? Net::HTTPSuccess
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def log msg
|
|
20
|
-
http.request_get("/log?msg=#{URI.encode(msg)}", MOCK_SERVICE_ADMINISTRATON_HEADERS)
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def wait_for_interactions wait_max_seconds, poll_interval
|
|
24
|
-
wait_until_true(wait_max_seconds, poll_interval) do
|
|
25
|
-
response = http.request_get("/interactions/missing", MOCK_SERVICE_ADMINISTRATON_HEADERS)
|
|
26
|
-
JSON.parse(response.body)['size'] == 0
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def clear_interactions example_description
|
|
31
|
-
http.delete("/interactions?example_description=#{URI.encode(example_description)}", MOCK_SERVICE_ADMINISTRATON_HEADERS)
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def add_expected_interaction interaction
|
|
35
|
-
response = http.request_post('/interactions', MockServiceInteractionExpectation.new(interaction).to_json, MOCK_SERVICE_ADMINISTRATON_HEADERS.merge("Content-Type" => "application/json"))
|
|
36
|
-
raise "\e[31m#{response.body}\e[m" unless response.is_a? Net::HTTPSuccess
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def self.clear_interactions port, example_description
|
|
40
|
-
Net::HTTP.new("localhost", port).delete("/interactions?example_description=#{URI.encode(example_description)}", MOCK_SERVICE_ADMINISTRATON_HEADERS)
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def write_pact pacticipant_details
|
|
44
|
-
response = http.request_post("/pact", pacticipant_details.to_json, MOCK_SERVICE_ADMINISTRATON_HEADERS.merge("Content-Type" => "application/json"))
|
|
45
|
-
raise "\e[31m#{response.body}\e[m" unless response.is_a? Net::HTTPSuccess
|
|
46
|
-
response.body
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
private
|
|
50
|
-
|
|
51
|
-
attr_reader :http
|
|
52
|
-
|
|
53
|
-
#todo: in need a better home (where can we move it?)
|
|
54
|
-
def wait_until_true timeout=3, interval=0.1
|
|
55
|
-
time_limit = Time.now + timeout
|
|
56
|
-
loop do
|
|
57
|
-
result = yield
|
|
58
|
-
return if result || Time.now >= time_limit
|
|
59
|
-
sleep interval
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
end
|