class Capybara::Apparition::Keyboard

Constants

KEY_DEFINITIONS

/**

* @typedef {Object} KeyDefinition
* @property {number=} keyCode
* @property {number=} shiftKeyCode
* @property {string=} key
* @property {string=} shiftKey
* @property {string=} code
* @property {string=} text
* @property {string=} shiftText
* @property {number=} location
*/
MODIFIERS

Attributes

modifiers[R]

Public Class Methods

new(page) click to toggle source
# File lib/capybara/apparition/page/keyboard.rb, line 7
def initialize(page)
  @page = page
  @modifiers = 0
  @pressed_keys = {}
end

Public Instance Methods

down(description) click to toggle source
# File lib/capybara/apparition/page/keyboard.rb, line 27
def down(description)
  @modifiers |= modifier_bit(description.key)
  @pressed_keys[description.key] = description

  @page.command('Input.dispatchKeyEvent',
                type: 'keyDown',
                modifiers: @modifiers,
                windowsVirtualKeyCode: description.keyCode,
                code: description.code,
                key: description.key,
                text: description.text,
                unmodifiedText: description.text,
                autoRepeat: false,
                location: description.location,
                isKeypad: description.location == 3)
end
press(key) click to toggle source
# File lib/capybara/apparition/page/keyboard.rb, line 17
def press(key)
  if key.is_a? Symbol
    orig_key, key = key, key.to_s.gsub(/([a-z\d])([A-Z])/, '\1_\2').downcase.to_sym
    warn "The use of :#{orig_key} is deprecated, please use :#{key} instead" unless key == orig_key
  end
  description = key_description(key)
  down(description)
  up(description) if modifier_bit(description.key).zero?
end
type(keys, delay:) click to toggle source
# File lib/capybara/apparition/page/keyboard.rb, line 13
def type(keys, delay:)
  type_with_modifiers(Array(keys), delay: delay)
end
up(description) click to toggle source
# File lib/capybara/apparition/page/keyboard.rb, line 44
def up(description)
  @modifiers &= ~modifier_bit(description.key)
  @pressed_keys.delete(description.key)

  @page.command('Input.dispatchKeyEvent',
                type: 'keyUp',
                modifiers: @modifiers,
                key: description.key,
                windowsVirtualKeyCode: description.keyCode,
                code: description.code,
                location: description.location)
end
with_keys(keys = []) { || ... } click to toggle source
# File lib/capybara/apparition/page/keyboard.rb, line 57
def with_keys(keys = [])
  old_pressed_keys, @pressed_keys = @pressed_keys, {}
  keys.each do |key|
    press key
  end
  yield
  release_pressed_keys
  @pressed_keys = old_pressed_keys
end

Private Instance Methods

insert_emoji(str) click to toggle source
# File lib/capybara/apparition/page/keyboard.rb, line 69
def insert_emoji(str)
  @page.command('Input.insertText', text: str)
end
key_description(key) click to toggle source
# File lib/capybara/apparition/page/keyboard.rb, line 109
def key_description(key)
  shift = (@modifiers & modifier_bit('Shift')).nonzero?
  description = OpenStruct.new(
    key: '',
    keyCode: 0,
    code: '',
    text: '',
    location: 0
  )

  if key.to_sym == :return
    warn '[DEPRECATION]: Key symbol :return is deprecated in favor of :enter'
    key = :enter
  end

  definition = KEY_DEFINITIONS[key.to_sym]
  raise KeyError, "Unknown key: #{key}" if definition.nil? && !key.is_a?(String)

  definition ||= { text: key }

  definition = OpenStruct.new definition

  description.key = definition.key if definition.key
  description.key = definition.shiftKey if shift && definition.shiftKey

  description.keyCode = definition.keyCode if definition.keyCode
  description.keyCode = definition.shiftKeyCode if shift && definition.shiftKeyCode

  description.code = definition.code if definition.code

  description.location = definition.location if definition.location

  description.text = description.key if description.key.length == 1
  description.text = definition.text if definition.text
  description.text = definition.shiftText if shift && definition.shiftText

  # if any modifiers besides shift are pressed, no text should be sent
  description.text = '' if (@modifiers & ~modifier_bit('Shift')).nonzero?

  description
end
modifier_bit(key) click to toggle source
# File lib/capybara/apparition/page/keyboard.rb, line 152
def modifier_bit(key)
  MODIFIERS[key]
end
release_pressed_keys() click to toggle source
# File lib/capybara/apparition/page/keyboard.rb, line 105
def release_pressed_keys
  @pressed_keys.each_value { |desc| up(desc) }
end
type_with_modifiers(keys, delay:) click to toggle source
# File lib/capybara/apparition/page/keyboard.rb, line 73
def type_with_modifiers(keys, delay:)
  old_pressed_keys, @pressed_keys = @pressed_keys, {}

  Array(keys).each do |sequence|
    case sequence
    when Array
      type_with_modifiers(sequence, delay: delay)
    when String
      clusters = sequence.grapheme_clusters.chunk { |gc| gc.match?(/\p{Emoji Presentation}/) }
      clusters.each do |emoji, chars|
        if emoji
          insert_emoji(chars.join)
          sleep delay
        else
          chars.each do |char|
            press char
            sleep delay
          end
        end
      end
    else
      press sequence
      sleep delay
    end
  end

  release_pressed_keys
  @pressed_keys = old_pressed_keys

  true
end