Skip to content

Commit

Permalink
feat: allow individual interactions to be re-run by setting PACT_BROK…
Browse files Browse the repository at this point in the history
…ER_INTERACTION_ID
  • Loading branch information
bethesque committed Jun 24, 2020
1 parent 32af081 commit a586d80
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 24 deletions.
2 changes: 2 additions & 0 deletions lib/pact/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ class CLI < Thor
default: Pact.configuration.interactions_replay_order
method_option :description, aliases: "-d", desc: "Interaction description filter"
method_option :provider_state, aliases: "-s", desc: "Provider state filter"
method_option :interaction_index, type: :numeric, desc: "Index filter"
method_option :pact_broker_interaction_id, desc: "Pact Broker interaction ID filter"
method_option :format, aliases: "-f", banner: "FORMATTER", desc: "RSpec formatter. Defaults to custom Pact formatter. [j]son may also be used."
method_option :out, aliases: "-o", banner: "FILE", desc: "Write output to a file instead of $stdout."

Expand Down
3 changes: 3 additions & 0 deletions lib/pact/cli/spec_criteria.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ def self.call options
criteria = {}

criteria[:description] = Regexp.new(options[:description]) if options[:description]
criteria[:_id] = options[:pact_broker_interaction_id] if options[:pact_broker_interaction_id]
criteria[:index] = options[:interaction_index] if options[:interaction_index]

provider_state = options[:provider_state]

if provider_state
if provider_state.length == 0
criteria[:provider_state] = nil #Allow PACT_PROVIDER_STATE="" to mean no provider state
Expand Down
25 changes: 20 additions & 5 deletions lib/pact/provider/rspec/formatter_rspec_3.rb
Original file line number Diff line number Diff line change
Expand Up @@ -93,17 +93,32 @@ def interaction_rerun_commands summary

def interaction_rerun_command_for example
example_description = example.metadata[:pact_interaction_example_description]
if ENV['PACT_INTERACTION_RERUN_COMMAND']

_id = example.metadata[:pact_interaction]._id
index = example.metadata[:pact_interaction].index
provider_state = example.metadata[:pact_interaction].provider_state
description = example.metadata[:pact_interaction].description
pactfile_uri = example.metadata[:pactfile_uri]

if _id && ENV['PACT_INTERACTION_RERUN_COMMAND_FOR_BROKER']
cmd = String.new(ENV['PACT_INTERACTION_RERUN_COMMAND_FOR_BROKER'])
cmd.gsub!("<PACT_URI>", example.metadata[:pactfile_uri].to_s)
cmd.gsub!("<PACT_BROKER_INTERACTION_ID>", "#{_id}")
colorizer.wrap("#{cmd} ", ::RSpec.configuration.failure_color) + colorizer.wrap("# #{example_description}", ::RSpec.configuration.detail_color)
elsif ENV['PACT_INTERACTION_RERUN_COMMAND']
cmd = String.new(ENV['PACT_INTERACTION_RERUN_COMMAND'])
provider_state = example.metadata[:pact_interaction].provider_state
description = example.metadata[:pact_interaction].description
pactfile_uri = example.metadata[:pactfile_uri]
cmd.gsub!("<PACT_URI>", pactfile_uri.to_s)
cmd.gsub!("<PACT_DESCRIPTION>", description)
cmd.gsub!("<PACT_PROVIDER_STATE>", "#{provider_state}")
cmd.gsub!("<PACT_INTERACTION_INDEX>", "#{index}")
colorizer.wrap("#{cmd} ", ::RSpec.configuration.failure_color) + colorizer.wrap("# #{example_description}", ::RSpec.configuration.detail_color)
else
colorizer.wrap("* #{example_description}", ::RSpec.configuration.failure_color)
message = if _id
"* #{example_description} (to re-run just this interaction, set environment variable PACT_BROKER_INTERACTION_ID=\"#{_id}\")"
else
"* #{example_description} (to re-run just this interaction, set environment variables PACT_DESCRIPTION=\"#{description}\" PACT_PROVIDER_STATE=\"#{provider_state}\")"
end
colorizer.wrap(message, ::RSpec.configuration.failure_color)
end
end

Expand Down
7 changes: 6 additions & 1 deletion lib/pact/tasks/task_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ module Pact
module TaskHelper

