class RSpec::Core::Formatters::ExceptionPresenter

@private

Constants

PENDING_DETAIL_FORMATTER

@private

Attributes

backtrace_formatter[R]
description[R]
detail_formatter[R]
example[R]
exception[R]
extra_detail_formatter[R]
message_color[R]

Public Class Methods

new(exception, example, options={}) click to toggle source
# File lib/rspec/core/formatters/exception_presenter.rb, line 13
def initialize(exception, example, options={})
  @exception               = exception
  @example                 = example
  @message_color           = options.fetch(:message_color)          { RSpec.configuration.failure_color }
  @description             = options.fetch(:description)            { example.full_description }
  @detail_formatter        = options.fetch(:detail_formatter)       { Proc.new {} }
  @extra_detail_formatter  = options.fetch(:extra_detail_formatter) { Proc.new {} }
  @backtrace_formatter     = options.fetch(:backtrace_formatter)    { RSpec.configuration.backtrace_formatter }
  @indentation             = options.fetch(:indentation, 2)
  @skip_shared_group_trace = options.fetch(:skip_shared_group_trace, false)
  @failure_lines           = options[:failure_lines]
end

Public Instance Methods

colorized_formatted_backtrace(colorizer=::RSpec::Core::Formatters::ConsoleCodes) click to toggle source
# File lib/rspec/core/formatters/exception_presenter.rb, line 68
def colorized_formatted_backtrace(colorizer=::RSpec::Core::Formatters::ConsoleCodes)
  formatted_backtrace.map do |backtrace_info|
    colorizer.wrap "# #{backtrace_info}", RSpec.configuration.detail_color
  end
end
colorized_message_lines(colorizer=::RSpec::Core::Formatters::ConsoleCodes) click to toggle source
# File lib/rspec/core/formatters/exception_presenter.rb, line 30
def colorized_message_lines(colorizer=::RSpec::Core::Formatters::ConsoleCodes)
  add_shared_group_lines(failure_lines, colorizer).map do |line|
    colorizer.wrap line, message_color
  end
end
formatted_backtrace(exception=@exception) click to toggle source
# File lib/rspec/core/formatters/exception_presenter.rb, line 36
def formatted_backtrace(exception=@exception)
  backtrace_formatter.format_backtrace(exception.backtrace, example.metadata) +
    formatted_cause(exception)
end
formatted_cause(exception) click to toggle source
# File lib/rspec/core/formatters/exception_presenter.rb, line 42
def formatted_cause(exception)
  last_cause = final_exception(exception)
  cause = []

  if exception.cause
    cause << '------------------'
    cause << '--- Caused by: ---'
    cause << "#{exception_class_name(last_cause)}:" unless exception_class_name(last_cause) =~ /RSpec/

    encoded_string(last_cause.message.to_s).split("\n").each do |line|
      cause << "  #{line}"
    end

    cause << ("  #{backtrace_formatter.format_backtrace(last_cause.backtrace, example.metadata).first}")
  end

  cause
end
fully_formatted(failure_number, colorizer=::RSpec::Core::Formatters::ConsoleCodes) click to toggle source
# File lib/rspec/core/formatters/exception_presenter.rb, line 74
def fully_formatted(failure_number, colorizer=::RSpec::Core::Formatters::ConsoleCodes)
  lines = fully_formatted_lines(failure_number, colorizer)
  lines.join("\n") << "\n"
end
fully_formatted_lines(failure_number, colorizer) click to toggle source
# File lib/rspec/core/formatters/exception_presenter.rb, line 79
def fully_formatted_lines(failure_number, colorizer)
  lines = [
    description,
    detail_formatter.call(example, colorizer),
    formatted_message_and_backtrace(colorizer),
    extra_detail_formatter.call(failure_number, colorizer),
  ].compact.flatten

  lines = indent_lines(lines, failure_number)
  lines.unshift("")
  lines
end
message_lines() click to toggle source
# File lib/rspec/core/formatters/exception_presenter.rb, line 26
def message_lines
  add_shared_group_lines(failure_lines, Notifications::NullColorizer)
end

Private Instance Methods

add_shared_group_lines(lines, colorizer) click to toggle source
# File lib/rspec/core/formatters/exception_presenter.rb, line 188
def add_shared_group_lines(lines, colorizer)
  return lines if @skip_shared_group_trace

  example.metadata[:shared_group_inclusion_backtrace].each do |frame|
    lines << colorizer.wrap(frame.description, RSpec.configuration.default_color)
  end

  lines
end
encoded_string(string) click to toggle source
# File lib/rspec/core/formatters/exception_presenter.rb, line 107
def encoded_string(string)
  RSpec::Support::EncodedString.new(string, Encoding.default_external)
