Skip to content

Commit

Permalink
feat: allow pacts to be dynamically fetched from a pact broker by pro…
Browse files Browse the repository at this point in the history
…vider name and tags
  • Loading branch information
bethesque committed Jun 24, 2018
1 parent fca52f2 commit ef97898
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 73 deletions.
39 changes: 19 additions & 20 deletions lib/pact/provider/configuration/pact_verification_from_broker.rb
Original file line number Diff line number Diff line change
@@ -1,30 +1,33 @@
require 'pact/provider/pact_verification'
require 'pact/provider/pact_uri'
require 'pact/shared/dsl'
require 'pact/provider/world'
require 'pact/pact_broker/fetch_pacts'

module Pact
module Provider

module Configuration

class PactVerificationFromBroker

extend Pact::DSL

attr_accessor :name, :pact_broker_base_url, :tags
# If user declares a variable with the same name as one of these attributes
# in parent scope, it will clash with these ones,
# so put an underscore in front of the name to be safer.

def initialize(name, options = {})
@tags = options.fetch(:consumer_version_tags) || []
@pact_broker_base_url = options.fetch(:pact_broker_base_url) || ''
@provider_name = name
@options = options
attr_accessor :_provider_name, :_pact_broker_base_url, :_consumer_version_tags, :_basic_auth_options

def initialize(provider_name)
@_provider_name = provider_name
@_consumer_version_tags = []
end

dsl do
def pact_broker_base_url pact_broker_base_url, options
@pact_broker_base_url = URI(pact_broker_base_url)
@pact_broker_base_url.set_user(options[:username]) if options[:username] # not sure about this exactly, I'll work it out when I get there.
def pact_broker_base_url pact_broker_base_url, basic_auth_options = {}
self._pact_broker_base_url = pact_broker_base_url
self._basic_auth_options = basic_auth_options
end

def consumer_version_tags consumer_version_tags
self._consumer_version_tags = *consumer_version_tags
end
end

Expand All @@ -36,17 +39,13 @@ def finalize
private

def create_pact_verification
pacts = Pact::PactBroker::FetchPacts.call(@provider_name, tags, pact_broker_base_url, @options)
pacts.each do |pact_uri|
verification = Pact::Provider::PactVerification.new(nil, pact_uri, nil)
Pact.provider_world.add_pact_verification verification
end
fetch_pacts = Pact::PactBroker::FetchPacts.new(_provider_name, _consumer_version_tags, _pact_broker_base_url, _basic_auth_options)
Pact.provider_world.add_pact_uri_source fetch_pacts
end

def validate
raise "Please provide a pact_broker_base_url for the verification" unless pact_broker_base_url
raise Pact::Error.new("Please provide a pact_broker_base_url from which to retrieve the pacts") unless _pact_broker_base_url
end

end
end
end
Expand Down
8 changes: 4 additions & 4 deletions lib/pact/provider/configuration/service_provider_dsl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,17 +55,17 @@ def honours_pact_with consumer_name, options = {}, &block
create_pact_verification consumer_name, options, &block
end

def honours_pacts_from_pact_broker options = {}, &block
create_pact_verification_from_broker options, &block
def honours_pacts_from_pact_broker &block
create_pact_verification_from_broker &block
end
end

def create_pact_verification consumer_name, options, &block
PactVerification.build(consumer_name, options, &block)
end

def create_pact_verification_from_broker(options, &block)
PactVerificationFromBroker.build(name, options, &block)
def create_pact_verification_from_broker(&block)
PactVerificationFromBroker.build(name, &block)
end

def finalize
Expand Down
18 changes: 16 additions & 2 deletions lib/pact/provider/world.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,22 @@ def pact_verifications
end

def pact_urls
pact_verifications.collect(&:uri)
(pact_verifications.collect(&:uri) + pact_uris_from_pact_uri_sources).compact
end

def add_pact_uri_source pact_uri_source
pact_uri_sources << pact_uri_source
end

private

def pact_uri_sources
@pact_uri_sources ||= []
end

def pact_uris_from_pact_uri_sources
pact_uri_sources.collect{| pact_uri_source| pact_uri_source.call }.flatten
end
end
end
end
end
Original file line number Diff line number Diff line change
@@ -1,52 +1,92 @@
require 'spec_helper'
require 'pact/provider/configuration/pact_verification'
require 'pact/pact_broker/fetch_pacts'

module Pact
module Provider
module Configuration
describe PactVerification do

describe 'create_verification' do
let(:url) { 'http://some/uri' }
describe PactVerificationFromBroker do
describe 'build' do
let(:provider_name) {'provider-name'}
let(:pact_repository_uri_options) do
let(:base_url) { "http://broker.org" }
let(:basic_auth_options) do
{
username: 'pact_broker_username',
password: 'pact_broker_password'
}
end
let(:tag) do
{
name: 'tag-name',
all: false,
fallback: 'master'
}
end
let(:tags) { ['master'] }

let(:options) do
{
pact_broker_base_url: url,
consumer_version_tags: [tag]
}
before do
allow(Pact::PactBroker::FetchPacts).to receive(:new).and_return(fetch_pacts)
allow(Pact.provider_world).to receive(:add_pact_uri_source)
end

