240 lines
6.2 KiB
Ruby
240 lines
6.2 KiB
Ruby
module Capybara::Webkit
|
|
class Node < Capybara::Driver::Node
|
|
def initialize(driver, base, browser)
|
|
super(driver, base)
|
|
@browser = browser
|
|
end
|
|
|
|
def visible_text
|
|
text = invoke(:text).to_s
|
|
if Capybara::VERSION.to_f < 3.0
|
|
Capybara::Helpers.normalize_whitespace(text)
|
|
else
|
|
text.gsub(/\ +/, ' ')
|
|
.gsub(/[\ \n]*\n[\ \n]*/, "\n")
|
|
.gsub(/\A[[:space:]&&[^\u00a0]]+/, "")
|
|
.gsub(/[[:space:]&&[^\u00a0]]+\z/, "")
|
|
.tr("\u00a0", ' ')
|
|
end
|
|
end
|
|
alias_method :text, :visible_text
|
|
|
|
def all_text
|
|
text = invoke(:allText)
|
|
if Capybara::VERSION.to_f < 3.0
|
|
Capybara::Helpers.normalize_whitespace(text)
|
|
else
|
|
text.gsub(/[\u200b\u200e\u200f]/, '')
|
|
.gsub(/[\ \n\f\t\v\u2028\u2029]+/, ' ')
|
|
.gsub(/\A[[:space:]&&[^\u00a0]]+/, "")
|
|
.gsub(/[[:space:]&&[^\u00a0]]+\z/, "")
|
|
.tr("\u00a0", ' ')
|
|
end
|
|
end
|
|
|
|
def [](name)
|
|
name = name.to_s
|
|
tn = tag_name
|
|
if (tn == "img" && name == "src") || (tn == "a" && name == "href")
|
|
# Although the attribute matters, the property is consistent. Return that in
|
|
# preference to the attribute for links and images.
|
|
# if attribute exists get the property
|
|
val = invoke(:attribute, name) && invoke(:property, name)
|
|
else
|
|
val = invoke(:property, name)
|
|
val = invoke(:attribute, name) if val.nil? || val.is_a?(Hash)
|
|
end
|
|
val
|
|
end
|
|
|
|
def value
|
|
if multiple_select?
|
|
self.find_xpath(".//option").select(&:selected?).map(&:value)
|
|
else
|
|
invoke "value"
|
|
end
|
|
end
|
|
|
|
def inner_html
|
|
invoke 'getInnerHTML'
|
|
end
|
|
|
|
def inner_html=(value)
|
|
invoke 'setInnerHTML', value
|
|
end
|
|
|
|
def set(value, options = {})
|
|
warn "Options passed to Node#set but capybara-webkit doesn't currently support any - ignoring" unless options.empty?
|
|
invoke "set", *[value].flatten
|
|
end
|
|
|
|
def send_keys(*keys)
|
|
# Currently unsupported keys specified by Capybara
|
|
# :separator
|
|
invoke("sendKeys", convert_to_named_keys(keys).to_json)
|
|
end
|
|
|
|
def select_option
|
|
invoke "selectOption"
|
|
end
|
|
|
|
def unselect_option
|
|
select = find_xpath("ancestor::select").first
|
|
if select.multiple_select?
|
|
invoke "unselectOption"
|
|
else
|
|
raise Capybara::UnselectNotAllowed
|
|
end
|
|
end
|
|
|
|
def click(keys = [], offset = {})
|
|
invoke("leftClick", keys.to_json, offset.to_json)
|
|
end
|
|
|
|
def double_click(keys = [], offset = {})
|
|
invoke("doubleClick", keys.to_json, offset.to_json)
|
|
end
|
|
|
|
def right_click(keys = [], offset = {})
|
|
invoke("rightClick", keys.to_json, offset.to_json)
|
|
end
|
|
|
|
def hover
|
|
invoke("hover")
|
|
end
|
|
|
|
def drag_to(element)
|
|
invoke 'dragTo', element.native
|
|
end
|
|
|
|
def tag_name
|
|
invoke "tagName"
|
|
end
|
|
|
|
def visible?
|
|
invoke("visible") == true
|
|
end
|
|
|
|
def selected?
|
|
invoke("selected") == true
|
|
end
|
|
|
|
def checked?
|
|
!!self["checked"]
|
|
end
|
|
|
|
def disabled?
|
|
xpath = "parent::optgroup[@disabled] | " \
|
|
"ancestor::select[@disabled] | " \
|
|
"parent::fieldset[@disabled] | " \
|
|
"ancestor::*[not(self::legend) or " \
|
|
"preceding-sibling::legend][parent::fieldset[@disabled]]"
|
|
|
|
self["disabled"] || !find_xpath(xpath).empty?
|
|
end
|
|
|
|
def path
|
|
invoke "path"
|
|
end
|
|
|
|
def submit(opts = {})
|
|
invoke "submit"
|
|
end
|
|
|
|
def trigger(event)
|
|
invoke "trigger", event
|
|
end
|
|
|
|
def find_xpath(xpath)
|
|
invoke("findXpathWithin", xpath).split(',').map do |native|
|
|
self.class.new(driver, native, @browser)
|
|
end
|
|
end
|
|
|
|
alias_method :find, :find_xpath
|
|
|
|
def find_css(selector)
|
|
invoke("findCssWithin", selector).split(',').map do |native|
|
|
self.class.new(driver, native, @browser)
|
|
end
|
|
end
|
|
|
|
def invoke(name, *args)
|
|
result = @browser.command "Node", name, allow_unattached_nodes?, native, *args
|
|
JSON.parse(result, quirks_mode: true)
|
|
end
|
|
|
|
def allow_unattached_nodes?
|
|
!automatic_reload?
|
|
end
|
|
|
|
def automatic_reload?
|
|
session_option(:automatic_reload)
|
|
end
|
|
|
|
def attached?
|
|
warn "[DEPRECATION] The Capybara::Webkit::Node#attached? " \
|
|
"method is deprecated without replacement."
|
|
result = @browser.command("Node", "isAttached", native)
|
|
JSON.parse(result, quirks_mode: true)
|
|
end
|
|
|
|
def multiple_select?
|
|
self.tag_name == "select" && self["multiple"]
|
|
end
|
|
|
|
def ==(other)
|
|
invoke("equals", other.native)
|
|
end
|
|
|
|
private
|
|
|
|
def session_option(name)
|
|
if driver.respond_to?(:session_options)
|
|
driver.session_options.public_send(name)
|
|
else
|
|
Capybara.respond_to?(name) && Capybara.public_send(name)
|
|
end
|
|
end
|
|
|
|
def convert_to_named_keys(key)
|
|
if key.is_a? Array
|
|
key.map { |k| convert_to_named_keys(k)}
|
|
else
|
|
case key
|
|
when :cancel, :help, :backspace, :tab, :clear, :return, :enter, :insert, :delete, :pause, :escape,
|
|
:space, :end, :home, :left, :up, :right, :down, :semicolon,
|
|
:f1, :f2, :f3, :f4, :f5, :f6, :f7, :f8, :f9, :f10, :f11, :f12,
|
|
:shift, :control, :alt, :meta
|
|
{ "key" => key.to_s.capitalize }
|
|
when :equals
|
|
{ "key" => "Equal" }
|
|
when :page_up
|
|
{ "key" => "PageUp" }
|
|
when :page_down
|
|
{ "key" => "PageDown" }
|
|
when :numpad0, :numpad1, :numpad2, :numpad3, :numpad4,
|
|
:numpad5, :numpad6, :numpad7, :numpad8, :numpad9
|
|
{ "key" => key[-1], "modifier" => "keypad" }
|
|
when :multiply
|
|
{ "key" => "Asterisk", "modifier" => "keypad" }
|
|
when :divide
|
|
{ "key" => "Slash", "modifier" => "keypad" }
|
|
when :add
|
|
{ "key" => "Plus", "modifier" => "keypad" }
|
|
when :subtract
|
|
{ "key" => "Minus", "modifier" => "keypad" }
|
|
when :decimal
|
|
{ "key" => "Period", "modifier" => "keypad" }
|
|
when :command
|
|
{ "key" => "Meta" }
|
|
when String
|
|
key.to_s
|
|
else
|
|
raise Capybara::NotSupportedByDriverError.new
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|