class RSpecApprovals::Matchers::Base

A base matcher for approvals

Attributes

actual[R]
actual_distance[R]
approval_name[R]
distance[R]

Public Class Methods

new(approval_name=nil) click to toggle source
# File lib/rspec_approvals/matchers/base.rb, line 8
def initialize(approval_name=nil)
  @before = nil
  @approval_name = approval_name
end

Public Instance Methods

approval_file() click to toggle source

Returns the path to the approval file

# File lib/rspec_approvals/matchers/base.rb, line 96
def approval_file
  "#{approvals_dir}/#{approval_name}"
end
approvals_dir() click to toggle source

Returns the path to the approvals directory. Default: `spec/approvals`

# File lib/rspec_approvals/matchers/base.rb, line 91
def approvals_dir
  RSpec.configuration.approvals_path
end
before(proc) click to toggle source

Enables the ability to adjust the actual string before checking for matches: `expect(a).to match_approval(f).before ->(actual) { actual.gsub /one/, 'two' }`

# File lib/rspec_approvals/matchers/base.rb, line 47
def before(proc)
  @before ||= []
  @before << proc
  self
end
diff(distance) click to toggle source

Enables the ability to do something like: `expect(string).to match_approval(file).diff(10) The distance argument is the max allowed Levenshtein Distance.

# File lib/rspec_approvals/matchers/base.rb, line 31
def diff(distance)
  @distance = distance
  self
end
diffable?() click to toggle source

Lets RSpec know these matchers support diffing

# File lib/rspec_approvals/matchers/base.rb, line 72
def diffable?
  true
end
except(regex, replace = '...') click to toggle source

Enables the ability to do something like: `expect(string).to match_approval(file).except(/d+/)

# File lib/rspec_approvals/matchers/base.rb, line 38
def except(regex, replace = '...')
  before ->(str) do
    str.gsub regex, replace
  end
end
expected() click to toggle source

Returns the expected value, from an approval file

# File lib/rspec_approvals/matchers/base.rb, line 54
def expected
  @expected ||= expected!
end
failure_message() click to toggle source

Called by RSpec when there is a failure

# File lib/rspec_approvals/matchers/base.rb, line 59
def failure_message
  return "actual string is empty" if actual.empty?

  result = "expected: #{actual}\nto match: #{expected}"
  
  if distance
    result = "#{result}\n(actual distance is #{actual_distance} instead of the expected #{distance})"
  end

  result
end
interactive?() click to toggle source

Returns true if RSpec is configured to allow interactivity. By default, interactivity is enabled unless the environment variable `CI` is set.

# File lib/rspec_approvals/matchers/base.rb, line 85
def interactive?
  RSpec.configuration.interactive_approvals
end
matches?(actual) click to toggle source

Called by RSpec. This will be overridden by child matchers.

# File lib/rspec_approvals/matchers/base.rb, line 14
def matches?(actual)
  @actual ||= actual
  return false if @actual.empty?

  @actual = sanitize @actual
  success = strings_match?

  if success or !interactive?
    success
  else
    approve_approval
  end
end
sanitize?() click to toggle source

Returns true if RSpec is configured to sanitize (remove ANSI escape codes) from the actual strings before proceeeding to comparing them.

# File lib/rspec_approvals/matchers/base.rb, line 78
def sanitize?
  RSpec.configuration.strip_ansi_escape
end

Protected Instance Methods

approve_approval() click to toggle source

Asks for user approval. Used by child classes.

# File lib/rspec_approvals/matchers/base.rb, line 103
def approve_approval
  approval_handler = ApprovalHandler.new
  approval_handler.run expected, actual, approval_file
end
expected!() click to toggle source

Returns the actual approval file content.

# File lib/rspec_approvals/matchers/base.rb, line 109
def expected!
  File.exist?(approval_file) ? File.read(approval_file) : ''
end
sanitize(string) click to toggle source

Returns the input string stripped of ANSI escape codes if the strip_ansi_escape configuration setting was set to true

# File lib/rspec_approvals/matchers/base.rb, line 142
def sanitize(string)
  sanitize? ? Strings::ANSI.sanitize(string) : string
end
strings_match?() click to toggle source

Do the actual test.

  • If .before() was used, we foreward the actual output to the proc for processing first.

  • If before_approval proc was configured, forward the acual output to the proc for processing.

  • If .diff() was used, then distance will be set and then we “levenshtein it”.

  • Otherwise, compare with ==

# File lib/rspec_approvals/matchers/base.rb, line 121
def strings_match?
  if @before
    @before.each do |proc|
      @actual = proc.call actual 
    end
  end
  
  if RSpec.configuration.before_approval.is_a? Proc
    @actual = RSpec.configuration.before_approval.call actual
  end

  if distance
    @actual_distance = String::Similarity.levenshtein_distance expected, actual
    @actual_distance <= distance
  else
    actual == expected
  end
end