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,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d03714d68367ea0d1b939b26305c60fd5001fcf06aa799af6104f8af29b63605
4
+ data.tar.gz: e6d8605e16ebb00fc2e490fff29a89d09c678a67a03f61520e6bf89862e34c09
5
+ SHA512:
6
+ metadata.gz: c541690678b17da0ac3031efb5500e179ec5db255cbc5ddf8448bf3e523fed70432c014b91696d604932c64bcf8e74c350c43e5af5dd3d91496ac7481047971a
7
+ data.tar.gz: 1459f7bf5ed5af8fd5b45e015a9d3cf8ea525ec566976c821e750e58336ec9e6e2f8cc69345a9682173fa1ee9369dd68fb1f8859b9b6b52c366ce50ff679ebd6
@@ -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
@@ -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
@@ -0,0 +1,88 @@
1
+ <a name="v0.5.0"></a>
2
+ ### v0.5.0 (2018-10-04)
3
+
4
+
5
+ #### Features
6
+
7
+ * **pact specification v3**
8
+ * add support for multiple provider states and params ([b2c1cc7](/../../commit/b2c1cc7))
9
+
10
+
11
+ <a name="v0.4.5"></a>
12
+ ### v0.4.5 (2018-07-07)
13
+
14
+
15
+ #### Bug Fixes
16
+
17
+ * include metaData in message pact ([e68ca4f](/../../commit/e68ca4f))
18
+
19
+
20
+ <a name="v0.4.3"></a>
21
+ ### v0.4.3 (2018-05-06)
22
+
23
+
24
+ #### Features
25
+
26
+ * **version**
27
+ * add version command to CLI, fixes #10 ([f928248](/../../commit/f928248))
28
+
29
+
30
+ #### Bug Fixes
31
+
32
+ * **content**
33
+ * rename message content -> contents. fixes #9 ([0908962](/../../commit/0908962))
34
+
35
+
36
+ <a name="v0.4.1"></a>
37
+ ### v0.4.1 (2018-04-05)
38
+
39
+
40
+ #### Features
41
+
42
+ * read/write metaData from/to v3 pact files ([7dfcbb9](/../../commit/7dfcbb9))
43
+
44
+
45
+ #### Bug Fixes
46
+
47
+ * locate content matching rules from correct path ([5254c01](/../../commit/5254c01))
48
+
49
+
50
+ <a name="v0.4.0"></a>
51
+ ### v0.4.0 (2018-04-03)
52
+
53
+
54
+ #### Features
55
+
56
+ * add *partial* support for reading/writing array of provider states as specified in v3 spec ([e9ec6c3](/../../commit/e9ec6c3))
57
+
58
+
59
+ <a name="v0.3.0"></a>
60
+ ### v0.3.0 (2018-04-03)
61
+
62
+
63
+ #### Features
64
+
65
+ * add pact-message reify to cli ([782a09b](/../../commit/782a09b))
66
+
67
+
68
+ <a name="v0.1.5"></a>
69
+ ### v0.1.5 (2018-03-26)
70
+
71
+
72
+ #### Features
73
+
74
+ * upgrade to pact-support 1.5 ([20fea42](/../../commit/20fea42))
75
+ * move pact message classes out of pact-support into pact-message ([a187c4a](/../../commit/a187c4a))
76
+ * update DSL syntax ([8766965](/../../commit/8766965))
77
+ * add cli for other languages to use ([b111edd](/../../commit/b111edd))
78
+ * reuse consumer contract writer from pact-mock_service ([93aa122](/../../commit/93aa122))
79
+ * create dsl and basic pact file writer ([5333564](/../../commit/5333564))
80
+
81
+
82
+ #### Bug Fixes
83
+
84
+ * set pact_specification_version in cli ([834d671](/../../commit/834d671))
85
+ * requires ([886068c](/../../commit/886068c))
86
+ * change executables path from exe to bin ([921a1c3](/../../commit/921a1c3))
87
+
88
+
@@ -0,0 +1 @@
1
+ # Contributing
@@ -0,0 +1,33 @@
1
+ # Developer documentation
2
+
3
+ ## Touchpoints with other gems
4
+
5
+ Because the HTTP interaction is so baked into the pact gems, the changes required to add message support to the existing code have been spread out across the various gems. I've tried to make extension points where possible in each gem so that pact-http code does not know about or rely on pact-message code at all, but in some places it was unavoidable with the current structure.
6
+
7
+ ### pact-support
8
+
9
+ To get a Pact::ConsumerContract with messages instead of http interactions (extensible design):
10
+
11
+ # lib/pact/message/consumer_contract_parser.rb
12
+ Pact::ConsumerContract.add_parser(Pact::Message::ConsumerContractParser.new)
13
+
14
+ ### pact-mock_service
15
+
16
+ To write a message pact (extensible design):
17
+
18
+ # lib/pact/message/consumer/update_pact.rb
19
+ Pact::ConsumerContractWriter.new(details, Logger.new(StringIO.new))
20
+
21
+ ### pact
22
+
23
+ To verify a message pact (yucky design, but too much work to separate it nicely right now):
24
+
25
+ # lib/pact/provider/rspec.rb
26
+
27
+ if interaction.respond_to?(:message?) && interaction.message?
28
+ describe_message Pact::Response.new(interaction.response), interaction_context
29
+ else
30
+ describe "with #{interaction.request.method_and_path}" do
31
+ describe_response Pact::Response.new(interaction.response), interaction_context
32
+ end
33
+ end
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
@@ -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.
@@ -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
@@ -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).
@@ -0,0 +1,8 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+ Dir.glob('./lib/tasks/**/*.rake').each { |task| load task }
4
+ Dir.glob('./tasks/**/*.rake').each { |task| load task }
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task :default => :spec
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require 'pact/message/cli'
3
+ Pact::Message::CLI.start
@@ -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,142 @@
1
+ require 'pact/consumer_contract/message/contents'
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/contents'
9
+
10
+ module Pact
11
+ class ConsumerContract
12
+ class Message
13
+ include Pact::ActiveSupportSupport
14
+ include Pact::SymbolizeKeys
15
+
16
+ attr_accessor :description, :contents, :provider_state, :provider_states, :metadata
17
+
18
+ def initialize attributes = {}
19
+ @description = attributes[:description]
20
+ @provider_state = attributes[:provider_state] || attributes[:providerState]
21
+ @provider_states = attributes[:provider_states] || []
22
+ @contents = attributes[:contents]
23
+ @metadata = attributes[:metadata]
24
+ end
25
+
26
+ def self.from_hash hash, options = {}
27
+ opts = options.dup
28
+ unless opts[:pact_specification_version]
29
+ opts[:pact_specification_version] = Pact::SpecificationVersion::NIL_VERSION
30
+ end
31
+ contents_matching_rules = hash['matchingRules'] && hash['matchingRules']['body']
32
+ contents_hash = Pact::MatchingRules.merge(hash['contents'], contents_matching_rules, opts)
33
+ contents = Pact::ConsumerContract::Message::Contents.from_hash(contents_hash)
34
+ metadata = hash['metaData'] || hash['metadata']
35
+ provider_state = hash['providerStates'] && hash['providerStates'].first && hash['providerStates'].first['name']
36
+ provider_states = parse_provider_states(hash['providerStates'])
37
+ new(symbolize_keys(hash).merge(
38
+ contents: contents,
39
+ provider_state: provider_state,
40
+ provider_states: provider_states,
41
+ metadata: metadata))
42
+ end
43
+
44
+ def to_hash
45
+ {
46
+ description: description,
47
+ provider_states: [{ name: provider_state }],
48
+ contents: contents.to_hash,
49
+ metadata: metadata
50
+ }
51
+ end
52
+
53
+ def request
54
+ @request ||= Pact::Consumer::Request::Actual.from_hash(
55
+ path: '/',
56
+ method: 'POST',
57
+ query: nil,
58
+ headers: { 'Content-Type' => 'application/json' },
59
+ body: {
60
+ description: description,
61
+ providerStates: [{
62
+ name: provider_state,
63
+ params: {}
64
+ }]
65
+ }
66
+ )
67
+ end
68
+
69
+ # custom media type?
70
+ def response
71
+ @response ||= Pact::Response.new(
72
+ status: 200,
73
+ headers: {'Content-Type' => 'application/json'},
74
+ body: {
75
+ contents: contents
76
+ }
77
+ )
78
+ end
79
+
80
+ def http?
81
+ false
82
+ end
83
+
84
+ def message?
85
+ true
86
+ end
87
+
88
+ def validate!
89
+ raise Pact::InvalidMessageError.new(self) unless description && contents
90
+ end
91
+
92
+ def == other
93
+ other.is_a?(Message) && to_hash == other.to_hash
94
+ end
95
+
96
+ def matches_criteria? criteria
97
+ criteria.each do | key, value |
98
+ unless match_criterion self.send(key.to_s), value
99
+ return false
100
+ end
101
+ end
102
+ true
103
+ end
104
+
105
+ def match_criterion target, criterion
106
+ target == criterion || (criterion.is_a?(Regexp) && criterion.match(target))
107
+ end
108
+
109
+ def eq? other
110
+ self == other
111
+ end
112
+
113
+ def description_with_provider_state_quoted
114
+ provider_state ? "\"#{description}\" given \"#{provider_state}\"" : "\"#{description}\""
115
+ end
116
+
117
+ def to_s
118
+ to_hash.to_s
119
+ end
120
+
121
+ private
122
+
123
+ def self.parse_provider_states provider_states
124
+ (provider_states || []).collect do | provider_state_hash |
125
+ Pact::ProviderState.new(provider_state_hash['name'], provider_state_hash['params'])
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
131
+
132
+ module Pact
133
+ module Message
134
+ def self.new *args
135
+ Pact::ConsumerContract::Message.new(*args)
136
+ end
137
+
138
+ def self.from_hash *args
139
+ Pact::ConsumerContract::Message.from_hash(*args)
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,49 @@
1
+ module Pact
2
+ class ConsumerContract
3
+ class Message
4
+ class Contents
5
+ include ActiveSupportSupport
6
+ include SymbolizeKeys
7
+
8
+ # Could technically be an array
9
+ def self.from_hash contents, options = {}
10
+ new(contents)
11
+ end
12
+
13
+ def initialize contents
14
+ @contents = contents
15
+ end
16
+
17
+ def to_s
18
+ if @contents.is_a?(Hash) || @contents.is_a?(Array)
19
+ @contents.to_json
20
+ else
21
+ @contents.to_s
22
+ end
23
+ end
24
+
25
+ def contents
26
+ @contents
27
+ end
28
+
29
+ def as_json
30
+ @contents
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ module Pact
38
+ module Message
39
+ class Contents
40
+ def self.new *args
41
+ Pact::ConsumerContract::Message::Contents.new(*args)
42
+ end
43
+
44
+ def self.from_hash *args
45
+ Pact::ConsumerContract::Message::Contents.from_hash(*args)
46
+ end
47
+ end
48
+ end
49
+ end