pact 1.19.1 → 1.19.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 91a3bec55f1ec0ebd0ce051fc4b52613b8143bf2
4
- data.tar.gz: 978814b2a193198db83d41d68b5c55315ae839b5
3
+ metadata.gz: 5600e03dfa36e82f5046524a577d8d0b3fbfb65c
4
+ data.tar.gz: 806e61b3debf79d48dbdf7d6782f842b51d4e878
5
5
  SHA512:
6
- metadata.gz: a546703241a9770b086de20318f1eaa8d2223fc56800a446dcb6fd4466da28051778d08efc3c2ef0721064d1da4d22ef0bd953d96b51e813bb894ae96b2ba8b5
7
- data.tar.gz: 39237141c5ac6febcf2c4209a4d5d9a1bd610689e394d247d8ddccff67b05954d7ae36e1a324c32e2eb69cad93d4f0ec546e3305c408db70599f9e2547faabd5
6
+ metadata.gz: 716c814749febf3a308cf0fd4ceef616483f1ddc44cb5bd4e06d8abe6a8b2ea2c76046c87dd5db1f34e1c469cd71aeffa1a69aa9c1bfb245b7de726117f6b877
7
+ data.tar.gz: 71b3a60fab8ce4def9d6718ca78f806215c28e83b47ebdef2c8c4436536339d577e0b1ac754d3c2d274e1b135308acbfdad42bbe2cc1a8dba2f5b9e3cba17ffa
data/CHANGELOG.md CHANGED
@@ -1,3 +1,23 @@
1
+ <a name="v1.19.2"></a>
2
+ ### v1.19.2 (2017-11-16)
3
+
4
+
5
+ #### Features
6
+
7
+ * **publish test results**
8
+ * rename example to test in JSON ([cd2b79e](/../../commit/cd2b79e))
9
+ * remove ansi colours from error messages ([4416d04](/../../commit/4416d04))
10
+ * only publish for rspec 3 ([31192d0](/../../commit/31192d0))
11
+ * only publish verification results when all interactions have been run ([0c56752](/../../commit/0c56752))
12
+ * enable test results to be published to the pact broker in the verification results ([e0dad27](/../../commit/e0dad27))
13
+
14
+
15
+ #### Bug Fixes
16
+
17
+ * **verifications**
18
+ * tag provider version, not consumer version ([b347588](/../../commit/b347588))
19
+
20
+
1
21
  <a name="v1.19.1"></a>
2
22
  ### v1.19.1 (2017-10-31)
3
23
 
@@ -8,6 +8,7 @@ require 'pact/rspec'
8
8
  require 'pact/provider/pact_source'
9
9
  require 'pact/provider/help/write'
10
10
  require 'pact/provider/verification_results/publish_all'
11
+ require 'pact/provider/rspec/pact_broker_formatter'
11
12
 
12
13
  require_relative 'rspec'
13
14
 
@@ -61,6 +62,10 @@ module Pact
61
62
  config.output_stream = Pact.configuration.output_stream
62
63
  end
63
64
 
65
+ Pact::RSpec.with_rspec_3 do
66
+ ::RSpec.configuration.add_formatter Pact::Provider::RSpec::PactBrokerFormatter, StringIO.new
67
+ end
68
+
64
69
  if options[:format]
65
70
  ::RSpec.configuration.add_formatter options[:format]
66
71
  # Don't want to mess up the JSON parsing with messages to stdout, so send it to stderr
@@ -82,14 +87,12 @@ module Pact
82
87
  Pact.configuration.provider.app
83
88
  end
84
89
 
90
+ # For the Pact::Provider::RSpec::PactBrokerFormatter
91
+ Pact.provider_world.pact_sources = pact_sources
85
92
  jsons = pact_jsons
86
- sources = pact_sources
87
93
 
88
94
  config.after(:suite) do | suite |
89
95
  Pact::Provider::Help::Write.call(jsons)
