From a81931b2655f04a587ef35d2b43c3be8cbf72f9a Mon Sep 17 00:00:00 2001 From: Beth Skurrie Date: Wed, 6 Sep 2023 12:28:35 +1000 Subject: [PATCH] test: add unit tests for publishing provider contracts --- .../client/provider_contracts/publish.rb | 28 ++- .../publish_provider_contract.approved.txt | 2 + .../publish_provider_contract_spec.rb | 57 ++++++ .../client/provider_contracts/publish_spec.rb | 170 ++++++++++++++++++ ...pactflow_publish_provider_contract_spec.rb | 9 +- spec/spec_helper.rb | 4 + 6 files changed, 250 insertions(+), 20 deletions(-) create mode 100644 spec/fixtures/approvals/publish_provider_contract.approved.txt create mode 100644 spec/integration/publish_provider_contract_spec.rb create mode 100644 spec/lib/pactflow/client/provider_contracts/publish_spec.rb diff --git a/lib/pactflow/client/provider_contracts/publish.rb b/lib/pactflow/client/provider_contracts/publish.rb index c04a5c13..1a793ec0 100644 --- a/lib/pactflow/client/provider_contracts/publish.rb +++ b/lib/pactflow/client/provider_contracts/publish.rb @@ -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 @@ -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 @@ -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 @@ -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 diff --git a/spec/fixtures/approvals/publish_provider_contract.approved.txt b/spec/fixtures/approvals/publish_provider_contract.approved.txt new file mode 100644 index 00000000..28346172 --- /dev/null +++ b/spec/fixtures/approvals/publish_provider_contract.approved.txt @@ -0,0 +1,2 @@ +some notice +some other notice diff --git a/spec/integration/publish_provider_contract_spec.rb b/spec/integration/publish_provider_contract_spec.rb new file mode 100644 index 00000000..8cae54bf --- /dev/null +++ b/spec/integration/publish_provider_contract_spec.rb @@ -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 diff --git a/spec/lib/pactflow/client/provider_contracts/publish_spec.rb b/spec/lib/pactflow/client/provider_contracts/publish_spec.rb new file mode 100644 index 00000000..9513f08d --- /dev/null +++ b/spec/lib/pactflow/client/provider_contracts/publish_spec.rb @@ -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 diff --git a/spec/service_providers/pactflow_publish_provider_contract_spec.rb b/spec/service_providers/pactflow_publish_provider_contract_spec.rb index 66af77df..b3d417a6 100644 --- a/spec/service_providers/pactflow_publish_provider_contract_spec.rb +++ b/spec/service_providers/pactflow_publish_provider_contract_spec.rb @@ -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 @@ -29,8 +36,6 @@ } end - let(:body) { { some: "body" }.to_json } - let(:request_body) do { "pacticipantVersionNumber" => "1", diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 9e40586c..113e155f 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -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