From f6903b23fef796e54faf9366ce3d5842b5e48205 Mon Sep 17 00:00:00 2001 From: Beth Skurrie Date: Mon, 5 Oct 2020 10:33:26 +1100 Subject: [PATCH] fix(can-i-deploy): gracefully handle pacticipant not found --- lib/pact_broker/api/resources/can_i_deploy.rb | 14 +++++ lib/pact_broker/locale/en.yml | 1 + .../api/resources/can_i_deploy_spec.rb | 51 +++++++++++++++++++ 3 files changed, 66 insertions(+) create mode 100644 spec/lib/pact_broker/api/resources/can_i_deploy_spec.rb diff --git a/lib/pact_broker/api/resources/can_i_deploy.rb b/lib/pact_broker/api/resources/can_i_deploy.rb index 511aea209..a262cd0b1 100644 --- a/lib/pact_broker/api/resources/can_i_deploy.rb +++ b/lib/pact_broker/api/resources/can_i_deploy.rb @@ -1,11 +1,14 @@ require 'pact_broker/api/resources/matrix' require 'pact_broker/matrix/can_i_deploy_query_schema' require 'pact_broker/matrix/parse_can_i_deploy_query' +require 'pact_broker/messages' module PactBroker module Api module Resources class CanIDeploy < Matrix + include PactBroker::Messages + def initialize super @query_params = JSON.parse(Rack::Utils.parse_nested_query(request.uri.query).to_json, symbolize_names: true) @@ -16,6 +19,9 @@ def malformed_request? if (errors = query_schema.call(query_params)).any? set_json_validation_error_messages(errors) true + elsif !pacticipant + set_json_validation_error_messages(pacticipant: [message('errors.validation.pacticipant_not_found', name: pacticipant_name)]) + true else false end @@ -32,6 +38,14 @@ def policy_name def query_schema PactBroker::Api::Contracts::CanIDeployQuerySchema end + + def pacticipant + @pacticipant ||= pacticipant_service.find_pacticipant_by_name(pacticipant_name) + end + + def pacticipant_name + selectors.first.pacticipant_name + end end end end diff --git a/lib/pact_broker/locale/en.yml b/lib/pact_broker/locale/en.yml index 222d32b27..529201932 100644 --- a/lib/pact_broker/locale/en.yml +++ b/lib/pact_broker/locale/en.yml @@ -45,6 +45,7 @@ en: pacticipant_name_mismatch: "in pact ('%{name_in_pact}') does not match %{pacticipant} name in path ('%{name}')." connection_encoding_not_utf8: "The Sequel connection encoding (%{encoding}) is strongly recommended to be \"utf8\". If you need to set it to %{encoding} for some particular reason, then disable this check by setting config.validate_database_connection_config = false" invalid_webhook_uuid: The UUID can only contain the characters A-Z, a-z, 0-9, _ and -, and must be 16 or more characters. + pacticipant_not_found: No pacticipant with name '%{name}' found duplicate_pacticipant: | This is the first time a pact has been published for "%{new_name}". The name "%{new_name}" is very similar to the following existing consumers/providers: diff --git a/spec/lib/pact_broker/api/resources/can_i_deploy_spec.rb b/spec/lib/pact_broker/api/resources/can_i_deploy_spec.rb new file mode 100644 index 000000000..90ef2a20c --- /dev/null +++ b/spec/lib/pact_broker/api/resources/can_i_deploy_spec.rb @@ -0,0 +1,51 @@ +require 'pact_broker/api/resources/can_i_deploy' + +module PactBroker + module Api + module Resources + describe CanIDeploy do + include_context "stubbed services" + + before do + allow(pacticipant_service).to receive(:find_pacticipant_by_name).and_return(pacticipant) + allow(matrix_service).to receive(:find).and_return(results) + allow_any_instance_of(described_class).to receive(:matrix_service).and_return(matrix_service) + allow(PactBroker::Api::Decorators::MatrixDecorator).to receive(:new).and_return(decorator) + end + + let(:results) { double('results') } + let(:pacticipant) { double('pacticipant') } + let(:decorator) { instance_double('PactBroker::Api::Decorators::MatrixDecorator', to_json: 'response_body') } + let(:matrix_service) { class_double("PactBroker::Matrix::Service").as_stubbed_const } + + let(:query) do + { + pacticipant: "Foo", + version: "1.2.3", + to: "prod" + } + end + + subject { get("/can-i-deploy", query, { 'HTTP_ACCEPT' => 'application/hal+json'}) } + + context "with the wrong query" do + let(:query) { {} } + + it "returns a 400" do + expect(subject.status).to eq 400 + expect(JSON.parse(subject.body)["errors"]["pacticipant"].first).to_not be_empty + end + end + + context "when the pacticipant does not exist" do + let(:pacticipant) { nil } + + it "returns a 400" do + expect(subject.status).to eq 400 + expect(JSON.parse(subject.body)["errors"]["pacticipant"].first).to match /Foo.*found/ + end + end + end + end + end +end