workable-pact-message 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
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