end
encoding_of(string) click to toggle source
# File lib/rspec/core/formatters/exception_presenter.rb, line 103
def encoding_of(string)
  string.encoding
end
exception_backtrace() click to toggle source
# File lib/rspec/core/formatters/exception_presenter.rb, line 235
def exception_backtrace
  exception.backtrace || []
end
exception_class_name(exception=@exception) click to toggle source
# File lib/rspec/core/formatters/exception_presenter.rb, line 136
def exception_class_name(exception=@exception)
  name = exception.class.name.to_s
  name = "(anonymous error class)" if name == ''
  name
end
exception_lines() click to toggle source
# File lib/rspec/core/formatters/exception_presenter.rb, line 168
def exception_lines
  lines = []
  lines << "#{exception_class_name}:" unless exception_class_name =~ /RSpec/
  encoded_string(exception.message.to_s).split("\n").each do |line|
    lines << (line.empty? ? line : "  #{line}")
  end
  lines
end
extra_failure_lines() click to toggle source
# File lib/rspec/core/formatters/exception_presenter.rb, line 177
def extra_failure_lines
  @extra_failure_lines ||= begin
    lines = Array(example.metadata[:extra_failure_lines])
    unless lines.empty?
      lines.unshift('')
      lines.push('')
    end
    lines
  end
end
failure_lines() click to toggle source
# File lib/rspec/core/formatters/exception_presenter.rb, line 142
def failure_lines
  @failure_lines ||= [].tap do |lines|
    lines.concat(failure_slash_error_lines)

    sections = [failure_slash_error_lines, exception_lines]
    if sections.any? { |section| section.size > 1 } && !exception_lines.first.empty?
      lines << ''
    end

    lines.concat(exception_lines)
    lines.concat(extra_failure_lines)
  end
end
failure_slash_error_lines() click to toggle source
# File lib/rspec/core/formatters/exception_presenter.rb, line 156
def failure_slash_error_lines
  lines = read_failed_lines
  if lines.count == 1
    lines[0] = "Failure/Error: #{lines[0].strip}"
  else
    least_indentation = SnippetExtractor.least_indentation_from(lines)
    lines = lines.map { |line| line.sub(/^#{least_indentation}/, '  ') }
    lines.unshift('Failure/Error:')
  end
  lines
end
final_exception(exception) click to toggle source
# File lib/rspec/core/formatters/exception_presenter.rb, line 94
def final_exception(exception)
  if exception.cause
    final_exception(exception.cause)
  else
    exception
  end
end
find_failed_line() click to toggle source
# File lib/rspec/core/formatters/exception_presenter.rb, line 216
def find_failed_line
  line_regex = RSpec.configuration.in_project_source_dir_regex
  loaded_spec_files = RSpec.configuration.loaded_spec_files

  exception_backtrace.find do |line|
    next unless (line_path = line[/(.+?):(\d+)(|:\d+)/, 1])
    path = File.expand_path(line_path)
    loaded_spec_files.include?(path) || path =~ line_regex
  end || exception_backtrace.first
end
formatted_message_and_backtrace(colorizer) click to toggle source
# File lib/rspec/core/formatters/exception_presenter.rb, line 227
def formatted_message_and_backtrace(colorizer)
  lines = colorized_message_lines(colorizer) + colorized_formatted_backtrace(colorizer)
  encoding = encoding_of("")
  lines.map do |line|
    RSpec::Support::EncodedString.new(line, encoding)
  end
end
indent_lines(lines, failure_number) click to toggle source
# File lib/rspec/core/formatters/exception_presenter.rb, line 121
def indent_lines(lines, failure_number)
  alignment_basis = "#{' ' * @indentation}#{failure_number}) "
  indentation = ' ' * alignment_basis.length

  lines.each_with_index.map do |line, index|
    if index == 0
      "#{alignment_basis}#{line}"
    elsif line.empty?
      line
    else
      "#{indentation}#{line}"
    end
  end
end
read_failed_lines() click to toggle source
# File lib/rspec/core/formatters/exception_presenter.rb, line 198
def read_failed_lines
  matching_line = find_failed_line
  unless matching_line
    return ["Unable to find matching line from backtrace"]
  end

  file_path, line_number = matching_line.match(/(.+?):(\d+)(|:\d+)/)[1..2]
  max_line_count = RSpec.configuration.max_displayed_failure_line_count
  lines = SnippetExtractor.extract_expression_lines_at(file_path, line_number.to_i, max_line_count)
  RSpec.world.source_cache.syntax_highlighter.highlight(lines)
rescue SnippetExtractor::NoSuchFileError
  ["Unable to find #{file_path} to read failed line"]
rescue SnippetExtractor::NoSuchLineError
  ["Unable to find matching line in #{file_path}"]
rescue SecurityError
  ["Unable to read failed line"]
end