context "with valid values" do
subject do
PactVerificationFromBroker.build(provider_name, options) do
PactVerificationFromBroker.build(provider_name) do
pact_broker_base_url base_url, basic_auth_options
consumer_version_tags tags
end
end

let(:fetch_pacts) { double('FetchPacts') }

it "creates a instance of Pact::PactBroker::FetchPacts" do
expect(Pact::PactBroker::FetchPacts).to receive(:new).with(provider_name, tags, base_url, basic_auth_options)
subject
end

it "adds a pact_uri_source to the provider world" do
expect(Pact.provider_world).to receive(:add_pact_uri_source).with(fetch_pacts)
subject
end
end

context "with a missing base url" do
subject do
PactVerificationFromBroker.build(provider_name) do

end
end

let(:fetch_pacts) { double('FetchPacts') }

it "raises an error" do
expect { subject }.to raise_error Pact::Error, /Please provide a pact_broker_base_url/
end
end

context "with a non array object for consumer_version_tags" do
subject do
PactVerificationFromBroker.build(provider_name) do
pact_broker_base_url base_url
consumer_version_tags "master"
end
end

let(:fetch_pacts) { double('FetchPacts') }

it "coerces the value into an array" do
expect(Pact::PactBroker::FetchPacts).to receive(:new).with(anything, ["master"], anything, anything)
subject
end
end

context "when no consumer_version_tags are provided" do
subject do
PactVerificationFromBroker.build(provider_name) do
pact_broker_base_url base_url
end
end

it "creates a Verification" do
allow(Pact::PactBroker::FetchPacts).to receive(:call).and_return(['pact-urls'])
let(:fetch_pacts) { double('FetchPacts') }

tags = [tag]
expect(Pact::PactBroker::FetchPacts).to receive(:call).with(provider_name, tags, url, options)
expect(Pact::Provider::PactVerification).to receive(:new).with(nil, 'pact-urls', nil)
it "creates an instance of FetchPacts with an emtpy array for the consumer_version_tags" do
expect(Pact::PactBroker::FetchPacts).to receive(:new).with(anything, [], anything, anything)
subject
end
end
end
end
end
end
end
end
37 changes: 36 additions & 1 deletion spec/lib/pact/provider/world_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,51 @@ module Provider
describe World do

subject { World.new }

describe "provider_states" do
it "returns a provider state proxy" do
expect(subject.provider_states).to be_instance_of State::ProviderStateProxy
end
it "returns the same object each time" do
expect(subject.provider_states).to be subject.provider_states
end

end

describe "pact_urls" do
context "with pact_uri_sources" do
before do
subject.add_pact_uri_source(pact_uri_source_1)
subject.add_pact_uri_source(pact_uri_source_2)
end

let(:pact_uri_source_1) { double('pact_uri_source_1', call: ["uri-1"]) }
let(:pact_uri_source_2) { double('pact_uri_source_2', call: ["uri-2"]) }

let(:pact_urls) { subject.pact_urls }

it "invokes call on the pact_uri_sources" do
expect(pact_uri_source_1).to receive(:call)
expect(pact_uri_source_2).to receive(:call)
pact_urls
end

it "concatenates the results" do
expect(pact_urls).to eq ["uri-1", "uri-2"]
end

context "with a pact_verification" do
before do
subject.add_pact_verification(pact_verification)
end

let(:pact_verification) { double('PactVerification', uri: "uri-3") }

it "concatenates the results with those of the pact_uri_sources" do
expect(pact_urls).to eq ["uri-3", "uri-1", "uri-2"]
end
end
end
end
end
end
end
43 changes: 24 additions & 19 deletions spec/support/bar_pact_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,31 @@
require 'pact/provider/rspec'

module Pact
module Test
class BarApp
def call env
[200, {'Content-Type' => 'application/json'}, [{"status" => "5"},{"status" => "6"}].to_json]
end
end
module Test
class BarApp
def call env
[200, {'Content-Type' => 'application/json'}, [{"status" => "5"},{"status" => "6"}].to_json]
end
end

Pact.configure do | config |
config.logger.level = Logger::DEBUG
end
Pact.configure do | config |
config.logger.level = Logger::DEBUG
end

Pact.service_provider "Bar" do
app { BarApp.new }
app_version '1.2.3'
app_version_tags ['master']
publish_verification_results true
Pact.service_provider "Bar" do
app { BarApp.new }
app_version '1.2.3'
app_version_tags ['master']
publish_verification_results true

honours_pact_with 'Foo' do
pact_uri './spec/support/foo-bar.json'
end
end
end
honours_pacts_from_pact_broker do
pact_broker_base_url "http://localhost:9292"
consumer_version_tags ["prod"]
end

honours_pact_with 'Foo' do
pact_uri './spec/support/foo-bar.json'
end
end
end
end
3 changes: 2 additions & 1 deletion tasks/foo-bar.rake
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ task 'pact:foobar:publish' do
puts response.code unless response.code == '200'
end

#'./spec/pacts/foo-bar.json'
Pact::VerificationTask.new('foobar') do | pact |
pact.uri './spec/pacts/foo-bar.json', pact_helper: './spec/support/bar_pact_helper.rb'
pact.uri nil, pact_helper: './spec/support/bar_pact_helper.rb'
end


Expand Down

0 comments on commit ef97898

Please sign in to comment.