<commit_before># frozen_string_literal: true

module RubyEventStore
  module RSpec
    class HavePublished
      class CrudeFailureMessageFormatter
        def initialize(differ)
          @differ = differ
        end

        def failure_message(_matcher, expected, events, _expected_count, _strict)
          "expected #{expected} to be published, diff:" +
            differ.diff_as_string(expected.to_s, events.to_a.to_s)
        end

        def negated_failure_message(_matcher, expected, events, _expected_count, _strict)
          "expected #{expected} not to be published, diff:" +
            differ.diff_as_string(expected.to_s, events.to_a.to_s)
        end

        private
        attr_reader :differ
      end

      class StepByStepFailureMessageFormatter
        def initialize(differ)
          @differ = differ
          @fallback = CrudeFailureMessageFormatter.new(differ)
        end

        def failure_message(_matcher, expected, events, expected_count, strict)
          return fallback.failure_message(_matcher, expected, events, expected_count, strict) if strict
          expected.each do |expected_event|
            correct_event_count = 0
            event_with_correct_type = nil
            events.each do |actual_event|
              if expected_event.matches?(actual_event)
                correct_event_count += 1
              elsif BeEvent::KindMatcher.new(expected_event.expected).matches?(actual_event)
                event_with_correct_type = actual_event
              end
            end

            if expected_count && correct_event_count >= 1 && correct_event_count != expected_count
              return <<~EOS
              expected event #{expected}
              to be published #{expected_count} times
              but was published #{correct_event_count} times
              EOS
            elsif event_with_correct_type
              return <<~EOS
              expected event #{expected}
              to be published, but it was not published

              there is an event of correct type but with incorrect payload:
              #{data_diff(expected_event, event_with_correct_type)}#{metadata_diff(expected_event, event_with_correct_type)}
              EOS
            elsif correct_event_count.zero?
              return <<~EOS
              expected event #{expected}
              to be published, but there is no event with such type
              EOS
            end
          end
        end

        def negated_failure_message(_matcher, expected, events, expected_count, strict)
          return fallback.negated_failure_message(_matcher, expected, events, expected_count, strict) if strict
          "expected #{expected} not to be published, diff:" +
            differ.diff_as_string(expected.to_s, events.to_a.to_s)
        end

        private
        attr_reader :differ, :fallback

        def data_diff(expected_event, event_with_correct_type)
          if expected_event.expected_data.nil?
            ""
          else
            "data diff:#{differ.diff_as_object(expected_event.expected_data, event_with_correct_type.data)}"
          end<commit_msg>Extract texts to separate methods<commit_after># frozen_string_literal: true

module RubyEventStore
  module RSpec
    class HavePublished
      class CrudeFailureMessageFormatter
        def initialize(differ)
          @differ = differ
        end

        def failure_message(_matcher, expected, events, _expected_count, _strict)
          "expected #{expected} to be published, diff:" +
            differ.diff_as_string(expected.to_s, events.to_a.to_s)
        end

        def negated_failure_message(_matcher, expected, events, _expected_count, _strict)
          "expected #{expected} not to be published, diff:" +
            differ.diff_as_string(expected.to_s, events.to_a.to_s)
        end

        private
        attr_reader :differ
      end

      class StepByStepFailureMessageFormatter
        def initialize(differ)
          @differ = differ
          @fallback = CrudeFailureMessageFormatter.new(differ)
        end

        def failure_message(_matcher, expected, events, expected_count, strict)
          return fallback.failure_message(_matcher, expected, events, expected_count, strict) if strict
          expected.each do |expected_event|
            correct_event_count = 0
            event_with_correct_type = nil
            events.each do |actual_event|
              if expected_event.matches?(actual_event)
                correct_event_count += 1
              elsif BeEvent::KindMatcher.new(expected_event.expected).matches?(actual_event)
                event_with_correct_type = actual_event
              end
            end

            if expected_count && correct_event_count >= 1 && correct_event_count != expected_count
              return failure_message_incorrect_count(expected, expected_count, correct_event_count)
            elsif event_with_correct_type
              return failure_message_correct_type_incorrect_payload(expected, expected_event, event_with_correct_type)
            elsif correct_event_count.zero?
              return failure_message_incorrect_type(expected)
            end
          end
        end

        def negated_failure_message(_matcher, expected, events, expected_count, strict)
          return fallback.negated_failure_message(_matcher, expected, events, expected_count, strict) if strict
          "expected #{expected} not to be published, diff:" +
            differ.diff_as_string(expected.to_s, events.to_a.to_s)
        end

        private
        attr_reader :differ, :fallback

        def failure_message_incorrect_count(expected, expected_count, correct_event_count)
          return <<~EOS
          expected event #{expected}
          to be published #{expected_count} times
          but was published #{correct_event_count} times
          EOS
        end

        def failure_message_correct_type_incorrect_payload(expected, expected_event, event_with_correct_type)
          return <<~EOS
          expected event #{expected}
          to be published, but it was not published

          there is an event of correct type but with incorrect payload:
          #{data_diff(expected_event, event_with_correct_type)}#{metadata_diff(expected_event, event_with_correct_type)}
          EOS
        end

        def failure_message_incorrect_type(expected)
          return <<~EOS
          expected event #{expected}
          to be published, but there is no event with such type
          EOS
        end

        def data_diff(expected_event, event_with_correct_type)
          if expected_event.expected_data.nil?
            ""
          else
            "data diff:#{differ.diff_as_object(expected_event.expected_data, event_with_correct_type.data)}"
          end
{'fraction_non_alphanumeric': 0.06143445032333921, 'fraction_numerical': 0.0008818342151675485, 'mean_word_length': 2.3406971035837016, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6720919', 'n_tokens_mistral': 1785, 'n_tokens_neox': 1764, 'n_words': 438}