PACT_INTERACTION_RERUN_COMMAND = "bundle exec rake pact:verify:at[<PACT_URI>] PACT_DESCRIPTION=\"<PACT_DESCRIPTION>\" PACT_PROVIDER_STATE=\"<PACT_PROVIDER_STATE>\""
PACT_INTERACTION_RERUN_COMMAND_FOR_BROKER = "bundle exec rake pact:verify:at[<PACT_URI>] PACT_BROKER_INTERACTION_ID=\"<PACT_BROKER_INTERACTION_ID>\""

extend self

Expand Down Expand Up @@ -34,14 +35,18 @@ def verify_command pact_helper, pact_uri, rspec_opts, verification_opts
command_parts << "--backtrace" if ENV['BACKTRACE'] == 'true'
command_parts << "--description #{Shellwords.escape(ENV['PACT_DESCRIPTION'])}" if ENV['PACT_DESCRIPTION']
command_parts << "--provider-state #{Shellwords.escape(ENV['PACT_PROVIDER_STATE'])}" if ENV['PACT_PROVIDER_STATE']
command_parts << "--pact-broker-interaction-id #{Shellwords.escape(ENV['PACT_BROKER_INTERACTION_ID'])}" if ENV['PACT_BROKER_INTERACTION_ID']
command_parts << "--interaction-index #{Shellwords.escape(ENV['PACT_INTERACTION_INDEX'])}" if ENV['PACT_INTERACTION_INDEX']
command_parts.flatten.join(" ")
end

def execute_cmd command
Pact.configuration.output_stream.puts command
temporarily_set_env_var 'PACT_EXECUTING_LANGUAGE', 'ruby' do
temporarily_set_env_var 'PACT_INTERACTION_RERUN_COMMAND', PACT_INTERACTION_RERUN_COMMAND do
exit_status = system(command) ? 0 : 1
temporarily_set_env_var 'PACT_INTERACTION_RERUN_COMMAND_FOR_BROKER', PACT_INTERACTION_RERUN_COMMAND_FOR_BROKER do
exit_status = system(command) ? 0 : 1
end
end
end
end
Expand Down
30 changes: 18 additions & 12 deletions spec/lib/pact/cli/spec_criteria_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,41 @@
module Pact
module Cli
describe SpecCriteria do

describe "#spec_criteria" do