90
- Pact::RSpec.with_rspec_3 do
91
- Pact::Provider::VerificationResults::PublishAll.call(sources, ::RSpec.configuration.reporter.failed_examples)
92
- end
93
96
  end
94
97
 
95
98
  end
@@ -25,7 +25,7 @@ module Pact
25
25
  Pact.configuration.output_stream.puts "INFO: Filtering interactions by: #{options[:criteria]}" if options[:criteria] && options[:criteria].any?
26
26
  consumer_contract = Pact::ConsumerContract.from_json(pact_json)
27
27
  ::RSpec.describe "Verifying a pact between #{consumer_contract.consumer.name} and #{consumer_contract.provider.name}", pactfile_uri: pact_uri do
28
- honour_consumer_contract consumer_contract, options.merge(pact_json: pact_json)
28
+ honour_consumer_contract consumer_contract, options.merge(pact_json: pact_json, pact_uri: pact_uri)
29
29
  end
30
30
  end
31
31
 
@@ -61,19 +61,24 @@ module Pact
61
61
 
62
62
  def describe_interaction interaction, options
63
63
 
64
+ # pact_uri and pact_interaction are used by
65
+ # Pact::Provider::RSpec::PactBrokerFormatter
66
+
67
+ # pact_interaction_example_description is used by
68
+ # Pact::Provider::RSpec::Formatter and Pact::Provider::RSpec::Formatter2
69
+
70
+ # pact: verify is used to allow RSpec before and after hooks.
64
71
  metadata = {
65
72
  pact: :verify,
66
73
  pact_interaction: interaction,
67
74
  pact_interaction_example_description: interaction_description_for_rerun_command(interaction),
68
- pact_json: options[:pact_json]
75
+ pact_uri: options[:pact_uri]
69
76
  }
70
77
 
71
78
  describe description_for(interaction), metadata do
72
79
 
73
-
74
80
  describe "with #{interaction.request.method_and_path}" do
75
81
 
76
-
77
82
  interaction_context = InteractionContext.new
78
83
 
79
84
  before do | example |
@@ -0,0 +1,67 @@
1
+ require 'rspec/core/formatters'
2
+ require 'pact/provider/verification_results/publish_all'
3
+ require 'term/ansicolor'
4
+
5
+ module Pact
6
+ module Provider
7
+ module RSpec
8
+ class PactBrokerFormatter < ::RSpec::Core::Formatters::BaseFormatter
9
+ Pact::RSpec.with_rspec_3 do
10
+ ::RSpec::Core::Formatters.register self, :message, :dump_summary, :stop, :seed, :close
11
+ end
12
+
13
+ attr_reader :output_hash
14
+
15
+ def initialize(output)
16
+ super
17
+ @output_hash = {
18
+ :version => ::RSpec::Core::Version::STRING
19
+ }
20
+ end
21
+
22
+ def message(notification)
23
+ (@output_hash[:messages] ||= []) << notification.message
24
+ end
25
+
26
+ def dump_summary(summary)
27
+ end
28
+
29
+ def stop(notification)
30
+ @output_hash[:tests] = notification
31
+ .examples
32
+ .map { |example| format_example(example) }
33
+ end
34
+
35
+ def seed(notification)
36
+ return unless notification.seed_used?
37
+ @output_hash[:seed] = notification.seed
38
+ end
39
+
40
+ def close(_notification)
41
+ Pact::Provider::VerificationResults::PublishAll.call(Pact.provider_world.pact_sources, output_hash)
42
+ end
43
+
44
+ private
45
+
46
+ def format_example(example)
47
+ {
48
+ testDescription: example.description,
49
+ testFullDescription: example.full_description,
50
+ status: example.execution_result.status.to_s,
51
+ interactionProviderState: example.metadata[:pact_interaction].provider_state,
52
+ interactionDescription: example.metadata[:pact_interaction].description,
53
+ pact_uri: example.metadata[:pact_uri],
54
+ pact_interaction: example.metadata[:pact_interaction]
55
+ }.tap do |hash|
56
+ if example.exception
57
+ hash[:exception] = {
58
+ class: example.exception.class.name,
59
+ message: ::Term::ANSIColor.uncolor(example.exception.message)
60
+ }
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -4,38 +4,67 @@ module Pact
4
4
  module VerificationResults
