Class: Applitools::Selenium::Driver

Inherits:
SimpleDelegator
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/applitools/selenium/driver.rb

Constant Summary collapse

RIGHT_ANGLE =
90
FINDERS =

Available finders

{
  class: 'class name',
  class_name: 'class name',
  css: 'css',
  id: 'id',
  link: 'link text',
  link_text: 'link text',
  name: 'name',
  partial_link_text: 'partial link text',
  tag_name: 'tag name',
  xpath: 'xpath'
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(eyes, options) ⇒ Driver

Initializes a class instance.

If driver is not provided, Applitools::Selenium::Driver will raise an EyesError exception.

Parameters:

Options Hash (options):

  • :driver (Selenium::WebDriver::Driver)

    The Selenium webdriver instance.

  • :is_mobile_device (Boolean)

    Whether is a mobile device or not.



46
47
48
49
50
51
52
53
# File 'lib/applitools/selenium/driver.rb', line 46

def initialize(eyes, options)
  super(options[:driver])
  @is_mobile_device = options.fetch(:is_mobile_device, false)
  @eyes = eyes
  @frame_chain = Applitools::Selenium::FrameChain.new
  @browser = Applitools::Selenium::Browser.new(self, @eyes)
  Applitools::EyesLogger.warn '"screenshot_as" method not found!' unless driver.respond_to? :screenshot_as
end

Instance Attribute Details

#browserObject (readonly)

Returns the value of attribute browser.



32
33
34
# File 'lib/applitools/selenium/driver.rb', line 32

def browser
  @browser
end

#rotationObject

Returns the value of attribute rotation.



33
34
35
# File 'lib/applitools/selenium/driver.rb', line 33

def rotation
  @rotation
end

Class Method Details

.normalize_image(driver, image, rotation) ⇒ Object



333
334
335
336
# File 'lib/applitools/selenium/driver.rb', line 333

def normalize_image(driver, image, rotation)
  normalize_rotation(driver, image, rotation)
  normalize_width(driver, image)
end

.normalize_rotation(driver, image, rotation) ⇒ Object

Rotates the image as necessary. The rotation is either manually forced by passing a value in the rotation parameter, or automatically inferred if the rotation parameter is nil.

driver

Applitools::Selenium::Driver The driver which produced the screenshot.

image

ChunkyPNG::Canvas The image to normalize.

rotation

Integer|nil The degrees by which to rotate the image: positive values = clockwise rotation,

negative values = counter-clockwise, 0 = force no rotation, +nil+ = rotate automatically when needed.


345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
# File 'lib/applitools/selenium/driver.rb', line 345

def normalize_rotation(driver, image, rotation)
  return if rotation && rotation.zero?

  num_quadrants = 0
  if !rotation.nil?
    if (rotation % RIGHT_ANGLE).nonzero?
      raise Applitools::EyesError.new('Currently only quadrant rotations are supported. Current rotation: '\
      "#{rotation}")
    end
    num_quadrants = (rotation / RIGHT_ANGLE).to_i
  elsif rotation.nil? && driver.mobile_device? && driver.landscape_orientation? && image.height > image.width
    # For Android, we need to rotate images to the right, and for iOS to the left.
    num_quadrants = driver.android? ? 1 : -1
  end

  Applitools::Utils::ImageUtils.quadrant_rotate!(image, num_quadrants)
end

.normalize_width(driver, image) ⇒ Object



363
364
365
366
367
368
# File 'lib/applitools/selenium/driver.rb', line 363

def normalize_width(driver, image)
  return if driver.mobile_device?

  normalization_factor = driver.browser.image_normalization_factor(image)
  Applitools::Utils::ImageUtils.scale!(image, normalization_factor) unless normalization_factor == 1
end

Instance Method Details

#default_content_viewport_size(force_query = false) ⇒ Applitools::RectangleSize

Gets default_content_viewport_size.

Parameters:

  • force_query (Boolean) (defaults to: false)

    if set to true, forces querying of viewport size from the browser, otherwise returns cached value.

Returns:

  • (Applitools::RectangleSize)

    The default content viewport size.



207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/applitools/selenium/driver.rb', line 207

def default_content_viewport_size(force_query = false)
  logger.info('default_content_viewport_size()')
  if cached_default_content_viewport_size && !force_query
    logger.info "Using cached viewport_size #{cached_default_content_viewport_size}"
    return cached_default_content_viewport_size
  end

  current_frames = frame_chain
  switch_to.default_content unless current_frames.empty?
  logger.info 'Extracting viewport size...'
  @cached_default_content_viewport_size = utils.extract_viewport_size(self)
  logger.info "Done! Viewport size is #{@cached_default_content_viewport_size}"

  switch_to.frames(frame_chain: current_frames) unless current_frames.empty?
  @cached_default_content_viewport_size
end

#execute_script(*args) ⇒ Object

Executes javascript in browser context.

Raises:

  • (Applitools::EyesDriverOperationException)


58
59
60
# File 'lib/applitools/selenium/driver.rb', line 58

def execute_script(*args)
  raises_error { __getobj__.execute_script(*args) }
end

#find_element(how, what) ⇒ Applitools::Selenium::Element

Finds an element in a window.

Examples:

driver.find_element :css, '.some_class'
driver.find_element :css => '.some_class'
driver.find_element :id, 'element_id'

Parameters:

  • how (Symbol)

    Defines the way that what parameter will be interpreted (finder). Can be one of: :class, :class_name, :css, :id, :link, :link_text, :name, :partial_link_text, :tag_name, :xpath

  • what (String)

    The selector to find an element

Returns:

Raises:

  • (ArgumentError)

    if invalid finder (how) is passed



140
141
142
143
144
145
146
147
# File 'lib/applitools/selenium/driver.rb', line 140

def find_element(*args)
  how, what = extract_args(args)
  return find_element_by_name_or_id(what) if how == :name_or_id
  # Make sure that "how" is a valid locator.
  raise ArgumentError, "cannot find element by: #{how.inspect}" unless FINDERS[how.to_sym]

  Applitools::Selenium::Element.new(self, driver.find_element(how, what))
end

#find_element_by_name_or_id(name_or_id) ⇒ Object



149
150
151
152
153
# File 'lib/applitools/selenium/driver.rb', line 149

def find_element_by_name_or_id(name_or_id)
  found_by_name = find_elements name: name_or_id
  return found_by_name.first unless found_by_name.empty?
  find_element id: name_or_id
end

#find_elements(how, what) ⇒ [Applitools::Selenium::Element]

Finds elements in a window.

Examples:

driver.find_elements :css, '.some_class'
driver.find_elements :css => '.some_class'
driver.find_elements :id, 'element_id'

Parameters:

  • how (Symbol)

    Defines the way that what parameter will be interpreted (finder). Can be one of: :class, :class_name, :css, :id, :link, :link_text, :name, :partial_link_text, :tag_name, :xpath

  • what (String)

    The selector to find an element

Returns:

Raises:

  • (ArgumentError)

    if invalid finder (how) is passed



170
171
172
173
174
175
176
# File 'lib/applitools/selenium/driver.rb', line 170

def find_elements(*args)
  how, what = extract_args(args)

  raise ArgumentError, "cannot find element by: #{how.inspect}" unless FINDERS[how.to_sym]

  driver.find_elements(how, what).map { |el| Applitools::Selenium::Element.new(self, el) }
end

#frame_chainApplitools::Selenium::FrameChain

Returns a copy of current frame chain. Frame chain stores information about all parent frames,

including scroll offset an frame coordinates.

Returns:

  • (Applitools::Selenium::FrameChain)

    The frame chain.



192
193
194
# File 'lib/applitools/selenium/driver.rb', line 192

def frame_chain
  Applitools::Selenium::FrameChain.new other: @frame_chain
end

#frame_chain!Object

Returns current frame chain. Frame chain stores information about all parent frames,

including scroll offset an frame coordinates


198
199
200
# File 'lib/applitools/selenium/driver.rb', line 198

def frame_chain!
  @frame_chain
end

#hide_scrollbarsObject

Hide the main document’s scrollbars and returns the original overflow value.



93
94
95
# File 'lib/applitools/selenium/driver.rb', line 93

def hide_scrollbars
  @browser.hide_scrollbars
end

#landscape_orientation?Boolean

Returns true if the driver orientation is landscape.

Returns:

  • (Boolean)


78
79
80
81
82
83
# File 'lib/applitools/selenium/driver.rb', line 78

def landscape_orientation?
  driver.orientation.to_s.upcase == LANDSCAPE
rescue NameError, Selenium::WebDriver::Error::WebDriverError, Selenium::WebDriver::Error::UnknownError
  Applitools::EyesLogger.debug 'driver has no "orientation" attribute. Assuming: portrait.'
  false
end

#mobile_device?Boolean

Returns true if the platform running the test is a mobile platform. false otherwise.

Returns:

  • (Boolean)


86
87
88
89
90
# File 'lib/applitools/selenium/driver.rb', line 86

def mobile_device?
  # We CAN'T check if the device is an +Appium::Driver+ since it is not a RemoteWebDriver. Because of that we use a
  # flag we got as an option in the constructor.
  @is_mobile_device
end

#overflow=(overflow) ⇒ Object Also known as: set_overflow

Set the overflow value for document element and return the original overflow value.



98
99
100
# File 'lib/applitools/selenium/driver.rb', line 98

def overflow=(overflow)
  @browser.set_overflow(overflow)
end

#remote_web_driverObject

Returns native driver

Returns:

  • Selenium::WebDriver



105
106
107
# File 'lib/applitools/selenium/driver.rb', line 105

def remote_web_driver
  driver
end

#screenshot_as(format) {|png_screenshot| ... } ⇒ String

Takes a screenshot.

Parameters:

  • format (:Symbol)

    A format to store screenshot (one of :base64 or :png)

Yields:

  • (png_screenshot)

Returns:

  • (String)

    A byte string, representing the screenshot



115
116
117
118
119
120
121
122
123
# File 'lib/applitools/selenium/driver.rb', line 115

def screenshot_as(format)
  raise "Invalid format (#{format}) passed! Available formats: :png, :base64" unless [:base64, :png].include? format
  png_screenshot = driver.screenshot_as(:png)
  yield png_screenshot if block_given?
  screenshot = Applitools::Screenshot.from_any_image(png_screenshot)
  self.class.normalize_rotation(self, screenshot, rotation)
  return Applitools::Utils::ImageUtils.base64_from_png_image(screenshot.restore) if format == :base64
  screenshot.to_blob
end

#switch_toObject



224
225
226
227
228
# File 'lib/applitools/selenium/driver.rb', line 224

def switch_to
  @switch_to ||= Applitools::Selenium::EyesTargetLocator.new(
    self, driver.switch_to, FrameChangeEventListener.new(self)
  )
end

#universal_driver_configObject



230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/applitools/selenium/driver.rb', line 230

def universal_driver_config
  if respond_to?(:session_id)
    {
      serverUrl: server_url,
      sessionId: session_id,
      capabilities: capabilities.as_json
    }
  else
    {
      serverUrl: server_url,
      sessionId: bridge.session_id,
      capabilities: capabilities.as_json
    }
  end
end