Skip to content

Commit

Permalink
feat: add back support for GET requests to the 'pacts for verificatio…
Browse files Browse the repository at this point in the history
…n' API with a deprecation notice in the response
  • Loading branch information
bethesque committed Sep 12, 2020
1 parent 29aed95 commit 8f45cc9
Show file tree
Hide file tree
Showing 7 changed files with 223 additions and 23 deletions.
37 changes: 37 additions & 0 deletions lib/pact_broker/api/contracts/verifiable_pacts_query_schema.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
require 'dry-validation'
require 'pact_broker/api/contracts/dry_validation_workarounds'
require 'pact_broker/api/contracts/dry_validation_predicates'

module PactBroker
module Api
module Contracts
class VerifiablePactsQuerySchema
extend DryValidationWorkarounds
using PactBroker::HashRefinements

SCHEMA = Dry::Validation.Schema do
configure do
predicates(DryValidationPredicates)
config.messages_file = File.expand_path("../../../locale/en.yml", __FILE__)
end
optional(:provider_version_tags).maybe(:array?)
optional(:consumer_version_selectors).each do
schema do
required(:tag).filled(:str?)
optional(:latest).filled(included_in?: ["true", "false"])
optional(:fallback_tag).filled(:str?)
optional(:consumer).filled(:str?, :not_blank?)
end
end
optional(:include_pending_status).filled(included_in?: ["true", "false"])
optional(:include_wip_pacts_since).filled(:date?)
end

def self.call(params)
select_first_message(flatten_indexed_messages(SCHEMA.call(params&.symbolize_keys).messages(full: true)))
end

end
end
end
end
10 changes: 5 additions & 5 deletions lib/pact_broker/api/decorators/verifiable_pact_decorator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ class VerifiablePactDecorator < BaseDecorator

property :pending,
if: ->(context) { context[:options][:user_options][:include_pending_status] }
property :wip, if: -> (context) { context[:represented].wip }

property :notices, getter: -> (context) { context[:decorator].notices(context[:options][:user_options]) }
property :noteToDevelopers, getter: -> (_) { "Please print out the text from the 'notices' rather than using the inclusionReason and the pendingReason fields. These will be removed when this API moves out of beta."}
property :wip,
if: -> (context) { context[:represented].wip }
property :notices,
getter: -> (context) { context[:decorator].notices(context[:options][:user_options]) }

def notices(user_options)
pact_url = pact_version_url(represented, user_options[:base_url])
PactBroker::Pacts::BuildVerifiablePactNotices.call(represented, pact_url, include_pending_status: user_options[:include_pending_status])
PactBroker::Pacts::BuildVerifiablePactNotices.call(represented, pact_url, user_options)
end
end

Expand Down
21 changes: 14 additions & 7 deletions lib/pact_broker/api/resources/provider_pacts_for_verification.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require 'pact_broker/api/resources/provider_pacts'
require 'pact_broker/api/decorators/verifiable_pacts_decorator'
require 'pact_broker/api/contracts/verifiable_pacts_query_schema'
require 'pact_broker/api/decorators/verifiable_pacts_query_decorator'
require 'pact_broker/api/contracts/verifiable_pacts_json_query_schema'
require 'pact_broker/hash_refinements'
Expand All @@ -11,7 +12,7 @@ class ProviderPactsForVerification < ProviderPacts
using PactBroker::HashRefinements

def allowed_methods
["POST", "OPTIONS"]
["GET", "POST", "OPTIONS"]
end

def content_types_accepted
Expand Down Expand Up @@ -51,11 +52,21 @@ def resource_title
end

def to_json
PactBroker::Api::Decorators::VerifiablePactsDecorator.new(pacts).to_json(to_json_options)
PactBroker::Api::Decorators::VerifiablePactsDecorator.new(pacts).to_json(
decorator_options(
include_pending_status: parsed_query_params.include_pending_status,
title: "Pacts to be verified by provider #{provider_name}",
deprecated: request.get?
)
)
end

def query_schema
PactBroker::Api::Contracts::VerifiablePactsJSONQuerySchema
if request.get?
PactBroker::Api::Contracts::VerifiablePactsQuerySchema
else
PactBroker::Api::Contracts::VerifiablePactsJSONQuerySchema
end
end

def parsed_query_params
Expand All @@ -71,10 +82,6 @@ def query
end
end
end

def to_json_options
super.deep_merge(user_options: { include_pending_status: parsed_query_params.include_pending_status })
end
end
end
end
Expand Down
11 changes: 7 additions & 4 deletions lib/pact_broker/pacts/build_verifiable_pact_notices.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@ class BuildVerifiablePactNotices
def self.call(verifiable_pact, pact_url, options)
messages = VerifiablePactMessages.new(verifiable_pact, pact_url)

notices = [{
when: 'before_verification',
text: messages.inclusion_reason
}]
notices = []

if options[:deprecated]
append_notice(notices, 'before_verification', 'WARNING - this version of the Pact library uses a beta version of the API which will be removed in the future. Please upgrade your Pact library. See https://docs.pact.io/pact_broker/advanced_topics/provider_verification_results/#pacts-for-verification for minimum required versions.')
end

append_notice(notices, 'before_verification', messages.inclusion_reason)