5
5
  class Create
6
6
 
7
- def self.call pact_json, failed_examples
8
- new(pact_json, failed_examples).call
7
+ def self.call pact_source, test_results_hash
8
+ new(pact_source, test_results_hash).call
9
9
  end
10
10
 
11
- def initialize pact_json, failed_examples
12
- @pact_json = pact_json
13
- @failed_examples = failed_examples
11
+ def initialize pact_source, test_results_hash
12
+ @pact_source = pact_source
13
+ @test_results_hash = test_results_hash
14
14
  end
15
15
 
16
16
  def call
17
- VerificationResult.new(!any_failures?, Pact.configuration.provider.application_version)
17
+ VerificationResult.new(publishable?, !any_failures?, Pact.configuration.provider.application_version, test_results_hash_for_pact_uri)
18
18
  end
19
19
 
20
20
  private
21
21
 
22
- def pact_hash
23
- @pact_hash ||= json_load(pact_json)
22
+ def pact_uri
23
+ @pact_uri ||= pact_source.uri
24
24
  end
25
25
 
26
- def json_load json
27
- JSON.load(json, nil, { max_nesting: 50 })
26
+ def any_failures?
27
+ count_failures_for_pact_uri > 0
28
28
  end
29
29
 
30
- def count_failures_for_pact_json
31
- failed_examples.collect{ |e| e.metadata[:pact_json] == pact_json }.uniq.size
30
+ def publishable?
31
+ executed_interactions_count == all_interactions_count && all_interactions_count > 0
32
32
  end
33
33
 
34
- def any_failures?
35
- count_failures_for_pact_json > 0
34
+ def examples_for_pact_uri
35
+ @examples_for_pact_uri ||= test_results_hash[:tests].select{ |e| e[:pact_uri] == pact_uri }
36
+ end
37
+
38
+ def count_failures_for_pact_uri
39
+ examples_for_pact_uri.count{ |e| e[:status] != 'passed' }
40
+ end
41
+
42
+ def executed_interactions_count
43
+ examples_for_pact_uri
44
+ .collect { |e| e[:pact_interaction].object_id }
45
+ .uniq
46
+ .count
47
+ end
48
+
49
+ def all_interactions_count
50
+ pact_source.pact_hash['interactions'].count
51
+ end
52
+
53
+ def test_results_hash_for_pact_uri
54
+ {
55
+ tests: examples_for_pact_uri.collect{ |e| clean_example(e) },
56
+ summary: {
57
+ testCount: examples_for_pact_uri.size,
58
+ failureCount: count_failures_for_pact_uri
59
+ }
60
+ }
61
+ end
62
+
63
+ def clean_example(example)
64
+ example.reject{ |k, v| k == :pact_uri || k == :pact_interaction }
36
65
  end
37
66
 
38
- attr_reader :pact_json, :failed_examples
67
+ attr_reader :pact_source, :test_results_hash
39
68
  end
40
69
  end
41
70
  end
@@ -22,32 +22,50 @@ module Pact
22
22
  end
23
23
 
24
24
  def call
25
- if Pact.configuration.provider.publish_verification_results?
26
- if Pact.configuration.provider.tags.any?
27
- if tag_url('')
28
- tag_versions
29
- else
30
- Pact.configuration.error_stream.puts "WARN: Cannot tag provider version as there is no link named pb:tag-version in the pact JSON."
31
- end
32
- end
33
-
34
- if publication_url
35
- publish
36
- else
37
- Pact.configuration.error_stream.puts "WARN: Cannot publish verification for #{consumer_name} as there is no link named pb:publish-verification-results in the pact JSON. If you are using a pact broker, please upgrade to version 2.0.0 or later."
38
- end
25
+ if can_publish_verification_results?
26
+ tag_versions_if_configured
27
+ publish_verification_results
39
28
  end
