class Rudra

Selenium IDE-like WebDriver based upon Ruby binding @author Aaron Chen @attr_reader [Symbol] browser The chosen browser @attr_reader [Selenium::WebDriver::Driver] driver The driver instance

of the chosen browser

@attr_reader [String] install_dir The install directory of WebDrivers @attr_reader [String] locale The browser locale @attr_reader [Boolean] headless Headless mode for Google Chrome @attr_reader [String] window_size Chrome window size when headless @attr_reader [String] screen_dir The screenshot directory of save_screenshot @attr_reader [String] log_prefix Prefix for logging descriptions and methods @attr_reader [Integer] timeout The driver timeout @attr_reader [Boolean] verbose Turn on/off Verbose mode @attr_reader [Boolean] silent Turn off Turn on/off descriptions @attr_reader [String] auth_username username for Basic Access Authentication Extension (Chrome only) @attr_reader [String] auth_password password for Basic Access Authentication Extension (Chrome only)

Constants

ATTRIBUTES

Attributes

BROWSERS

Supported Browsers

HOWS

Element Finder Methods

Attributes

auth_password[RW]
auth_username[RW]
browser[R]
driver[R]
headless[R]
install_dir[R]
locale[R]
log_prefix[R]
main_label[RW]
screen_dir[R]
silent[RW]
timeout[R]
verbose[R]
window_size[RW]

Public Class Methods

new(options = {}) click to toggle source

Initialize an instance of Rudra @param [Hash] options the options to initialize Rudra @option options [Symbol] :browser (:chrome) the supported

browsers: :chrome, :firefox, :safari

@option options [String] :install_dir ('./webdrivers/') the install

directory of WebDrivers

@option options [Symbol] :locale (:en) the browser locale @option options [Boolean] :headless (false) headless mode @option options [String] :window_size ('1280,720') window size when headless @option options [String] :screen_dir ('./screens/') the location of screenshots @option options [String] :log_prefix (' - ') prefix for logging descriptions and methods @option options [Integer] :timeout (30) implicit_wait timeout @option options [Boolean] :verbose (false) Turn on/off verbose mode @option options [Boolean] :silent (false) Turn on/off descriptions @option options [String] :auth_username ('') username for Basic Access Authentication extension @option options [String] :auth_password ('') password for Basic Access Authentication extension

# File lib/rudra.rb, line 63
def initialize(options = {})
  self.browser = options.fetch(:browser, :chrome)
  self.install_dir = options.fetch(:install_dir, './webdrivers/')
  self.locale = options.fetch(:locale, :en)
  self.headless = options.fetch(:headless, false)
  self.window_size = options.fetch(:window_size, '1280,720')
  self.screen_dir = options.fetch(:screen_dir, './screens/')
  self.log_prefix = options.fetch(:log_prefix, ' - ')
  self.verbose = options.fetch(:verbose, false)
  self.silent = options.fetch(:silent, false)
  self.auth_username = options.fetch(:auth_username, '')
  self.auth_password = options.fetch(:auth_password, '')
  self.main_label = caller_locations(2, 1).first.label

  initialize_driver

  self.timeout = options.fetch(:timeout, 30)
end

Public Instance Methods

action() click to toggle source

Initialize ActionBuilder @return [Selenium::WebDriver::ActionBuilder] ActionBuilder

# File lib/rudra.rb, line 88
def action
  driver.action
end
active_element() click to toggle source

Get the active element @return [Selenium::WebDriver::Element] the active element

# File lib/rudra.rb, line 94
def active_element
  driver.switch_to.active_element
end
alert_accept() click to toggle source

Accept an alert

# File lib/rudra.rb, line 110
def alert_accept
  switch_to_alert.accept
end
alert_dismiss() click to toggle source

Dismiss an alert

# File lib/rudra.rb, line 115
def alert_dismiss
  switch_to_alert.dismiss
end
alert_send_keys(keys) click to toggle source

Send keys to an alert @param [String] keys keystrokes to send

# File lib/rudra.rb, line 121
def alert_send_keys(keys)
  switch_to_alert.send_keys(keys)
end
attribute(locator, attribute) click to toggle source

Get the value of the given attribute of the element, identified by locator @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element

@param [String] attribute the name of the attribute @return [String, nil] attribute value

# File lib/rudra.rb, line 478
def attribute(locator, attribute)
  find_element(locator).attribute(attribute)
end
attribute?(locator, attribute) click to toggle source

If the element, identified by locator, has the given attribute @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element

@param [String] attribute the name of the attribute @return [Boolean] the result of the existence of the given attribute

# File lib/rudra.rb, line 487
def attribute?(locator, attribute)
  execute_script(%(
    return arguments[0].hasAttribute(arguments[1]);
  ), find_element(locator), attribute)
end
back() click to toggle source

Move back a single entry in the browser's history

# File lib/rudra.rb, line 126
def back
  driver.navigate.back
end
blank() click to toggle source

Open a blank page

# File lib/rudra.rb, line 131
def blank
  open('about:blank')
end
blur(locator) click to toggle source

Blur the given element, identfied by locator @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element
# File lib/rudra.rb, line 496
def blur(locator)
  execute_script(
    'var element = arguments[0]; element.blur();',
    find_element(locator)
  )
end
clear(locator) click to toggle source

Clear the input of the given element, identified by locator @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element
# File lib/rudra.rb, line 506
def clear(locator)
  find_element(locator).clear
end
clear_drawings() click to toggle source

Clear all drawing

# File lib/rudra.rb, line 871
def clear_drawings
  execute_script(%(
    var elements = window.document.body.querySelectorAll('[id*="rudra_"]');
    for (var i = 0; i < elements.length; i++) {
      elements[i].remove();
    }
    window.rudraTooltipSymbol = 9311;
    window.rudraTooltipLastPos = { x: 0, y: 0 };
  ))
