diff --git a/doc/pacts/markdown/Pact Broker Client - Pact Broker.md b/doc/pacts/markdown/Pact Broker Client - Pact Broker.md index a96d2396..5104d834 100644 --- a/doc/pacts/markdown/Pact Broker Client - Pact Broker.md +++ b/doc/pacts/markdown/Pact Broker Client - Pact Broker.md @@ -26,6 +26,8 @@ * [A request for the index resource](#a_request_for_the_index_resource_given_the_pb:latest-version_relation_exists_in_the_index_resource) given the pb:latest-version relation exists in the index resource +* [A request for the index resource with the webhook relation](#a_request_for_the_index_resource_with_the_webhook_relation) + * [A request for the list of the latest pacts from all consumers for the Pricing Service'](#a_request_for_the_list_of_the_latest_pacts_from_all_consumers_for_the_Pricing_Service'_given_a_latest_pact_between_Condor_and_the_Pricing_Service_exists) given a latest pact between Condor and the Pricing Service exists * [A request for the list of the latest prod pacts from all consumers for the Pricing Service'](#a_request_for_the_list_of_the_latest_prod_pacts_from_all_consumers_for_the_Pricing_Service'_given_tagged_as_prod_pact_between_Condor_and_the_Pricing_Service_exists) given tagged as prod pact between Condor and the Pricing Service exists @@ -38,6 +40,8 @@ * [A request to create a webhook for a consumer and provider](#a_request_to_create_a_webhook_for_a_consumer_and_provider_given_'Condor'_does_not_exist_in_the_pact-broker) given 'Condor' does not exist in the pact-broker +* [A request to create a webhook with a JSON body and a uuid](#a_request_to_create_a_webhook_with_a_JSON_body_and_a_uuid_given_the_'Pricing_Service'_and_'Condor'_already_exist_in_the_pact-broker) given the 'Pricing Service' and 'Condor' already exist in the pact-broker + * [A request to create a webhook with a JSON body for a consumer](#a_request_to_create_a_webhook_with_a_JSON_body_for_a_consumer_given_the_'Pricing_Service'_and_'Condor'_already_exist_in_the_pact-broker) given the 'Pricing Service' and 'Condor' already exist in the pact-broker * [A request to create a webhook with a JSON body for a consumer and provider](#a_request_to_create_a_webhook_with_a_JSON_body_for_a_consumer_and_provider_given_the_'Pricing_Service'_and_'Condor'_already_exist_in_the_pact-broker) given the 'Pricing Service' and 'Condor' already exist in the pact-broker @@ -557,6 +561,34 @@ Pact Broker will respond with: } } ``` + +Upon receiving **a request for the index resource with the webhook relation** from Pact Broker Client, with +```json +{ + "method": "get", + "path": "/", + "headers": { + "Accept": "application/hal+json" + } +} +``` +Pact Broker will respond with: +```json +{ + "status": 200, + "headers": { + "Content-Type": "application/hal+json;charset=utf-8" + }, + "body": { + "_links": { + "pb:webhook": { + "href": "http://localhost:1234/webhooks/{uuid}", + "templated": true + } + } + } +} +``` Given **a latest pact between Condor and the Pricing Service exists**, upon receiving **a request for the list of the latest pacts from all consumers for the Pricing Service'** from Pact Broker Client, with ```json @@ -781,6 +813,61 @@ Pact Broker will respond with: } } ``` + +Given **the 'Pricing Service' and 'Condor' already exist in the pact-broker**, upon receiving **a request to create a webhook with a JSON body and a uuid** from Pact Broker Client, with +```json +{ + "method": "put", + "path": "/webhooks/9999", + "headers": { + "Content-Type": "application/json", + "Accept": "application/hal+json" + }, + "body": { + "events": [ + { + "name": "contract_content_changed" + } + ], + "request": { + "url": "https://webhook", + "method": "POST", + "headers": { + "Foo": "bar", + "Bar": "foo" + }, + "body": { + "some": "body" + }, + "username": "username", + "password": "password" + }, + "provider": { + "name": "Pricing Service" + }, + "consumer": { + "name": "Condor" + } + } +} +``` +Pact Broker will respond with: +```json +{ + "status": 201, + "headers": { + "Content-Type": "application/hal+json;charset=utf-8" + }, + "body": { + "_links": { + "self": { + "href": "http://localhost:1234/some-url", + "title": "A title" + } + } + } +} +``` Given **the 'Pricing Service' and 'Condor' already exist in the pact-broker**, upon receiving **a request to create a webhook with a JSON body for a consumer** from Pact Broker Client, with ```json diff --git a/lib/pact_broker/client/cli/broker.rb b/lib/pact_broker/client/cli/broker.rb index 2a59d9c4..9eadaeca 100644 --- a/lib/pact_broker/client/cli/broker.rb +++ b/lib/pact_broker/client/cli/broker.rb @@ -109,67 +109,21 @@ def describe_version exit(1) unless result.success end - method_option :request, banner: "METHOD", aliases: "-X", desc: "HTTP method", required: true - method_option :header, aliases: "-H", type: :array, desc: "Header" - method_option :data, aliases: "-d", desc: "Data" - method_option :user, aliases: "-u", desc: "Basic auth username and password eg. username:password" - method_option :consumer, desc: "Consumer name" - method_option :provider, desc: "Provider name" - method_option :broker_base_url, required: true, aliases: "-b", desc: "The base URL of the Pact Broker" - method_option :broker_username, desc: "Pact Broker basic auth username" - method_option :broker_password, aliases: "-p", desc: "Pact Broker basic auth password" - method_option :broker_token, aliases: "-k", desc: "Pact Broker bearer token" - method_option :contract_content_changed, type: :boolean, desc: "Trigger this webhook when the pact content changes" - method_option :provider_verification_published, type: :boolean, desc: "Trigger this webhook when a provider verification result is published" - method_option :verbose, aliases: "-v", type: :boolean, default: false, required: false, desc: "Verbose output. Default: false" + shared_options_for_webhook_commands desc 'create-webhook URL', 'Creates a webhook using the same switches as a curl request.' long_desc File.read(File.join(File.dirname(__FILE__), 'create_webhook_long_desc.txt')) def create_webhook webhook_url - require 'pact_broker/client/webhooks/create' - - if !(options.contract_content_changed || options.provider_verification_published) - raise PactBroker::Client::Error.new("You must select at least one of --contract-content-changed or --provider-verification-published") - end - - username = options.user ? options.user.split(":", 2).first : nil - password = options.user ? options.user.split(":", 2).last : nil - - headers = (options.header || []).each_with_object({}) { | header, headers | headers[header.split(":", 2).first.strip] = header.split(":", 2).last.strip } - - body = options.data - if body && body.start_with?("@") - filepath = body[1..-1] - begin - body = File.read(filepath) - rescue StandardError => e - raise PactBroker::Client::Error.new("Couldn't read data from file \"#{filepath}\" due to #{e.class} #{e.message}") - end - end - - events = [] - events << 'contract_content_changed' if options.contract_content_changed - events << 'provider_verification_published' if options.provider_verification_published + run_webhook_commands webhook_url + end - params = { - http_method: options.request, - url: webhook_url, - headers: headers, - username: username, - password: password, - body: body, - consumer: options.consumer, - provider: options.provider, - events: events - } + shared_options_for_webhook_commands + method_option :uuid, type: :string, required: true, desc: "Specify the uuid for the webhook" - begin - result = PactBroker::Client::Webhooks::Create.call(params, options.broker_base_url, pact_broker_client_options) - $stdout.puts result.message - exit(1) unless result.success - rescue PactBroker::Client::Error => e - raise WebhookCreationError, "#{e.class} - #{e.message}" - end + desc 'create-or-update-webhook URL', 'Creates or updates a webhook with a provided uuid and using the same switches as a curl request.' + long_desc File.read(File.join(File.dirname(__FILE__), 'create_or_update_webhook_long_desc.txt')) + def create_or_update_webhook webhook_url + run_webhook_commands webhook_url end desc 'version', "Show the pact_broker-client gem version" @@ -232,6 +186,54 @@ def pact_broker_client_options client_options end + + def run_webhook_commands webhook_url + require 'pact_broker/client/webhooks/create' + + if !(options.contract_content_changed || options.provider_verification_published) + raise PactBroker::Client::Error.new("You must select at least one of --contract-content-changed or --provider-verification-published") + end + + username = options.user ? options.user.split(":", 2).first : nil + password = options.user ? options.user.split(":", 2).last : nil + + headers = (options.header || []).each_with_object({}) { | header, headers | headers[header.split(":", 2).first.strip] = header.split(":", 2).last.strip } + + body = options.data + if body && body.start_with?("@") + filepath = body[1..-1] + begin + body = File.read(filepath) + rescue StandardError => e + raise PactBroker::Client::Error.new("Couldn't read data from file \"#{filepath}\" due to #{e.class} #{e.message}") + end + end + + events = [] + events << 'contract_content_changed' if options.contract_content_changed + events << 'provider_verification_published' if options.provider_verification_published + + params = { + uuid: options.uuid, + http_method: options.request, + url: webhook_url, + headers: headers, + username: username, + password: password, + body: body, + consumer: options.consumer, + provider: options.provider, + events: events + } + + begin + result = PactBroker::Client::Webhooks::Create.call(params, options.broker_base_url, pact_broker_client_options) + $stdout.puts result.message + exit(1) unless result.success + rescue PactBroker::Client::Error => e + raise WebhookCreationError, "#{e.class} - #{e.message}" + end + end end end end diff --git a/lib/pact_broker/client/cli/create_or_update_webhook_long_desc.txt b/lib/pact_broker/client/cli/create_or_update_webhook_long_desc.txt new file mode 100644 index 00000000..91faa593 --- /dev/null +++ b/lib/pact_broker/client/cli/create_or_update_webhook_long_desc.txt @@ -0,0 +1 @@ +Create a curl command that executes the request that you want your webhook to execute, then replace "curl" with "pact-broker create-or-update-webhook" and add the consumer, provider, event types and broker details. Note that the URL must be the first parameter when executing create-webhook and a uuid must also be provided. \ No newline at end of file diff --git a/lib/pact_broker/client/cli/custom_thor.rb b/lib/pact_broker/client/cli/custom_thor.rb index 543c2c9d..5eecd4c1 100644 --- a/lib/pact_broker/client/cli/custom_thor.rb +++ b/lib/pact_broker/client/cli/custom_thor.rb @@ -64,6 +64,22 @@ def self.turn_muliple_tag_options_into_array argv end new_argv.flatten end + + def self.shared_options_for_webhook_commands + method_option :request, banner: "METHOD", aliases: "-X", desc: "HTTP method", required: true + method_option :header, aliases: "-H", type: :array, desc: "Header" + method_option :data, aliases: "-d", desc: "Data" + method_option :user, aliases: "-u", desc: "Basic auth username and password eg. username:password" + method_option :consumer, desc: "Consumer name" + method_option :provider, desc: "Provider name" + method_option :broker_base_url, required: true, aliases: "-b", desc: "The base URL of the Pact Broker" + method_option :broker_username, desc: "Pact Broker basic auth username" + method_option :broker_password, aliases: "-p", desc: "Pact Broker basic auth password" + method_option :broker_token, aliases: "-k", desc: "Pact Broker bearer token" + method_option :contract_content_changed, type: :boolean, desc: "Trigger this webhook when the pact content changes" + method_option :provider_verification_published, type: :boolean, desc: "Trigger this webhook when a provider verification result is published" + method_option :verbose, aliases: "-v", type: :boolean, default: false, required: false, desc: "Verbose output. Default: false" + end end end end diff --git a/lib/pact_broker/client/webhooks/create.rb b/lib/pact_broker/client/webhooks/create.rb index 18d4a7d1..a67b1c2b 100644 --- a/lib/pact_broker/client/webhooks/create.rb +++ b/lib/pact_broker/client/webhooks/create.rb @@ -24,7 +24,7 @@ def initialize(params, pact_broker_base_url, pact_broker_client_options) end def call - if params.consumer && params.provider + if params.consumer && params.provider && !params.uuid create_webhook_with_consumer_and_provider else create_webhook_with_optional_consumer_and_provider @@ -41,7 +41,11 @@ def create_webhook_with_consumer_and_provider end def create_webhook_with_optional_consumer_and_provider - webhook_entity = index_link.get!._link("pb:webhooks").post(request_body_with_optional_consumer_and_provider) + if params.uuid + webhook_entity = index_link.get!._link("pb:webhook").expand(uuid: params.uuid).put(request_body_with_optional_consumer_and_provider) + else + webhook_entity = index_link.get!._link("pb:webhooks").post(request_body_with_optional_consumer_and_provider) + end if webhook_entity.response.status == 405 raise PactBroker::Client::Error.new(WEBHOOKS_WITH_OPTIONAL_PACTICICPANTS_NOT_SUPPORTED) diff --git a/spec/lib/pact_broker/client/cli/broker_create_or_update_webhook_spec.rb b/spec/lib/pact_broker/client/cli/broker_create_or_update_webhook_spec.rb new file mode 100644 index 00000000..75febbd7 --- /dev/null +++ b/spec/lib/pact_broker/client/cli/broker_create_or_update_webhook_spec.rb @@ -0,0 +1,23 @@ +require 'pact_broker/client/cli/broker' +require 'pact_broker/client/webhooks/create' + +module PactBroker + module Client + module CLI + describe Broker do + describe "create_or_update_webhook" do + + let(:broker) { Broker.new } + + subject { broker.create_or_update_webhook "http://webhook" } + + it "calls PactBroker::Client::Webhooks::Create with the webhook params" do + expect(broker).to receive(:run_webhook_commands).with("http://webhook") + + subject + end + end + end + end + end +end diff --git a/spec/lib/pact_broker/client/cli/broker_create_webhook_spec.rb b/spec/lib/pact_broker/client/cli/broker_create_webhook_spec.rb index d72a333c..71d427a0 100644 --- a/spec/lib/pact_broker/client/cli/broker_create_webhook_spec.rb +++ b/spec/lib/pact_broker/client/cli/broker_create_webhook_spec.rb @@ -6,184 +6,16 @@ module Client module CLI describe Broker do describe "create_webhook" do - before do - allow($stdout).to receive(:puts) - allow(PactBroker::Client::Webhooks::Create).to receive(:call).and_return(command_result) - broker.options = OpenStruct.new(options_hash) - end let(:broker) { Broker.new } - let(:data) { 'data' } - let(:user) { "username:password" } - let(:command_result) { double('command result', success: success, message: 'message') } - let(:success) { true } - let(:header) { ["Foo: bar", "Bar: foo"] } - - let(:options_hash) do - { - request: "POST", - header: header, - data: data, - user: user, - consumer: "consumer", - provider: "provider", - broker_base_url: "http://broker", - broker_username: "username", - broker_password: "password", - broker_token: "token", - contract_content_changed: true, - verbose: true - } - end - - let(:expected_params) do - { - http_method: "POST", - url: "http://webhook", - headers: { "Foo" => "bar", "Bar" => "foo"}, - username: "username", - password: "password", - body: "data", - consumer: "consumer", - provider: "provider", - events: ["contract_content_changed"] - }.tap { |it| Pact::Fixture.add_fixture(:create_webhook_params, it) } - end - subject { broker.create_webhook "http://webhook" } + subject { broker.create_webhook "http://webhook" } it "calls PactBroker::Client::Webhooks::Create with the webhook params" do - expect(PactBroker::Client::Webhooks::Create).to receive(:call) do | params, _, _ | - expect(params).to eq expected_params - command_result - end - subject - end + expect(broker).to receive(:run_webhook_commands).with("http://webhook") - it "calls PactBroker::Client::Webhooks::Create with pact broker details" do - expect(PactBroker::Client::Webhooks::Create).to receive(:call) do | _, broker_base_url, pact_broker_client_options | - expect(broker_base_url).to eq "http://broker" - expect(pact_broker_client_options).to eq(basic_auth: { username: "username", password: "password"}, token: "token", verbose: true) - command_result - end subject end - - context "when neither event type is selected" do - before do - options_hash.delete(:contract_content_changed) - broker.options = OpenStruct.new(options_hash) - end - - it "raises an error" do - expect { subject }.to raise_error PactBroker::Client::Error, /You must select at least one/ - end - end - - context "with no basic auth" do - before do - options_hash.delete(:broker_username) - options_hash.delete(:broker_password) - broker.options = OpenStruct.new(options_hash) - end - - it "calls Webhooks::Create without basic auth" do - expect(PactBroker::Client::Webhooks::Create).to receive(:call) do | _, _, pact_broker_client_options | - expect(pact_broker_client_options).to eq(token: "token", verbose: true) - command_result - end - subject - end - end - - context "when there are no headers specified" do - let(:header) { nil } - - it "calls Webhooks::Create with an empty hash of headers" do - expect(PactBroker::Client::Webhooks::Create).to receive(:call) do | params, _, _ | - expect(params[:headers]).to eq({}) - command_result - end - subject - end - end - - context "when data is nil" do - let(:data) { nil } - - it "alls Webhooks::Create with a nil body" do - expect(PactBroker::Client::Webhooks::Create).to receive(:call) do | params, _, _ | - expect(params[:body]).to be nil - command_result - end - subject - end - end - - context "when a file reference is passed for the data" do - before do - FileUtils.mkdir_p "tmp" - File.open("tmp/body.json", "w") { |file| file << "file" } - end - - let(:data) { "@tmp/body.json" } - - it "reads the file and passes it in to the Webhooks::Create call" do - expect(PactBroker::Client::Webhooks::Create).to receive(:call) do | params, _, _ | - expect(params[:body]).to eq "file" - command_result - end - subject - end - - context "when the file is not found" do - - let(:data) { "@doesnotexist.json" } - - it "raises a PactBroker::Client::Error" do - expect { subject }.to raise_error PactBroker::Client::Error, /Couldn't read data from file/ - end - end - - context "when successful" do - it "prints the message to stdout" do - expect($stdout).to receive(:puts).with('message') - subject - end - end - - context "when not successful" do - let(:success) { false } - - it "prints the message to stderr" do - expect($stdout).to receive(:puts).with('message') - begin - subject - rescue SystemExit - end - end - - it "exits with code 1" do - exited_with_error = false - begin - subject - rescue SystemExit - exited_with_error = true - end - expect(exited_with_error).to be true - end - end - - context "when a PactBroker::Client::Error is raised" do - before do - allow(PactBroker::Client::Webhooks::Create).to receive(:call).and_raise(PactBroker::Client::Error, "foo") - end - - it "raises a WebhookCreationError which does not show an ugly stack trace" do - expect { subject }.to raise_error(WebhookCreationError, /foo/) - end - end - end end end end diff --git a/spec/lib/pact_broker/client/cli/broker_run_webhook_commands_spec.rb b/spec/lib/pact_broker/client/cli/broker_run_webhook_commands_spec.rb new file mode 100644 index 00000000..e9b7bdf7 --- /dev/null +++ b/spec/lib/pact_broker/client/cli/broker_run_webhook_commands_spec.rb @@ -0,0 +1,210 @@ +require 'pact_broker/client/cli/broker' +require 'pact_broker/client/webhooks/create' + +module PactBroker + module Client + module CLI + describe Broker do + describe "run_webhook_commands" do + before do + allow($stdout).to receive(:puts) + allow(PactBroker::Client::Webhooks::Create).to receive(:call).and_return(command_result) + broker.options = OpenStruct.new(options_hash) + end + + let(:broker) { Broker.new } + let(:data) { 'data' } + let(:user) { "username:password" } + let(:command_result) { double('command result', success: success, message: 'message') } + let(:success) { true } + let(:header) { ["Foo: bar", "Bar: foo"] } + + let(:options_hash) do + { + uuid: '9999', + request: "POST", + header: header, + data: data, + user: user, + consumer: "consumer", + provider: "provider", + broker_base_url: "http://broker", + broker_username: "username", + broker_password: "password", + broker_token: "token", + contract_content_changed: true, + verbose: true + } + end + + let(:expected_params) do + { + uuid: '9999', + http_method: "POST", + url: "http://webhook", + headers: { "Foo" => "bar", "Bar" => "foo"}, + username: "username", + password: "password", + body: "data", + consumer: "consumer", + provider: "provider", + events: ["contract_content_changed"] + }.tap { |it| Pact::Fixture.add_fixture(:create_webhook_params, it) } + end + + subject { broker.run_webhook_commands "http://webhook" } + + it "calls PactBroker::Client::Webhooks::Create with the webhook params" do + expect(PactBroker::Client::Webhooks::Create).to receive(:call) do | params, _, _ | + expect(params).to eq expected_params + command_result + end + subject + end + + it "calls PactBroker::Client::Webhooks::Create with pact broker details" do + expect(PactBroker::Client::Webhooks::Create).to receive(:call) do | _, broker_base_url, pact_broker_client_options | + expect(broker_base_url).to eq "http://broker" + expect(pact_broker_client_options).to eq(basic_auth: { username: "username", password: "password"}, token: "token", verbose: true) + command_result + end + subject + end + + context "when neither event type is selected" do + before do + options_hash.delete(:contract_content_changed) + broker.options = OpenStruct.new(options_hash) + end + + it "raises an error" do + expect { subject }.to raise_error PactBroker::Client::Error, /You must select at least one/ + end + end + + context "with no basic auth" do + before do + options_hash.delete(:broker_username) + options_hash.delete(:broker_password) + broker.options = OpenStruct.new(options_hash) + end + + it "calls Webhooks::Create without basic auth" do + expect(PactBroker::Client::Webhooks::Create).to receive(:call) do | _, _, pact_broker_client_options | + expect(pact_broker_client_options).to eq(token: "token", verbose: true) + command_result + end + subject + end + end + + context "when there are no headers specified" do + let(:header) { nil } + + it "calls Webhooks::Create with an empty hash of headers" do + expect(PactBroker::Client::Webhooks::Create).to receive(:call) do | params, _, _ | + expect(params[:headers]).to eq({}) + command_result + end + subject + end + end + + context "when data is nil" do + let(:data) { nil } + + it "alls Webhooks::Create with a nil body" do + expect(PactBroker::Client::Webhooks::Create).to receive(:call) do | params, _, _ | + expect(params[:body]).to be nil + command_result + end + subject + end + end + + context "when a uuid is provided" do + before do + options_hash.merge!(uuid: '9999') + expected_params.merge!(uuid: '9999') + + broker.options = OpenStruct.new(options_hash) + end + + it "calls PactBroker::Client::Webhooks::Create with uuid in params" do + expect(PactBroker::Client::Webhooks::Create).to receive(:call) do | params, _, _ | + expect(params).to eq expected_params + command_result + end + subject + end + end + + context "when a file reference is passed for the data" do + before do + FileUtils.mkdir_p "tmp" + File.open("tmp/body.json", "w") { |file| file << "file" } + end + + let(:data) { "@tmp/body.json" } + + it "reads the file and passes it in to the Webhooks::Create call" do + expect(PactBroker::Client::Webhooks::Create).to receive(:call) do | params, _, _ | + expect(params[:body]).to eq "file" + command_result + end + subject + end + + context "when the file is not found" do + + let(:data) { "@doesnotexist.json" } + + it "raises a PactBroker::Client::Error" do + expect { subject }.to raise_error PactBroker::Client::Error, /Couldn't read data from file/ + end + end + + context "when successful" do + it "prints the message to stdout" do + expect($stdout).to receive(:puts).with('message') + subject + end + end + + context "when not successful" do + let(:success) { false } + + it "prints the message to stderr" do + expect($stdout).to receive(:puts).with('message') + begin + subject + rescue SystemExit + end + end + + it "exits with code 1" do + exited_with_error = false + begin + subject + rescue SystemExit + exited_with_error = true + end + expect(exited_with_error).to be true + end + end + + context "when a PactBroker::Client::Error is raised" do + before do + allow(PactBroker::Client::Webhooks::Create).to receive(:call).and_raise(PactBroker::Client::Error, "foo") + end + + it "raises a WebhookCreationError which does not show an ugly stack trace" do + expect { subject }.to raise_error(WebhookCreationError, /foo/) + end + end + end + end + end + end + end +end diff --git a/spec/pacts/pact_broker_client-pact_broker.json b/spec/pacts/pact_broker_client-pact_broker.json index f1bbcae5..05aa9db8 100644 --- a/spec/pacts/pact_broker_client-pact_broker.json +++ b/spec/pacts/pact_broker_client-pact_broker.json @@ -1701,6 +1701,97 @@ } } } + }, + { + "description": "a request for the index resource with the webhook relation", + "request": { + "method": "get", + "path": "/", + "headers": { + "Accept": "application/hal+json" + } + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/hal+json;charset=utf-8" + }, + "body": { + "_links": { + "pb:webhook": { + "href": "http://localhost:1234/webhooks/{uuid}", + "templated": true + } + } + }, + "matchingRules": { + "$.body._links.pb:webhook.href": { + "match": "regex", + "regex": "http:\\/\\/.*\\/webhooks\\/{uuid}" + } + } + } + }, + { + "description": "a request to create a webhook with a JSON body and a uuid", + "providerState": "the 'Pricing Service' and 'Condor' already exist in the pact-broker", + "request": { + "method": "put", + "path": "/webhooks/9999", + "headers": { + "Content-Type": "application/json", + "Accept": "application/hal+json" + }, + "body": { + "events": [ + { + "name": "contract_content_changed" + } + ], + "request": { + "url": "https://webhook", + "method": "POST", + "headers": { + "Foo": "bar", + "Bar": "foo" + }, + "body": { + "some": "body" + }, + "username": "username", + "password": "password" + }, + "provider": { + "name": "Pricing Service" + }, + "consumer": { + "name": "Condor" + } + } + }, + "response": { + "status": 201, + "headers": { + "Content-Type": "application/hal+json;charset=utf-8" + }, + "body": { + "_links": { + "self": { + "href": "http://localhost:1234/some-url", + "title": "A title" + } + } + }, + "matchingRules": { + "$.body._links.self.href": { + "match": "regex", + "regex": "http:\\/\\/.*" + }, + "$.body._links.self.title": { + "match": "type" + } + } + } } ], "metadata": { diff --git a/spec/service_providers/pact_helper.rb b/spec/service_providers/pact_helper.rb index 0abed329..6048de5d 100644 --- a/spec/service_providers/pact_helper.rb +++ b/spec/service_providers/pact_helper.rb @@ -63,4 +63,25 @@ def mock_pact_broker_index(context) } ) end + + def mock_pact_broker_index_with_webhook_relation(context) + pact_broker + .upon_receiving("a request for the index resource with the webhook relation") + .with( + method: :get, + path: '/', + headers: context.get_request_headers). + will_respond_with( + status: 200, + headers: context.pact_broker_response_headers, + body: { + _links: { + :'pb:webhook' => { + href: Pact.term(pact_broker.mock_service_base_url + "/webhooks/{uuid}", %r{http://.*/webhooks/{uuid}}), + templated: true + } + } + } + ) + end end diff --git a/spec/service_providers/webhooks_create_spec.rb b/spec/service_providers/webhooks_create_spec.rb index 8f45cd7a..d0831004 100644 --- a/spec/service_providers/webhooks_create_spec.rb +++ b/spec/service_providers/webhooks_create_spec.rb @@ -252,4 +252,29 @@ expect(subject.success).to be true end end + + context "when a uuid is specified" do + before do + params.merge!(uuid: '9999') + request_body["provider"] = { "name" => "Pricing Service" } + request_body["consumer"] = { "name" => "Condor" } + mock_pact_broker_index_with_webhook_relation(self) + + pact_broker + .upon_receiving("a request to create a webhook with a JSON body and a uuid") + .given("the 'Pricing Service' and 'Condor' already exist in the pact-broker") + .with( + method: :put, + path: '/webhooks/9999', + headers: put_request_headers, + body: request_body) + .will_respond_with(success_response) + end + + it "returns a CommandResult with success = true" do + expect(subject).to be_a PactBroker::Client::CommandResult + expect(subject.success).to be true + expect(subject.message).to eq "Webhook \"A title\" created" + end + end end