Class: Applitools::Selenium::SeleniumEyes

Inherits:
EyesBase
  • Object
show all
Extended by:
Forwardable
Includes:
Concerns::SeleniumEyes
Defined in:
lib/applitools/selenium/selenium_eyes.rb

Overview

The main API gateway for the SDK

Constant Summary collapse

DEFAULT_DEVICE_PIXEL_RATIO =

The pixel ratio will be used if detection of device pixel ratio is failed

1
DEFAULT_WAIT_BEFORE_SCREENSHOTS =

Seconds

0.1
DEFAULT_STITCHING_OVERLAP =

Pixels

0
ENTIRE_ELEMENT_SCREENSHOT =
0
FULLPAGE_SCREENSHOT =
1
VIEWPORT_SCREENSHOT =
2

Constants included from Concerns::SeleniumEyes

Concerns::SeleniumEyes::USE_DEFAULT_MATCH_TIMEOUT

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Concerns::SeleniumEyes

#check_frame, #check_in_frame, #check_region, #check_region_in_frame, #check_window, #test

Constructor Details

#initialize(*args) ⇒ SeleniumEyes

Creates a new (possibly disabled) Eyes instance that interacts with the Eyes Server at the specified url.

Parameters:

  • server_url

    The Eyes Server URL.



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
# File 'lib/applitools/selenium/selenium_eyes.rb', line 104

def initialize(*args)
  ensure_config
  super
  self.runner = Applitools::ClassicRunner.new unless runner
  self.base_agent_id = "eyes.selenium.ruby/#{Applitools::VERSION}".freeze
  self.check_frame_or_element = false
  self.region_to_check = nil
  # self.force_full_page_screenshot = false
  self.dont_get_title = false
  self.device_pixel_ratio = UNKNOWN_DEVICE_PIXEL_RATIO
  self.stitch_mode = Applitools::STITCH_MODE[:scroll]
  self.wait_before_screenshots = DEFAULT_WAIT_BEFORE_SCREENSHOTS
  self.region_visibility_strategy = MoveToRegionVisibilityStrategy.new
  self.debug_screenshots = false
  self.debug_screenshot_provider = Applitools::DebugScreenshotProvider.new
                                                                      .tag_access { tag_for_debug }
                                                                      .debug_flag_access { debug_screenshots }
  self.disable_horizontal_scrolling = false
  self.disable_vertical_scrolling = false
  self.explicit_entire_size = nil
  self.force_driver_resolution_as_viewport_size = false
  self.stitching_overlap = DEFAULT_STITCHING_OVERLAP
  self.full_page_capture_algorithm_left_top_offset = Applitools::Location::TOP_LEFT
  self.send_dom = true
  self.use_dom = false
  self.enable_patterns = false
  self.prevent_dom_processing = false
  self.utils = Applitools::Utils::EyesSeleniumUtils
end

Instance Attribute Details

#base_agent_idObject

Returns the value of attribute base_agent_id.



89
90
91
# File 'lib/applitools/selenium/selenium_eyes.rb', line 89

def base_agent_id
  @base_agent_id
end

#configObject

Returns the value of attribute config.



89
90
91
# File 'lib/applitools/selenium/selenium_eyes.rb', line 89

def config
  @config
end

#debug_screenshot_providerObject

Returns the value of attribute debug_screenshot_provider.



89
90
91
# File 'lib/applitools/selenium/selenium_eyes.rb', line 89

def debug_screenshot_provider
  @debug_screenshot_provider
end

#debug_screenshotsObject

Returns the value of attribute debug_screenshots.



89
90
91
# File 'lib/applitools/selenium/selenium_eyes.rb', line 89

def debug_screenshots
  @debug_screenshots
end

#disable_horizontal_scrollingObject

Returns the value of attribute disable_horizontal_scrolling.



89
90
91
# File 'lib/applitools/selenium/selenium_eyes.rb', line 89

def disable_horizontal_scrolling
  @disable_horizontal_scrolling
end

#disable_vertical_scrollingObject

Returns the value of attribute disable_vertical_scrolling.



89
90
91
# File 'lib/applitools/selenium/selenium_eyes.rb', line 89

def disable_vertical_scrolling
  @disable_vertical_scrolling
end

#driverObject

Returns the value of attribute driver.



95
96
97
# File 'lib/applitools/selenium/selenium_eyes.rb', line 95

def driver
  @driver
end

#enable_patternsObject

Returns the value of attribute enable_patterns.



89
90
91
# File 'lib/applitools/selenium/selenium_eyes.rb', line 89