40
29
  end
41
30
 
42
31
  private
43
32
 
33
+ def can_publish_verification_results?
34
+ return false unless Pact.configuration.provider.publish_verification_results?
35
+
36
+ if publication_url.nil?
37
+ Pact.configuration.error_stream.puts "WARN: Cannot publish verification for #{consumer_name} as there is no link named pb:publish-verification-results in the pact JSON. If you are using a pact broker, please upgrade to version 2.0.0 or later."
38
+ return false
39
+ end
40
+
41
+ if !verification_result.publishable?
42
+ Pact.configuration.error_stream.puts "WARN: Cannot publish verification for #{consumer_name} as not all interactions have been verified. Re-run the verification without the filter parameters or environment variables to publish the verification."
43
+ return false
44
+ end
45
+ true
46
+ end
47
+
44
48
  def publication_url
45
49
  @publication_url ||= pact_source.pact_hash.fetch('_links', {}).fetch('pb:publish-verification-results', {})['href']
46
50
  end
47
51
 
48
52
  def tag_url tag
49
- href = pact_source.pact_hash.fetch('_links', {}).fetch('pb:tag-version', {})['href']
50
- href ? href.gsub('{tag}', tag) : nil
53
+ # This is so dodgey, need to use proper HAL
54
+ if publication_url
55
+ u = URI(publication_url)
56
+ if match = publication_url.match(%r{/provider/([^/]+)})
57
+ provider_name = match[1]
58
+ base_url = "#{u.scheme}://#{u.host}:#{u.host == u.default_port ? '' : u.port}"
59
+ provider_application_version = Pact.configuration.provider.application_version
60
+ "#{base_url}/pacticipants/#{provider_name}/versions/#{provider_application_version}/tags/#{tag}"
61
+ end
62
+ end
63
+ end
64
+
65
+ def tag_versions_if_configured
66
+ if Pact.configuration.provider.tags.any?
67
+ tag_versions if tag_url('')
68
+ end
51
69
  end
52
70
 
53
71
  def tag_versions
@@ -71,9 +89,9 @@ module Pact
71
89
  end
72
90
  end
73
91
 
74
- def publish
92
+ def publish_verification_results
75
93
  uri = URI(publication_url)
76
- request = build_request('Post', uri, verification_result.to_json, "Publishing verification result #{verification_result.to_json} to")
94
+ request = build_request('Post', uri, verification_result.to_json, "Publishing verification result #{verification_result} to")
77
95
  response = nil
78
96
  begin
79
97
  options = {:use_ssl => uri.scheme == 'https'}
@@ -81,12 +99,17 @@ module Pact
81
99
  http.request request
82
100
  end
83
101
  rescue StandardError => e
84
- error_message = "Failed to publish verification result due to: #{e.class} #{e.message}"
102
+ error_message = "Failed to publish verification results due to: #{e.class} #{e.message}"
85
103
  raise PublicationError.new(error_message)
86
104
  end
87
105
 
88
- unless response.code.start_with?("2")
89
- raise PublicationError.new("Error returned from verification result publication #{response.code} #{response.body}")
106
+
107
+
108
+ if response.code.start_with?("2")
109
+ new_resource_url = JSON.parse(response.body)['_links']['self']['href']
110
+ $stdout.puts "INFO: Verification results published to #{new_resource_url}"
111
+ else
112
+ raise PublicationError.new("Error returned from verification results publication #{response.code} #{response.body}")
90
113
  end
91
114
  end
92
115
 
@@ -6,19 +6,18 @@ module Pact
6
6
  module VerificationResults
7
7
  class PublishAll
8
8
 
9
- def self.call pact_sources, rspec_summary
10
- new(pact_sources, rspec_summary).call
9
+ def self.call pact_sources, test_results_hash
10
+ new(pact_sources, test_results_hash).call
11
11
  end
