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

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



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/applitools/selenium/selenium_eyes.rb', line 111

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.hide_scrollbars = 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 = false
  self.use_dom = false
  self.enable_patterns = false
  self.prevent_dom_processing = false
end

Instance Attribute Details

#base_agent_idObject

Returns the value of attribute base_agent_id.



97
98
99
# File 'lib/applitools/selenium/selenium_eyes.rb', line 97

def base_agent_id
  @base_agent_id
end

#configObject

Returns the value of attribute config.



97
98
99
# File 'lib/applitools/selenium/selenium_eyes.rb', line 97

def config
  @config
end

#debug_screenshot_providerObject

Returns the value of attribute debug_screenshot_provider.



97
98
99
# File 'lib/applitools/selenium/selenium_eyes.rb', line 97

def debug_screenshot_provider
  @debug_screenshot_provider
end

#debug_screenshotsObject

Returns the value of attribute debug_screenshots.



97
98
99
# File 'lib/applitools/selenium/selenium_eyes.rb', line 97

def debug_screenshots
  @debug_screenshots
end

#disable_horizontal_scrollingObject

Returns the value of attribute disable_horizontal_scrolling.



97
98
99
# File 'lib/applitools/selenium/selenium_eyes.rb', line 97

def disable_horizontal_scrolling
  @disable_horizontal_scrolling
end

#disable_vertical_scrollingObject

Returns the value of attribute disable_vertical_scrolling.



97
98
99
# File 'lib/applitools/selenium/selenium_eyes.rb', line 97

def disable_vertical_scrolling
  @disable_vertical_scrolling
end

#driverObject (readonly)

Returns the value of attribute driver.



102
103
104
# File 'lib/applitools/selenium/selenium_eyes.rb', line 102

def driver
  @driver
end

#enable_patternsObject

Returns the value of attribute enable_patterns.



97
98
99
# File 'lib/applitools/selenium/selenium_eyes.rb', line 97

def enable_patterns
  @enable_patterns
end

#explicit_entire_sizeObject

Returns the value of attribute explicit_entire_size.



97
98
99
# File 'lib/applitools/selenium/selenium_eyes.rb', line 97

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



97
98
99
100
101
# File 'lib/applitools/selenium/selenium_eyes.rb', line 97

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,
:config

#full_page_capture_algorithm_left_top_offsetObject

Returns the value of attribute full_page_capture_algorithm_left_top_offset.



97
98
99
# File 'lib/applitools/selenium/selenium_eyes.rb', line 97

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



97
98
99
100
101
# File 'lib/applitools/selenium/selenium_eyes.rb', line 97

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,
:config

#screenshotObject

Returns the value of attribute screenshot.



97
98
99
# File 'lib/applitools/selenium/selenium_eyes.rb', line 97

def screenshot
  @screenshot
end

#screenshot_typeObject

Returns the value of attribute screenshot_type.



97
98
99
# File 'lib/applitools/selenium/selenium_eyes.rb', line 97

def screenshot_type
  @screenshot_type
end

#send_domObject

Returns the value of attribute send_dom.



97
98
99
# File 'lib/applitools/selenium/selenium_eyes.rb', line 97

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)



97
98
99
100
101
# File 'lib/applitools/selenium/selenium_eyes.rb', line 97

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,
:config

#stitching_overlapObject

Returns the value of attribute stitching_overlap.



97
98
99
# File 'lib/applitools/selenium/selenium_eyes.rb', line 97

def stitching_overlap
  @stitching_overlap
end

#use_domObject

Returns the value of attribute use_dom.



97
98
99
# File 'lib/applitools/selenium/selenium_eyes.rb', line 97

def use_dom
  @use_dom
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.



97
98
99
100
101
# File 'lib/applitools/selenium/selenium_eyes.rb', line 97

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,
:config

Class Method Details

.eyes_driver(driver, eyes = nil) ⇒ Object



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

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



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

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



713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
# File 'lib/applitools/selenium/selenium_eyes.rb', line 713

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:



58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/applitools/selenium/selenium_eyes.rb', line 58

def set_viewport_size(driver, viewport_size)
  Applitools::ArgumentGuard.not_nil(driver, 'Driver')
  Applitools::ArgumentGuard.not_nil(viewport_size, 'viewport_size')
  Applitools::ArgumentGuard.is_a?(viewport_size, 'viewport_size', Applitools::RectangleSize)
  begin
    Applitools::Utils::EyesSeleniumUtils.set_viewport_size eyes_driver(driver), viewport_size
  rescue => e
    Applitools::EyesLogger.error e.class
    Applitools::EyesLogger.error e.message
    raise Applitools::EyesError.new 'Failed to set viewport size!'
  end
end

Instance Method Details

#abort_asyncObject



379
380
381
# File 'lib/applitools/selenium/selenium_eyes.rb', line 379

def abort_async
  abort
end

#add_mouse_trigger(mouse_action, element) ⇒ Object



584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
# File 'lib/applitools/selenium/selenium_eyes.rb', line 584

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



619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
# File 'lib/applitools/selenium/selenium_eyes.rb', line 619

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



567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
# File 'lib/applitools/selenium/selenium_eyes.rb', line 567

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(name, target) ⇒ Applitools::MatchResult

Takes a snapshot and matches it with the expected output.

Parameters:

Returns:

  • (Applitools::MatchResult)

    The match results.



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

def check(name, target)
  logger.info "check(#{name}) is called"
  self.tag_for_debug = name
  Applitools::ArgumentGuard.is_a? target, 'target', Applitools::Selenium::Target
  target_to_check = target.finalize
  original_overflow = nil
  original_position_provider = position_provider
  original_force_full_page_screenshot = force_full_page_screenshot

  eyes_element = nil
  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 = !((!target.options[:send_dom].nil? && target.options[:send_dom]) ||
  #     send_dom || stitch_mode == Applitools::STITCH_MODE[:css])

  self.prevent_dom_processing = !((!target.options[:send_dom].nil? && target.options[:send_dom]) ||
      send_dom)

  check_in_frame target_frames: target_to_check.frames do
    begin
      match_data = Applitools::MatchWindowData.new(default_match_settings)
      match_data.tag = name
      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
          )
        end
      end

      check_window_base(
        region_provider, timeout, match_data
      )
    ensure
      eyes_element.overflow = original_overflow unless original_overflow.nil?
      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



375
376
377
# File 'lib/applitools/selenium/selenium_eyes.rb', line 375

def close_async
  close(false)
end

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

Yields:



145
146
147
148
# File 'lib/applitools/selenium/selenium_eyes.rb', line 145

def configure
  return unless block_given?
  yield(config)
end

#dom_dataObject



365
366
367
368
369
370
371
372
373
# File 'lib/applitools/selenium/selenium_eyes.rb', line 365

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



141
142
143
# File 'lib/applitools/selenium/selenium_eyes.rb', line 141

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:



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
195
196
197
198
199
# File 'lib/applitools/selenium/selenium_eyes.rb', line 163

def 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