Skip to content

Commit

Permalink
test: add unit tests for publishing provider contracts
Browse files Browse the repository at this point in the history
  • Loading branch information
bethesque committed Sep 6, 2023
1 parent fc65cc4 commit a81931b
Show file tree
Hide file tree
Showing 6 changed files with 250 additions and 20 deletions.
28 changes: 10 additions & 18 deletions lib/pactflow/client/provider_contracts/publish.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
require "base64"
require "pact_broker/client/base_command"
require "pact_broker/client/colorize_notices"

require "pactflow/client/provider_contracts/publish_the_old_way"

module Pactflow
module Client
Expand All @@ -26,16 +26,16 @@ def initialize(params, options, pact_broker_client_options)
attr_reader :provider_name, :provider_version_number, :branch_name, :tags, :build_url, :contract, :verification_results

def do_call
if !force_use_old_api? && index_resource.can?(PUBLISH_RELATION)
if enabled? && index_resource.assert_success!.can?(PUBLISH_RELATION)
publish_provider_contracts
PactBroker::Client::CommandResult.new(success?, message)
else
PublishPactsTheOldWay.call(pact_broker_base_url, pact_file_paths, consumer_version_params, options, pact_broker_client_options)
PublishTheOldWay.call(params, options, pact_broker_client_options)
end
end

def force_use_old_api?
ENV.fetch("PACT_BROKER_FEATURES", "").include?("publish_provider_contracts_using_old_api")
def enabled?
ENV.fetch("PACT_BROKER_FEATURES", "").include?("publish_provider_contracts_all_in_one")
end

def publish_provider_contracts
Expand All @@ -53,10 +53,10 @@ def contract_params
}.compact

contract_params = {
content: encode_content(contract[:content]),
specification: contract[:specification],
contentType: contract[:content_type]
}.compact
content: encode_content(contract[:content]),
specification: contract[:specification],
contentType: contract[:content_type]
}.compact

if verification_results_params.any?
contract_params[:selfVerificationResults] = verification_results_params
Expand Down Expand Up @@ -88,15 +88,7 @@ def success?
end

def text_message
if success?
if @response_entity.notices
PactBroker::Client::ColorizeNotices.call(@response_entity.notices.collect{ |n| OpenStruct.new(n) } )
else
"Successfully published provider contract for #{provider_name} version #{provider_version_number} to PactFlow"
end
else
::Term::ANSIColor.red(@response_entity.response.raw_body)
end
PactBroker::Client::ColorizeNotices.call(@response_entity.notices.collect{ |n| OpenStruct.new(n) } )
end
end
end
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
some notice
some other notice
57 changes: 57 additions & 0 deletions spec/integration/publish_provider_contract_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
require "pactflow/client/cli/pactflow"

RSpec.describe "publish-provider-contract" do
before do
allow(ENV).to receive(:fetch).and_call_original
allow(ENV).to receive(:fetch).with("PACT_BROKER_FEATURES", "").and_return("publish_provider_contracts_all_in_one")
end
let(:index_body_hash) do
{
_links: {
"pf:publish-provider-contract" => {
href: "http://broker/some-publish/{provider}"
}
}
}
end

let(:post_response_body) do
{
"notices"=>[{"text"=>"some notice", "type"=>"info"}, {"text"=>"some other notice", "type"=>"info"}]
}
end

let!(:index_request) do
stub_request(:get, "http://broker").to_return(status: 200, body: index_body_hash.to_json, headers: { "Content-Type" => "application/hal+json" } )
end

let!(:publish_request) do
stub_request(:post, "http://broker/some-publish/Bar").to_return(status: 200, body: post_response_body.to_json, headers: { "Content-Type" => "application/hal+json" } )
end

let(:parameters) do
%w{
publish-provider-contract
script/oas.yml
--provider Bar
--broker-base-url http://broker
--provider-app-version 1013b5650d61214e19f10558f97fb5a3bb082d44
--branch main
--tag dev
--specification oas
--content-type application/yml
--verification-exit-code 0
--verification-results script/verification-results.txt
--verification-results-content-type text/plain
--verification-results-format text
--verifier my-custom-tool
--verifier-version "1.0"
}
end

subject { capture(:stdout) { Pactflow::Client::CLI::Pactflow.start(parameters) } }

it "prints the notices" do
Approvals.verify(subject, :name => "publish_provider_contract", format: :txt)
end
end
170 changes: 170 additions & 0 deletions spec/lib/pactflow/client/provider_contracts/publish_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
require "pactflow/client/provider_contracts/publish"

module Pactflow
module Client
module ProviderContracts
describe Publish do
before do
allow_any_instance_of(PactBroker::Client::Hal::HttpClient).to receive(:sleep)
allow_any_instance_of(PactBroker::Client::Hal::HttpClient).to receive(:default_max_tries).and_return(1)
allow(ENV).to receive(:fetch).and_call_original
allow(ENV).to receive(:fetch).with("PACT_BROKER_FEATURES", "").and_return("publish_provider_contracts_all_in_one")
end

