From 89fe1c4311abcd73f02eec63d2a8ff121290f199 Mon Sep 17 00:00:00 2001 From: Honza2 Date: Mon, 24 Feb 2020 00:07:38 +0100 Subject: [PATCH] feat(generators): Pass provider state results back so we can use ProviderState generator --- .../set_up_provider_state.rb | 7 +- spec/integration_with_provider_state_spec.rb | 23 +++++++ ...p_provider_state_inject_parameters_spec.rb | 67 +++++++++++++++++++ .../pacts/pact-with-provider-state.json | 42 ++++++++++++ spec/support/provider_with_state_generator.rb | 19 ++++++ 5 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 spec/integration_with_provider_state_spec.rb create mode 100644 spec/lib/pact/provider_verifier/set_up_provider_state_inject_parameters_spec.rb create mode 100644 spec/support/pacts/pact-with-provider-state.json create mode 100644 spec/support/provider_with_state_generator.rb diff --git a/lib/pact/provider_verifier/set_up_provider_state.rb b/lib/pact/provider_verifier/set_up_provider_state.rb index 1674d18..0d33bf2 100644 --- a/lib/pact/provider_verifier/set_up_provider_state.rb +++ b/lib/pact/provider_verifier/set_up_provider_state.rb @@ -28,6 +28,11 @@ def call log_request response = post_to_provider_state check_for_error response + begin + JSON.parse(response.body) + rescue + {} + end end private @@ -49,11 +54,11 @@ def post_to_provider_state # https://github.com/pact-foundation/pact-go/issues/42 # eg. https://ci.appveyor.com/project/mefellows/pact-go/build/25#L1202 + faraday.request :retry, max: 2, interval: 0.05, interval_randomness: 0.5, backoff_factor: 2, methods:[:post], exceptions: [Faraday::ConnectionFailed] - faraday.response :logger if verbose faraday.adapter Faraday.default_adapter end diff --git a/spec/integration_with_provider_state_spec.rb b/spec/integration_with_provider_state_spec.rb new file mode 100644 index 0000000..a17e03c --- /dev/null +++ b/spec/integration_with_provider_state_spec.rb @@ -0,0 +1,23 @@ +require 'json' + +describe "pact-provider-verifier with a provider state injected to a pact file" do + before(:all) do + @pipe = IO.popen("bundle exec rackup -p 5837 spec/support/provider_with_state_generator.rb") + sleep 2 + end + + subject { `bundle exec bin/pact-provider-verifier spec/support/pacts/pact-with-provider-state.json -a 1 --provider-base-url http://localhost:5837/ --provider-states-setup-url http://localhost:5837/provider_state -v` } + + it "exits with a 0 exit code" do + subject + expect($?).to eq 0 + end + + it "the output contains a success message" do + expect(subject).to include "1 interaction, 0 failures" + end + + after(:all) do + Process.kill 'KILL', @pipe.pid + end +end diff --git a/spec/lib/pact/provider_verifier/set_up_provider_state_inject_parameters_spec.rb b/spec/lib/pact/provider_verifier/set_up_provider_state_inject_parameters_spec.rb new file mode 100644 index 0000000..4efea0c --- /dev/null +++ b/spec/lib/pact/provider_verifier/set_up_provider_state_inject_parameters_spec.rb @@ -0,0 +1,67 @@ +require 'pact/provider_verifier/set_up_provider_state' +require 'webmock/rspec' + +module Pact + module ProviderVerifier + + describe SetUpProviderState do + + let(:provider_states_setup_url) { 'http://foo' } + let(:provider_state) { 'some state' } + let(:consumer) { 'Foo' } + let(:options) { { params: params } } + let(:params) { { "foo" => "bar" }} + subject { SetUpProviderState.call(provider_state, consumer, options) } + + before do + ENV['PROVIDER_STATES_SETUP_URL'] = provider_states_setup_url + stub_request(:post, provider_states_setup_url) + allow($stdout).to receive(:puts) + allow($stderr).to receive(:puts) + end + + it "makes a HTTP request to the configured URL with a JSON body containing the consumer and provider state names" do + subject + expect(WebMock).to have_requested(:post, provider_states_setup_url). + with(body: {consumer: consumer, state: provider_state, states: [provider_state], params: params}, headers: {'Content-Type' => "application/json"}) + end + + context "when an error is returned from the request to the setup URL" do + before do + stub_request(:post, provider_states_setup_url).to_return(status: 500, body: "Some error") + end + + it "raises an error" do + expect { subject }.to raise_error(SetUpProviderStateError, /500.*Some error/) + end + end + + context "when the provider_states_setup_url is nil" do + before do + ENV['PROVIDER_STATES_SETUP_URL'] = nil + end + + it "does not make a HTTP request" do + subject + expect(WebMock).to_not have_requested(:post, provider_states_setup_url) + end + + context "when a provider_state is present" do + it "logs a warning" do + expect($stderr).to receive(:puts).with("WARN: Skipping set up for provider state 'some state' for consumer 'Foo' as there is no --provider-states-setup-url specified.") + subject + end + end + + context "when a provider_state is not present" do + let(:provider_state) { nil } + + it "does not log a warning" do + expect($stderr).to_not receive(:puts) + subject + end + end + end + end + end +end diff --git a/spec/support/pacts/pact-with-provider-state.json b/spec/support/pacts/pact-with-provider-state.json new file mode 100644 index 0000000..6049e28 --- /dev/null +++ b/spec/support/pacts/pact-with-provider-state.json @@ -0,0 +1,42 @@ +{ + "provider": { + "name": "Foo" + }, + "consumer": { + "name": "Bar" + }, + "interactions": [ + { + "description": "returns book detail", + "request": { + "method": "GET", + "path": "/book/1", + "generators": { + "path": { + "type": "ProviderState", + "expression": "/book/${id}" + } + } + }, + "response": { + "status": 200, + "body": { + "name": "Injected Book" + } + }, + "providerStates": [ + { + "name": "returns book detail" + } + ] + } + ], + "metadata": { + "pactSpecification": { + "version": "3.0.0" + }, + "pact-jvm": { + "version": "4.0.5" + } + } +} \ No newline at end of file diff --git a/spec/support/provider_with_state_generator.rb b/spec/support/provider_with_state_generator.rb new file mode 100644 index 0000000..71ab45a --- /dev/null +++ b/spec/support/provider_with_state_generator.rb @@ -0,0 +1,19 @@ +require 'sinatra' +require 'sinatra/base' +require 'sinatra/json' +require 'json' + +class ProviderWithStateGenerator < Sinatra::Base + post '/provider_state' do + json :id => 2 + end + + get '/book/1' do + json :id => 1, :name => 'Unexpected Book' + end + + get '/book/2' do + json :id => 2, :name => 'Injected Book' + end + +end