def enable_patterns
  @enable_patterns
end

#explicit_entire_sizeObject

Returns the value of attribute explicit_entire_size.



89
90
91
# File 'lib/applitools/selenium/selenium_eyes.rb', line 89

def explicit_entire_size
  @explicit_entire_size
end

#force_full_page_screenshotboolean

Forces a full page screenshot (by scrolling and stitching) if the browser only supports viewport screenshots.

Returns:

  • (boolean)

    force full page screenshot flag



89
90
91
92
93
94
# File 'lib/applitools/selenium/selenium_eyes.rb', line 89

attr_accessor :base_agent_id, :screenshot, :force_full_page_screenshot, :hide_scrollbars,
:wait_before_screenshots, :debug_screenshots, :stitch_mode, :disable_horizontal_scrolling,
:disable_vertical_scrolling, :explicit_entire_size, :debug_screenshot_provider, :stitching_overlap,
:full_page_capture_algorithm_left_top_offset, :screenshot_type, :send_dom, :use_dom, :enable_patterns,
:utils,
:config

#full_page_capture_algorithm_left_top_offsetObject

Returns the value of attribute full_page_capture_algorithm_left_top_offset.



89
90
91
# File 'lib/applitools/selenium/selenium_eyes.rb', line 89

def full_page_capture_algorithm_left_top_offset
  @full_page_capture_algorithm_left_top_offset
end

#hide_scrollbarsboolean

Turns on/off hiding scrollbars before taking a screenshot

Returns:

  • (boolean)

    hide_scrollbars flag



89
90
91
92
93
94
# File 'lib/applitools/selenium/selenium_eyes.rb', line 89

attr_accessor :base_agent_id, :screenshot, :force_full_page_screenshot, :hide_scrollbars,
:wait_before_screenshots, :debug_screenshots, :stitch_mode, :disable_horizontal_scrolling,
:disable_vertical_scrolling, :explicit_entire_size, :debug_screenshot_provider, :stitching_overlap,
:full_page_capture_algorithm_left_top_offset, :screenshot_type, :send_dom, :use_dom, :enable_patterns,
:utils,
:config

#screenshotObject

Returns the value of attribute screenshot.



89
90
91
# File 'lib/applitools/selenium/selenium_eyes.rb', line 89

def screenshot
  @screenshot
end

#screenshot_typeObject

Returns the value of attribute screenshot_type.



89
90
91
# File 'lib/applitools/selenium/selenium_eyes.rb', line 89

def screenshot_type
  @screenshot_type
end

#send_domObject

Returns the value of attribute send_dom.



89
90
91
# File 'lib/applitools/selenium/selenium_eyes.rb', line 89

def send_dom
  @send_dom
end

#stitch_modeboolean

May be set to :CSS or :SCROLL (:SCROLL is default). When :CSS - SDK will use CSS transitions to perform scrolling, otherwise it will use Javascript window.scroll_to() function for scrolling purposes

Returns:

  • (boolean)

    stitch_mode (:CSS or :SCROLL)



89
90
91
92
93
94
# File 'lib/applitools/selenium/selenium_eyes.rb', line 89

attr_accessor :base_agent_id, :screenshot, :force_full_page_screenshot, :hide_scrollbars,
:wait_before_screenshots, :debug_screenshots, :stitch_mode, :disable_horizontal_scrolling,
:disable_vertical_scrolling, :explicit_entire_size, :debug_screenshot_provider, :stitching_overlap,
:full_page_capture_algorithm_left_top_offset, :screenshot_type, :send_dom, :use_dom, :enable_patterns,
:utils,
:config

#stitching_overlapObject

Returns the value of attribute stitching_overlap.



89
90
91
# File 'lib/applitools/selenium/selenium_eyes.rb', line 89

def stitching_overlap
  @stitching_overlap
end

#use_domObject

Returns the value of attribute use_dom.



89
90
91
# File 'lib/applitools/selenium/selenium_eyes.rb', line 89

def use_dom
  @use_dom
end

#utilsObject

Returns the value of attribute utils.



89
90
91
# File 'lib/applitools/selenium/selenium_eyes.rb', line 89

def utils
  @utils
end

#wait_before_screenshotsFloat

Sets the time to wait just before taking a screenshot (e.g., to allow positioning to stabilize when performing a full page stitching).

Returns:

  • (Float)

    The time to wait (Seconds). Values smaller or equal to 0, will cause the default value to be used.



89
90
91
92
93
94
# File 'lib/applitools/selenium/selenium_eyes.rb', line 89

