Class: Capybara::Screenshot::Screenshoter

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

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(capture_options, driver) ⇒ Screenshoter

Returns a new instance of Screenshoter.



11
12
13
14
15
# File 'lib/capybara/screenshot/diff/screenshoter.rb', line 11

def initialize(capture_options, driver)
  @capture_options = capture_options
  @comparison_options = comparison_options
  @driver = driver
end

Instance Attribute Details

#capture_optionsObject (readonly)

Returns the value of attribute capture_options.



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

def capture_options
  @capture_options
end

#comparison_optionsObject (readonly)

Returns the value of attribute comparison_options.



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

def comparison_options
  @comparison_options
end

#driverObject (readonly)

Returns the value of attribute driver.



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

def driver
  @driver
end

Class Method Details

.attempts_screenshot_paths(base_file) ⇒ Object



25
26
27
# File 'lib/capybara/screenshot/diff/screenshoter.rb', line 25

def self.attempts_screenshot_paths(base_file)
  Dir["#{base_file.to_s.chomp(".png")}.attempt_*.png"].sort
end

.cleanup_attempts_screenshots(base_file) ⇒ Object



29
30
31
# File 'lib/capybara/screenshot/diff/screenshoter.rb', line 29

def self.cleanup_attempts_screenshots(base_file)
  FileUtils.rm_rf attempts_screenshot_paths(base_file)
end

.gen_next_attempt_path(screenshot_path, iteration) ⇒ Object



45
46
47
# File 'lib/capybara/screenshot/diff/screenshoter.rb', line 45

def self.gen_next_attempt_path(screenshot_path, iteration)
  Pathname.new(screenshot_path).sub_ext(format(".attempt_%02i.png", iteration))
end

Instance Method Details

#browser_save_screenshot(screenshot_path) ⇒ Object



61
62
63
# File 'lib/capybara/screenshot/diff/screenshoter.rb', line 61

def browser_save_screenshot(screenshot_path)
  BrowserHelpers.session.save_screenshot(screenshot_path)
end

#cropObject



17
18
19
# File 'lib/capybara/screenshot/diff/screenshoter.rb', line 17

def crop
  @capture_options[:crop]
end

#notice_how_to_avoid_thisObject



93
94
95
96
97
98
99
# File 'lib/capybara/screenshot/diff/screenshoter.rb', line 93

def notice_how_to_avoid_this
  unless defined?(@_csd_retina_warned)
    warn "Halving retina screenshot.  " \
          'You should add "force-device-scale-factor=1" to your Chrome chromeOptions args.'
    @_csd_retina_warned = true
  end
end

#prepare_page_for_screenshot(timeout:) ⇒ Object



101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/capybara/screenshot/diff/screenshoter.rb', line 101

def prepare_page_for_screenshot(timeout:)
  wait_images_loaded(timeout: timeout)

  blurred_input = if Screenshot.blur_active_element
    BrowserHelpers.blur_from_focused_element
  end

  if Screenshot.hide_caret
    BrowserHelpers.hide_caret
  end

  blurred_input
end

#process_screenshot(screenshot_path) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/capybara/screenshot/diff/screenshoter.rb', line 65

def process_screenshot(screenshot_path)
  # TODO(uwe): Remove when chromedriver takes right size screenshots
  # TODO: Adds tests when this case is true
  if selenium_with_retina_screen?
    reduce_retina_image_size(screenshot_path)
  end
  # ODOT

  if crop
    image = driver.from_file(screenshot_path)
    cropped_image = driver.crop(crop, image)
    driver.save_image_to(cropped_image, screenshot_path)
  end
end

#reduce_retina_image_size(file_name) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/capybara/screenshot/diff/screenshoter.rb', line 80

def reduce_retina_image_size(file_name)
  expected_image_width = Screenshot.window_size[0]
  saved_image = driver.from_file(file_name.to_s)
  return if driver.width_for(saved_image) < expected_image_width * 2

  notice_how_to_avoid_this

  new_height = expected_image_width * driver.height_for(saved_image) / driver.width_for(saved_image)
  resized_image = driver.resize_image_to(saved_image, expected_image_width, new_height)

  driver.save_image_to(resized_image, file_name)
end

#take_comparison_screenshot(screenshot_path) ⇒ Object

Try to get screenshot from browser. On ‘stability_time_limit` it checks that page stop updating by comparison several screenshot attempts On reaching `wait` limit then it has been failed. On failing we annotate screenshot attempts to help to debug



36
37
38
39
40
41
42
43
# File 'lib/capybara/screenshot/diff/screenshoter.rb', line 36

def take_comparison_screenshot(screenshot_path)
  new_screenshot_path = Screenshoter.gen_next_attempt_path(screenshot_path, 0)

  take_screenshot(new_screenshot_path)

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

#take_screenshot(screenshot_path) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
# File 'lib/capybara/screenshot/diff/screenshoter.rb', line 49

def take_screenshot(screenshot_path)
  blurred_input = prepare_page_for_screenshot(timeout: wait)

  # Take browser screenshot and save
  browser_save_screenshot(screenshot_path)

  # Load saved screenshot and pre-process it
  process_screenshot(screenshot_path)
ensure
  blurred_input&.click
end

#waitObject



21
22
23
# File 'lib/capybara/screenshot/diff/screenshoter.rb', line 21

def wait
  @capture_options[:wait]
end

#wait_images_loaded(timeout:) ⇒ Object



115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/capybara/screenshot/diff/screenshoter.rb', line 115

def wait_images_loaded(timeout:)
  start = Time.now
  loop do
    pending_image = BrowserHelpers.pending_image_to_load
    break unless pending_image

    if (Time.now - start) >= timeout
      raise Capybara::Screenshot::Diff::ASSERTION, "Images not loaded after #{timeout}s: #{pending_image.inspect}"
    end

    sleep 0.025
  end
end