if options[:include_pending_status]
append_notice(notices, 'before_verification', messages.pending_reason)
Expand Down
26 changes: 26 additions & 0 deletions spec/features/get_provider_pacts_for_verification_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,28 @@

let(:path) { "/pacts/provider/Provider/for-verification" }

context "when using GET" do
it "returns a 200 HAL JSON response" do
expect(subject).to be_a_hal_json_success_response
end

it "returns a list of links to the pacts" do
expect(pacts.size).to eq 1
end

it "returns a deprecation notice" do
expect(last_response_body[:_embedded][:pacts].first[:verificationProperties][:notices].first[:text]).to start_with("WARNING")
end

context "when the provider does not exist" do
let(:path) { "/pacts/provider/ProviderThatDoesNotExist/for-verification" }

it "returns a 404 response" do
expect(subject).to be_a_404_response
end
end
end

context "when using POST" do
let(:request_body) do
{
Expand All @@ -44,6 +66,10 @@
expect(pacts.size).to eq 1
end

it "does not include a deprecation notice" do
expect(last_response_body[:_embedded][:pacts].first[:verificationProperties][:notices].first[:text]).to_not start_with("WARNING")
end

context "when the provider does not exist" do
let(:path) { "/pacts/provider/ProviderThatDoesNotExist/for-verification" }

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
require 'pact_broker/api/contracts/verifiable_pacts_query_schema'

module PactBroker
module Api
module Contracts
describe VerifiablePactsQuerySchema do
let(:params) do
{
provider_version_tags: provider_version_tags,
consumer_version_selectors: consumer_version_selectors
}
end

let(:provider_version_tags) { %w[master] }

let(:consumer_version_selectors) do
[{
tag: "master",
latest: "true"
}]
end

subject { VerifiablePactsQuerySchema.(params) }

context "when the params are valid" do
it "has no errors" do
expect(subject).to eq({})
end
end

context "when provider_version_tags is not an array" do
let(:provider_version_tags) { "foo" }

it { is_expected.to have_key(:provider_version_tags) }
end

context "when the consumer_version_selector is missing a tag" do
let(:consumer_version_selectors) do
[{}]
end

it "flattens the messages" do
expect(subject[:consumer_version_selectors].first).to eq "tag is missing at index 0"
end
end

context "when the consumer_version_selectors is missing the latest" do
let(:consumer_version_selectors) do
[{
tag: "master"
}]
end

it { is_expected.to be_empty }
end

context "when include_wip_pacts_since key exists" do
let(:include_wip_pacts_since) { nil }
let(:params) do
{
include_wip_pacts_since: include_wip_pacts_since
}
end

context "when it is nil" do
it { is_expected.to have_key(:include_wip_pacts_since) }
end

context "when it is not a date" do
let(:include_wip_pacts_since) { "foo" }

it { is_expected.to have_key(:include_wip_pacts_since) }
end

context "when it is a valid date" do
let(:include_wip_pacts_since) { "2013-02-13T20:04:45.000+11:00" }

it { is_expected.to_not have_key(:include_wip_pacts_since) }
end
end

context "when a blank consumer name is specified" do
let(:consumer_version_selectors) do
[{
tag: "feat-x",
consumer: ""
}]
end

it "has an error" do
expect(subject[:consumer_version_selectors].first).to include "blank"
end
end
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,35 @@ module Resources
}
end

subject { post(path, request_body.to_json, request_headers) }
subject { get(path, query) }

describe "GET" do
it "finds the pacts for verification by the provider" do
# Naughty not mocking out the query parsing...
expect(PactBroker::Pacts::Service).to receive(:find_for_verification).with(
"Bar",
["master"],
PactBroker::Pacts::Selectors.new([PactBroker::Pacts::Selector.latest_for_tag("dev")]),
{
include_wip_pacts_since: DateTime.parse('2018-01-01'),
include_pending_status: true
}
)
subject
end

context "when there are validation errors" do
let(:query) do
{
provider_version_tags: true,
}
end

it "returns the keys with the right case" do
expect(JSON.parse(subject.body)['errors']).to have_key('provider_version_tags')
end
end
end

describe "POST" do
let(:request_body) do
Expand All @@ -42,6 +70,8 @@ module Resources
}
end

subject { post(path, request_body.to_json, request_headers) }

it "finds the pacts for verification by the provider" do
# Naughty not mocking out the query parsing...
expect(PactBroker::Pacts::Service).to receive(:find_for_verification).with(
Expand All @@ -67,14 +97,14 @@ module Resources
expect(JSON.parse(subject.body)['errors']).to have_key('providerVersionTags')
end
end
end

it "uses the correct options for the decorator" do
expect(decorator).to receive(:to_json) do | options |
expect(options[:user_options][:title]).to eq "Pacts to be verified by provider Bar"
expect(options[:user_options][:include_pending_status]).to eq true
end
subject
it "uses the correct options for the decorator" do
expect(decorator).to receive(:to_json) do | options |
expect(options[:user_options][:title]).to eq "Pacts to be verified by provider Bar"
expect(options[:user_options][:include_pending_status]).to eq true
end
subject
end
end
end
Expand Down

0 comments on commit 8f45cc9

Please sign in to comment.