workable-pact-message 0.6.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.rspec +3 -0
- data/.travis.yml +12 -0
- data/CHANGELOG.md +88 -0
- data/CONTRIBUTING.md +1 -0
- data/DEVELOPER_DOCUMENTATION.md +33 -0
- data/Gemfile +11 -0
- data/LICENSE.txt +21 -0
- data/QUESTIONS.md +3 -0
- data/README.md +41 -0
- data/Rakefile +8 -0
- data/bin/pact-message +3 -0
- data/bin/setup +8 -0
- data/lib/pact/consumer_contract/message.rb +142 -0
- data/lib/pact/consumer_contract/message/contents.rb +49 -0
- data/lib/pact/message.rb +4 -0
- data/lib/pact/message/cli.rb +34 -0
- data/lib/pact/message/consumer/configuration.rb +4 -0
- data/lib/pact/message/consumer/configuration/configuration_extensions.rb +19 -0
- data/lib/pact/message/consumer/configuration/message_builder.rb +67 -0
- data/lib/pact/message/consumer/configuration/message_consumer.rb +38 -0
- data/lib/pact/message/consumer/configuration/message_provider.rb +39 -0
- data/lib/pact/message/consumer/consumer_contract_builder.rb +59 -0
- data/lib/pact/message/consumer/consumer_contract_builders.rb +12 -0
- data/lib/pact/message/consumer/consumer_contract_decorator.rb +25 -0
- data/lib/pact/message/consumer/dsl.rb +13 -0
- data/lib/pact/message/consumer/interaction_builder.rb +38 -0
- data/lib/pact/message/consumer/interaction_decorator.rb +56 -0
- data/lib/pact/message/consumer/rspec.rb +26 -0
- data/lib/pact/message/consumer/spec_hooks.rb +13 -0
- data/lib/pact/message/consumer/update_pact.rb +43 -0
- data/lib/pact/message/consumer_contract_parser.rb +38 -0
- data/lib/pact/message/version.rb +5 -0
- data/pact-message.gemspec +45 -0
- data/script/release.sh +13 -0
- data/script/update-pact.sh +15 -0
- data/tasks/release.rake +15 -0
- metadata +209 -0
data/lib/pact/message.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'thor'
|
2
|
+
|
3
|
+
module Pact
|
4
|
+
module Message
|
5
|
+
class CLI < Thor
|
6
|
+
|
7
|
+
method_option :consumer, required: true, desc: "The Consumer name"
|
8
|
+
method_option :provider, required: true, desc: "The Provider name"
|
9
|
+
method_option :pact_dir, required: true, desc: "The Pact directory"
|
10
|
+
method_option :pact_specification_version, required: false, default: "2.0.0", desc: "The Pact Specification version"
|
11
|
+
|
12
|
+
desc 'update MESSAGE_JSON', 'Update a pact with the given message, or create the pact if it does not exist. The MESSAGE_JSON may be in the legacy Ruby JSON format or the v2+ format.'
|
13
|
+
def update(message)
|
14
|
+
require 'pact/message'
|
15
|
+
require 'pact/message/consumer/update_pact'
|
16
|
+
pact_specification_version = Pact::SpecificationVersion.new(options.pact_specification_version)
|
17
|
+
message = Pact::Message.from_hash(JSON.load(message), { pact_specification_version: pact_specification_version })
|
18
|
+
Pact::Message::Consumer::UpdatePact.call(message, options.pact_dir, options.consumer, options.provider, options.pact_specification_version)
|
19
|
+
end
|
20
|
+
|
21
|
+
desc 'reify', "Take a JSON document with embedded pact matchers and return a concrete example"
|
22
|
+
def reify(json)
|
23
|
+
require 'pact/support'
|
24
|
+
puts Pact::Reification.from_term(JSON.load(json)).to_json
|
25
|
+
end
|
26
|
+
|
27
|
+
desc 'version', "Show the pact-message gem version"
|
28
|
+
def version
|
29
|
+
require 'pact/message/version.rb'
|
30
|
+
puts Pact::Message::VERSION
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'pact/configuration'
|
2
|
+
|
3
|
+
module Pact
|
4
|
+
module Message
|
5
|
+
module Consumer
|
6
|
+
module Configuration
|
7
|
+
module ConfigurationExtensions
|
8
|
+
def add_message_provider_verification &block
|
9
|
+
message_provider_verifications << block
|
10
|
+
end
|
11
|
+
|
12
|
+
def message_provider_verifications
|
13
|
+
@message_provider_verifications ||= []
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'pact/message/consumer/consumer_contract_builder'
|
2
|
+
require 'pact/message/consumer/consumer_contract_builders'
|
3
|
+
# require 'pact/consumer/world'
|
4
|
+
|
5
|
+
module Pact
|
6
|
+
module Message
|
7
|
+
module Consumer
|
8
|
+
module Configuration
|
9
|
+
class MessageBuilder
|
10
|
+
|
11
|
+
extend Pact::DSL
|
12
|
+
|
13
|
+
attr_accessor :provider_name, :consumer_name, :pact_specification_version
|
14
|
+
|
15
|
+
def initialize name, consumer_name, provider_name
|
16
|
+
@name = name
|
17
|
+
@consumer_name = consumer_name
|
18
|
+
@provider_name = provider_name
|
19
|
+
@pact_specification_version = nil
|
20
|
+
end
|
21
|
+
|
22
|
+
dsl do
|
23
|
+
def pact_specification_version pact_specification_version
|
24
|
+
self.pact_specification_version = pact_specification_version
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def finalize
|
29
|
+
configure_consumer_contract_builder
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def configure_consumer_contract_builder
|
35
|
+
consumer_contract_builder = create_consumer_contract_builder
|
36
|
+
create_consumer_contract_builders_method consumer_contract_builder
|
37
|
+
setup_verification(consumer_contract_builder)
|
38
|
+
consumer_contract_builder
|
39
|
+
end
|
40
|
+
|
41
|
+
def create_consumer_contract_builder
|
42
|
+
consumer_contract_builder_fields = {
|
43
|
+
:consumer_name => consumer_name,
|
44
|
+
:provider_name => provider_name,
|
45
|
+
}
|
46
|
+
# :pactfile_write_mode => Pact.configuration.pactfile_write_mode,
|
47
|
+
# :pact_dir => Pact.configuration.pact_dir
|
48
|
+
Pact::Message::Consumer::ConsumerContractBuilder.new consumer_contract_builder_fields
|
49
|
+
end
|
50
|
+
|
51
|
+
def setup_verification consumer_contract_builder
|
52
|
+
Pact.configuration.add_message_provider_verification do | example_description |
|
53
|
+
consumer_contract_builder.verify example_description
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def create_consumer_contract_builders_method consumer_contract_builder
|
58
|
+
Pact::Message::Consumer::ConsumerContractBuilders.send(:define_method, @name.to_sym) do
|
59
|
+
consumer_contract_builder
|
60
|
+
end
|
61
|
+
# Pact.consumer_world.add_consumer_contract_builder consumer_contract_builder
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'pact/shared/dsl'
|
2
|
+
require 'pact/message/consumer/configuration/message_provider'
|
3
|
+
|
4
|
+
module Pact
|
5
|
+
module Message
|
6
|
+
module Consumer
|
7
|
+
module Configuration
|
8
|
+
class MessageConsumer
|
9
|
+
|
10
|
+
extend Pact::DSL
|
11
|
+
|
12
|
+
attr_accessor :builder, :name
|
13
|
+
|
14
|
+
def initialize name
|
15
|
+
@name = name
|
16
|
+
end
|
17
|
+
|
18
|
+
dsl do
|
19
|
+
def has_pact_with message_provider_name, &block
|
20
|
+
MessageProvider.build(message_provider_name, self.name, &block)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def finalize
|
25
|
+
validate
|
26
|
+
register_consumer_app if @app
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def validate
|
32
|
+
raise "Please provide a consumer name" unless (name && !name.empty?)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'pact/shared/dsl'
|
2
|
+
require 'pact/message/consumer/configuration/message_builder'
|
3
|
+
|
4
|
+
module Pact
|
5
|
+
module Message
|
6
|
+
module Consumer
|
7
|
+
module Configuration
|
8
|
+
class MessageProvider
|
9
|
+
|
10
|
+
extend Pact::DSL
|
11
|
+
|
12
|
+
attr_accessor :builder, :consumer_name, :name
|
13
|
+
|
14
|
+
def initialize name, consumer_name
|
15
|
+
@name = name
|
16
|
+
@builder = nil
|
17
|
+
@consumer_name = consumer_name
|
18
|
+
end
|
19
|
+
|
20
|
+
dsl do
|
21
|
+
def builder builder_name, &block
|
22
|
+
self.builder = MessageBuilder.build(builder_name, consumer_name, name, &block)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def finalize
|
27
|
+
validate
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def validate
|
33
|
+
raise "Please configure a name for the message provider" unless name
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'pact/message/consumer/interaction_builder'
|
2
|
+
require 'pact/message/consumer/update_pact'
|
3
|
+
|
4
|
+
module Pact
|
5
|
+
module Message
|
6
|
+
module Consumer
|
7
|
+
class ConsumerContractBuilder
|
8
|
+
|
9
|
+
def initialize(attributes)
|
10
|
+
@interaction_builder = nil
|
11
|
+
@consumer_name = attributes[:consumer_name]
|
12
|
+
@provider_name = attributes[:provider_name]
|
13
|
+
@interactions = []
|
14
|
+
end
|
15
|
+
|
16
|
+
def given(provider_state)
|
17
|
+
interaction_builder.given(provider_state)
|
18
|
+
end
|
19
|
+
|
20
|
+
def is_expected_to_send(description)
|
21
|
+
interaction_builder.is_expected_to_send(provider_state)
|
22
|
+
end
|
23
|
+
|
24
|
+
def send_message
|
25
|
+
# TODO handle matchers
|
26
|
+
yield @contents_string if block_given?
|
27
|
+
end
|
28
|
+
|
29
|
+
def handle_interaction_fully_defined(interaction)
|
30
|
+
@contents_string = interaction.contents.to_s
|
31
|
+
@interactions << interaction
|
32
|
+
@interaction_builder = nil
|
33
|
+
# TODO pull these from pact config
|
34
|
+
Pact::Message::Consumer::UpdatePact.call(interaction, "./spec/pacts", consumer_name, provider_name, "2.0.0")
|
35
|
+
end
|
36
|
+
|
37
|
+
def verify example_description
|
38
|
+
#
|
39
|
+
# TODO check that message was actually yielded
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
attr_writer :interaction_builder
|
45
|
+
attr_accessor :consumer_name, :provider_name, :consumer_contract_details
|
46
|
+
|
47
|
+
def interaction_builder
|
48
|
+
@interaction_builder ||=
|
49
|
+
begin
|
50
|
+
interaction_builder = InteractionBuilder.new do | interaction |
|
51
|
+
handle_interaction_fully_defined(interaction)
|
52
|
+
end
|
53
|
+
interaction_builder
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'pact/consumer_contract/consumer_contract_decorator'
|
2
|
+
require 'pact/message/consumer/interaction_decorator'
|
3
|
+
|
4
|
+
module Pact
|
5
|
+
module Message
|
6
|
+
module Consumer
|
7
|
+
class ConsumerContractDecorator < Pact::ConsumerContractDecorator
|
8
|
+
|
9
|
+
|
10
|
+
def as_json(options = {})
|
11
|
+
fix_all_the_things(
|
12
|
+
consumer: consumer_contract.consumer.as_json,
|
13
|
+
provider: consumer_contract.provider.as_json,
|
14
|
+
messages: sorted_interactions.collect{ |i| InteractionDecorator.new(i, @decorator_options).as_json},
|
15
|
+
metadata: {
|
16
|
+
pactSpecification: {
|
17
|
+
version: pact_specification_version
|
18
|
+
}
|
19
|
+
}
|
20
|
+
)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'pact/reification'
|
2
|
+
|
3
|
+
module Pact
|
4
|
+
module Message
|
5
|
+
module Consumer
|
6
|
+
class InteractionBuilder
|
7
|
+
|
8
|
+
attr_reader :interaction
|
9
|
+
|
10
|
+
def initialize &block
|
11
|
+
@interaction = Pact::Message.new
|
12
|
+
@callback = block
|
13
|
+
end
|
14
|
+
|
15
|
+
def is_expected_to_send description
|
16
|
+
@interaction.description = description
|
17
|
+
self
|
18
|
+
end
|
19
|
+
|
20
|
+
def given provider_state
|
21
|
+
@interaction.provider_state = provider_state.nil? ? nil : provider_state.to_s
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
def with_metadata(object)
|
26
|
+
# TODO implement this
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
def with_content(object)
|
31
|
+
interaction.contents = Pact::Message::Contents.from_hash(object)
|
32
|
+
@callback.call interaction
|
33
|
+
self
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'pact/shared/active_support_support'
|
2
|
+
|
3
|
+
module Pact
|
4
|
+
module Message
|
5
|
+
module Consumer
|
6
|
+
class InteractionDecorator
|
7
|
+
|
8
|
+
include ActiveSupportSupport
|
9
|
+
|
10
|
+
def initialize message, decorator_options = {}
|
11
|
+
@message = message
|
12
|
+
@decorator_options = decorator_options
|
13
|
+
end
|
14
|
+
|
15
|
+
def as_json options = {}
|
16
|
+
hash = { :description => message.description }
|
17
|
+
hash[:providerStates] = provider_states
|
18
|
+
hash[:contents] = extract_contents
|
19
|
+
hash[:matchingRules] = extract_matching_rules
|
20
|
+
hash[:metaData] = message.metadata || {}
|
21
|
+
fix_all_the_things hash
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_json(options = {})
|
25
|
+
as_json(options).to_json(options)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
attr_reader :message
|
31
|
+
|
32
|
+
def decorate_contents
|
33
|
+
message.contents.as_json
|
34
|
+
end
|
35
|
+
|
36
|
+
def extract_contents
|
37
|
+
Pact::Reification.from_term(message.contents.contents)
|
38
|
+
end
|
39
|
+
|
40
|
+
def provider_states
|
41
|
+
message.provider_states.collect(&:as_json)
|
42
|
+
end
|
43
|
+
|
44
|
+
def extract_matching_rules
|
45
|
+
{
|
46
|
+
body: Pact::MatchingRules.extract(message.contents.contents, pact_specification_version: pact_specification_version)
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
def pact_specification_version
|
51
|
+
Pact::SpecificationVersion.new(@decorator_options[:pact_specification_version])
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'pact/rspec'
|
3
|
+
require 'pact/message/consumer/consumer_contract_builders'
|
4
|
+
require 'pact/message/consumer/spec_hooks'
|
5
|
+
require 'pact/helpers'
|
6
|
+
|
7
|
+
module Pact
|
8
|
+
module Message
|
9
|
+
module Consumer
|
10
|
+
module RSpec
|
11
|
+
include Pact::Message::Consumer::ConsumerContractBuilders
|
12
|
+
include Pact::Helpers
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
hooks = Pact::Message::Consumer::SpecHooks.new
|
19
|
+
|
20
|
+
RSpec.configure do |config|
|
21
|
+
config.include Pact::Message::Consumer::RSpec, :pact => :message
|
22
|
+
|
23
|
+
config.after :each, :pact => true do | example |
|
24
|
+
hooks.after_each Pact::RSpec.full_description(example)
|
25
|
+
end
|
26
|
+
end
|