From 5db4134b40c0f1164f43e5fb69c32916b8f20d6c Mon Sep 17 00:00:00 2001 From: Beth Skurrie Date: Tue, 24 Jul 2018 21:06:44 +1000 Subject: [PATCH] feat: raise error when an expected HAL relation cannot be found in a resource --- lib/pact/hal/entity.rb | 13 +++++++++++-- lib/pact/hal/link.rb | 12 ++++++------ lib/pact/pact_broker/fetch_pacts.rb | 6 +++--- .../provider/verification_results/publish.rb | 2 +- spec/lib/pact/hal/entity_spec.rb | 17 ++++++++++++++++- spec/lib/pact/hal/link_spec.rb | 4 ++-- spec/lib/pact/pact_broker/fetch_pacts_spec.rb | 10 ++++++++++ 7 files changed, 49 insertions(+), 15 deletions(-) diff --git a/lib/pact/hal/entity.rb b/lib/pact/hal/entity.rb index 235398dd..399af85c 100644 --- a/lib/pact/hal/entity.rb +++ b/lib/pact/hal/entity.rb @@ -4,8 +4,12 @@ module Pact module Hal + class RelationNotFoundError < ::Pact::Error; end + class Entity - def initialize(data, http_client, response = nil) + + def initialize(href, data, http_client, response = nil) + @href = href @data = data @links = (@data || {}).fetch("_links", {}) @client = http_client @@ -40,6 +44,10 @@ def _link(key) end end + def _link!(key) + _link(key) or raise RelationNotFoundError.new("Could not find relation '#{key}' in resource at #{@href}") + end + def success? true end @@ -69,7 +77,8 @@ def respond_to_missing?(method_name, include_private = false) class ErrorEntity < Entity - def initialize(data, http_client, response = nil) + def initialize(href, data, http_client, response = nil) + @href = href @data = data @links = {} @client = http_client diff --git a/lib/pact/hal/link.rb b/lib/pact/hal/link.rb index 4804b9ad..1fa272c2 100644 --- a/lib/pact/hal/link.rb +++ b/lib/pact/hal/link.rb @@ -25,15 +25,15 @@ def run(payload = nil) end def get(payload = {}, headers = {}) - wrap_response(@http_client.get(href, payload, headers)) + wrap_response(href, @http_client.get(href, payload, headers)) end def put(payload = nil, headers = {}) - wrap_response(@http_client.put(href, payload ? JSON.dump(payload) : nil, headers)) + wrap_response(href, @http_client.put(href, payload ? JSON.dump(payload) : nil, headers)) end def post(payload = nil, headers = {}) - wrap_response(@http_client.post(href, payload ? JSON.dump(payload) : nil, headers)) + wrap_response(href, @http_client.post(href, payload ? JSON.dump(payload) : nil, headers)) end def expand(params) @@ -44,12 +44,12 @@ def expand(params) private - def wrap_response(http_response) + def wrap_response(href, http_response) require 'pact/hal/entity' # avoid circular reference if http_response.success? - Entity.new(http_response.body, @http_client, http_response) + Entity.new(href, http_response.body, @http_client, http_response) else - ErrorEntity.new(http_response.raw_body, @http_client, http_response) + ErrorEntity.new(href, http_response.raw_body, @http_client, http_response) end end diff --git a/lib/pact/pact_broker/fetch_pacts.rb b/lib/pact/pact_broker/fetch_pacts.rb index f9f8cff1..26a14261 100644 --- a/lib/pact/pact_broker/fetch_pacts.rb +++ b/lib/pact/pact_broker/fetch_pacts.rb @@ -64,9 +64,9 @@ def tagged_pacts_for_provider def link_for(tag) if !tag[:all] - index_entity._link(LATEST_PROVIDER_TAG_RELATION) + index_entity._link!(LATEST_PROVIDER_TAG_RELATION) else - index_entity._link(ALL_PROVIDER_TAG_RELATION) + index_entity._link!(ALL_PROVIDER_TAG_RELATION) end end @@ -75,7 +75,7 @@ def index end def latest_pacts_for_provider - link = index_entity._link(LATEST_PROVIDER_RELATION) + link = index_entity._link!(LATEST_PROVIDER_RELATION) pact_urls(link.expand(provider: provider).get) end diff --git a/lib/pact/provider/verification_results/publish.rb b/lib/pact/provider/verification_results/publish.rb index c56122f0..f0f91c79 100644 --- a/lib/pact/provider/verification_results/publish.rb +++ b/lib/pact/provider/verification_results/publish.rb @@ -32,7 +32,7 @@ def initialize pact_source, verification_result end @http_client = Pact::Hal::HttpClient.new(http_client_options) - @pact_entity = Pact::Hal::Entity.new(pact_source.pact_hash, http_client) + @pact_entity = Pact::Hal::Entity.new(pact_source.uri, pact_source.pact_hash, http_client) end def call diff --git a/spec/lib/pact/hal/entity_spec.rb b/spec/lib/pact/hal/entity_spec.rb index ce947568..e444cbba 100644 --- a/spec/lib/pact/hal/entity_spec.rb +++ b/spec/lib/pact/hal/entity_spec.rb @@ -32,7 +32,7 @@ module Hal } end - subject(:entity) { Entity.new(pact_hash, http_client) } + subject(:entity) { Entity.new("http://pact", pact_hash, http_client) } it "delegates to the properties in the data" do expect(subject.name).to eq "a name" @@ -74,6 +74,21 @@ module Hal end end + describe "_link!" do + context 'when the key exists' do + it 'returns a Link' do + expect(subject._link!('pb:provider')).to be_a(Link) + expect(subject._link!('pb:provider').href).to eq 'http://provider' + end + end + + context 'when the key does not exist' do + it 'raises an error' do + expect { subject._link!('foo') }.to raise_error RelationNotFoundError, "Could not find relation 'foo' in resource at http://pact" + end + end + end + describe 'fetch' do context 'when the key exists' do it 'returns fetched value' do diff --git a/spec/lib/pact/hal/link_spec.rb b/spec/lib/pact/hal/link_spec.rb index 5f9a6cfb..c81c9715 100644 --- a/spec/lib/pact/hal/link_spec.rb +++ b/spec/lib/pact/hal/link_spec.rb @@ -48,7 +48,7 @@ module Hal end it "creates an Entity" do - expect(Pact::Hal::Entity).to receive(:new).with(response_body, http_client, response) + expect(Pact::Hal::Entity).to receive(:new).with("http://foo/{bar}", response_body, http_client, response) do_run end @@ -64,7 +64,7 @@ module Hal let(:success) { false } it "creates an ErrorEntity" do - expect(Pact::Hal::ErrorEntity).to receive(:new).with(response_body.to_json, http_client, response) + expect(Pact::Hal::ErrorEntity).to receive(:new).with("http://foo/{bar}", response_body.to_json, http_client, response) do_run end end diff --git a/spec/lib/pact/pact_broker/fetch_pacts_spec.rb b/spec/lib/pact/pact_broker/fetch_pacts_spec.rb index 19f15f8f..096960d0 100644 --- a/spec/lib/pact/pact_broker/fetch_pacts_spec.rb +++ b/spec/lib/pact/pact_broker/fetch_pacts_spec.rb @@ -31,6 +31,16 @@ module PactBroker end end + context "when there is a HAL relation missing" do + before do + stub_request(:get, "http://broker.org/").to_return(status: 200, body: {"_links" => {} }.to_json, headers: {}) + end + + it "raises a Pact::Error" do + expect { subject }.to raise_error Pact::Error, /Could not find relation/ + end + end + context "for the latest tag" do it "logs a message" do expect(Pact.configuration.output_stream).to receive(:puts).with("INFO: Fetching pacts for Foo from http://broker.org for tags: latest master, latest prod")