Skip to content

Commit

Permalink
feat: update HAL client from pact codebase
Browse files Browse the repository at this point in the history
  • Loading branch information
bethesque committed Nov 15, 2018
1 parent 7a9c8c4 commit ed77fe0
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 26 deletions.
39 changes: 34 additions & 5 deletions lib/pact_broker/client/hal/entity.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
require 'uri'
require 'erb'
require 'delegate'
require 'pact_broker/client/hal/link'

module PactBroker
module Client
module Hal
class RelationNotFoundError < ::PactBroker::Client::Error; end

class ErrorResponseReturned < ::PactBroker::Client::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
Expand All @@ -33,14 +39,20 @@ def follow(key, http_method, *args)
Link.new(@links[key].merge(method: http_method), @client).run(*args)
end

def _link(key)
def _link(key, fallback_key = nil)
if @links[key]
Link.new(@links[key], @client)
elsif fallback_key && @links[fallback_key]
Link.new(@links[fallback_key], @client)
else
nil
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
Expand All @@ -49,8 +61,8 @@ def response
@response
end

def fetch(key)
@links[key]
def fetch(key, fallback_key = nil)
@links[key] || (fallback_key && @links[fallback_key])
end

def method_missing(method_name, *args, &block)
Expand All @@ -66,12 +78,29 @@ def method_missing(method_name, *args, &block)
def respond_to_missing?(method_name, include_private = false)
@data.key?(method_name) || @links.key?(method_name)
end

def assert_success!
self
end
end

class ErrorEntity < Entity

def initialize(href, data, http_client, response = nil)
@href = href
@data = data
@links = {}
@client = http_client
@response = response
end

def success?
false
end

def assert_success!
raise ErrorResponseReturned.new("Error retrieving #{@href} status=#{response ? response.code: nil} #{response ? response.raw_body : ''}")
end
end
end
end
Expand Down
5 changes: 3 additions & 2 deletions lib/pact_broker/client/hal/http_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module PactBroker
module Client
module Hal
class HttpClient
attr_reader :username, :password, :verbose
attr_accessor :username, :password, :verbose

def initialize options
@username = options[:username]
Expand Down Expand Up @@ -56,7 +56,7 @@ def perform_request request, uri

class Response < SimpleDelegator
def body
bod = __getobj__().body
bod = raw_body
if bod && bod != ''
JSON.parse(bod)
else
Expand All @@ -77,6 +77,7 @@ def success?
end
end
end

end
end
end
20 changes: 9 additions & 11 deletions lib/pact_broker/client/hal/link.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,15 @@ def name
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)
Expand All @@ -57,21 +57,19 @@ def expand(params)

private

def wrap_response(http_response)
require 'pact_broker/client/hal/entity' # avoid circular reference
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.body, @http_client, http_response)
ErrorEntity.new(href, http_response.raw_body, @http_client, http_response)
end
end

def expand_url(params, url)
new_url = url
params.each do | key, value |
new_url = new_url.gsub('{' + key.to_s + '}', URI.escape(value))
params.inject(url) do | url, (key, value) |
url.gsub('{' + key.to_s + '}', ERB::Util.url_encode(value))
end
new_url
end
end
end
Expand Down
64 changes: 59 additions & 5 deletions spec/lib/pact_broker/client/hal/entity_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -60,6 +60,32 @@ module Hal
end
end

describe "assert_success!" do
context "when the response is successful" do
it "returns the entity" do
expect(entity.assert_success!).to be entity
end
end

context "when the response is not successful and there is no response" do
subject(:entity) { ErrorEntity.new("http://pact", pact_hash, http_client) }

it "raises an error" do
expect { entity.assert_success! }.to raise_error ErrorResponseReturned, "Error retrieving http://pact status= "
end
end

context "when the response is not successful and there is a response" do
let(:response) { double('response', code: 200, raw_body: "body") }

subject(:entity) { ErrorEntity.new("http://pact", pact_hash, http_client, response) }

it "raises an error" do
expect { entity.assert_success! }.to raise_error ErrorResponseReturned, "Error retrieving http://pact status=200 body"
end
end
end

describe "can?" do
context "when the relation exists" do
it "returns true" do
Expand All @@ -74,19 +100,47 @@ 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 exist' do
context 'when the key exists' do
it 'returns fetched value' do
expect(subject.fetch('pb:provider')).to be do
{href: 'http://provider'}
end
expect(subject.fetch('pb:provider')).to eq("href" => 'http://provider')
end
end

context "when the key doesn't not exist" do
it 'returns nil' do
expect(subject.fetch('i-dont-exist')).to be nil
end
end

context "when a fallback key is provided" do
context "when the fallback value exists" do
it "returns the fallback value" do
expect(subject.fetch('i-dont-exist', 'pb:provider')).to eq("href" => 'http://provider')
end
end

context "when the fallback value does not exist" do
it "returns nil" do
expect(subject.fetch('i-dont-exist', 'i-also-dont-exist')).to be nil
end
end
end
end
end
end
Expand Down
10 changes: 7 additions & 3 deletions spec/lib/pact_broker/client/hal/link_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ module Hal
end

let(:response) do
instance_double('PactBroker::Client::Hal::HttpClient::Response', success?: success, body: response_body)
instance_double('PactBroker::Client::Hal::HttpClient::Response', success?: success, body: response_body, raw_body: response_body.to_json)
end

let(:success) { true }
Expand Down Expand Up @@ -48,7 +48,7 @@ module Hal
end

it "creates an Entity" do
expect(PactBroker::Client::Hal::Entity).to receive(:new).with(response_body, http_client, response)
expect(PactBroker::Client::Hal::Entity).to receive(:new).with("http://foo/{bar}", response_body, http_client, response)
do_run
end

Expand All @@ -64,7 +64,7 @@ module Hal
let(:success) { false }

it "creates an ErrorEntity" do
expect(PactBroker::Client::Hal::ErrorEntity).to receive(:new).with(response_body, http_client, response)
expect(PactBroker::Client::Hal::ErrorEntity).to receive(:new).with("http://foo/{bar}", response_body.to_json, http_client, response)
do_run
end
end
Expand Down Expand Up @@ -102,6 +102,10 @@ module Hal
it "returns a duplicate Link with the expanded href with URL escaping" do
expect(subject.expand(bar: 'wiffle meep').href).to eq "http://foo/wiffle%20meep"
end

it "returns a duplicate Link with the expanded href with URL escaping for forward slashes" do
expect(subject.expand(bar: 'wiffle/meep').href).to eq "http://foo/wiffle%2Fmeep"
end
end
end
end
Expand Down

0 comments on commit ed77fe0

Please sign in to comment.