end
click(locator) click to toggle source

Click the given element, identified by locator @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element
# File lib/rudra.rb, line 513
def click(locator)
  wait_for do
    begin
      element = find_element(locator)
      element.enabled? && element.click.nil?
    rescue Selenium::WebDriver::Error::ElementClickInterceptedError
      false
    end
  end
end
click_at(locator, offset = {}) click to toggle source

Click the given element, identified by locator, with an offset @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element

@param [Hash] offset the offset coordinates @option offset [Integer] :x (0) offset on x coordinate @option offset [Integer] :y (0) offset on y coordinate

# File lib/rudra.rb, line 530
def click_at(locator, offset = {})
  x = offset.fetch(:x, 0)
  y = offset.fetch(:y, 0)

  element = find_element(locator)

  action
    .move_to(element, x, y)
    .click
    .perform
end
close() click to toggle source

Close the current window, or the browser if no windows are left

# File lib/rudra.rb, line 136
def close
  driver.close
end
css_value(locator, property) click to toggle source

Get the value of the given CSS property of the given element @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element

@param [String] property the longhand name of the property

# File lib/rudra.rb, line 546
def css_value(locator, property)
  find_element(locator).css_value(property)
end
current_url() click to toggle source

Get the URL of the current page @return (String) the URL of the current page

# File lib/rudra.rb, line 149
def current_url
  driver.current_url
end
delete_all_cookies() click to toggle source

Delete all cookies

# File lib/rudra.rb, line 154
def delete_all_cookies
  driver.manage.delete_all_cookies
end
displayed?(locator) click to toggle source

If the given element, identified by locator, is displayed @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element

@return [Boolean]

# File lib/rudra.rb, line 554
def displayed?(locator)
  find_element(locator).displayed?
end
double_click(locator, offset = {}) click to toggle source

Double-click the given element, identified by locator, with an offset @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element

@param [Hash] offset the offset coordinates @option offset [Integer] :x (0) offset on x coordinate @option offset [Integer] :y (0) offset on y coordinate

# File lib/rudra.rb, line 564
def double_click(locator, offset = {})
  x = offset.fetch(:x, 0)
  y = offset.fetch(:y, 0)

  element = find_element(locator)

  action
    .move_to(element, x, y)
    .double_click
    .perform
end
drag_and_drop(from_locator, to_locator) click to toggle source

Drag and drop @param [String] from_locator the locator to emulate button down at @param [String] to_locator the locator to to move to and release

the mouse at
# File lib/rudra.rb, line 580
def drag_and_drop(from_locator, to_locator)
  el1 = find_element(from_locator)
  el2 = find_element(to_locator)

  action.drag_and_drop(el1, el2).perform
end
drag_and_drop_by(source, offset = {}) click to toggle source

Drag and drop to an offset @param [String] source the locator to emulate button down at @param [Hash] offset the offset coordinates @option offset [Integer] :x (0) offset on x coordinate @option offset [Integer] :y (0) offset on y coordinate

# File lib/rudra.rb, line 592
def drag_and_drop_by(source, offset = {})
  element = find_element(source)
  x = offset.fetch(:x, 0)
  y = offset.fetch(:y, 0)

  action.drag_and_drop_by(element, x, y).perform
end
draw_arrow(from_locator, to_locator) click to toggle source

Draw an arrow from an element to an element2 @param [String, Selenium::WebDriver::Element] from_locator the locator

or Selenium::WebDriver::Element where the arrow starts

@param [String, Selenium::WebDriver::Element] to_locator the locator

or Selenium::WebDriver::Element where the arrow ends

@return [Selenium::WebDriver::Element] the arrow element

# File lib/rudra.rb, line 888
def draw_arrow(from_locator, to_locator)
  id = random_id

  execute_script(%(
    var element1 = arguments[0];
    var element2 = arguments[1];
    var rect1 = element1.getBoundingClientRect();
    var rect2 = element2.getBoundingClientRect();
    var from = {y: rect1.top};
    var to = {y: rect2.top};
    if (rect1.left > rect2.left) {
      from.x = rect1.left; to.x = rect2.right;
    } else if (rect1.left < rect2.left) {
      from.x = rect1.right; to.x = rect2.left;
    } else {
      from.x = rect1.left; to.x = rect2.left;
    }
    // create canvas
    var canvas = document.createElement('canvas');
    canvas.id = "#{id}";
    canvas.style.left = "0px";
    canvas.style.top = "0px";
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    canvas.style.zIndex = '100000';
    canvas.style.position = "absolute";
    document.body.appendChild(canvas);
    var headlen = 10;
    var angle = Math.atan2(to.y - from.y, to.x - from.x);
    var ctx = canvas.getContext("2d");
    // line
    ctx.beginPath();
    ctx.moveTo(from.x, from.y);
    ctx.lineTo(to.x, to.y);
    ctx.lineWidth  = 3;
    ctx.strokeStyle = '#f00';
    ctx.stroke();
    // arrow
    ctx.beginPath();
    ctx.moveTo(to.x, to.y);
    ctx.lineTo(
      to.x - headlen * Math.cos(angle - Math.PI/7),
      to.y - headlen * Math.sin(angle - Math.PI/7)
    );
    ctx.lineTo(
      to.x - headlen * Math.cos(angle + Math.PI/7),
      to.y - headlen * Math.sin(angle + Math.PI/7)
    );
    ctx.lineTo(to.x, to.y);
    ctx.lineTo(
      to.x - headlen * Math.cos(angle - Math.PI/7),
      to.y - headlen * Math.sin(angle - Math.PI/7)
    );
    ctx.lineWidth  = 3;
    ctx.strokeStyle = '#f00';
    ctx.stroke();
    return;
  ), find_element(from_locator), find_element(to_locator))

  find_element("id=#{id}")
