Class: ActionDispatch::IntegrationTest

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

Overview

TODO(uwe): Move this code to module Capybara::Screenshot::Diff::TestMethods,

and use Module#prepend/include to insert.

Add the screenshot method to ActionDispatch::IntegrationTest rubocop:disable Metrics/ClassLength

Constant Summary collapse

ON_WINDOWS =
RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/
SILENCE_ERRORS =
ON_WINDOWS ? '2>nul' : '2>/dev/null'
IMAGE_WAIT_SCRIPT =
"function pending_image() {\n  var images = document.images;\n  for (var i = 0; i < images.length; i++) {\n    if (!images[i].complete) {\n        return images[i].src;\n    }\n  }\n  return false;\n}()\n".freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeIntegrationTest

Returns a new instance of IntegrationTest.



43
44
45
46
47
48
49
50
# File 'lib/capybara/screenshot/diff/capybara_setup.rb', line 43

def initialize(*)
  super
  @screenshot_counter = nil
  @screenshot_group = nil
  @screenshot_section = nil
  @test_screenshot_errors = nil
  @test_screenshots = nil
end

Class Method Details

.os_nameObject



14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/capybara/screenshot/diff/capybara_setup.rb', line 14

def self.os_name
  case RbConfig::CONFIG['host_os']
  when /darwin/
    'macos'
  when /mswin|mingw|cygwin/
    'windows'
  when /linux/
    'linux'
  else
    'unknown'
  end
end

.screenshot_areaObject



32
33
34
35
36
37
# File 'lib/capybara/screenshot/diff/capybara_setup.rb', line 32

def self.screenshot_area
  parts = ['doc/screenshots']
  parts << Capybara.default_driver.to_s if Capybara::Screenshot.add_driver_path
  parts << os_name if Capybara::Screenshot.add_os_path
  File.join parts
end

.screenshot_area_absObject



39
40
41
# File 'lib/capybara/screenshot/diff/capybara_setup.rb', line 39

def self.screenshot_area_abs
  "#{screenshot_root}/#{screenshot_area}".freeze
end

.screenshot_rootObject



27
28
29
30
# File 'lib/capybara/screenshot/diff/capybara_setup.rb', line 27

def self.screenshot_root
  Capybara::Screenshot.screenshot_root ||
      (defined?(Rails.root) && Rails.root) || File.expand_path('.')
end

Instance Method Details

#assert_image_not_changed(caller, name, file_name, committed_file_name, new_name, org_name) ⇒ Object



172
173
174
175
176
177
178
# File 'lib/capybara/screenshot/diff/capybara_setup.rb', line 172

def assert_image_not_changed(caller, name, file_name, committed_file_name, new_name, org_name)
  if Capybara::Screenshot::Diff::ImageCompare.compare(committed_file_name, file_name,
      Capybara::Screenshot.window_size)
    (@test_screenshot_errors ||= []) <<
        "Screenshot does not match for '#{name}'\n#{file_name}\n#{org_name}\n#{new_name}\nat #{caller}"
  end
end

#assert_images_loaded(timeout: Capybara.default_max_wait_time) ⇒ Object



147
148
149
150
151
152
153
154
155
156
157
# File 'lib/capybara/screenshot/diff/capybara_setup.rb', line 147

def assert_images_loaded(timeout: Capybara.default_max_wait_time)
  return unless respond_to? :evaluate_script
  start = Time.now
  loop do
    pending_image = evaluate_script IMAGE_WAIT_SCRIPT
    break unless pending_image
    assert (Time.now - start) < timeout,
        "Image not loaded after #{timeout}s: #{pending_image.inspect}"
    sleep 0.1
  end
end

#full_name(name) ⇒ Object



59
60
61
# File 'lib/capybara/screenshot/diff/capybara_setup.rb', line 59

def full_name(name)
  File.join group_parts.<<(name).map(&:to_s)
end

#group_partsObject



52
53
54
55
56
57
# File 'lib/capybara/screenshot/diff/capybara_setup.rb', line 52

def group_parts
  parts = []
  parts << @screenshot_section if @screenshot_section.present?
  parts << @screenshot_group if @screenshot_group.present?
  parts
end

#screenshot(name) ⇒ Object



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/capybara/screenshot/diff/capybara_setup.rb', line 95

def screenshot(name)
  return unless Capybara::Screenshot.active?
  if Capybara.default_driver == :selenium && Capybara::Screenshot.window_size
    return unless page.driver.browser.manage.window
        .size == Selenium::WebDriver::Dimension.new(*Capybara::Screenshot.window_size)
  end
  if @screenshot_counter
    name = "#{'%02i' % @screenshot_counter}_#{name}"
    @screenshot_counter += 1
  end
  name = full_name(name)
  file_name = "#{self.class.screenshot_area_abs}/#{name}.png"
  org_name = "#{self.class.screenshot_area_abs}/#{name}_0.png~"
  new_name = "#{self.class.screenshot_area_abs}/#{name}_1.png~"

  FileUtils.mkdir_p File.dirname(file_name)
  svn_file_name = "#{self.class.screenshot_area_abs}/.svn/text-base/#{name}.png.svn-base"
  if File.exist?(svn_file_name)
    committed_file_name = svn_file_name
  else
    svn_info = `svn info #{file_name} #{SILENCE_ERRORS}`
    if svn_info.present?
      wc_root = svn_info.slice(/(?<=Working Copy Root Path: ).*$/)
      checksum = svn_info.slice(/(?<=Checksum: ).*$/)
      if checksum
        committed_file_name = "#{wc_root}/.svn/pristine/#{checksum[0..1]}/#{checksum}.svn-base"
      end
    else
      committed_file_name = org_name
      `git show HEAD~0:#{self.class.screenshot_area}/#{name}.png > #{committed_file_name} #{SILENCE_ERRORS}`
      if File.size(committed_file_name) == 0
        FileUtils.rm_f committed_file_name
      end
    end
  end
  take_stable_screenshot(file_name)
  return unless committed_file_name && File.exist?(committed_file_name)
  (@test_screenshots ||= []) << [caller[0], name, file_name, committed_file_name, new_name, org_name]
end

#screenshot_dirObject



63
64
65
# File 'lib/capybara/screenshot/diff/capybara_setup.rb', line 63

def screenshot_dir
  File.join [self.class.screenshot_area] + group_parts
end

#screenshot_group(name) ⇒ Object



88
89
90
91
92
93
# File 'lib/capybara/screenshot/diff/capybara_setup.rb', line 88

def screenshot_group(name)
  @screenshot_group = name.to_s
  @screenshot_counter = 0
  return unless Capybara::Screenshot.active? && name.present?
  FileUtils.rm_rf screenshot_dir
end

#screenshot_section(name) ⇒ Object



84
85
86
# File 'lib/capybara/screenshot/diff/capybara_setup.rb', line 84

def screenshot_section(name)
  @screenshot_section = name.to_s
end

#take_stable_screenshot(file_name) ⇒ Object



159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/capybara/screenshot/diff/capybara_setup.rb', line 159

def take_stable_screenshot(file_name)
  assert_images_loaded
  old_file_size = nil
  loop do
    save_screenshot(file_name)
    break unless Capybara::Screenshot.stability_time_limit
    new_file_size = File.size(file_name)
    break if new_file_size == old_file_size
    old_file_size = new_file_size
    sleep Capybara::Screenshot.stability_time_limit
  end
end