attr_accessor :base_agent_id, :screenshot, :force_full_page_screenshot, :hide_scrollbars,
:wait_before_screenshots, :debug_screenshots, :stitch_mode, :disable_horizontal_scrolling,
:disable_vertical_scrolling, :explicit_entire_size, :debug_screenshot_provider, :stitching_overlap,
:full_page_capture_algorithm_left_top_offset, :screenshot_type, :send_dom, :use_dom, :enable_patterns,
:utils,
:config

Class Method Details

.eyes_driver(driver, eyes = nil) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/applitools/selenium/selenium_eyes.rb', line 28

def eyes_driver(driver, eyes = nil)
  if driver.respond_to? :driver_for_eyes
    driver.driver_for_eyes eyes
  else
    unless driver.is_a?(Applitools::Selenium::Driver)
      Applitools::EyesLogger.warn("Unrecognized driver type: (#{driver.class.name})!")
      is_mobile_device = driver.respond_to?(:capabilities) && driver.capabilities['platformName']
      Applitools::Selenium::Driver.new(eyes, driver: driver, is_mobile_device: is_mobile_device)
    end
    raise Applitools::EyesError.new "Unknown driver #{driver}!"
  end
end

.obtain_screenshot_type(is_element, inside_a_frame, stitch_content, force_fullpage) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/applitools/selenium/selenium_eyes.rb', line 41

def obtain_screenshot_type(is_element, inside_a_frame, stitch_content, force_fullpage)
  if stitch_content || force_fullpage
    unless inside_a_frame
      return FULLPAGE_SCREENSHOT if force_fullpage && !stitch_content
      return FULLPAGE_SCREENSHOT if stitch_content && !is_element
    end
    return ENTIRE_ELEMENT_SCREENSHOT if inside_a_frame
    return ENTIRE_ELEMENT_SCREENSHOT if stitch_content
  else
    return VIEWPORT_SCREENSHOT unless stitch_content || force_fullpage
  end
  VIEWPORT_SCREENSHOT
end

.position_provider(stitch_mode, driver, disable_horizontal = false, disable_vertical = false, explicit_entire_size = nil) ⇒ Object



735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
# File 'lib/applitools/selenium/selenium_eyes.rb', line 735

def position_provider(stitch_mode, driver, disable_horizontal = false, disable_vertical = false,
  explicit_entire_size = nil)

  max_width = nil
  max_height = nil
  unless explicit_entire_size.nil?
    max_width = explicit_entire_size.width
    max_height = explicit_entire_size.height
  end
  case stitch_mode
  when Applitools::Selenium::StitchModes::SCROLL
    Applitools::Selenium::ScrollPositionProvider.new(driver, disable_horizontal, disable_vertical,
      max_width, max_height)
  when Applitools::Selenium::StitchModes::CSS
    Applitools::Selenium::CssTranslatePositionProvider.new(driver, disable_horizontal, disable_vertical,
      max_width, max_height)
  end
end

.set_viewport_size(driver, viewport_size) ⇒ Object

Set the viewport size.

Parameters:



59
60
61
# File 'lib/applitools/selenium/selenium_eyes.rb', line 59

def set_viewport_size(driver, viewport_size)
  super
end

Instance Method Details

#abort_asyncObject



416
417
418
# File 'lib/applitools/selenium/selenium_eyes.rb', line 416

def abort_async
  abort
end

#add_mouse_trigger(mouse_action, element) ⇒ Object



603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
# File 'lib/applitools/selenium/selenium_eyes.rb', line 603

def add_mouse_trigger(mouse_action, element)
  if disabled?
    logger.info "Ignoring #{mouse_action} (disabled)"
    return
  end

  if element.is_a? Hash
    return add_mouse_trigger_by_region_and_location(mouse_action, element[:region], element[:location]) if
        element.key?(:location) && element.key?(:region)
    raise Applitools::EyesIllegalArgument.new 'Element[] doesn\'t contain required keys!'
  end

  Applitools::ArgumentGuard.not_nil element, 'element'
  Applitools::ArgumentGuard.is_a? element, 'element', Applitools::Selenium::Element

  pl = element.location
  ds = element.size

  element_region = Applitools::Region.new(pl.x, pl.y, ds.width, ds.height)

  unless last_screenshot
    logger.info "Ignoring #{mouse_action} (no screenshot)"
    return
  end

  unless driver.frame_chain.same_frame_chain? last_screenshot.frame_chain
    logger.info "Ignoring #{mouse_action} (different_frame)"
    return
  end

  add_mouse_trigger_base(mouse_action, element_region, element_region.middle_offset)
