module Capybara::Screenshot::Diff::TestMethods

Public Class Methods

new(*) click to toggle source

@!attribute [rw] test_screenshots

@return [Array(Array(Array(String), String, ImageCompare))] An array where each element is an array containing the caller context,
  the name of the screenshot, and the comparison object. This attribute stores information about each screenshot
  scheduled for comparison to ensure they do not show any unintended differences.
Calls superclass method
# File lib/capybara/screenshot/diff/test_methods.rb, line 32
def initialize(*)
  super
  @screenshot_counter = nil
  @screenshot_group = nil
  @screenshot_section = nil
  @test_screenshot_errors = nil
  @test_screenshots = []
end

Public Instance Methods

assert_image_not_changed(caller, name, comparison) click to toggle source

Asserts that an image has not changed compared to its baseline.

@param caller [Array] The caller context, used for error reporting. @param name [String] The name of the screenshot being verified. @param comparison [Object] The comparison object containing the result and details of the comparison. @return [String, nil] Returns an error message if the screenshot differs from the baseline, otherwise nil. @note This method is used internally to verify individual screenshots.

# File lib/capybara/screenshot/diff/test_methods.rb, line 154
def assert_image_not_changed(caller, name, comparison)
  result = comparison.different?

  # Cleanup after comparisons
  if !result && comparison.base_image_path.exist?
    FileUtils.mv(comparison.base_image_path, comparison.image_path, force: true)
  else
    FileUtils.rm_rf(comparison.base_image_path)
  end

  return unless result

  "Screenshot does not match for '#{name}' #{comparison.error_message}\n#{caller}"
end
build_full_name(name) click to toggle source

Builds the full name for a screenshot, incorporating counters and group names for uniqueness.

@param name [String] The base name for the screenshot. @return [String] The full, unique name for the screenshot.

# File lib/capybara/screenshot/diff/test_methods.rb, line 64
def build_full_name(name)
  if @screenshot_counter
    name = format("%02i_#{name}", @screenshot_counter)
    @screenshot_counter += 1
  end

  File.join(*group_parts.push(name.to_s))
end
group_parts() click to toggle source
# File lib/capybara/screenshot/diff/test_methods.rb, line 104
def group_parts
  parts = []
  parts << @screenshot_section if @screenshot_section.present?
  parts << @screenshot_group if @screenshot_group.present?
  parts
end
schedule_match_job(job) click to toggle source

Schedules a screenshot comparison job for later execution.

This method adds a job to the queue of screenshots to be matched. It’s used when ‘Capybara::Screenshot::Diff.delayed` is set to true, allowing for batch processing of screenshot comparisons at a later point, typically at the end of a test.

@param job [Array(Array(String), String, ImageCompare)] The job to be scheduled, consisting of the caller context, screenshot name, and comparison object. @return [Boolean] Always returns true, indicating the job was successfully scheduled.

# File lib/capybara/screenshot/diff/test_methods.rb, line 99
def schedule_match_job(job)
  (@test_screenshots ||= []) << job
  true
end
screenshot(name, skip_stack_frames: 0, **options) click to toggle source

Takes a screenshot and optionally compares it against a baseline image.

@param name [String] The name of the screenshot, used to generate the filename. @param skip_stack_frames [Integer] The number of stack frames to skip when reporting errors, for cleaner error messages. @param options [Hash] Additional options for taking the screenshot, such as custom dimensions or selectors. @return [Boolean] Returns true if the screenshot was successfully captured and matches the baseline, false otherwise. @raise [CapybaraScreenshotDiff::ExpectationNotMet] If the screenshot does not match the baseline image and fail_if_new is set to true. @example Capture a full-page screenshot named ‘login_page’

screenshot('login_page', skip_stack_frames: 1, full: true)
# File lib/capybara/screenshot/diff/test_methods.rb, line 120
        def screenshot(name, skip_stack_frames: 0, **options)
          return false unless Screenshot.active?

          screenshot_full_name = build_full_name(name)
          job = build_screenshot_matches_job(screenshot_full_name, options)

          unless job
            if Screenshot::Diff.fail_if_new
              raise_error(<<-ERROR.strip_heredoc, caller(2))
                No existing screenshot found for #{screenshot_full_name}!
                To stop seeing this error disable by `Capybara::Screenshot::Diff.fail_if_new=false`
              ERROR
            end

            return false
          end

          job.prepend(caller(skip_stack_frames))

          if Screenshot::Diff.delayed
            schedule_match_job(job)
          else
            error_msg = assert_image_not_changed(*job)
            raise_error(error_msg, caller(2)) if error_msg
          end
        end
screenshot_dir() click to toggle source

Determines the directory path for saving screenshots.

@return [String] The full path to the directory where screenshots are saved.

# File lib/capybara/screenshot/diff/test_methods.rb, line 76
def screenshot_dir
  File.join(*([Screenshot.screenshot_area] + group_parts))
end
screenshot_group(name) click to toggle source
# File lib/capybara/screenshot/diff/test_methods.rb, line 84
def screenshot_group(name)
  @screenshot_group = name.to_s
  @screenshot_counter = @screenshot_group.present? ? 0 : nil
  return unless Screenshot.active? && name.present?

  FileUtils.rm_rf screenshot_dir
end
screenshot_section(name) click to toggle source
# File lib/capybara/screenshot/diff/test_methods.rb, line 80
def screenshot_section(name)
  @screenshot_section = name.to_s
end
verify_screenshots!(screenshots = @test_screenshots) click to toggle source

Verifies that all scheduled screenshots do not show any unintended differences.

@param screenshots [Array(Array(Array(String), String, ImageCompare))] The list of match screenshots jobs. Defaults to all screenshots taken during the test. @return [Array, nil] Returns an array of error messages if there are screenshot differences, otherwise nil. @note This method is typically called at the end of a test to assert all screenshots are as expected.

# File lib/capybara/screenshot/diff/test_methods.rb, line 46
def verify_screenshots!(screenshots = @test_screenshots)
  return unless ::Capybara::Screenshot.active? && ::Capybara::Screenshot::Diff.fail_on_difference

  test_screenshot_errors = screenshots.map do |caller, name, compare|
    assert_image_not_changed(caller, name, compare)
  end

  test_screenshot_errors.compact!

  test_screenshot_errors.presence
ensure
  screenshots.clear
end

Private Instance Methods

build_screenshot_matches_job(screenshot_full_name, options) click to toggle source
# File lib/capybara/screenshot/diff/test_methods.rb, line 175
def build_screenshot_matches_job(screenshot_full_name, options)
  ScreenshotMatcher
    .new(screenshot_full_name, options)
    .build_screenshot_matches_job
end
raise_error(error_msg, backtrace) click to toggle source
# File lib/capybara/screenshot/diff/test_methods.rb, line 171
def raise_error(error_msg, backtrace)
  raise CapybaraScreenshotDiff::ExpectationNotMet.new(error_msg).tap { _1.set_backtrace(backtrace) }
end