File: expecteds_for_multiple_diffs.rb

package info (click to toggle)
ruby-rspec 3.12.0c0e1m1s0-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 6,752 kB
  • sloc: ruby: 69,818; sh: 1,861; makefile: 99
file content (82 lines) | stat: -rw-r--r-- 2,622 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
module RSpec
  module Matchers
    # @api private
    # Handles list of expected values when there is a need to render
    # multiple diffs. Also can handle one value.
    class ExpectedsForMultipleDiffs
      # @private
      # Default diff label when there is only one matcher in diff
      # output
      DEFAULT_DIFF_LABEL = "Diff:".freeze

      # @private
      # Maximum readable matcher description length
      DESCRIPTION_MAX_LENGTH = 65

      def initialize(expected_list)
        @expected_list = expected_list
      end

      # @api private
      # Wraps provided expected value in instance of
      # ExpectedForMultipleDiffs. If provided value is already an
      # ExpectedForMultipleDiffs then it just returns it.
      # @param [Any] expected value to be wrapped
      # @return [RSpec::Matchers::ExpectedsForMultipleDiffs]
      def self.from(expected)
        return expected if self === expected
        new([[expected, DEFAULT_DIFF_LABEL]])
      end

      # @api private
      # Wraps provided matcher list in instance of
      # ExpectedForMultipleDiffs.
      # @param [Array<Any>] matchers list of matchers to wrap
      # @return [RSpec::Matchers::ExpectedsForMultipleDiffs]
      def self.for_many_matchers(matchers)
        new(matchers.map { |m| [m.expected, diff_label_for(m)] })
      end

      # @api private
      # Returns message with diff(s) appended for provided differ
      # factory and actual value if there are any
      # @param [String] message original failure message
      # @param [Proc] differ
      # @param [Any] actual value
      # @return [String]
      def message_with_diff(message, differ, actual)
        diff = diffs(differ, actual)
        message = "#{message}\n#{diff}" unless diff.empty?
        message
      end

    private

      class << self
        private

        def diff_label_for(matcher)
          "Diff for (#{truncated(RSpec::Support::ObjectFormatter.format(matcher))}):"
        end

        def truncated(description)
          return description if description.length <= DESCRIPTION_MAX_LENGTH
          description[0...DESCRIPTION_MAX_LENGTH - 3] << "..."
        end
      end

      def diffs(differ, actual)
        @expected_list.map do |(expected, diff_label)|
          diff = differ.diff(actual, expected)
          next if diff.strip.empty?
          if diff == "\e[0m\n\e[0m"
            "#{diff_label}\n" \
              "  <The diff is empty, are your objects producing identical `#inspect` output?>"
          else
            "#{diff_label}#{diff}"
          end
        end.compact.join("\n")
      end
    end
  end
end