end

#add_mouse_trigger_by_region_and_location(mouse_action, control, cursor) ⇒ Object

control - Region cursor - Location



638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
# File 'lib/applitools/selenium/selenium_eyes.rb', line 638

def add_mouse_trigger_by_region_and_location(mouse_action, control, cursor)
  unless last_screenshot
    logger.info "Ignoring #{mouse_action} (no screenshot)"
    return
  end

  Applitools::ArgumentGuard.is_a? control, 'control', Applitools::Region
  Applitools::ArgumentGuard.is_a? cursor, 'cursor', Applitools::Location

  if driver.frame_chain.same_frame_chain? last_screenshot.frame_chain
    logger.info "Ignoring #{mouse_action} (different_frame)"
    return
  end

  add_mouse_trigger_base(mouse_action, control, cursor)
end

#add_text_trigger(control, text) ⇒ Object



586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
# File 'lib/applitools/selenium/selenium_eyes.rb', line 586

def add_text_trigger(control, text)
  if disabled?
    logger.info "Ignoring #{text} (disabled)"
    return
  end

  Applitools::ArgumentGuard.not_nil control, 'control'
  return _add_text_trigger(control, text) if control.is_a? Applitools::Region

  pl = control.location
  ds = control.size

  element_region = Applitools::Region.new(pl.x, pl.y, ds.width, ds.height)

  return _add_text_trigger(element_region, text) if control.is_a? Applitools::Selenium::Element
end

#check(*args) ⇒ Applitools::MatchResult

Takes a snapshot and matches it with the expected output.

Parameters:

Returns:

  • (Applitools::MatchResult)

    The match results.



232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
# File 'lib/applitools/selenium/selenium_eyes.rb', line 232

def check(*args)
  args.compact!
  case (first_arg = args.shift)
  when String
    name = first_arg
    target = args.shift
  when Applitools::Selenium::Target
    target = first_arg
  when Hash
    target = first_arg[:target]
    name = first_arg[:name] || first_arg[:tag]
  end
  logger.info "check(#{name}) is called"
  self.tag_for_debug = name
  Applitools::ArgumentGuard.is_a? target, 'target', Applitools::Selenium::Target

  return universal_check(name, target)

  target_to_check = target.finalize
  original_overflow = nil
  original_position_provider = position_provider
  original_force_full_page_screenshot = force_full_page_screenshot

  timeout = target_to_check.options[:timeout] || USE_DEFAULT_MATCH_TIMEOUT

  self.eyes_screenshot_factory = lambda do |image|
    Applitools::Selenium::ViewportScreenshot.new(
      image,
      region_provider: region_to_check
    )
  end

  self.prevent_dom_processing = send_dom?(target_to_check) ? false : true

  # rubocop:disable BlockLength
  check_in_frame target_frames: target_to_check.frames do
    begin
      match_data = Applitools::MatchWindowData.new(default_match_settings)
      match_data.tag = name
      match_data.variation_group_id = target_to_check.options[:variation_group_id] if target_to_check.options[:variation_group_id]
      eyes_element = target_to_check.region_to_check.call(driver)

      unless force_full_page_screenshot
        region_visibility_strategy.move_to_region(
          original_position_provider,
          Applitools::Location.new(eyes_element.location.x.to_i, eyes_element.location.y.to_i)
        )
        driver.find_element(:css, 'html').scroll_data_attribute = true
      end

      region_provider = Applitools::Selenium::RegionProvider.new(driver, region_for_element(eyes_element))

      self.region_to_check = region_provider

      match_data.read_target(target_to_check, driver)
      match_data.use_dom = use_dom unless match_data.use_dom
      match_data.enable_patterns = enable_patterns unless match_data.enable_patterns

      is_element = eyes_element.is_a? Applitools::Selenium::Element
      inside_a_frame = !driver.frame_chain.empty?

      self.screenshot_type = self.class.obtain_screenshot_type(
        is_element,
        inside_a_frame,
        target_to_check.options[:stitch_content],
        force_full_page_screenshot
      )

      case screenshot_type
      when ENTIRE_ELEMENT_SCREENSHOT
        if eyes_element.is_a? Applitools::Selenium::Element
          original_overflow = eyes_element.overflow
          eyes_element.overflow = 'hidden'
          eyes_element.scroll_data_attribute = true
          eyes_element.overflow_data_attribute = original_overflow
          self.position_provider = Applitools::Selenium::CssTranslateElementPositionProvider.new(
            driver,
            eyes_element
          )
          ensure_block = -> { eyes_element.overflow = original_overflow if original_overflow }
        end
      else
        if hide_scrollbars
          begin
            original_overflow = self.utils.hide_scrollbars driver
            driver.find_element(:css, 'html').overflow_data_attribute = original_overflow
          rescue Applitools::EyesDriverOperationException => e
            logger.warn "Failed to hide scrollbars! Error: #{e.message}"
          ensure
            ensure_block = lambda do
              begin
                self.utils.set_overflow driver, original_overflow if original_overflow
              rescue Applitools::EyesDriverOperationException => e
                logger.warn "Failed to revert overflow! Error: #{e.message}"
              end
            end
          end
        end
      end

      check_window_base(
        region_provider, timeout, match_data
      )
    ensure
      ensure_block.call if ensure_block
      self.check_frame_or_element = false
      self.force_full_page_screenshot = original_force_full_page_screenshot
      self.position_provider = original_position_provider
      self.region_to_check = nil
      self.full_page_capture_algorithm_left_top_offset = Applitools::Location::TOP_LEFT
      region_visibility_strategy.return_to_original_position original_position_provider
    end
    # rubocop:enable BlockLength
  end
  self.prevent_dom_processing = false
