Module: Capybara::Screenshot::Diff::TestMethods

Included in:
CapybaraScreenshotDiff::DSL
Defined in:
lib/capybara/screenshot/diff/test_methods.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#test_screenshotsArray(Array(Array(String), String, ImageCompare | Minitest::Mock))

Returns 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.

Returns:

  • (Array(Array(Array(String), String, ImageCompare | Minitest::Mock)))

    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.



32
33
34
35
36
37
38
39
# 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

Instance Method Details

#assert_image_not_changed(caller, name, comparison) ⇒ String?

Note:

This method is used internally to verify individual screenshots.

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

Parameters:

  • caller (Array(String))

    The caller context, used for error reporting.

  • name (String)

    The name of the screenshot being verified.

  • comparison (Object)

    The comparison object containing the result and details of the comparison.

Returns:

  • (String, nil)

    Returns an error message if the screenshot differs from the baseline, otherwise nil.



154
155
156
157
158
159
160
161
162
163
164
165
166
167
# 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.join(", ")}"
end

#build_full_name(name) ⇒ String

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

Parameters:

  • name (String)

    The base name for the screenshot.

Returns:

  • (String)

    The full, unique name for the screenshot.



64
65
66
67
68
69
70
71
# 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_partsObject



104
105
106
107
108
109
# 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

#initializeObject



32
33
34
35
36
37
38
39
# 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

#schedule_match_job(job) ⇒ Boolean

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.

Parameters:

  • job (Array(Array(String), String, ImageCompare))

    The job to be scheduled, consisting of the caller context, screenshot name, and comparison object.

Returns:

  • (Boolean)

    Always returns true, indicating the job was successfully scheduled.



99
100
101
102
# 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) ⇒ Boolean

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

Examples:

Capture a full-page screenshot named ‘login_page’

screenshot('login_page', skip_stack_frames: 1, full: true)

Parameters:

  • name (String)

    The name of the screenshot, used to generate the filename.

  • skip_stack_frames (Integer) (defaults to: 0)

    The number of stack frames to skip when reporting errors, for cleaner error messages.

  • options (Hash)

    Additional options for taking the screenshot, such as custom dimensions or selectors.

Returns:

  • (Boolean)

    Returns true if the screenshot was successfully captured and matches the baseline, false otherwise.

Raises:



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# 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_dirString

Determines the directory path for saving screenshots.

Returns:

  • (String)

    The full path to the directory where screenshots are saved.



76
77
78
# File 'lib/capybara/screenshot/diff/test_methods.rb', line 76

def screenshot_dir
  File.join(*([Screenshot.screenshot_area] + group_parts))
end

#screenshot_group(name) ⇒ Object



84
85
86
87
88
89
90
# 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) ⇒ Object



80
81
82
# 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) ⇒ Array?

Note:

This method is typically called at the end of a test to assert all screenshots are as expected.

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

Parameters:

  • screenshots (Array(Array(Array(String), String, ImageCompare))) (defaults to: @test_screenshots)

    The list of match screenshots jobs. Defaults to all screenshots taken during the test.

Returns:

  • (Array, nil)

    Returns an array of error messages if there are screenshot differences, otherwise nil.



46
47
48
49
50
51
52
53
54
55
56
57
58
# 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