Class: Capybara::Screenshot::Diff::StableScreenshoter

Inherits:
Object
  • Object
show all
Defined in:
lib/capybara/screenshot/diff/stable_screenshoter.rb

Constant Summary collapse

STABILITY_OPTIONS =
[:stability_time_limit, :wait]

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(capture_options, comparison_options = nil) ⇒ StableScreenshoter

Initializes a new instance of StableScreenshoter

This method sets up a new screenshoter with specific capture and comparison options. It validates the presence of :stability_time_limit and :wait in capture options and ensures that :stability_time_limit is less than or equal to :wait.

Parameters:

  • capture_options (Hash)

    The options for capturing screenshots, must include :stability_time_limit and :wait.

  • comparison_options (Hash, nil) (defaults to: nil)

    The options for comparing screenshots, defaults to nil which uses Diff.default_options.

Raises:

  • (ArgumentError)

    If :wait or :stability_time_limit are not provided, or if :stability_time_limit is greater than :wait.



19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/capybara/screenshot/diff/stable_screenshoter.rb', line 19

def initialize(capture_options, comparison_options = nil)
  @stability_time_limit, @wait = capture_options.fetch_values(:stability_time_limit, :wait)

  raise ArgumentError, "wait should be provided for stable screenshots" unless wait
  raise ArgumentError, "stability_time_limit should be provided for stable screenshots" unless stability_time_limit
  raise ArgumentError, "stability_time_limit (#{stability_time_limit}) should be less or equal than wait (#{wait}) for stable screenshots" unless stability_time_limit <= wait

  @comparison_options = comparison_options || Diff.default_options

  driver = Diff::Drivers.for(@comparison_options)
  @screenshoter = Diff.screenshoter.new(capture_options.except(*STABILITY_OPTIONS), driver)
end

Instance Attribute Details

#stability_time_limitObject (readonly)

Returns the value of attribute stability_time_limit.



9
10
11
# File 'lib/capybara/screenshot/diff/stable_screenshoter.rb', line 9

def stability_time_limit
  @stability_time_limit
end

#waitObject (readonly)

Returns the value of attribute wait.



9
10
11
# File 'lib/capybara/screenshot/diff/stable_screenshoter.rb', line 9

def wait
  @wait
end

Instance Method Details

#take_comparison_screenshot(screenshot_path) ⇒ void

This method returns an undefined value.

Takes a comparison screenshot ensuring page stability

Attempts to take a stable screenshot of the page by comparing several screenshot attempts until the page stops updating or the :wait limit is reached. If unable to achieve a stable state within the time limit, it annotates the attempts to aid debugging.

Parameters:

  • screenshot_path (String, Pathname)

    The path where the screenshot will be saved.

Raises:

  • (RuntimeError)

    If a stable screenshot cannot be obtained within the specified :wait time.



41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/capybara/screenshot/diff/stable_screenshoter.rb', line 41

def take_comparison_screenshot(screenshot_path)
  new_screenshot_path = take_stable_screenshot(screenshot_path)

  # We failed to get stable browser state! Generate difference between attempts to overview moving parts!
  unless new_screenshot_path
    # FIXME(uwe): Change to store the failure and only report if the test succeeds functionally.
    annotate_attempts_and_fail!(screenshot_path)
  end

  FileUtils.mv(new_screenshot_path, screenshot_path, force: true)
  Screenshoter.cleanup_attempts_screenshots(screenshot_path)
end

#take_stable_screenshot(screenshot_path) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/capybara/screenshot/diff/stable_screenshoter.rb', line 54

def take_stable_screenshot(screenshot_path)
  screenshot_path = screenshot_path.is_a?(String) ? Pathname.new(screenshot_path) : screenshot_path
  # We try to compare first attempt with checkout version, in order to not run next screenshots
  attempt_path = nil
  deadline_at = Process.clock_gettime(Process::CLOCK_MONOTONIC) + wait

  # Cleanup all previous attempts for sure
  Screenshoter.cleanup_attempts_screenshots(screenshot_path)

  0.step do |i|
    # FIXME: it should be wait, and wait should be replaced with stability_time_limit
    sleep(stability_time_limit) unless i == 0
    attempt_path, prev_attempt_path = attempt_next_screenshot(attempt_path, i, screenshot_path)
    return attempt_path if attempt_successful?(attempt_path, prev_attempt_path)
    return nil if timeout?(deadline_at)
  end
end