end

#close_asyncObject



412
413
414
# File 'lib/applitools/selenium/selenium_eyes.rb', line 412

def close_async
  close(false)
end

#configure {|config| ... } ⇒ Object

Yields:



138
139
140
141
# File 'lib/applitools/selenium/selenium_eyes.rb', line 138

def configure
  return unless block_given?
  yield(config)
end

#dom_dataObject



397
398
399
400
401
402
403
404
405
# File 'lib/applitools/selenium/selenium_eyes.rb', line 397

def dom_data
  return {} if prevent_dom_processing
  begin
    Applitools::Selenium::DomCapture.full_window_dom(driver, server_connector, logger, position_provider)
  rescue Applitools::EyesError => e
    logger.error "DOM capture failed! #{e.message}"
    return {}
  end
end

#ensure_configObject



134
135
136
# File 'lib/applitools/selenium/selenium_eyes.rb', line 134

def ensure_config
  self.config = Applitools::Selenium::Configuration.new
end

#open(options = {}) ⇒ Applitools::Selenium::Driver

Starts a test

Parameters:

  • options (Hash) (defaults to: {})

    options

Options Hash (options):

  • :driver (Object)

    The driver that controls the browser hosting the application under the test. (Required option)

  • :app_name (String)

    The name of the application under the test. (Required option)

  • :test_name (String)

    The test name (Required option)

  • :viewport_size (String | Hash)

    The required browser’s viewport size (i.e., the visible part of the document’s body) or nil to use the current window’s viewport.

  • :session_type (Object)

    The type of the test (e.g., standard test / visual performance test). Default value is ‘SEQUENTAL’

Returns:



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/applitools/selenium/selenium_eyes.rb', line 156

def open(options = {})
  # runner.add_batch(batch.id) { runner.close_batch(batch.id) } if runner
  universal_open(options)
  # original_driver = options.delete(:driver)
  # options[:viewport_size] = Applitools::RectangleSize.from_any_argument options[:viewport_size] if
  #     options[:viewport_size]
  # Applitools::ArgumentGuard.not_nil original_driver, 'options[:driver]'
  # # Applitools::ArgumentGuard.hash options, 'open(options)', [:app_name, :test_name]
  #
  # if disabled?
  #   logger.info('Ignored')
  #   return driver
  # end
  #
  # @driver = self.class.eyes_driver(original_driver, self)
  # perform_driver_specific_settings(original_driver)
  #
  # self.device_pixel_ratio = UNKNOWN_DEVICE_PIXEL_RATIO
  # self.position_provider = self.class.position_provider(
  #   stitch_mode, driver, disable_horizontal_scrolling, disable_vertical_scrolling, explicit_entire_size
  # )
  #
  # self.eyes_screenshot_factory = lambda do |image|
  #   Applitools::Selenium::ViewportScreenshot.new(
  #     image, driver: @driver, force_offset: position_provider.force_offset
  #   )
  # end
  #
  # open_base(options) do
  #   self.viewport_size = get_viewport_size if force_driver_resolution_as_viewport_size
  #   ensure_running_session
  # end
  # if runner
  #   runner.add_batch(batch.id) do
  #     server_connector.close_batch(batch.id)
  #   end
  # end
  # @driver
end