workable-pact-message 0.6.2

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.
Files changed (39) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +12 -0
  5. data/CHANGELOG.md +88 -0
  6. data/CONTRIBUTING.md +1 -0
  7. data/DEVELOPER_DOCUMENTATION.md +33 -0
  8. data/Gemfile +11 -0
  9. data/LICENSE.txt +21 -0
  10. data/QUESTIONS.md +3 -0
  11. data/README.md +41 -0
  12. data/Rakefile +8 -0
  13. data/bin/pact-message +3 -0
  14. data/bin/setup +8 -0
  15. data/lib/pact/consumer_contract/message.rb +142 -0
  16. data/lib/pact/consumer_contract/message/contents.rb +49 -0
  17. data/lib/pact/message.rb +4 -0
  18. data/lib/pact/message/cli.rb +34 -0
  19. data/lib/pact/message/consumer/configuration.rb +4 -0
  20. data/lib/pact/message/consumer/configuration/configuration_extensions.rb +19 -0
  21. data/lib/pact/message/consumer/configuration/message_builder.rb +67 -0
  22. data/lib/pact/message/consumer/configuration/message_consumer.rb +38 -0
  23. data/lib/pact/message/consumer/configuration/message_provider.rb +39 -0
  24. data/lib/pact/message/consumer/consumer_contract_builder.rb +59 -0
  25. data/lib/pact/message/consumer/consumer_contract_builders.rb +12 -0
  26. data/lib/pact/message/consumer/consumer_contract_decorator.rb +25 -0
  27. data/lib/pact/message/consumer/dsl.rb +13 -0
  28. data/lib/pact/message/consumer/interaction_builder.rb +38 -0
  29. data/lib/pact/message/consumer/interaction_decorator.rb +56 -0
  30. data/lib/pact/message/consumer/rspec.rb +26 -0
  31. data/lib/pact/message/consumer/spec_hooks.rb +13 -0
  32. data/lib/pact/message/consumer/update_pact.rb +43 -0
  33. data/lib/pact/message/consumer_contract_parser.rb +38 -0
  34. data/lib/pact/message/version.rb +5 -0
  35. data/pact-message.gemspec +45 -0
  36. data/script/release.sh +13 -0
  37. data/script/update-pact.sh +15 -0
  38. data/tasks/release.rake +15 -0
  39. metadata +209 -0
@@ -0,0 +1,4 @@
1
+ require "pact/message/version"
2
+ require "pact/message/consumer/configuration"
3
+ require "pact/message/consumer_contract_parser"
4
+ require "pact/consumer_contract/message"
@@ -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,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,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,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.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