let(:command_params) do
{
provider_name: "Bar",
provider_version_number: "1",
branch_name: "main",
tags: ["dev"],
build_url: "http://build",
contract: {
content: { "some" => "contract" }.to_yaml,
content_type: "application/yaml",
specification: "oas"
},
verification_results: {
success: true,
content: "some results",
content_type: "text/plain",
format: "text",
verifier: "my custom tool",
verifier_version: "1.0"
}
}
end

let(:options) do
{
verbose: false
}
end

let(:pact_broker_client_options) do
{ pact_broker_base_url: "http://pactflow" }
end

let(:index_body_hash) do
{
_links: {
"pf:publish-provider-contract" => {
href: "http://pactflow/some-publish/{provider}"
}
}
}
end

let(:post_response_body) do
{
"notices"=>[{"text"=>"some notice", "type"=>"info"}]
}
end

let!(:index_request) do
stub_request(:get, "http://pactflow").to_return(status: index_status, body: index_body_hash.to_json, headers: { "Content-Type" => "application/hal+json" } )
end
let(:index_status) { 200 }

let!(:publish_request) do
stub_request(:post, "http://pactflow/some-publish/Bar").to_return(status: publish_status, body: post_response_body.to_json, headers: { "Content-Type" => "application/hal+json" } )
end
let(:publish_status) { 200 }

subject { Publish.call(command_params, options, pact_broker_client_options) }

context "when there is no relation pf:publish-provider-contract" do
before do
allow(PublishTheOldWay).to receive(:call).with(command_params, options, pact_broker_client_options).and_return(instance_double(PactBroker::Client::CommandResult))
end

let(:index_body_hash) do
{
_links: {}
}
end

it "publishes the provider contracts the old way" do
expect(PublishTheOldWay).to receive(:call).with(command_params, options, pact_broker_client_options)
subject
end
end

context "when the feature is not enabled" do
before do
allow(ENV).to receive(:fetch).with("PACT_BROKER_FEATURES", "").and_return("")
end

it "publishes the provider contracts the old way" do
expect(PublishTheOldWay).to receive(:call).with(command_params, options, pact_broker_client_options)
subject
end
end

it "returns a result and message" do
expect(subject.success).to be true
expect(subject.message).to include("some notice")
end

it "colourises the notices" do
expect(PactBroker::Client::ColorizeNotices).to receive(:call).with([OpenStruct.new(text: "some notice", type: "info")]).and_return("coloured notices")
expect(subject.message).to eq "coloured notices"
end

context "when the output is json" do
let(:options) { { output: "json" } }

it "returns the raw response" do
expect(subject.message).to eq post_response_body.to_json
end
end

context "when there is an error retrieving the index" do
let(:index_status) { 500 }
let(:index_body_hash) { { "some" => "error" }}

it "returns an error result with the response body" do
expect(subject.success).to be false
expect(subject.message).to match(/some.*error/)
end

end

context "when there is an error response from publishing" do
let(:publish_status) { 400 }
let(:post_response_body) do
{
"some" => "error"
}
end

it "returns an error result with the response body" do
expect(subject.success).to be false
expect(subject.message).to match(/some.*error/)
end

context "when the output is json" do
let(:options) { { output: "json" } }

it "returns the raw response" do
expect(subject.message).to eq post_response_body.to_json
end
end
end

context "when there is an error response from publishing" do
let(:publish_status) { 400 }
let(:post_response_body) do
{
"some" => "error"
}
end

it "returns an error result with the response body" do
expect(subject.success).to be false
expect(subject.message).to match(/some.*error/)
end
end
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@
require "pactflow/client/provider_contracts/publish"

RSpec.describe "publishing a provider contract to PactFlow", pact: true do
before do
allow_any_instance_of(PactBroker::Client::Hal::HttpClient).to receive(:sleep)
allow_any_instance_of(PactBroker::Client::Hal::HttpClient).to receive(:default_max_tries).and_return(1)
allow(ENV).to receive(:fetch).and_call_original
allow(ENV).to receive(:fetch).with("PACT_BROKER_FEATURES", "").and_return("publish_provider_contracts_all_in_one")
end

include_context "pact broker"
include PactBrokerPactHelperMethods

Expand All @@ -29,8 +36,6 @@
}
end

let(:body) { { some: "body" }.to_json }

let(:request_body) do
{
"pacticipantVersionNumber" => "1",
Expand Down
4 changes: 4 additions & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ def capture(stream)
eval "$#{stream} = StringIO.new"
yield
result = eval("$#{stream}").string
rescue SystemExit => e
puts "CAUGHT SYSTEM EXIT"
puts e
puts e.backtrace
ensure
eval("$#{stream} = #{stream.upcase}")
end
Expand Down

0 comments on commit a81931b

Please sign in to comment.