12
12
 
13
- def initialize pact_sources, rspec_summary
13
+ def initialize pact_sources, test_results_hash
14
14
  @pact_sources = pact_sources
15
- @rspec_summary = rspec_summary
15
+ @test_results_hash = test_results_hash
16
16
  end
17
17
 
18
- # TODO do not publish unless all interactions have been run
19
18
  def call
20
- verification_results.collect do | pair |
21
- Publish.call(pair.first, pair.last)
19
+ verification_results.collect do | (pact_source, verification_result) |
20
+ Publish.call(pact_source, verification_result)
22
21
  end
23
22
  end
24
23
 
@@ -26,11 +25,11 @@ module Pact
26
25
 
27
26
  def verification_results
28
27
  pact_sources.collect do | pact_source |
29
- [pact_source, Create.call(pact_source.pact_json, rspec_summary)]
28
+ [pact_source, Create.call(pact_source, test_results_hash)]
30
29
  end
31
30
  end
32
31
 
33
- attr_reader :pact_sources, :rspec_summary
32
+ attr_reader :pact_sources, :test_results_hash
34
33
  end
35
34
  end
36
35
  end
@@ -1,11 +1,19 @@
1
+ require 'json'
2
+
1
3
  module Pact
2
4
  module Provider
3
5
  module VerificationResults
4
6
  class VerificationResult
5
7
 
6
- def initialize success, provider_application_version
8
+ def initialize publishable, success, provider_application_version, test_results_hash
9
+ @publishable = publishable
7
10
  @success = success
8
11
  @provider_application_version = provider_application_version
12
+ @test_results_hash = test_results_hash
13
+ end
14
+
15
+ def publishable?
16
+ @publishable
9
17
  end
10
18
 
11
19
  def provider_application_version_set?
@@ -15,13 +23,18 @@ module Pact
15
23
  def to_json
16
24
  {
17
25
  success: success,
18
- providerApplicationVersion: provider_application_version
26
+ providerApplicationVersion: provider_application_version,
27
+ #testResults: test_results_hash # not yet
19
28
  }.to_json
20
29
  end
21
30
 
31
+ def to_s
32
+ "[success: #{success}, providerApplicationVersion: #{provider_application_version}]"
33
+ end
34
+
22
35
  private
23
36
 
24
- attr_reader :success, :provider_application_version
37
+ attr_reader :success, :provider_application_version, :test_results_hash
25
38
  end
26
39
  end
27
40
  end
@@ -14,6 +14,8 @@ module Pact
14
14
  module Provider
15
15
  class World
16
16
 
17
+ attr_accessor :pact_sources
18
+
17
19
  def provider_states
18
20
  @provider_states_proxy ||= Pact::Provider::State::ProviderStateProxy.new
19
21
  end
@@ -29,7 +31,6 @@ module Pact
29
31
  def pact_urls
30
32
  pact_verifications.collect(&:uri)
31
33
  end
32
-
33
34
  end
34
35
  end
35
36
  end
data/lib/pact/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  # Remember to bump pact-provider-proxy when this changes major version
2
2
  module Pact
3
- VERSION = "1.19.1"
3
+ VERSION = "1.19.2"
4
4
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pact
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.19.1
4
+ version: 1.19.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Fraser
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2017-10-31 00:00:00.000000000 Z
15
+ date: 2017-11-16 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: randexp
@@ -366,6 +366,7 @@ files:
366
366
  - lib/pact/provider/rspec/formatter_rspec_2.rb
367
367
  - lib/pact/provider/rspec/formatter_rspec_3.rb
368
368
  - lib/pact/provider/rspec/matchers.rb
369
+ - lib/pact/provider/rspec/pact_broker_formatter.rb
369
370
  - lib/pact/provider/state/provider_state.rb
370
371
  - lib/pact/provider/state/provider_state_configured_modules.rb
371
372
  - lib/pact/provider/state/provider_state_manager.rb