module RuboCop::RSpec::ExpectOffense
def expect_correction(correction, loop: true, source: nil)
def expect_correction(correction, loop: true, source: nil) if source expected_annotations = parse_annotations(source, raise_error: false) @processed_source = parse_processed_source(expected_annotations.plain_source) _investigate(cop, @processed_source) end raise '`expect_correction` must follow `expect_offense`' unless @processed_source source = @processed_source.raw_source raise 'Use `expect_no_corrections` if the code will not change' if correction == source iteration = 0 new_source = loop do iteration += 1 corrected_source = @last_corrector.rewrite break corrected_source unless loop break corrected_source if @last_corrector.empty? break corrected_source if corrected_source == @processed_source.buffer.source if iteration > RuboCop::Runner::MAX_ITERATIONS raise RuboCop::Runner::InfiniteCorrectionLoop.new(@processed_source.path, [@offenses]) end # Prepare for next loop @processed_source = parse_source(corrected_source, @processed_source.path) _investigate(cop, @processed_source) end raise 'Expected correction but no corrections were made' if new_source == source expect(new_source).to eq(correction) end
def expect_no_corrections
def expect_no_corrections raise '`expect_no_corrections` must follow `expect_offense`' unless @processed_source return if @last_corrector.empty? # In order to print a nice diff, e.g. what source got corrected to, # we need to run the actual corrections new_source = @last_corrector.rewrite expect(new_source).to eq(@processed_source.buffer.source) end
def expect_no_offenses(source, file = nil)
def expect_no_offenses(source, file = nil) offenses = inspect_source(source, file) expected_annotations = AnnotatedSource.parse(source) actual_annotations = expected_annotations.with_offense_annotations(offenses) expect(actual_annotations.to_s).to eq(source) end
def expect_offense(source, file = nil, severity: nil, chomp: false, **replacements)
def expect_offense(source, file = nil, severity: nil, chomp: false, **replacements) expected_annotations = parse_annotations(source, **replacements) source = expected_annotations.plain_source source = source.chomp if chomp @processed_source = parse_processed_source(source, file) @offenses = _investigate(cop, @processed_source) actual_annotations = expected_annotations.with_offense_annotations(@offenses) expect(actual_annotations).to eq(expected_annotations), '' expect(@offenses.map(&:severity).uniq).to eq([severity]) if severity @offenses end
def format_offense(source, **replacements)
def format_offense(source, **replacements) replacements.each do |keyword, value| value = value.to_s source = source.gsub("%{#{keyword}}", value) .gsub("^{#{keyword}}", '^' * value.size) .gsub("_{#{keyword}}", ' ' * value.size) end source end
def parse_annotations(source, raise_error: true, **replacements)
def parse_annotations(source, raise_error: true, **replacements) set_formatter_options source = format_offense(source, **replacements) annotations = AnnotatedSource.parse(source) return annotations unless raise_error && annotations.plain_source == source raise 'Use `expect_no_offenses` to assert that no offenses are found' end
def parse_processed_source(source, file = nil)
def parse_processed_source(source, file = nil) processed_source = parse_source(source, file) return processed_source if processed_source.valid_syntax? raise 'Error parsing example code: ' \ "#{processed_source.diagnostics.map(&:render).join("\n")}" end
def set_formatter_options
def set_formatter_options RuboCop::Formatter::DisabledConfigFormatter.config_to_allow_offenses = {} RuboCop::Formatter::DisabledConfigFormatter.detected_styles = {} cop.instance_variable_get(:@options)[:autocorrect] = true end