pact-message 0.1.1

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 40da9a34d550a04c42e1d76e5f777db9ad4ab27a
4
+ data.tar.gz: '06333869e35b99613dac5fa66f65346b5f7e233c'
5
+ SHA512:
6
+ metadata.gz: cf8980b59a3909f73d188c2a81ec86cacb72ca4eba101a72ada87e12ef3e2b8c3efbd9c706814e99f9231719226438cb0e9edecc291093231b2cf5796025f4b6
7
+ data.tar.gz: 8796c96f56684c33ff357aebff1425a4569ce35a6bd607f92cf7194af91e5ed6dbef914ad6bedcaa0a832272d6bbf313a139b95a3340a2c80cdde4f6a74bebef
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ spec/pacts/foo_consumer-bar_producer.json
11
+ spec/pacts/zoo_consumer-zoo_provider.json
12
+
13
+ # rspec failure tracking
14
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper.rb
data/.travis.yml ADDED
@@ -0,0 +1,12 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.4.1
5
+ before_install: gem install bundler -v 1.15.4
6
+ notifications:
7
+ webhooks:
8
+ urls:
9
+ - https://webhooks.gitter.im/e/6523128341fad111ed79
10
+ on_success: change
11
+ on_failure: always
12
+ on_start: never
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in pact-message.gemspec
6
+ gemspec
7
+
8
+ if ENV['X_PACT_DEVELOPMENT']
9
+ gem "pact-support", path: '../pact-support'
10
+ gem "pact-mock_service", path: '../pact-mock_service'
11
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 Beth Skurrie
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/QUESTIONS.md ADDED
@@ -0,0 +1,3 @@
1
+ * Do we reuse Pact.configuration or make Pact::Message.configuration?
2
+ * Do we put the pacts in the same directory or a different one?
3
+ * Check the message format
data/README.md ADDED
@@ -0,0 +1,41 @@
1
+ # Pact::Message
2
+
3
+ [![Join the chat at https://gitter.im/pact-foundation/pact-message-ruby](https://badges.gitter.im/pact-foundation/pact-message-ruby.svg)](https://gitter.im/pact-foundation/pact-message-ruby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
4
+
5
+ Create and verify consumer driven contracts for messages.
6
+
7
+ This project is still under development and is not ready for production use.
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem 'pact-message'
15
+ ```
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install pact-message
24
+
25
+ ## Usage
26
+
27
+
28
+
29
+ ## Development
30
+
31
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
32
+
33
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
34
+
35
+ ## Contributing
36
+
37
+ Bug reports and pull requests are welcome on GitHub at https://github.com/pact-foundation/pact-message-ruby.
38
+
39
+ ## License
40
+
41
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "pact/message"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/pact-message ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require 'pact/message/cli'
3
+ Pact::Message::CLI.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,40 @@
1
+ module Pact
2
+ class ConsumerContract
3
+ class Message
4
+ class Content
5
+ include ActiveSupportSupport
6
+ include SymbolizeKeys
7
+
8
+ def initialize content
9
+ @content = content
10
+ end
11
+
12
+ def to_s
13
+ if @content.is_a?(Hash) || @content.is_a?(Array)
14
+ @content.to_json
15
+ else
16
+ @content.to_s
17
+ end
18
+ end
19
+
20
+ def as_json
21
+ @content
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ module Pact
29
+ module Message
30
+ class Content
31
+ def self.new *args
32
+ Pact::ConsumerContract::Message::Content.new(*args)
33
+ end
34
+
35
+ def self.from_hash *args
36
+ Pact::ConsumerContract::Message::Content.from_hash(*args)
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,127 @@
1
+ require 'pact/consumer_contract/message/content'
2
+ require 'pact/symbolize_keys'
3
+ require 'pact/shared/active_support_support'
4
+ require 'pact/matching_rules'
5
+ require 'pact/errors'
6
+ require 'pact/consumer/request'
7
+ require 'pact/consumer_contract/response'
8
+ require 'pact/consumer_contract/message/content'
9
+
10
+ module Pact
11
+ class ConsumerContract
12
+ class Message
13
+ include Pact::ActiveSupportSupport
14
+ include Pact::SymbolizeKeys
15
+
16
+ attr_accessor :description, :content, :provider_state
17
+
18
+ def initialize attributes = {}
19
+ @description = attributes[:description]
20
+ @provider_state = attributes[:provider_state] || attributes[:providerState]
21
+ @content = attributes[:content]
22
+ end
23
+
24
+ def self.from_hash hash
25
+ content_hash = Pact::MatchingRules.merge(hash['content'], hash['content']['matchingRules'])
26
+ content = Pact::ConsumerContract::Message::Content.new(content_hash)
27
+ new(symbolize_keys(hash).merge(content: content))
28
+ end
29
+
30
+ def to_hash
31
+ {
32
+ description: description,
33
+ provider_state: provider_state,
34
+ content: content.to_hash,
35
+ }
36
+ end
37
+
38
+ # todo move this proper decorator
39
+ def as_json
40
+ {
41
+ description: description,
42
+ providerState: provider_state,
43
+ content: content.as_json
44
+ }
45
+ end
46
+
47
+ def request
48
+ @request ||= Pact::Consumer::Request::Actual.from_hash(
49
+ path: '/',
50
+ method: 'POST',
51
+ query: nil,
52
+ headers: {'Content-Type' => 'application/json'},
53
+ body: {
54
+ description: description,
55
+ providerStates: [{
56
+ name: provider_state
57
+ }]
58
+ }
59
+ )
60
+ end
61
+
62
+ # custom media type?
63
+ def response
64
+ @response ||= Pact::Response.new(
65
+ status: 200,
66
+ headers: {'Content-Type' => 'application/json'},
67
+ body: {
68
+ content: content
69
+ }
70
+ )
71
+ end
72
+
73
+ def http?
74
+ false
75
+ end
76
+
77
+ def message?
78
+ true
79
+ end
80
+
81
+ def validate!
82
+ raise Pact::InvalidMessageError.new(self) unless description && content
83
+ end
84
+
85
+ def == other
86
+ other.is_a?(Message) && to_hash == other.to_hash
87
+ end
88
+
89
+ def matches_criteria? criteria
90
+ criteria.each do | key, value |
91
+ unless match_criterion self.send(key.to_s), value
92
+ return false
93
+ end
94
+ end
95
+ true
96
+ end
97
+
98
+ def match_criterion target, criterion
99
+ target == criterion || (criterion.is_a?(Regexp) && criterion.match(target))
100
+ end
101
+
102
+ def eq? other
103
+ self == other
104
+ end
105
+
106
+ def description_with_provider_state_quoted
107
+ provider_state ? "\"#{description}\" given \"#{provider_state}\"" : "\"#{description}\""
108
+ end
109
+
110
+ def to_s
111
+ to_hash.to_s
112
+ end
113
+ end
114
+ end
115
+ end
116
+
117
+ module Pact
118
+ module Message
119
+ def self.new *args
120
+ Pact::ConsumerContract::Message.new(*args)
121
+ end
122
+
123
+ def self.from_hash *args
124
+ Pact::ConsumerContract::Message.from_hash(*args)
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,21 @@
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
+ message = Pact::Message.from_hash(JSON.parse(message))
17
+ Pact::Message::Consumer::UpdatePact.call(message, options.pact_dir, options.consumer, options.provider, options.pact_specification_version)
18
+ end
19
+ end
20
+ end
21
+ 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,4 @@
1
+ require 'pact/message/consumer/dsl'
2
+ require 'pact/message/consumer/configuration/configuration_extensions'
3
+ Pact.send(:extend, Pact::Message::Consumer::DSL)
4
+ Pact::Configuration.send(:include, Pact::Message::Consumer::Configuration::ConfigurationExtensions)
@@ -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 @content_string if block_given?
27
+ end
28
+
29
+ def handle_interaction_fully_defined(interaction)
30
+ @content_string = interaction.content.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,12 @@
1
+ module Pact
2
+ module Message
3
+ module Consumer
4
+ module ConsumerContractBuilders
5
+ # Placeholder for mock service methods which will be dynamically created
6
+ # from the Pact configuration.
7
+
8
+ # To be included in RSpec
9
+ end
10
+ end
11
+ end
12
+ 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,13 @@
1
+ require 'pact/message/consumer/configuration/message_consumer'
2
+
3
+ module Pact
4
+ module Message
5
+ module Consumer
6
+ module DSL
7
+ def message_consumer name, &block
8
+ Configuration::MessageConsumer.build(name, &block)
9
+ end
10
+ end
11
+ end
12
+ end
13
+ 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.content = Pact::Message::Content.new(object)
32
+ @callback.call interaction
33
+ self
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,36 @@
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 interaction, decorator_options = {}
11
+ @interaction = interaction
12
+ @decorator_options = decorator_options
13
+ end
14
+
15
+ def as_json options = {}
16
+ hash = { :description => interaction.description }
17
+ hash[:providerState] = interaction.provider_state if interaction.provider_state
18
+ hash[:content] = decorate_content
19
+ fix_all_the_things hash
20
+ end
21
+
22
+ def to_json(options = {})
23
+ as_json(options).to_json(options)
24
+ end
25
+
26
+ private
27
+
28
+ attr_reader :interaction
29
+
30
+ def decorate_content
31
+ interaction.content.as_json
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,25 @@
1
+ require 'rspec'
2
+ require 'pact/rspec'
3
+ require 'pact/message/consumer/consumer_contract_builders'
4
+ require 'pact/message/consumer/spec_hooks'
5
+
6
+ module Pact
7
+ module Message
8
+ module Consumer
9
+ module RSpec
10
+ include Pact::Message::Consumer::ConsumerContractBuilders
11
+ include Pact::Helpers
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ hooks = Pact::Message::Consumer::SpecHooks.new
18
+
19
+ RSpec.configure do |config|
20
+ config.include Pact::Message::Consumer::RSpec, :pact => :message
21
+
22
+ config.after :each, :pact => true do | example |
23
+ hooks.after_each Pact::RSpec.full_description(example)
24
+ end
25
+ end
@@ -0,0 +1,13 @@
1
+ module Pact
2
+ module Message
3
+ module Consumer
4
+ class SpecHooks
5
+ def after_each example_description
6
+ Pact.configuration.message_provider_verifications.each do | message_provider_verification |
7
+ message_provider_verification.call example_description
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,43 @@
1
+ require 'pact/consumer_contract/consumer_contract_writer'
2
+ require 'pact/message/consumer/consumer_contract_decorator'
3
+
4
+ module Pact
5
+ module Message
6
+ module Consumer
7
+ class UpdatePact
8
+
9
+ def initialize message, pact_dir, consumer_name, provider_name, pact_specification_version
10
+ @pact_dir = pact_dir
11
+ @message = message
12
+ @consumer_name = consumer_name
13
+ @provider_name = provider_name
14
+ @pact_specification_version = pact_specification_version
15
+ end
16
+
17
+ def self.call(message, pact_dir, consumer_name, provider_name, pact_specification_version)
18
+ new(message, pact_dir, consumer_name, provider_name, pact_specification_version).call
19
+ end
20
+
21
+ def call
22
+ details = {
23
+ consumer: {name: consumer_name},
24
+ provider: {name: provider_name},
25
+ interactions: [message],
26
+ pactfile_write_mode: :update,
27
+ pact_dir: pact_dir,
28
+ pact_specification_version: pact_specification_version,
29
+ error_stream: StringIO.new,
30
+ output_stream: StringIO.new,
31
+ consumer_contract_decorator_class: Pact::Message::Consumer::ConsumerContractDecorator
32
+ }
33
+ writer = Pact::ConsumerContractWriter.new(details, Logger.new(StringIO.new))
34
+ writer.write
35
+ end
36
+
37
+ private
38
+
39
+ attr_reader :message, :pact_dir, :consumer_name, :provider_name, :pact_specification_version
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,27 @@
1
+ require 'pact/consumer_contract'
2
+ require 'pact/consumer_contract/message'
3
+ require 'pact/consumer_contract/message/content'
4
+
5
+ module Pact
6
+ module Message
7
+ class ConsumerContractParser
8
+ include SymbolizeKeys
9
+
10
+ def call(hash)
11
+ hash = symbolize_keys(hash)
12
+ interactions = hash[:messages].collect { |hash| Pact::ConsumerContract::Message.from_hash(hash)}
13
+ ConsumerContract.new(
14
+ :consumer => ServiceConsumer.from_hash(hash[:consumer]),
15
+ :provider => ServiceProvider.from_hash(hash[:provider]),
16
+ :interactions => interactions
17
+ )
18
+ end
19
+
20
+ def can_parse?(hash)
21
+ hash.key?('messages') || hash.key?(:messages)
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ Pact::ConsumerContract.add_parser(Pact::Message::ConsumerContractParser.new)
@@ -0,0 +1,5 @@
1
+ module Pact
2
+ module Message
3
+ VERSION = "0.1.1"
4
+ end
5
+ end
@@ -0,0 +1,13 @@
1
+ module Pact
2
+ module Message
3
+
4
+ end
5
+ end
6
+
7
+ require "pact/message/version"
8
+ require "pact/message/consumer/configuration"
9
+ # Require this after so that Pact::Message.new and Pact::Message.from_hash
10
+ # are defined correctly in pact-support/lib/pact/consumer_contract/message.rb
11
+ require "pact/support"
12
+ require "pact/consumer_contract/message"
13
+ require "pact/consumer_contract/message/content"
@@ -0,0 +1,43 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "pact/message/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "pact-message"
8
+ spec.version = Pact::Message::VERSION
9
+ spec.authors = ["Beth Skurrie"]
10
+ spec.email = ["beth@bethesque.com"]
11
+
12
+ spec.summary = %q{Consumer contract library for messages}
13
+ spec.homepage = "http://pact.io"
14
+ spec.license = "MIT"
15
+
16
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
17
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
18
+ if spec.respond_to?(:metadata)
19
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
20
+ else
21
+ raise "RubyGems 2.0 or newer is required to protect against " \
22
+ "public gem pushes."
23
+ end
24
+
25
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
26
+ f.match(%r{^(test|spec|features)/})
27
+ end
28
+ spec.bindir = "exe"
29
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
30
+ spec.require_paths = ["lib"]
31
+
32
+ spec.add_runtime_dependency "pact-support", "1.2.99.alpha.1"
33
+ # pact-mock_service dependencies are Pact::ConsumerContractDecorator
34
+ # and Pact::ConsumerContractWriter. Potentially we should extract
35
+ # or duplicate these classes to remove the pact-mock_service dependency.
36
+ spec.add_runtime_dependency "pact-mock_service", "~> 2.6"
37
+ spec.add_runtime_dependency "thor", "~> 0.20"
38
+
39
+ spec.add_development_dependency "bundler", "~> 1.15"
40
+ spec.add_development_dependency "rake", "~> 10.0"
41
+ spec.add_development_dependency "rspec", "~> 3.0"
42
+ spec.add_development_dependency "pry-byebug"
43
+ end
metadata ADDED
@@ -0,0 +1,175 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pact-message
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Beth Skurrie
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2018-03-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: pact-support
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 1.2.99.alpha.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 1.2.99.alpha.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: pact-mock_service
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.6'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.6'
41
+ - !ruby/object:Gem::Dependency
42
+ name: thor
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.20'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.20'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.15'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.15'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '10.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '10.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: pry-byebug
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description:
112
+ email:
113
+ - beth@bethesque.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - ".gitignore"
119
+ - ".rspec"
120
+ - ".travis.yml"
121
+ - Gemfile
122
+ - LICENSE.txt
123
+ - QUESTIONS.md
124
+ - README.md
125
+ - Rakefile
126
+ - bin/console
127
+ - bin/pact-message
128
+ - bin/setup
129
+ - lib/pact/consumer_contract/message.rb
130
+ - lib/pact/consumer_contract/message/content.rb
131
+ - lib/pact/message.rb
132
+ - lib/pact/message/cli.rb
133
+ - lib/pact/message/consumer/configuration.rb
134
+ - lib/pact/message/consumer/configuration/configuration_extensions.rb
135
+ - lib/pact/message/consumer/configuration/message_builder.rb
136
+ - lib/pact/message/consumer/configuration/message_consumer.rb
137
+ - lib/pact/message/consumer/configuration/message_provider.rb
138
+ - lib/pact/message/consumer/consumer_contract_builder.rb
139
+ - lib/pact/message/consumer/consumer_contract_builders.rb
140
+ - lib/pact/message/consumer/consumer_contract_decorator.rb
141
+ - lib/pact/message/consumer/dsl.rb
142
+ - lib/pact/message/consumer/interaction_builder.rb
143
+ - lib/pact/message/consumer/interaction_decorator.rb
144
+ - lib/pact/message/consumer/rspec.rb
145
+ - lib/pact/message/consumer/spec_hooks.rb
146
+ - lib/pact/message/consumer/update_pact.rb
147
+ - lib/pact/message/consumer_contract_parser.rb
148
+ - lib/pact/message/version.rb
149
+ - pact-message.gemspec
150
+ homepage: http://pact.io
151
+ licenses:
152
+ - MIT
153
+ metadata:
154
+ allowed_push_host: https://rubygems.org
155
+ post_install_message:
156
+ rdoc_options: []
157
+ require_paths:
158
+ - lib
159
+ required_ruby_version: !ruby/object:Gem::Requirement
160
+ requirements:
161
+ - - ">="
162
+ - !ruby/object:Gem::Version
163
+ version: '0'
164
+ required_rubygems_version: !ruby/object:Gem::Requirement
165
+ requirements:
166
+ - - ">="
167
+ - !ruby/object:Gem::Version
168
+ version: '0'
169
+ requirements: []
170
+ rubyforge_project:
171
+ rubygems_version: 2.6.11
172
+ signing_key:
173
+ specification_version: 4
174
+ summary: Consumer contract library for messages
175
+ test_files: []