diff --git a/lib/pact/cli.rb b/lib/pact/cli.rb index 4f261b5c..3038f53a 100755 --- a/lib/pact/cli.rb +++ b/lib/pact/cli.rb @@ -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." diff --git a/lib/pact/cli/spec_criteria.rb b/lib/pact/cli/spec_criteria.rb index f9b84a2e..b2212af6 100644 --- a/lib/pact/cli/spec_criteria.rb +++ b/lib/pact/cli/spec_criteria.rb @@ -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 diff --git a/lib/pact/provider/rspec/formatter_rspec_3.rb b/lib/pact/provider/rspec/formatter_rspec_3.rb index 9d4b7192..0ae3134e 100644 --- a/lib/pact/provider/rspec/formatter_rspec_3.rb +++ b/lib/pact/provider/rspec/formatter_rspec_3.rb @@ -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!("", example.metadata[:pactfile_uri].to_s) + cmd.gsub!("", "#{_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!("", pactfile_uri.to_s) cmd.gsub!("", description) cmd.gsub!("", "#{provider_state}") + cmd.gsub!("", "#{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 diff --git a/lib/pact/tasks/task_helper.rb b/lib/pact/tasks/task_helper.rb index 1daaab0a..3f533d54 100644 --- a/lib/pact/tasks/task_helper.rb +++ b/lib/pact/tasks/task_helper.rb @@ -7,6 +7,7 @@ module Pact module TaskHelper PACT_INTERACTION_RERUN_COMMAND = "bundle exec rake pact:verify:at[] PACT_DESCRIPTION=\"\" PACT_PROVIDER_STATE=\"\"" + PACT_INTERACTION_RERUN_COMMAND_FOR_BROKER = "bundle exec rake pact:verify:at[] PACT_BROKER_INTERACTION_ID=\"\"" extend self @@ -34,6 +35,8 @@ 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 @@ -41,7 +44,9 @@ 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 diff --git a/spec/lib/pact/cli/spec_criteria_spec.rb b/spec/lib/pact/cli/spec_criteria_spec.rb index c9bcb214..9ba242fe 100644 --- a/spec/lib/pact/cli/spec_criteria_spec.rb +++ b/spec/lib/pact/cli/spec_criteria_spec.rb @@ -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 @@ -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 diff --git a/spec/lib/pact/provider/rspec/formatter_rspec_3_spec.rb b/spec/lib/pact/provider/rspec/formatter_rspec_3_spec.rb index 643e3dc1..3194335d 100644 --- a/spec/lib/pact/provider/rspec/formatter_rspec_3_spec.rb +++ b/spec/lib/pact/provider/rspec/formatter_rspec_3_spec.rb @@ -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 } @@ -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 } @@ -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) @@ -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