diff --git a/lib/cucumber/formatter/message_builder.rb b/lib/cucumber/formatter/message_builder.rb index 7285083e5..7c424c54c 100644 --- a/lib/cucumber/formatter/message_builder.rb +++ b/lib/cucumber/formatter/message_builder.rb @@ -9,6 +9,8 @@ require 'cucumber/formatter/query/test_case_started_by_test_case' require 'cucumber/formatter/query/test_run_started' +require 'cucumber/query' + module Cucumber module Formatter class MessageBuilder @@ -39,6 +41,8 @@ def initialize(config) @current_test_run_started_id = nil @current_test_case_started_id = nil @current_test_step_id = nil + + @query = Cucumber::Query.new end def output_message @@ -272,6 +276,7 @@ def on_undefined_parameter_type(event) end def test_case_started_id(test_case) + # a = @query.instance_variable_get(:@test_case_started_by_id) @test_case_started_by_test_case.test_case_started_id_by_test_case(test_case) end end diff --git a/lib/cucumber/formatter/new_rerun.rb b/lib/cucumber/formatter/new_rerun.rb new file mode 100644 index 000000000..77d125dc1 --- /dev/null +++ b/lib/cucumber/formatter/new_rerun.rb @@ -0,0 +1,67 @@ +# frozen_string_literal: true + +require 'cucumber/formatter/io' +require 'cucumber/query' +require 'cucumber/formatter/message_builder' + +module Cucumber + module Formatter + class NewRerun < MessageBuilder + include Formatter::Io + + def initialize(config) + @io = ensure_io(config.out_stream, config.error_stream) + + # Old implementation + + @failures = {} + # config.on_event :test_case_finished do |event| + # test_case, result = *event.attributes + # if @config.strict.strict?(:flaky) + # next if result.ok?(strict: @config.strict) + # + # add_to_failures(test_case) + # else + # unless @latest_failed_test_case.nil? + # if @latest_failed_test_case != test_case + # add_to_failures(@latest_failed_test_case) + # @latest_failed_test_case = nil + # elsif result.ok?(strict: @config.strict) + # @latest_failed_test_case = nil + # end + # end + # @latest_failed_test_case = test_case unless result.ok?(strict: @config.strict) + # end + # end + # config.on_event :test_run_finished do + # add_to_failures(@latest_failed_test_case) unless @latest_failed_test_case.nil? + # next if @failures.empty? + # + # @io.print file_failures.join("\n") + # end + + # End of old implementation + + super(config) + end + + def output_envelope(envelope) + @io.write(envelope.to_json) + @io.write("\n") + @query.update(envelope) + end + + private + + def file_failures + @failures.map { |file, lines| [file, lines].join(':') } + end + + def add_to_failures(test_case) + location = test_case.location + @failures[location.file] ||= [] + @failures[location.file] << location.lines.max unless @failures[location.file].include?(location.lines.max) + end + end + end +end diff --git a/lib/cucumber/query.rb b/lib/cucumber/query.rb new file mode 100644 index 000000000..0099ec00d --- /dev/null +++ b/lib/cucumber/query.rb @@ -0,0 +1,145 @@ +module Cucumber + class Query + attr_reader :attachments_by_test_case_started_id, + :attachments_by_test_case_finished_id, + :hooks_by_id, + :lineage_by_id, + :meta, + :pickle_by_id, + :pickle_step_by_id, + :pickle_step_id_by_test_step_id, + :step_by_id, + :step_definition_by_id, + :step_matches_by_test_step_id, + :test_case_by_id, + :test_case_by_pickle_id, + :test_case_finished_by_test_case_started_id, + :test_case_started_by_id, + :test_run_started, + :test_run_finished, + :test_step_finished_by_test_case_started_id, + :test_step_ids_by_pickle_step_id, + :test_step_result_by_pickle_id, + :test_step_results_by_pickle_step_id, + :test_step_results_by_test_step_id, + :test_step_started_by_test_case_started_id + + def initialize + @attachments_by_test_case_started_id = [[]] + @attachments_by_test_step_id = [] + @hooks_by_id = {} + @lineage_by_id = [] + @meta = :not_sure_on_this + @pickle_by_id = [] + @pickle_id_by_test_step_id = [] + @pickle_step_by_id = [] + @pickle_step_id_by_test_step_id = [] + @step_by_id = [] + @step_definition_by_id = {} + @step_match_arguments_lists_by_pickle_step_id = [{}] + @test_case_by_id = {} # Should be working + @test_case_by_pickle_id = [] + @test_case_finished_by_test_case_started_id = [[]] + @test_case_started_by_id = {} # Should be working + @test_run_started = :not_sure_on_this + @test_run_finished = :not_sure_on_this + @test_step_finished_by_test_case_started_id = {} # Should be working + @test_step_ids_by_pickle_step_id = [{}] + @test_step_result_by_pickle_id = [{}] + @test_step_results_by_pickle_step_id = [[]] + @test_step_results_by_test_step_id = [[]] + @test_step_started_by_test_case_started_id = [[]] + end + + # FIRST TWO THINGS TO FIX + # Use query to establish + # 1) `on_test_step_started` - Establish what the TestStepStarted message property is for `test_case_started_id` is + # 2) `on_test_step_finished` - Establish what the TestStepFinished message property is for `test_case_started_id` is + def update(envelope) + return @meta = envelope.meta if envelope.meta + return update_gherkin_document(envelope.gherkin_document) if envelope.gherkin_document + return update_pickle(envelope.pickle) if envelope.gherkin_document + return @hooks_by_id[envelope.hook.id] = envelope.hook if envelope.hook + return @step_definition_by_id[envelope.step_definition.id] = envelope.step_definition if envelope.step_definition + return @test_run_started = envelope.test_run_started if envelope.test_run_started + return update_test_case(envelope.test_case) if envelope.test_case + return update_test_case_started(envelope.test_case_started) if envelope.test_case_started + return update_test_step_started(envelope.test_step_started) if envelope.test_step_started + return update_attachment(envelope.attachment) if envelope.attachment + return update_test_step_finished(envelope.test_step_finished) if envelope.test_step_finished + return update_test_case_finished(envelope.test_case_finished) if envelope.test_case_finished + @test_run_finished = envelope.test_run_finished if envelope.test_run_finished + end + + private + + def update_gherkin_document(gherkin_document) + :not_yet_implemented + end + + def update_pickle(pickle) + :not_yet_implemented + end + + def update_test_case(test_case) + @test_case_by_id[test_case.id] = test_case + + # NOT YET IMPLEMENTED THE BELOW - NEXT STEPS from javascript implementation + # this.testCaseByPickleId.set(testCase.pickleId, testCase) + # testCase.testSteps.forEach((testStep) => { + # this.testStepById.set(testStep.id, testStep) + # this.pickleIdByTestStepId.set(testStep.id, testCase.pickleId) + # this.pickleStepIdByTestStepId.set(testStep.id, testStep.pickleStepId) + # this.testStepIdsByPickleStepId.put(testStep.pickleStepId, testStep.id) + # this.stepMatchArgumentsListsByPickleStepId.set( + # testStep.pickleStepId, + # testStep.stepMatchArgumentsLists + # ) + # }) + end + + def update_test_case_started(test_case_started) + @test_case_started_by_id[test_case_started.id] = test_case_started + + # NOT YET IMPLEMENTED THE BELOW - NEXT STEPS from javascript implementation + # /* + # when a test case attempt starts besides the first one, clear all existing results + # and attachments for that test case, so we always report on the latest attempt + # (applies to legacy pickle-oriented query methods only) + # */ + # const testCase = this.testCaseById.get(testCaseStarted.testCaseId) + # if (testCase) { + # this.testStepResultByPickleId.delete(testCase.pickleId) + # for (const testStep of testCase.testSteps) { + # this.testStepResultsByPickleStepId.delete(testStep.pickleStepId) + # this.testStepResultsbyTestStepId.delete(testStep.id) + # this.attachmentsByTestStepId.delete(testStep.id) + # } + # } + end + + def update_test_step_started(test_step_started) + :not_yet_implemented + end + + def update_attachment(attachment) + :not_yet_implemented + end + + def update_test_step_finished(test_step_finished) + @test_step_finished_by_test_case_started_id[test_step_finished.test_case_started_id] = test_step_finished + + # NOT YET IMPLEMENTED THE BELOW - NEXT STEPS from javascript implementation + # const pickleId = this.pickleIdByTestStepId.get(testStepFinished.testStepId) + # this.testStepResultByPickleId.put(pickleId, testStepFinished.testStepResult) + # const testStep = this.testStepById.get(testStepFinished.testStepId) + # this.testStepResultsByPickleStepId.put(testStep.pickleStepId, testStepFinished.testStepResult) + # this.testStepResultsbyTestStepId.put(testStep.id, testStepFinished.testStepResult) + # } + end + + def update_test_case_finished(test_case_finished) + :not_yet_implemented + end + end +end diff --git a/spec/cucumber/formatter/rerun_spec.rb b/spec/cucumber/formatter/rerun_spec.rb index a4ffb226d..109084702 100644 --- a/spec/cucumber/formatter/rerun_spec.rb +++ b/spec/cucumber/formatter/rerun_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'cucumber/formatter/rerun' +require 'cucumber/formatter/new_rerun' require 'cucumber/core' require 'cucumber/core/gherkin/writer' require 'support/standard_step_actions' @@ -9,7 +9,7 @@ module Cucumber module Formatter - describe Rerun do + describe NewRerun do include Cucumber::Core::Gherkin::Writer include Cucumber::Core @@ -34,6 +34,7 @@ module Formatter end end end + described_class.new(config) execute [gherkin], [StandardStepActions.new], config.event_bus config.event_bus.test_run_finished