pact 1.0.10 → 1.0.11
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +5 -1
- data/Gemfile.lock +4 -1
- data/lib/pact/consumer/app_manager.rb +1 -1
- data/lib/pact/consumer/consumer_contract_builder.rb +4 -0
- data/lib/pact/consumer/mock_service/app.rb +3 -3
- data/lib/pact/consumer/mock_service/interaction_delete.rb +13 -8
- data/lib/pact/consumer/mock_service/interaction_post.rb +15 -9
- data/lib/pact/consumer/mock_service/interaction_replay.rb +21 -19
- data/lib/pact/consumer/mock_service/log_get.rb +28 -0
- data/lib/pact/consumer/mock_service/missing_interactions_get.rb +11 -7
- data/lib/pact/consumer/mock_service/mock_service_administration_endpoint.rb +31 -0
- data/lib/pact/consumer/mock_service/verification_get.rb +18 -13
- data/lib/pact/consumer/mock_service_client.rb +12 -5
- data/lib/pact/shared/dsl.rb +37 -4
- data/lib/pact/version.rb +1 -1
- data/pact.gemspec +1 -0
- data/spec/integration/consumer_spec.rb +6 -6
- data/spec/lib/pact/consumer/configuration_spec.rb +5 -4
- data/spec/lib/pact/shared/dsl_spec.rb +44 -0
- metadata +21 -2
- data/lib/pact/consumer/mock_service/startup_poll.rb +0 -22
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
### 1.0.11 (26 September 2014)
|
2
|
+
* Added X-Pact-Mock-Service headers to all mock service administration requests, reducing the risk of the client project making a request that is unintentionally intercepted by the mock service administration handlers. [Beth Skurrie]
|
3
|
+
|
1
4
|
### 1.0.10 (24 September 2014)
|
2
5
|
* Removing unused requires [Beth Skurrie, 20 hours ago]
|
3
6
|
* Adding example changes [Beth Skurrie, 20 hours ago]
|
@@ -15,8 +18,9 @@
|
|
15
18
|
* Moving request file into consumer_contract folder. [Beth Skurrie, 7 days ago]
|
16
19
|
* Symbolizing keys so from_hash does not have to duplicate so much of the constructor methods. Service provider is now mandatory. [Beth Skurrie, 7 days ago]
|
17
20
|
* Removed Hashie from run time dependencies. [Beth Skurrie, 7 days ago]
|
18
|
-
* Starting to clean up mock service. Adding integration tests for failure scenarios.
|
21
|
+
* Starting to clean up mock service. Adding integration tests for failure scenarios. [Beth Skurrie, 7 days ago]
|
19
22
|
* Added RSpec fire to ensure stubbed methods exist. Pulled the recreation of a repayable request from an expected request out of the TestHelper into its own class. [Beth Skurrie, 7 days ago]
|
23
|
+
* Fixed problem where methods in previous scope could not be accessed by the DSL delegator [Beth Skurrie]
|
20
24
|
|
21
25
|
### 1.0.9 (16 September 2013)
|
22
26
|
|
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.11)
|
5
5
|
awesome_print (~> 1.1.0)
|
6
6
|
find_a_port (~> 1.0.1)
|
7
7
|
json
|
@@ -47,6 +47,8 @@ GEM
|
|
47
47
|
rspec-core (2.14.5)
|
48
48
|
rspec-expectations (2.14.3)
|
49
49
|
diff-lcs (>= 1.1.3, < 2.0)
|
50
|
+
rspec-fire (1.2.0)
|
51
|
+
rspec (~> 2.11)
|
50
52
|
rspec-mocks (2.14.3)
|
51
53
|
safe_yaml (0.9.5)
|
52
54
|
slop (3.4.6)
|
@@ -69,4 +71,5 @@ DEPENDENCIES
|
|
69
71
|
pact!
|
70
72
|
pry
|
71
73
|
rake (~> 10.0.3)
|
74
|
+
rspec-fire
|
72
75
|
webmock (~> 1.9.3)
|
@@ -47,6 +47,10 @@ module Pact
|
|
47
47
|
mock_service_client.verify example_description
|
48
48
|
end
|
49
49
|
|
50
|
+
def log msg
|
51
|
+
mock_service_client.log msg
|
52
|
+
end
|
53
|
+
|
50
54
|
def wait_for_interactions options
|
51
55
|
wait_max_seconds = options.fetch(:wait_max_seconds, 3)
|
52
56
|
poll_interval = options.fetch(:poll_interval, 0.1)
|
@@ -5,12 +5,12 @@ require 'awesome_print'
|
|
5
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
6
|
require 'pact/consumer/request'
|
7
7
|
require 'pact/consumer/mock_service/interaction_list'
|
8
|
-
require 'pact/consumer/mock_service/startup_poll'
|
9
8
|
require 'pact/consumer/mock_service/interaction_delete'
|
10
9
|
require 'pact/consumer/mock_service/interaction_post'
|
11
10
|
require 'pact/consumer/mock_service/interaction_replay'
|
12
11
|
require 'pact/consumer/mock_service/missing_interactions_get'
|
13
12
|
require 'pact/consumer/mock_service/verification_get'
|
13
|
+
require 'pact/consumer/mock_service/log_get'
|
14
14
|
|
15
15
|
AwesomePrint.defaults = {
|
16
16
|
indent: -2,
|
@@ -38,11 +38,11 @@ module Pact
|
|
38
38
|
|
39
39
|
@name = options.fetch(:name, "MockService")
|
40
40
|
@handlers = [
|
41
|
-
StartupPoll.new(@name, @logger),
|
42
41
|
MissingInteractionsGet.new(@name, @logger, interaction_list),
|
43
|
-
VerificationGet.new(@name, @logger,
|
42
|
+
VerificationGet.new(@name, @logger, interaction_list, log_description),
|
44
43
|
InteractionPost.new(@name, @logger, interaction_list),
|
45
44
|
InteractionDelete.new(@name, @logger, interaction_list),
|
45
|
+
LogGet.new(@name, @logger),
|
46
46
|
InteractionReplay.new(@name, @logger, interaction_list)
|
47
47
|
]
|
48
48
|
end
|
@@ -1,26 +1,31 @@
|
|
1
1
|
require 'pact/consumer/mock_service/rack_request_helper'
|
2
|
+
require 'pact/consumer/mock_service/mock_service_administration_endpoint'
|
2
3
|
|
3
4
|
module Pact
|
4
5
|
module Consumer
|
5
6
|
|
6
|
-
class InteractionDelete
|
7
|
+
class InteractionDelete < MockServiceAdministrationEndpoint
|
7
8
|
|
8
9
|
include RackRequestHelper
|
9
10
|
|
11
|
+
attr_accessor :interaction_list
|
12
|
+
|
10
13
|
def initialize name, logger, interaction_list
|
11
|
-
|
12
|
-
@logger = logger
|
14
|
+
super name, logger
|
13
15
|
@interaction_list = interaction_list
|
14
16
|
end
|
15
17
|
|
16
|
-
def
|
17
|
-
|
18
|
-
|
18
|
+
def request_path
|
19
|
+
'/interactions'
|
20
|
+
end
|
21
|
+
|
22
|
+
def request_method
|
23
|
+
'DELETE'
|
19
24
|
end
|
20
25
|
|
21
26
|
def respond env
|
22
|
-
|
23
|
-
|
27
|
+
interaction_list.clear
|
28
|
+
logger.info "Cleared interactions before example \"#{params_hash(env)['example_description']}\""
|
24
29
|
[200, {}, ['Deleted interactions']]
|
25
30
|
end
|
26
31
|
end
|
@@ -1,23 +1,29 @@
|
|
1
|
+
require 'pact/consumer/mock_service/mock_service_administration_endpoint'
|
2
|
+
|
1
3
|
module Pact
|
2
4
|
module Consumer
|
3
|
-
class InteractionPost
|
5
|
+
class InteractionPost < MockServiceAdministrationEndpoint
|
6
|
+
|
7
|
+
attr_accessor :interaction_list
|
4
8
|
|
5
9
|
def initialize name, logger, interaction_list
|
6
|
-
|
7
|
-
@logger = logger
|
10
|
+
super name, logger
|
8
11
|
@interaction_list = interaction_list
|
9
12
|
end
|
10
13
|
|
11
|
-
def
|
12
|
-
|
13
|
-
|
14
|
+
def request_path
|
15
|
+
'/interactions'
|
16
|
+
end
|
17
|
+
|
18
|
+
def request_method
|
19
|
+
'POST'
|
14
20
|
end
|
15
21
|
|
16
22
|
def respond env
|
17
23
|
interaction = Interaction.from_hash(JSON.load(env['rack.input'].string))
|
18
|
-
|
19
|
-
|
20
|
-
|
24
|
+
interaction_list.add interaction
|
25
|
+
logger.info "Registered expected interaction #{interaction.request.method_and_path} for #{name}"
|
26
|
+
logger.ap interaction.as_json
|
21
27
|
[200, {}, ['Added interactions']]
|
22
28
|
end
|
23
29
|
end
|
@@ -8,6 +8,8 @@ module Pact
|
|
8
8
|
include Pact::Matchers
|
9
9
|
include RackRequestHelper
|
10
10
|
|
11
|
+
attr_accessor :name, :logger, :interaction_list
|
12
|
+
|
11
13
|
def initialize name, logger, interaction_list
|
12
14
|
@name = name
|
13
15
|
@logger = logger
|
@@ -26,9 +28,9 @@ module Pact
|
|
26
28
|
|
27
29
|
def find_response request_hash
|
28
30
|
actual_request = Request::Actual.from_hash(request_hash)
|
29
|
-
|
30
|
-
|
31
|
-
candidate_interactions =
|
31
|
+
logger.info "#{name} received request #{actual_request.method_and_path}"
|
32
|
+
logger.ap actual_request.as_json
|
33
|
+
candidate_interactions = interaction_list.find_candidate_interactions actual_request
|
32
34
|
matching_interactions = find_matching_interactions actual_request, from: candidate_interactions
|
33
35
|
|
34
36
|
case matching_interactions.size
|
@@ -43,28 +45,28 @@ module Pact
|
|
43
45
|
candidate_interactions = opts.fetch(:from)
|
44
46
|
candidate_interactions.select do | candidate_interaction |
|
45
47
|
candidate_interaction.request.matches? actual_request
|
46
|
-
end
|
47
|
-
end
|
48
|
+
end
|
49
|
+
end
|
48
50
|
|
49
51
|
def handle_matched_interaction interaction
|
50
|
-
|
52
|
+
interaction_list.register_matched interaction
|
51
53
|
response = response_from(interaction.response)
|
52
|
-
|
53
|
-
|
54
|
-
response
|
54
|
+
logger.info "Found matching response on #{name}:"
|
55
|
+
logger.ap interaction.response
|
56
|
+
response
|
55
57
|
end
|
56
58
|
|
57
59
|
def multiple_interactions_found_response actual_request, matching_interactions
|
58
60
|
response = {
|
59
|
-
message: "Multiple interaction found for #{actual_request.method_and_path}",
|
61
|
+
message: "Multiple interaction found for #{actual_request.method_and_path}",
|
60
62
|
matching_interactions: matching_interactions.collect{ | interaction | request_summary_for(interaction) }
|
61
63
|
}
|
62
64
|
[500, {'Content-Type' => 'application/json'}, [response.to_json]]
|
63
65
|
end
|
64
66
|
|
65
67
|
def handle_more_than_one_matching_interaction actual_request, matching_interactions
|
66
|
-
|
67
|
-
|
68
|
+
logger.error "Multiple interactions found on #{name}:"
|
69
|
+
logger.ap matching_interactions.collect(&:as_json)
|
68
70
|
multiple_interactions_found_response actual_request, matching_interactions
|
69
71
|
end
|
70
72
|
|
@@ -72,7 +74,7 @@ module Pact
|
|
72
74
|
candidate_interactions.collect do | candidate_interaction |
|
73
75
|
diff = candidate_interaction.request.difference(actual_request)
|
74
76
|
diff_summary_for candidate_interaction, diff
|
75
|
-
end
|
77
|
+
end
|
76
78
|
end
|
77
79
|
|
78
80
|
def diff_summary_for interaction, diff
|
@@ -90,20 +92,20 @@ module Pact
|
|
90
92
|
|
91
93
|
def unrecognised_request_response actual_request, interaction_diffs
|
92
94
|
response = {
|
93
|
-
message: "No interaction found for #{actual_request.method_and_path}",
|
95
|
+
message: "No interaction found for #{actual_request.method_and_path}",
|
94
96
|
interaction_diffs: interaction_diffs
|
95
97
|
}
|
96
98
|
[500, {'Content-Type' => 'application/json'}, [response.to_json]]
|
97
99
|
end
|
98
100
|
|
99
101
|
def log_unrecognised_request_and_interaction_diff actual_request, interaction_diffs, candidate_interactions
|
100
|
-
|
101
|
-
|
102
|
-
|
102
|
+
logger.error "No interaction found on #{name} for #{actual_request.method_and_path}"
|
103
|
+
logger.error 'Interaction diffs for that route:'
|
104
|
+
logger.ap(interaction_diffs, :error)
|
103
105
|
end
|
104
106
|
|
105
107
|
def handle_unrecognised_request actual_request, candidate_interactions
|
106
|
-
|
108
|
+
interaction_list.register_unexpected_request actual_request
|
107
109
|
interaction_diffs = interaction_diffs(actual_request, candidate_interactions)
|
108
110
|
log_unrecognised_request_and_interaction_diff actual_request, interaction_diffs, candidate_interactions
|
109
111
|
unrecognised_request_response actual_request, interaction_diffs
|
@@ -119,7 +121,7 @@ module Pact
|
|
119
121
|
end
|
120
122
|
|
121
123
|
def logger_info_ap msg
|
122
|
-
|
124
|
+
logger.info msg
|
123
125
|
end
|
124
126
|
end
|
125
127
|
end
|
@@ -0,0 +1,28 @@
|
|
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,23 +1,27 @@
|
|
1
|
+
require 'pact/consumer/mock_service/mock_service_administration_endpoint'
|
2
|
+
|
1
3
|
module Pact
|
2
4
|
module Consumer
|
3
5
|
|
4
|
-
class MissingInteractionsGet
|
6
|
+
class MissingInteractionsGet < MockServiceAdministrationEndpoint
|
5
7
|
include RackRequestHelper
|
6
8
|
|
7
9
|
def initialize name, logger, interaction_list
|
8
|
-
|
9
|
-
@logger = logger
|
10
|
+
super name, logger
|
10
11
|
@interaction_list = interaction_list
|
11
12
|
end
|
12
13
|
|
13
|
-
def
|
14
|
-
|
15
|
-
|
14
|
+
def request_path
|
15
|
+
'/number_of_missing_interactions'
|
16
|
+
end
|
17
|
+
|
18
|
+
def request_method
|
19
|
+
'GET'
|
16
20
|
end
|
17
21
|
|
18
22
|
def respond env
|
19
23
|
number_of_missing_interactions = @interaction_list.missing_interactions.size
|
20
|
-
|
24
|
+
logger.info "Number of missing interactions for mock \"#{name}\" = #{number_of_missing_interactions}"
|
21
25
|
[200, {}, ["#{number_of_missing_interactions}"]]
|
22
26
|
end
|
23
27
|
|
@@ -0,0 +1,31 @@
|
|
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,29 +1,34 @@
|
|
1
|
+
require 'pact/consumer/mock_service/mock_service_administration_endpoint'
|
2
|
+
|
1
3
|
module Pact
|
2
4
|
module Consumer
|
3
|
-
class VerificationGet
|
5
|
+
class VerificationGet < MockServiceAdministrationEndpoint
|
4
6
|
|
5
7
|
include RackRequestHelper
|
8
|
+
attr_accessor :interaction_list, :log_description
|
6
9
|
|
7
|
-
def initialize name, logger,
|
8
|
-
|
9
|
-
@logger = logger
|
10
|
-
@log_description = log_description
|
10
|
+
def initialize name, logger, interaction_list, log_description
|
11
|
+
super name, logger
|
11
12
|
@interaction_list = interaction_list
|
13
|
+
@log_description = log_description
|
14
|
+
end
|
15
|
+
|
16
|
+
def request_path
|
17
|
+
'/verify'
|
12
18
|
end
|
13
19
|
|
14
|
-
def
|
15
|
-
|
16
|
-
env['REQUEST_METHOD'] == 'GET'
|
20
|
+
def request_method
|
21
|
+
'GET'
|
17
22
|
end
|
18
23
|
|
19
24
|
def respond env
|
20
|
-
if
|
21
|
-
|
25
|
+
if interaction_list.all_matched?
|
26
|
+
logger.info "Verifying - interactions matched for example \"#{example_description(env)}\""
|
22
27
|
[200, {}, ['Interactions matched']]
|
23
28
|
else
|
24
|
-
|
25
|
-
|
26
|
-
[500, {}, ["Actual interactions do not match expected interactions for mock #{
|
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."]]
|
27
32
|
end
|
28
33
|
end
|
29
34
|
|
@@ -3,32 +3,39 @@ require 'pact/consumer/mock_service_interaction_expectation'
|
|
3
3
|
module Pact
|
4
4
|
module Consumer
|
5
5
|
class MockServiceClient
|
6
|
+
|
7
|
+
MOCK_SERVICE_ADMINISTRATON_HEADERS = {'X-Pact-Mock-Service' => 'true'}
|
8
|
+
|
6
9
|
def initialize name, port
|
7
10
|
@http = Net::HTTP.new('localhost', port)
|
8
11
|
end
|
9
12
|
|
10
13
|
def verify example_description
|
11
|
-
response = http.request_get("/verify?example_description=#{URI.encode(example_description)}")
|
14
|
+
response = http.request_get("/verify?example_description=#{URI.encode(example_description)}", MOCK_SERVICE_ADMINISTRATON_HEADERS)
|
12
15
|
raise response.body unless response.is_a? Net::HTTPSuccess
|
13
16
|
end
|
14
17
|
|
18
|
+
def log msg
|
19
|
+
http.request_get("/log?msg=#{URI.encode(msg)}", MOCK_SERVICE_ADMINISTRATON_HEADERS)
|
20
|
+
end
|
21
|
+
|
15
22
|
def wait_for_interactions wait_max_seconds, poll_interval
|
16
23
|
wait_until_true(wait_max_seconds, poll_interval) do
|
17
|
-
response = http.request_get("/number_of_missing_interactions")
|
24
|
+
response = http.request_get("/number_of_missing_interactions", MOCK_SERVICE_ADMINISTRATON_HEADERS)
|
18
25
|
response.body == '0'
|
19
26
|
end
|
20
27
|
end
|
21
28
|
|
22
29
|
def clear_interactions example_description
|
23
|
-
http.delete("/interactions?example_description=#{URI.encode(example_description)}")
|
30
|
+
http.delete("/interactions?example_description=#{URI.encode(example_description)}", MOCK_SERVICE_ADMINISTRATON_HEADERS)
|
24
31
|
end
|
25
32
|
|
26
33
|
def add_expected_interaction interaction
|
27
|
-
http.request_post('/interactions', MockServiceInteractionExpectation.new(interaction).to_json)
|
34
|
+
http.request_post('/interactions', MockServiceInteractionExpectation.new(interaction).to_json, MOCK_SERVICE_ADMINISTRATON_HEADERS)
|
28
35
|
end
|
29
36
|
|
30
37
|
def self.clear_interactions port, example_description
|
31
|
-
Net::HTTP.new("localhost", port).delete("/interactions?example_description=#{URI.encode(example_description)}")
|
38
|
+
Net::HTTP.new("localhost", port).delete("/interactions?example_description=#{URI.encode(example_description)}", MOCK_SERVICE_ADMINISTRATON_HEADERS)
|
32
39
|
end
|
33
40
|
|
34
41
|
private
|
data/lib/pact/shared/dsl.rb
CHANGED
@@ -1,20 +1,53 @@
|
|
1
1
|
require 'delegate'
|
2
2
|
|
3
3
|
module Pact
|
4
|
+
|
5
|
+
class DslDelegator < SimpleDelegator
|
6
|
+
def instance_eval_with_previous_context_available(*args, &b)
|
7
|
+
meth = self.class.class_eval do
|
8
|
+
define_method :cloaker_, &b
|
9
|
+
meth = instance_method :cloaker_
|
10
|
+
remove_method :cloaker_
|
11
|
+
meth
|
12
|
+
end
|
13
|
+
with_previous_context(b.binding) {meth.bind(self).call(*args)}
|
14
|
+
end
|
15
|
+
|
16
|
+
def with_previous_context(binding, &block)
|
17
|
+
@previous_context = binding.eval('self')
|
18
|
+
result = block.call
|
19
|
+
@previous_context = nil
|
20
|
+
result
|
21
|
+
end
|
22
|
+
|
23
|
+
def method_missing(method, *args, &block)
|
24
|
+
if __getobj__().respond_to? method
|
25
|
+
super
|
26
|
+
elsif @previous_context
|
27
|
+
@previous_context.send(method, *args, &block)
|
28
|
+
else
|
29
|
+
super
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
|
4
35
|
# Ripped from http://blog.joecorcoran.co.uk/2013/09/04/simple-pattern-ruby-dsl
|
36
|
+
# and then fixed up by using http://www.skorks.com/2013/03/a-closure-is-not-always-a-closure-in-ruby/
|
37
|
+
# to access variables and methods defined in the calling scope.
|
5
38
|
module DSL
|
6
39
|
def build(*args, &block)
|
7
40
|
base = self.new(*args)
|
8
|
-
delegator_klass = self.const_get('
|
41
|
+
delegator_klass = self.const_get('DSL_DELEGATOR')
|
9
42
|
delegator = delegator_klass.new(base)
|
10
|
-
delegator.
|
43
|
+
delegator.instance_eval_with_previous_context_available(&block)
|
11
44
|
base.finalize
|
12
45
|
base
|
13
46
|
end
|
14
47
|
|
15
48
|
def dsl(&block)
|
16
|
-
delegator_klass = Class.new(
|
17
|
-
self.const_set('
|
49
|
+
delegator_klass = Class.new(DslDelegator, &block)
|
50
|
+
self.const_set('DSL_DELEGATOR', delegator_klass)
|
18
51
|
end
|
19
52
|
end
|
20
53
|
end
|
data/lib/pact/version.rb
CHANGED
data/pact.gemspec
CHANGED
@@ -5,7 +5,7 @@ require 'pact/consumer/rspec'
|
|
5
5
|
describe "A service consumer side of a pact", :pact => true do
|
6
6
|
|
7
7
|
context "with more than one matching interaction found" do
|
8
|
-
let(:expected_response) do
|
8
|
+
let(:expected_response) do
|
9
9
|
{"message"=>"Multiple interaction found for GET /path", "matching_interactions"=>[{"description"=>"a request", "request"=>{"method"=>"get", "path"=>"/path", "body"=>{"a"=>"some body"}, "headers"=>{"Content-Type"=>"application/json"}}}, {"description"=>"an identical request", "request"=>{"method"=>"get", "path"=>"/path", "body"=>{"a"=>"some body"}, "headers"=>{"Content-Type"=>"application/json"}}}]}
|
10
10
|
end
|
11
11
|
|
@@ -48,20 +48,20 @@ describe "A service consumer side of a pact", :pact => true do
|
|
48
48
|
|
49
49
|
context "with no matching interaction found" do
|
50
50
|
|
51
|
-
let(:expected_response) do
|
51
|
+
let(:expected_response) do
|
52
52
|
{
|
53
|
-
"message"=>"No interaction found for GET /path",
|
53
|
+
"message"=>"No interaction found for GET /path",
|
54
54
|
"interaction_diffs"=>[{
|
55
55
|
"description" => "a request that will not be properly matched",
|
56
56
|
"provider_state" => "something",
|
57
57
|
"body"=>{
|
58
58
|
"a"=>{
|
59
|
-
"expected"=>"some body",
|
59
|
+
"expected"=>"some body",
|
60
60
|
"actual"=>"not matching body"
|
61
61
|
}
|
62
62
|
}
|
63
63
|
}]
|
64
|
-
}
|
64
|
+
}
|
65
65
|
end
|
66
66
|
|
67
67
|
it "returns an error" do
|
@@ -132,7 +132,7 @@ describe "A service consumer side of a pact", :pact => true do
|
|
132
132
|
before do
|
133
133
|
Pact.clear_configuration
|
134
134
|
|
135
|
-
Pact.service_consumer "Consumer" do
|
135
|
+
Pact.service_consumer "Consumer" do
|
136
136
|
has_pact_with "Zebra Service" do
|
137
137
|
mock_service :zebra_service do
|
138
138
|
verify true
|
@@ -8,9 +8,10 @@ module Pact::Consumer::Configuration
|
|
8
8
|
Pact.clear_configuration
|
9
9
|
Pact::Consumer::AppManager.instance.stub(:register_mock_service_for)
|
10
10
|
end
|
11
|
+
|
11
12
|
describe "configure_consumer_contract_builder" do
|
12
13
|
let(:consumer_name) {'consumer'}
|
13
|
-
subject {
|
14
|
+
subject {
|
14
15
|
MockService.build :mock_service, consumer_name, provider_name do
|
15
16
|
port 1234
|
16
17
|
standalone true
|
@@ -36,18 +37,18 @@ module Pact::Consumer::Configuration
|
|
36
37
|
end
|
37
38
|
end
|
38
39
|
context "when not standalone" do
|
39
|
-
subject {
|
40
|
+
subject {
|
40
41
|
MockService.build :mock_service, consumer_name, provider_name do
|
41
42
|
port 1234
|
42
43
|
standalone false
|
43
44
|
verify true
|
44
45
|
end
|
45
|
-
}
|
46
|
+
}
|
46
47
|
it "registers the app with the AppManager" do
|
47
48
|
Pact::Consumer::AppManager.instance.should_receive(:register_mock_service_for).with(provider_name, url)
|
48
49
|
subject.finalize
|
49
50
|
end
|
50
|
-
end
|
51
|
+
end
|
51
52
|
end
|
52
53
|
end
|
53
54
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'pact/shared/dsl'
|
3
|
+
|
4
|
+
module Pact
|
5
|
+
describe DSL do
|
6
|
+
|
7
|
+
class TestDSL
|
8
|
+
extend DSL
|
9
|
+
attr_accessor :thing, :blah, :finally
|
10
|
+
|
11
|
+
dsl do
|
12
|
+
def with_thing thing
|
13
|
+
self.thing = thing
|
14
|
+
end
|
15
|
+
def with_blah blah
|
16
|
+
self.blah = blah
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def finalize
|
21
|
+
@finally = 'yay'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "build" do
|
26
|
+
it "should support calling other variables and methods in scope" do
|
27
|
+
def my_method
|
28
|
+
'LA LA LA'
|
29
|
+
end
|
30
|
+
|
31
|
+
my_local_var = 123
|
32
|
+
|
33
|
+
test = TestDSL.build do
|
34
|
+
with_thing my_method
|
35
|
+
with_blah my_local_var
|
36
|
+
end
|
37
|
+
|
38
|
+
expect(test.thing).to eq my_method
|
39
|
+
expect(test.blah).to eq my_local_var
|
40
|
+
expect(test.finally).to eq 'yay'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
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.11
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -239,6 +239,22 @@ dependencies:
|
|
239
239
|
- - ~>
|
240
240
|
- !ruby/object:Gem::Version
|
241
241
|
version: '2.0'
|
242
|
+
- !ruby/object:Gem::Dependency
|
243
|
+
name: rspec-fire
|
244
|
+
requirement: !ruby/object:Gem::Requirement
|
245
|
+
none: false
|
246
|
+
requirements:
|
247
|
+
- - ! '>='
|
248
|
+
- !ruby/object:Gem::Version
|
249
|
+
version: '0'
|
250
|
+
type: :development
|
251
|
+
prerelease: false
|
252
|
+
version_requirements: !ruby/object:Gem::Requirement
|
253
|
+
none: false
|
254
|
+
requirements:
|
255
|
+
- - ! '>='
|
256
|
+
- !ruby/object:Gem::Version
|
257
|
+
version: '0'
|
242
258
|
description: Define a pact between service consumers and providers
|
243
259
|
email:
|
244
260
|
- james.fraser@alumni.swinburne.edu
|
@@ -289,9 +305,10 @@ files:
|
|
289
305
|
- lib/pact/consumer/mock_service/interaction_list.rb
|
290
306
|
- lib/pact/consumer/mock_service/interaction_post.rb
|
291
307
|
- lib/pact/consumer/mock_service/interaction_replay.rb
|
308
|
+
- lib/pact/consumer/mock_service/log_get.rb
|
292
309
|
- lib/pact/consumer/mock_service/missing_interactions_get.rb
|
310
|
+
- lib/pact/consumer/mock_service/mock_service_administration_endpoint.rb
|
293
311
|
- lib/pact/consumer/mock_service/rack_request_helper.rb
|
294
|
-
- lib/pact/consumer/mock_service/startup_poll.rb
|
295
312
|
- lib/pact/consumer/mock_service/verification_get.rb
|
296
313
|
- lib/pact/consumer/mock_service_client.rb
|
297
314
|
- lib/pact/consumer/mock_service_interaction_expectation.rb
|
@@ -367,6 +384,7 @@ files:
|
|
367
384
|
- spec/lib/pact/provider/rspec_spec.rb
|
368
385
|
- spec/lib/pact/provider/test_methods_spec.rb
|
369
386
|
- spec/lib/pact/reification_spec.rb
|
387
|
+
- spec/lib/pact/shared/dsl_spec.rb
|
370
388
|
- spec/lib/pact/term_spec.rb
|
371
389
|
- spec/lib/pact/verification_task_spec.rb
|
372
390
|
- spec/spec_helper.rb
|
@@ -434,6 +452,7 @@ test_files:
|
|
434
452
|
- spec/lib/pact/provider/rspec_spec.rb
|
435
453
|
- spec/lib/pact/provider/test_methods_spec.rb
|
436
454
|
- spec/lib/pact/reification_spec.rb
|
455
|
+
- spec/lib/pact/shared/dsl_spec.rb
|
437
456
|
- spec/lib/pact/term_spec.rb
|
438
457
|
- spec/lib/pact/verification_task_spec.rb
|
439
458
|
- spec/spec_helper.rb
|
@@ -1,22 +0,0 @@
|
|
1
|
-
module Pact
|
2
|
-
module Consumer
|
3
|
-
|
4
|
-
class StartupPoll
|
5
|
-
|
6
|
-
def initialize name, logger
|
7
|
-
@name = name
|
8
|
-
@logger = logger
|
9
|
-
end
|
10
|
-
|
11
|
-
def match? env
|
12
|
-
env['REQUEST_PATH'] == '/index.html' &&
|
13
|
-
env['REQUEST_METHOD'] == 'GET'
|
14
|
-
end
|
15
|
-
|
16
|
-
def respond env
|
17
|
-
@logger.info "#{@name} started up"
|
18
|
-
[200, {}, ['Started up fine']]
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|