let(:env_description) { "pact description set in ENV"}
let(:env_provider_state) { "provider state set in ENV"}
let(:env_criteria){ {:description=>/#{env_description}/, :provider_state=>/#{env_provider_state}/} }
let(:env_pact_broker_interaction_id) { "interaction id set in ENV" }
let(:interaction_index) { 2 }
let(:env_criteria) do
{
:description=>/#{env_description}/,
:provider_state=>/#{env_provider_state}/,
:_id => env_pact_broker_interaction_id,
:index => interaction_index
}
end

let(:defaults) { {:description => default_description, :provider_state => default_provider_state} }

let(:subject) { Pact::App.new }

context "when options are defined" do
before do

allow(ENV).to receive(:[])
allow(ENV).to receive(:[]).with("PACT_DESCRIPTION").and_return(env_description)
allow(ENV).to receive(:[]).with("PACT_PROVIDER_STATE").and_return(env_provider_state)
let(:options) do
{
description: env_description,
provider_state: env_provider_state,
pact_broker_interaction_id: env_pact_broker_interaction_id,
interaction_index: interaction_index
}
end

let(:options) { {description: env_description, provider_state: env_provider_state} }

it "returns the env vars as regexes" do
expect(Pact::Cli::SpecCriteria.call(options)).to eq(env_criteria)
end
end

context "when ENV variables are not defined" do

let(:options) { {} }

it "returns an empty hash" do
Expand All @@ -39,8 +46,7 @@ module Cli
end

context "when provider state is an empty string" do

let(:options) { {provider_state: ''} }
let(:options) { { provider_state: '' } }

it "returns a nil provider state so that it matches a nil provider state on the interaction" do
expect(Pact::Cli::SpecCriteria.call(options)[:provider_state]).to be_nil
Expand Down
47 changes: 41 additions & 6 deletions spec/lib/pact/provider/rspec/formatter_rspec_3_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ module Provider
module RSpec
describe Formatter do

let(:interaction) { InteractionFactory.create 'provider_state' => 'a state', 'description' => 'a description'}
let(:interaction) { InteractionFactory.create 'provider_state' => 'a state', 'description' => 'a description', '_id' => id, 'index' => 2 }
let(:id) { nil }
let(:pactfile_uri) { 'pact_file_uri' }
let(:description) { 'an interaction' }
let(:pact_json) { {some: 'pact json'}.to_json }
Expand All @@ -29,11 +30,13 @@ module RSpec
let(:failed_examples) { [example, example] }
let(:examples) { [example, example, example_2]}
let(:output) { StringIO.new }
let(:rerun_command) { "rake pact:verify:at[pact_file_uri] PACT_DESCRIPTION=\"a description\" PACT_PROVIDER_STATE=\"a state\" # an interaction" }
let(:rerun_command) { 'PACT_DESCRIPTION="a description" PACT_PROVIDER_STATE="a state" # an interaction' }
let(:broker_rerun_command) { "rake pact:verify:at[pact_file_uri] PACT_BROKER_INTERACTION_ID=\"1234\" # an interaction" }
let(:missing_provider_states) { 'missing_provider_states'}
let(:summary) { double("summary", failure_count: 1, failed_examples: failed_examples, examples: examples)}
let(:pact_executing_language) { 'ruby' }
let(:pact_interaction_rerun_command) { Pact::TaskHelper::PACT_INTERACTION_RERUN_COMMAND }
let(:pact_interaction_rerun_command_for_broker) { Pact::TaskHelper::PACT_INTERACTION_RERUN_COMMAND_FOR_BROKER }
let(:ignore_failures) { nil }

subject { Formatter.new output }
Expand All @@ -43,6 +46,7 @@ module RSpec
before do
allow(ENV).to receive(:[]).with('PACT_INTERACTION_RERUN_COMMAND').and_return(pact_interaction_rerun_command)
allow(ENV).to receive(:[]).with('PACT_EXECUTING_LANGUAGE').and_return(pact_executing_language)
allow(ENV).to receive(:[]).with('PACT_INTERACTION_RERUN_COMMAND_FOR_BROKER').and_return(pact_interaction_rerun_command_for_broker)
allow(PrintMissingProviderStates).to receive(:call)
allow(Pact::Provider::Help::PromptText).to receive(:call).and_return("some help")
allow(subject).to receive(:failed_examples).and_return(failed_examples)
Expand All @@ -69,15 +73,46 @@ module RSpec
end
end

context "when PACT_INTERACTION_RERUN_COMMAND is not set" do
context "when PACT_INTERACTION_RERUN_COMMAND_FOR_BROKER is set" do
context "when the _id is populated" do
let(:id) { "1234" }

it "prints a list of rerun commands" do
expect(output_result).to include(broker_rerun_command)
end

it "only prints unique commands" do
expect(output_result.scan(broker_rerun_command).size).to eq 1
end
end

context "when the _id is not populated" do
it "prints a list of rerun commands using the provider state and description" do
expect(output_result).to include(rerun_command)
end
end
end

context "when PACT_INTERACTION_RERUN_COMMAND and PACT_INTERACTION_RERUN_COMMAND_FOR_BROKER are not set" do
let(:pact_interaction_rerun_command) { nil }
let(:pact_interaction_rerun_command_for_broker) { nil }

context "when the _id is populated" do
let(:id) { "1234" }

it "prints a list of failed interactions" do
expect(output_result).to include('* an interaction (to re-run just this interaction, set environment variable PACT_BROKER_INTERACTION_ID="1234")')
end
end

it "prints a list of failed interactions" do
expect(output_result).to include("* #{description}\n")
context "when the _id is not populated" do
it "prints a list of failed interactions" do
expect(output_result).to include('* an interaction (to re-run just this interaction, set environment variables PACT_DESCRIPTION="a description" PACT_PROVIDER_STATE="a state")')
end
end

it "only prints unique commands" do
expect(output_result.scan("* #{description}\n").size).to eq 1
expect(output_result.scan("* #{description}").size).to eq 1
end
end

Expand Down

0 comments on commit a586d80

Please sign in to comment.