end
draw_color_fill(locator, color = 'rgba(255,0,0,0.8)') click to toggle source

Draw color fill on the given element, identfied by locator @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element

@param [String] color CSS style of backgroundColor @return [Selenium::WebDriver::Element] the color fill element

# File lib/rudra.rb, line 955
def draw_color_fill(locator, color = 'rgba(255,0,0,0.8)')
  rectangle = rect(locator)
  id = random_id

  execute_script(%(
    var colorfill = window.document.createElement('div');
    colorfill.id = '#{id}';
    colorfill.style.backgroundColor = '#{color}';
    colorfill.style.border = 'none';
    colorfill.style.display = 'block';
    colorfill.style.height = #{rectangle.height} + 'px';
    colorfill.style.left = #{rectangle.x} + 'px';
    colorfill.style.margin = '0px';
    colorfill.style.padding = '0px';
    colorfill.style.position = 'absolute';
    colorfill.style.top = #{rectangle.y} + 'px';
    colorfill.style.width = #{rectangle.width} + 'px';
    colorfill.style.zIndex = '99999';
    window.document.body.appendChild(colorfill);
    return;
  ))

  find_element("id=#{id}")
end
draw_flyover(locator, options = {}) click to toggle source

Draw tooltip of the given element, identfied by locator @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element

@param [Hash] options the options to create a tooltip @option options [String] :attribute (title) attribute to draw

the flyover with

@option options [Integer] :offset_x (5) offset on x coordinate @option options [Integer] :offset_y (15) offset on y coordinate @option options [Boolean] :from_last_pos (false) if to draw

from last position

@option options [Boolean] :draw_symbol (false) if to draw symbol @return [Selenium::WebDriver::Element] the tooltip element

# File lib/rudra.rb, line 992
def draw_flyover(locator, options = {})
  attribute_name = options.fetch(:attribute, 'title')
  offset_x = options.fetch(:offset_x, 5)
  offset_y = options.fetch(:offset_y, 15)
  from_last_pos = options.fetch(:from_last_pos, false)
  draw_symbol = options.fetch(:draw_symbol, false)

  symbol_id = random_id
  tooltip_id = random_id

  execute_script(%(
    var element = arguments[0];
    if (! window.rudraTooltipSymbol) {
      window.rudraTooltipSymbol = 9311;
    }
    if (! window.rudraTooltipLastPos) {
      window.rudraTooltipLastPos = { x: 0, y: 0 };
    }
    var rect = element.getBoundingClientRect();
    var title = element.getAttribute("#{attribute_name}") || 'N/A';
    var left = window.scrollX + rect.left;
    var top = window.scrollY + rect.top;
    if (#{draw_symbol}) {
      window.rudraTooltipSymbol++;
      var symbol = document.createElement('div');
      symbol.id = "#{symbol_id}";
      symbol.textContent = String.fromCharCode(rudraTooltipSymbol);
      symbol.style.color = '#f00';
      symbol.style.display = 'block';
      symbol.style.fontSize = '12px';
      symbol.style.left = (left - 12) + 'px';
      symbol.style.position = 'absolute';
      symbol.style.top = top + 'px';
      symbol.style.zIndex = '99999';
      document.body.appendChild(symbol);
    }
    var tooltip = document.createElement('div');
    tooltip.id = "#{tooltip_id}";
    tooltip.textContent = (#{draw_symbol}) ?
      String.fromCharCode(rudraTooltipSymbol) + " " + title : title;
    tooltip.style.position = 'absolute';
    tooltip.style.color = '#000';
    tooltip.style.backgroundColor = '#F5FCDE';
    tooltip.style.border = '3px solid #f00';
    tooltip.style.fontSize = '12px';
    tooltip.style.zIndex = '99999';
    tooltip.style.display = 'block';
    tooltip.style.height = '16px';
    tooltip.style.padding = '2px';
    tooltip.style.verticalAlign = 'middle';
    tooltip.style.top = ((#{from_last_pos}) ?
      window.rudraTooltipLastPos.y : (top + #{offset_y})) + 'px';
    tooltip.style.left = ((#{from_last_pos}) ?
      window.rudraTooltipLastPos.x : (left + #{offset_x})) + 'px';
    document.body.appendChild(tooltip);
    if (tooltip.scrollHeight > tooltip.offsetHeight) {
      tooltip.style.height = (tooltip.scrollHeight + 3) + 'px';
    }
    var lastPos = tooltip.getBoundingClientRect();
    window.rudraTooltipLastPos = {
      x: window.scrollX + lastPos.left, y: window.scrollY + lastPos.bottom
    };
    return;
  ), find_element(locator))

  find_element("id=#{tooltip_id}")
end
draw_redmark(locator, padding = {}) click to toggle source

Draw redmark around the given element, identfied by locator @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element

@param [Hash] padding the padding of the given redmark @option padding [Integer] :top (5) top padding @option padding [Integer] :right (5) right padding @option padding [Integer] :bottom (5) bottom padding @option padding [Integer] :left (5) left padding @return [Selenium::WebDriver::Element] the redmark element

# File lib/rudra.rb, line 1069
def draw_redmark(locator, padding = {})
  top = padding.fetch(:top, 5)
  right = padding.fetch(:right, 5)
  bottom = padding.fetch(:bottom, 5)
  left = padding.fetch(:left, 5)

  rectangle = rect(locator)
  id = random_id

  execute_script(%(
    var redmark = window.document.createElement('div');
    redmark.id = '#{id}';
    redmark.style.border = '3px solid red';
    redmark.style.display = 'block';
    redmark.style.height = (#{rectangle.height} + 8 + #{bottom}) + 'px';
    redmark.style.left = (#{rectangle.x} - 4 - #{left}) + 'px';
    redmark.style.margin = '0px';
    redmark.style.padding = '0px';
    redmark.style.position = 'absolute';
    redmark.style.top = (#{rectangle.y} - 4 - #{top}) + 'px';
    redmark.style.width = (#{rectangle.width} + 8 + #{right}) + 'px';
    redmark.style.zIndex = '99999';
    window.document.body.appendChild(redmark);
    return;
  ))

  find_element("id=#{id}")
end
draw_select(locator, options = {}) click to toggle source

Draw dropdown menu on the given SELECT element, identfied by locator @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element

@param [Hash] options the options to create the dropdown menu @option options [Integer] :offset_x (0) offset on x coordinate @option options [Integer] :offset_y (0) offset on y coordinate @return [Selenium::WebDriver::Element] the dropdown menu element

# File lib/rudra.rb, line 1105
def draw_select(locator, options = {})
  offset_x = options.fetch(:offset_x, 0)
  offset_y = options.fetch(:offset_y, 0)

  id = random_id

  execute_script(%(
    var element = arguments[0];
    var rect = element.getBoundingClientRect();
    var x = rect.left;
    var y = rect.bottom;
    var width = element.offsetWidth;
    function escape(str) {
      return str.replace(
        /[\\x26\\x0A<>'"]/g,
        function(r) { return "&#" + r.charCodeAt(0) + ";"; }
      );
    }
    var content = "";
    for (var i = 0; i < element.length; i++) {
      if (!element.options[i].disabled) {
        content += escape(element.options[i].text) + "<br />";
      }
    }
    var dropdown = document.createElement('div');
    dropdown.id = "#{id}";
    dropdown.innerHTML = content;
    dropdown.style.backgroundColor = '#fff';
    dropdown.style.border = '1px solid #000';
    dropdown.style.color = '#000';
    dropdown.style.display = 'block';
    dropdown.style.fontSize = '12px';
    dropdown.style.height = '1px';
    dropdown.style.padding = '2px';
    dropdown.style.position = 'absolute';
    dropdown.style.width = width + 'px';
    dropdown.style.zIndex = '99999';
    document.body.appendChild(dropdown);
    dropdown.style.height = (dropdown.scrollHeight + 8) + 'px';
    if (dropdown.scrollWidth > width) {
      dropdown.style.width = (dropdown.scrollWidth + 8) + 'px';
    }
    dropdown.style.left = (x + #{offset_x}) + "px";
    dropdown.style.top = (y + #{offset_y}) + "px";
    return;
  ), find_element(locator))

  find_element("id=#{id}")
end
draw_text(locator, text, options = {}) click to toggle source

Draw text on top of the given element, identfied by locator @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element

@param [String] text the text to draw @param [Hash] options the options to create the text @option options [String] :color ('#f00') the color of the text @option options [Integer] :font_size (13) the font size of the text @option options [Integer] :top (2) CSS style of top @option options [Integer] :right (20) CSS style of right @return [Selenium::WebDriver::Element] the text element

# File lib/rudra.rb, line 1165
def draw_text(locator, text, options = {})
  color = options.fetch(:color, '#f00')
  font_size = options.fetch(:font_size, 13)
  top = options.fetch(:top, 2)
  right = options.fetch(:right, 20)

  rect = rect(locator)
  id = random_id

  execute_script(%(
    var textbox = window.document.createElement('div');
    textbox.id = '#{id}';
    textbox.innerText = '#{text}';
    textbox.style.border = 'none';
    textbox.style.color = '#{color}';
    textbox.style.display = 'block';
    textbox.style.font = '#{font_size}px Verdana, sans-serif';
    textbox.style.left = #{rect.x} + 'px';
    textbox.style.margin = '0';
    textbox.style.padding = '0';
    textbox.style.position = 'absolute';
    textbox.style.right = #{right} + 'px';
    textbox.style.top = (#{rect.y} + #{rect.height} + #{top}) + 'px';
    textbox.style.zIndex = '99999';
    window.document.body.appendChild(textbox);
    return;
  ))

  find_element("id=#{id}")
end
element_found?(locator, seconds = 1) click to toggle source

Check if an element is found @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element

@param [Integer] seconds seconds before timed out

# File lib/rudra.rb, line 168
def element_found?(locator, seconds = 1)
  how, what = parse_locator(locator)

  implicit_wait(seconds)

  begin
    wait_for(seconds) { driver.find_element(how, what).displayed? }
  rescue Selenium::WebDriver::Error::TimeoutError
    false
  rescue Net::ReadTimeout
    false
  ensure
    implicit_wait(timeout)
  end
end
enabled?(locator) click to toggle source

If the given element, identified by locator, is enabled @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element

@return [Boolean]

# File lib/rudra.rb, line 604
def enabled?(locator)
  find_element(locator).enabled?
end
execute_script(script, *args) click to toggle source

Execute the given JavaScript @param [String] script JavaScript source to execute @param [Selenium::WebDriver::Element, Integer, Float, Boolean, NilClass,

String, Array] args arguments will be available in the given script
in the 'arguments' pseudo-array

@return [Selenium::WebDriver::Element, Integer, Float, Boolean, NilClass,

String, Array] the value returned from the script
# File lib/rudra.rb, line 191
def execute_script(script, *args)
  driver.execute_script(script, *args)
end
find_element(locator) click to toggle source

Find the first element matching the given locator @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element

@return [Selenium::WebDriver::Element] the element found

# File lib/rudra.rb, line 199
def find_element(locator)
  return locator if locator.is_a?(Selenium::WebDriver::Element)

  element = nil
  how, what = parse_locator(locator)

  if how == :css
    new_what, nth = what.scan(/(.*):eq\((\d+)\)/).flatten
    element = find_elements("#{how}=#{new_what}")[nth.to_i] if nth
  end

  element ||= driver.find_element(how, what)

  raise Selenium::WebDriver::Error::NoSuchElementError, "Failed to find element: #{locator}" unless element

  wait_for { element.displayed? }

  element
end
find_elements(locator) click to toggle source

Find all elements matching the given locator @param [String] locator the locator to identify the elements @return [Array<Selenium::WebDriver::Element>] the elements found

# File lib/rudra.rb, line 222
def find_elements(locator)
  how, what = parse_locator(locator)
  elements = driver.find_elements(how, what)

  raise Selenium::WebDriver::Error::NoSuchElementError, "Failed to find elements: #{locator}" if elements.empty?

  elements
end
focus(locator) click to toggle source

Focus the given element, identfied by locator @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element
# File lib/rudra.rb, line 611
def focus(locator)
  execute_script(
    'var element = arguments[0]; element.focus();',
    find_element(locator)
  )
end
forward() click to toggle source

Move forward a single entry in the browser's history

# File lib/rudra.rb, line 232
def forward
  driver.navigate.forward
end
full_screen() click to toggle source

Make the current window full screen

# File lib/rudra.rb, line 237
def full_screen
  driver.manage.window.full_screen
end
hide(locator) click to toggle source

Hide the given element, identfied by locator @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element
# File lib/rudra.rb, line 621
def hide(locator)
  execute_script(%(
    arguments[0].style.display = 'none';
  ), find_element(locator))
end
highlight(locator) click to toggle source

Hightlight the given element, identfied by locator @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element
# File lib/rudra.rb, line 630
def highlight(locator)
  execute_script(%(
    arguments[0].style.backgroundColor = '#ff3';
  ), find_element(locator))
end
implicit_wait(seconds) click to toggle source

Set implicit_wait timeout @param [Integer] seconds timeout for implicit_wait

# File lib/rudra.rb, line 638
def implicit_wait(seconds)
  driver.manage.timeouts.implicit_wait = seconds
end
js_click(locator) click to toggle source

Click the given element, identified by locator, via Javascript @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element
# File lib/rudra.rb, line 645
def js_click(locator)
  execute_script('arguments[0].click();', find_element(locator))
end
location(locator) click to toggle source

Get the location of the given element, identfied by locator @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element

@return [Selenium::WebDriver::Point] the point of the given element

# File lib/rudra.rb, line 653
def location(locator)
  find_element(locator).location
end
maximize() click to toggle source

Maximize the current window

# File lib/rudra.rb, line 247
def maximize
  driver.manage.window.maximize unless headless
end
maximize_to_screen() click to toggle source

Maximize the current window to the size of the screen

# File lib/rudra.rb, line 252
def maximize_to_screen
  size = execute_script(%(
    return { width: window.screen.width, height: window.screen.height };
  ))

  move_window_to(0, 0)
  resize_window_to(size['width'], size['height'])
end
minimize() click to toggle source

Minimize the current window

# File lib/rudra.rb, line 262
def minimize
  driver.manage.window.minimize
end
mkdir(dir) click to toggle source

Create directories, recursively, for the given dir @param [String] dir the directories to create

# File lib/rudra.rb, line 1198
def mkdir(dir)
  FileUtils.mkdir_p(dir)
end
move_by(right_by = 0, down_by = 0) click to toggle source

Moves the mouse from its current position (or 0,0) by the given offset @param [Integer] right_by horizontal offset @param [Integer] down_by vertical offset

# File lib/rudra.rb, line 660
def move_by(right_by = 0, down_by = 0)
  action.move_by(right_by, down_by).perform
end
move_to(locator, offset = {}) click to toggle source

Move to the given element, identified by locator, with an offset @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element

@param [Hash] offset the offset coordinates @option offset [Integer] :x (0) offset on x coordinate @option offset [Integer] :y (0) offset on y coordinate

# File lib/rudra.rb, line 670
def move_to(locator, offset = {})
  x = offset.fetch(:x, 0)
  y = offset.fetch(:y, 0)

  element = find_element(locator)

  action
    .move_to(element, x, y)
    .perform
end
move_window_to(point_x, point_y) click to toggle source

Move the current window to the given position @param [Integer] point_x the x coordinate @param [Integer] point_y the y coordinate

# File lib/rudra.rb, line 269
def move_window_to(point_x, point_y)
  driver.manage.window.move_to(point_x, point_y)
end
new_tab() click to toggle source

Open a new tab @return [String] the id of the new tab obtained from window_handles

# File lib/rudra.rb, line 275
def new_tab
  execute_script('window.open();')
  window_handles.last
end
new_window(name) click to toggle source

Open a new window @param [String] name the name of the window

# File lib/rudra.rb, line 282
def new_window(name)
  execute_script(%(
    var w = Math.max(
      document.documentElement.clientWidth, window.innerWidth || 0
    );
    var h = Math.max(
      document.documentElement.clientHeight, window.innerHeight || 0
    );
    window.open("about:blank", arguments[0], `width=${w},height=${h}`);
  ), name)
end
open(url) click to toggle source

Open the specified URL in the browser @param [String] url the URL of the page to open

# File lib/rudra.rb, line 296
def open(url)
  driver.get(url)
end
page_load(seconds) click to toggle source

Set page_load timeout @param [Integer] seconds timeout for page_load

# File lib/rudra.rb, line 683
def page_load(seconds)
  driver.manage.timeouts.page_load = seconds
end
page_source() click to toggle source

Get the source of the current page @return (String) the source of the current page

# File lib/rudra.rb, line 302
def page_source
  driver.page_source
end
puts(description) click to toggle source

Print description in the console @param [String] description description to show

# File lib/rudra.rb, line 308
def puts(description)
  $stdout.puts "#{log_prefix}#{description.chomp}" unless silent
end
quit() click to toggle source

Quit the browser

# File lib/rudra.rb, line 242
def quit
  driver.quit
end
rect(locator) click to toggle source

Get the dimensions and coordinates of the given element, identfied by locator @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element

@return [Selenium::WebDriver::Rectangle] the retangle of the given element

# File lib/rudra.rb, line 692
def rect(locator)
  find_element(locator).rect
end
refresh() click to toggle source

Refresh the current pagef

# File lib/rudra.rb, line 313
def refresh
  driver.navigate.refresh
end
remove_attribute(locator, attribute) click to toggle source

Remove the given attribute from the given element, identfied by locator @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element

@param [String] attribute the name of the attribute

# File lib/rudra.rb, line 701
def remove_attribute(locator, attribute)
  execute_script(%(
    var element = arguments[0];
    var attributeName = arguments[1];
    if (element.hasAttribute(attributeName)) {
      element.removeAttribute(attributeName);
    }
  ), find_element(locator), attribute)
end
resize_window_to(width, height) click to toggle source

Resize the current window to the given dimension @param [Integer] width the width of the window @param [Integer] height the height of the window

# File lib/rudra.rb, line 320
def resize_window_to(width, height)
  driver.manage.window.resize_to(width, height)
end
right_click(locator, offset = {}) click to toggle source

Right-click the given element, identified by locator, with an offset @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element

@param [Hash] offset the offset coordinates @option offset [Integer] :x (0) offset on x coordinate @option offset [Integer] :y (0) offset on y coordinate

# File lib/rudra.rb, line 717
def right_click(locator, offset = {})
  x = offset.fetch(:x, 0)
  y = offset.fetch(:y, 0)

  element = find_element(locator)
  action.move_to(element, x, y).context_click.perform
end
save_screenshot(filename) click to toggle source

Save a PNG screenshot to file @param [String] filename the filename of PNG screenshot

# File lib/rudra.rb, line 326
def save_screenshot(filename)
  file = File.join(
    @screen_dir,
    sanitize(filename.end_with?('.png') ? filename : "#{filename}.png")
  )

  dir = File.dirname(file)

  mkdir(dir) unless Dir.exist?(dir)

  driver.save_screenshot(file)
end
script_timeout(seconds) click to toggle source

Set script_timeout timeout @param [Integer] seconds timeout for script_timeout

# File lib/rudra.rb, line 727
def script_timeout(seconds)
  driver.manage.timeouts.script_timeout = seconds
end
scroll_into_view(locator, align_to = true) click to toggle source

Scroll the given element, identfied by locator, into view @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element

@param [Boolean] align_to true if aligned on top or

false if aligned at the bottom
# File lib/rudra.rb, line 736
def scroll_into_view(locator, align_to = true)
  execute_script(
    'arguments[0].scrollIntoView(arguments[1]);',
    find_element(locator),
    align_to
  )
end
select(option_locator) click to toggle source

Select the given option, identified by locator @param [String, Selenium::WebDriver::Element] option_locator the locator to

identify the element or Selenium::WebDriver::Element
# File lib/rudra.rb, line 747
def select(option_locator)
  find_element(option_locator).click
end
selected?(locator) click to toggle source

If the given element, identified by locator, is selected @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element

@return [Boolean]

# File lib/rudra.rb, line 755
def selected?(locator)
  find_element(locator).selected?
end
send_keys(locator, *args) click to toggle source

Send keystrokes to the given element, identfied by locator @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element

@param [String, Symbol, Array] args keystrokes to send

# File lib/rudra.rb, line 763
def send_keys(locator, *args)
  find_element(locator).send_keys(*args)
end
set_attribute(locator, attribute, value) click to toggle source

Set the attribute's value of the given element, identfied by locator @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element

@param [String] attribute the name of the attribute @param [String] value the value of the attribute

# File lib/rudra.rb, line 772
def set_attribute(locator, attribute, value)
  execute_script(%(
    var element = arguments[0];
    var attribute = arguments[1];
    var value = arguments[2];
    element.setAttribute(attribute, value);
  ), find_element(locator), attribute, value)
end
show(locator) click to toggle source

Show the given element, identfied by locator @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element
# File lib/rudra.rb, line 784
def show(locator)
  execute_script(%(
    arguments[0].style.display = '';
  ), find_element(locator))
end
size(locator) click to toggle source

Get the size of the given element, identfied by locator @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element

@return [Selenium::WebDriver::Dimension]

# File lib/rudra.rb, line 794
def size(locator)
  find_element(locator).size
end
submit(locator) click to toggle source

Submit the given element, identfied by locator @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element
# File lib/rudra.rb, line 801
def submit(locator)
  find_element(locator).submit
end
switch_to_alert() click to toggle source

Switch to the currently active modal dialog

# File lib/rudra.rb, line 340
def switch_to_alert
  driver.switch_to.alert
end
switch_to_default_content() click to toggle source

Select either the first frame on the page, or the main document when a page contains iframes

# File lib/rudra.rb, line 346
def switch_to_default_content
  driver.switch_to.default_content
end
switch_to_frame(id) click to toggle source

Switch to the frame with the given id @param [String] id the frame id

# File lib/rudra.rb, line 352
def switch_to_frame(id)
  driver.switch_to.frame(id)
end
switch_to_frame_and_wait_for_element_found(frame_id, locator) click to toggle source

Switch to a frame and wait until the element, identified by locator, is found @param [String] frame_id the frame id @param [String] locator the locator to identify the element

# File lib/rudra.rb, line 390
def switch_to_frame_and_wait_for_element_found(frame_id, locator)
  switch_to_frame frame_id

  how, what = parse_locator(locator)

  wait_for do
    begin
      driver.find_element(how, what)
    rescue Selenium::WebDriver::Error::NoSuchWindowError
      false
    end
  end
end
switch_to_parent_frame() click to toggle source

Switch to the parent frame

# File lib/rudra.rb, line 357
def switch_to_parent_frame
  driver.switch_to.parent_frame
end
switch_to_window(id) click to toggle source

Switch to the given window handle @param [String] id the window handle obtained through window_handles

# File lib/rudra.rb, line 363
def switch_to_window(id)
  driver.switch_to.window(id)
end
tag_name(locator) click to toggle source

Get the tag name of the given element, identfied by locator @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element

@return [String] the tag name of the given element

# File lib/rudra.rb, line 809
def tag_name(locator)
  find_element(locator).tag_name
end
text(locator) click to toggle source

Get the text content of the given element, identfied by locator @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element

@return [String] the text content of the given element

# File lib/rudra.rb, line 817
def text(locator)
  find_element(locator).text
end
title() click to toggle source

Get the title of the current page @return [String] the title of the current page

# File lib/rudra.rb, line 369
def title
  driver.title
end
trigger(locator, event) click to toggle source

Trigger the given event on the given element, identfied by locator @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element

@param [String] event the event name

# File lib/rudra.rb, line 825
def trigger(locator, event)
  execute_script(%(
    var element = arguments[0];
    var eventName = arguments[1];
    var event = new Event(eventName, {"bubbles": false, "cancelable": false});
    element.dispatchEvent(event);
  ), find_element(locator), event)
end
wait_for(seconds = timeout) { || ... } click to toggle source

Wait until the given block returns a true value @param [Integer] seconds seconds before timed out @return [Object] the result of the block

# File lib/rudra.rb, line 376
def wait_for(seconds = timeout)
  Selenium::WebDriver::Wait.new(timeout: seconds).until { yield }
end
wait_for_attribute_to_include(locator, attribute, value) click to toggle source

Wait until the element, identified by locator, attribute has value @param [String, Selenium::WebDriver::Element] locator the locator to identify the element @param [String] attribute the name of the attribute @param [String] value the value of the attribute

# File lib/rudra.rb, line 838
def wait_for_attribute_to_include(locator, attribute, value)
  how, what = parse_locator(locator)

  wait_for do
    begin
      driver.find_element(how, what)&.attribute(attribute)&.downcase&.include?(value.downcase)
    rescue Selenium::WebDriver::Error::StaleElementReferenceError
      false
    end
  end
end
wait_for_enabled(locator) click to toggle source

Wait until the element, identified by locator, is enabled @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element
# File lib/rudra.rb, line 383
def wait_for_enabled(locator)
  wait_for { find_element(locator).enabled? }
end
wait_for_not_visible(locator, seconds = 3) click to toggle source

Wait (in seconds) until the element is not displayed @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element

@param [Integer] seconds seconds before timed out

# File lib/rudra.rb, line 408
def wait_for_not_visible(locator, seconds = 3)
  how, what = parse_locator(locator)

  implicit_wait(seconds)

  begin
    wait_for(seconds) do
      begin
        elements = driver.find_elements(how, what)
        elements.empty? || elements.map(&:displayed?).none?
      rescue Selenium::WebDriver::Error::StaleElementReferenceError
        false
      end
    end
  rescue Selenium::WebDriver::Error::TimeoutError
    true
  rescue Net::ReadTimeout
    true
  ensure
    implicit_wait(timeout)
  end
end
wait_for_text_to_exclude(locator, string) click to toggle source

Wait until the element, identified by locator, excluding string in text @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element

@param [String] string the string to exclude

# File lib/rudra.rb, line 854
def wait_for_text_to_exclude(locator, string)
  wait_for { text(locator).exclude?(string) }
end
wait_for_text_to_include(locator, string) click to toggle source

Wait until the element, identified by locator, including string in text @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element

@param [String] string the string to compare

# File lib/rudra.rb, line 862
def wait_for_text_to_include(locator, string)
  wait_for { text(locator).include?(string) }
end
wait_for_title(string) click to toggle source

Wait until the title of the page including the given string @param [String] string the string to compare

# File lib/rudra.rb, line 433
def wait_for_title(string)
  wait_for { title.downcase.include?(string.downcase) }
end
wait_for_url(url) click to toggle source

Wait until the URL of the page including the given url @param [String] url the URL to compare

# File lib/rudra.rb, line 439
def wait_for_url(url)
  wait_for { current_url.include?(url) }
end
wait_for_visible(locator) click to toggle source

Wait until the element, identified by locator, is visible @param [String, Selenium::WebDriver::Element] locator the locator to

identify the element or Selenium::WebDriver::Element
# File lib/rudra.rb, line 446
def wait_for_visible(locator)
  wait_for { find_element(locator).displayed? }
end
window_handle() click to toggle source

Get the current window handle @return [String] the id of the current window handle

# File lib/rudra.rb, line 452
def window_handle
  driver.window_handle
end
window_handles() click to toggle source

Get the window handles of open browser windows @return [Array<String>] the ids of window handles

# File lib/rudra.rb, line 458
def window_handles
  driver.window_handles
end
zoom(scale) click to toggle source

Zoom the current page @param [Float] scale the scale of zoom

# File lib/rudra.rb, line 464
def zoom(scale)
  execute_script(%(document.body.style.zoom = arguments[0];), scale)
end

Private Instance Methods

browser=(brw) click to toggle source
# File lib/rudra.rb, line 1218
def browser=(brw)
  unless BROWSERS.include?(brw)
    browsers = BROWSERS.map { |b| ":#{b}" }.join(', ')
    abort("Supported browsers are: #{browsers}")
  end

  @browser = brw
end
chrome_basic_auth_extension(username, password) click to toggle source
# File lib/rudra.rb, line 1373
  def chrome_basic_auth_extension(username, password)
    manifest = {
      "manifest_version": 2,
      "name": 'Rudra Basic Access Authentication Extension',
      "version": '1.0.0',
      "permissions": ['*://*/*', 'webRequest', 'webRequestBlocking'],
      "background": {
        "scripts": ['background.js']
      }
    }

    background = <<~JAVASCRIPT
      var username = '#{username}';
      var password = '#{password}';

      chrome.webRequest.onAuthRequired.addListener(
        function handler(details) {
          if (username == null) {
            return { cancel: true };
          }

          var authCredentials = { username: username, password: username };
          username = password = null;

          return { authCredentials: authCredentials };
        },
        { urls: ['<all_urls>'] },
        ['blocking']
      );
    JAVASCRIPT

    stringio = Zip::OutputStream.write_buffer do |zos|
      zos.put_next_entry('manifest.json')
      zos.write manifest.to_json
      zos.put_next_entry('background.js')
      zos.write background
    end
    # File.open('basic_auth.crx', 'wb') do |f|
    #   f << stringio.string
    # end

    Base64.strict_encode64(stringio.string)
  end
chrome_options() click to toggle source
# File lib/rudra.rb, line 1280
def chrome_options
  options = Selenium::WebDriver::Chrome::Options.new
  options.add_argument('--disable-notifications')
  options.add_argument('--ignore-ssl-errors=yes')
  options.add_argument('--ignore-certificate-errors')

  if headless
    options.add_argument('--headless')
    options.add_argument("--window-size=#{window_size}")
  end

  if auth_username
    if headless
      $stdout.puts('Basic Access Authentication Extension cannot be installed while headless')
    else
      encoded = chrome_basic_auth_extension(auth_username, auth_password)
      options.add_encoded_extension(encoded)
    end
  end

  options.add_option(
    'excludeSwitches',
    %w[enable-automation enable-logging]
  )
  options.add_preference('intl.accept_languages', locale)
  options
end
firefox_options() click to toggle source

def edge_options

Selenium::WebDriver::Edge::Options.new

end

# File lib/rudra.rb, line 1312
def firefox_options
  options = Selenium::WebDriver::Firefox::Options.new
  options.add_preference('intl.accept_languages', locale)
  options.add_argument('--headless') if headless
  options
end
headless=(mode) click to toggle source
# File lib/rudra.rb, line 1239
def headless=(mode)
  @headless = true?(mode)
end
ie_options() click to toggle source
# File lib/rudra.rb, line 1319
def ie_options
  options = Selenium::WebDriver::IE::Options.new
  options.ensure_clean_session = true
  options.full_page_screenshot = true
  options.ignore_protected_mode_settings = true
  options.ignore_zoom_level = true
  options.native_events = false
  options
end
initialize_driver() click to toggle source
# File lib/rudra.rb, line 1266
def initialize_driver
  @driver = if browser == :chrome
              Selenium::WebDriver.for(:chrome, options: chrome_options)
            # elsif browser == :edge
            #   Selenium::WebDriver.for(:edge, options: edge_options)
            elsif browser == :firefox
              Selenium::WebDriver.for(:firefox, options: firefox_options)
            elsif browser == :ie
              Selenium::WebDriver.for(:ie, options: ie_options)
            else
              Selenium::WebDriver.for(:safari)
            end
end
install_dir=(path) click to toggle source
# File lib/rudra.rb, line 1227
def install_dir=(path)
  Webdrivers.install_dir = @install_dir = path
end
locale=(loc) click to toggle source
# File lib/rudra.rb, line 1231
def locale=(loc)
  @locale = if browser == :firefox
              loc.to_s.sub('_', '-').gsub(/(-[a-zA-Z]{2})$/, &:downcase)
            else
              loc.to_s.sub('_', '-').gsub(/(-[a-zA-Z]{2})$/, &:upcase)
            end
end
log(method_name, *args) click to toggle source
# File lib/rudra.rb, line 1349
def log(method_name, *args)
  return unless verbose && caller_locations(2, 1).first.label == main_label

  arguments = args.map(&:to_s).join(', ')

  puts log_prefix + (
    arguments.empty? ? method_name.to_s : "#{method_name}(#{arguments})"
  )
end
log_prefix=(prefix) click to toggle source
# File lib/rudra.rb, line 1247
def log_prefix=(prefix)
  @log_prefix = prefix.chomp
end
parse_locator(locator) click to toggle source
# File lib/rudra.rb, line 1329
def parse_locator(locator)
  unmatched, how, what = locator.split(/^([A-Za-z]+)=(.+)/)

  how = if !unmatched.strip.empty?
          what = unmatched
          case unmatched
          when /^[\.#\[]/
            :css
          when %r{^(\/|\()}
            :xpath
          end
        else
          how.to_sym
        end

  raise Selenium::WebDriver::Error::InvalidSelectorError, "Cannot parse locator: #{locator}" unless HOWS.include?(how)

  [how, what]
end
random_id(length = 8) click to toggle source
# File lib/rudra.rb, line 1367
def random_id(length = 8)
  charset = [(0..9), ('a'..'z')].flat_map(&:to_a)
  id = Array.new(length) { charset.sample }.join
  "rudra_#{id}"
end
sanitize(filename) click to toggle source
# File lib/rudra.rb, line 1359
def sanitize(filename)
  invalid_characters = ['/', '\\', '?', '%', '*', ':', '|', '"', '<', '>']
  invalid_characters.each do |character|
    filename.gsub!(character, '')
  end
  filename
end
screen_dir=(path) click to toggle source
# File lib/rudra.rb, line 1243
def screen_dir=(path)
  @screen_dir = File.join(path, @locale.to_s)
end
timeout=(seconds) click to toggle source
# File lib/rudra.rb, line 1251
def timeout=(seconds)
  implicit_wait(seconds)
  page_load(seconds)
  script_timeout(seconds)
  @timeout = seconds
end
true?(mode) click to toggle source
# File lib/rudra.rb, line 1262
def true?(mode)
  [1, true, '1', 'true'].include?(mode)
end
verbose=(mode) click to toggle source
# File lib/rudra.rb, line 1258
def verbose=(mode)
  @verbose = true?(mode)
end