class Watir::Element
Base
class for HTML elements.
Public Class Methods
# File lib/watir-webdriver/elements/element.rb, line 25 def initialize(parent, selector) @parent = parent @selector = selector @element = nil unless @selector.kind_of? Hash raise ArgumentError, "invalid argument: #{selector.inspect}" end end
Public Instance Methods
Returns true if two elements are equal.
@example
browser.text_field(name: "new_user_first_name") == browser.text_field(name: "new_user_first_name") #=> true
# File lib/watir-webdriver/elements/element.rb, line 65 def ==(other) other.is_a?(self.class) && wd == other.wd end
Returns given attribute value of element.
@example
browser.a(id: "link_2").attribute_value "title" #=> "link_title_2"
@param [String] attribute_name @return [String, nil]
# File lib/watir-webdriver/elements/element.rb, line 270 def attribute_value(attribute_name) assert_exists element_call { @element.attribute attribute_name } end
Returns browser.
@return [Watir::Browser]
# File lib/watir-webdriver/elements/element.rb, line 492 def browser @parent.browser end
Clicks the element, optionally while pressing the given modifier keys. Note that support for holding a modifier key is currently experimental, and may not work at all.
@example Click an element
browser.element(name: "new_user_button").click
@example Click an element with shift key pressed
browser.element(name: "new_user_button").click(:shift)
@example Click an element with several modifier keys pressed
browser.element(name: "new_user_button").click(:shift, :control)
@param [:shift, :alt, :control, :command, :meta] Modifier key(s) to press while clicking.
# File lib/watir-webdriver/elements/element.rb, line 113 def click(*modifiers) assert_exists assert_enabled element_call do if modifiers.any? assert_has_input_devices_for "click(#{modifiers.join ', '})" action = driver.action modifiers.each { |mod| action.key_down mod } action.click @element modifiers.each { |mod| action.key_up mod } action.perform else @element.click end end browser.after_hooks.run end
Double clicks the element. Note that browser support may vary.
@example
browser.element(name: "new_user_button").double_click
# File lib/watir-webdriver/elements/element.rb, line 143 def double_click assert_exists assert_has_input_devices_for :double_click element_call { driver.action.double_click(@element).perform } browser.after_hooks.run end
Drag and drop this element by the given offsets. Note that browser support may vary.
@example
browser.div(id: "draggable").drag_and_drop_by 100, -200
@param [Fixnum] right_by @param [Fixnum] down_by
# File lib/watir-webdriver/elements/element.rb, line 215 def drag_and_drop_by(right_by, down_by) assert_exists assert_has_input_devices_for :drag_and_drop_by element_call do driver.action. drag_and_drop_by(@element, right_by, down_by). perform end end
Drag and drop this element on to another element instance. Note that browser support may vary.
@example
a = browser.div(id: "draggable") b = browser.div(id: "droppable") a.drag_and_drop_on b
# File lib/watir-webdriver/elements/element.rb, line 192 def drag_and_drop_on(other) assert_is_element other assert_exists assert_has_input_devices_for :drag_and_drop_on element_call do driver.action. drag_and_drop(@element, other.wd). perform end end
@api private
# File lib/watir-webdriver/elements/element.rb, line 382 def driver @parent.driver end
Returns true if this element is present and enabled on the page.
@return [Boolean]
# File lib/watir-webdriver/elements/element.rb, line 412 def enabled? assert_exists element_call { @element.enabled? } end
Returns true if element exists.
@return [Boolean]
# File lib/watir-webdriver/elements/element.rb, line 41 def exists? assert_exists true rescue UnknownObjectException, UnknownFrameException false end
Simulates JavaScript events on element. Note that you may omit “on” from event name.
@example
browser.button(name: "new_user_button").fire_event :click browser.button(name: "new_user_button").fire_event "mousemove" browser.button(name: "new_user_button").fire_event "onmouseover"
@param [String, Symbol] event_name
# File lib/watir-webdriver/elements/element.rb, line 357 def fire_event(event_name) assert_exists event_name = event_name.to_s.sub(/^on/, '').downcase element_call { execute_atom :fireEvent, @element, event_name } end
Flashes (change background color far a moment) element.
@example
browser.text_field(name: "new_user_first_name").flash
# File lib/watir-webdriver/elements/element.rb, line 233 def flash background_color = style("backgroundColor") element_color = driver.execute_script("arguments[0].style.backgroundColor", @element) 10.times do |n| color = (n % 2 == 0) ? "red" : background_color driver.execute_script("arguments[0].style.backgroundColor = '#{color}'", @element) end driver.execute_script("arguments[0].style.backgroundColor = arguments[1]", @element, element_color) self end
Focuses element. Note that Firefox queues focus events until the window actually has focus.
@see code.google.com/p/selenium/issues/detail?id=157
# File lib/watir-webdriver/elements/element.rb, line 329 def focus assert_exists element_call { driver.execute_script "return arguments[0].focus()", @element } end
Returns true if this element is focused.
@return [Boolean]
# File lib/watir-webdriver/elements/element.rb, line 340 def focused? assert_exists element_call { @element == driver.switch_to.active_element } end
# File lib/watir-webdriver/elements/element.rb, line 70 def hash @element ? @element.hash : super end
Moves the mouse to the middle of this element. Note that browser support may vary.
@example
browser.element(name: "new_user_button").hover
# File lib/watir-webdriver/elements/element.rb, line 175 def hover assert_exists assert_has_input_devices_for :hover element_call { driver.action.move_to(@element).perform } end
Returns inner HTML code of element.
@example
browser.div(id: 'foo').inner_html #=> "<a href=\"#\">hello</a>"
@return [String]
# File lib/watir-webdriver/elements/element.rb, line 302 def inner_html assert_exists element_call { execute_atom(:getInnerHtml, @element) }.strip end
# File lib/watir-webdriver/elements/element.rb, line 49 def inspect if @selector.key?(:element) '#<%s:0x%x located=%s selector=%s>' % [self.class, hash*2, !!@element, '{element: (webdriver element)}'] else '#<%s:0x%x located=%s selector=%s>' % [self.class, hash*2, !!@element, selector_string] end end
Returns outer (inner + element itself) HTML code of element.
@example
browser.div(id: 'foo').outer_html #=> "<div id=\"foo\"><a href=\"#\">hello</a></div>"
@return [String]
# File lib/watir-webdriver/elements/element.rb, line 285 def outer_html assert_exists element_call { execute_atom(:getOuterHtml, @element) }.strip end
Returns parent element of current element.
# File lib/watir-webdriver/elements/element.rb, line 368 def parent assert_exists e = element_call { execute_atom :getParentElement, @element } if e.kind_of?(Selenium::WebDriver::Element) Watir.element_class_for(e.tag_name.downcase).new(@parent, element: e) end end
Returns true if the element exists and is visible on the page.
@return [Boolean] @see Watir::Wait
# File lib/watir-webdriver/elements/element.rb, line 424 def present? exists? && visible? rescue Selenium::WebDriver::Error::StaleElementReferenceError, UnknownObjectException # if the element disappears between the exists? and visible? calls, # consider it not present. false end
Right clicks the element. Note that browser support may vary.
@example
browser.element(name: "new_user_button").right_click
# File lib/watir-webdriver/elements/element.rb, line 159 def right_click assert_exists assert_has_input_devices_for :right_click element_call { driver.action.context_click(@element).perform } browser.after_hooks.run end
# File lib/watir-webdriver/extensions/select_text.rb, line 5 def select_text(str) assert_exists execute_atom :selectText, @element, str end
Sends sequence of keystrokes to element.
@example
browser.text_field(name: "new_user_first_name").send_keys "Watir", :return
@param [String, Symbol] *args
# File lib/watir-webdriver/elements/element.rb, line 316 def send_keys(*args) assert_exists assert_writable element_call { @element.send_keys(*args) } end
Returns given style property of this element.
@example
browser.button(value: "Delete").style #=> "border: 4px solid red;" browser.button(value: "Delete").style("border") #=> "4px solid rgb(255, 0, 0)"
@param [String] property @return [String]
# File lib/watir-webdriver/elements/element.rb, line 443 def style(property = nil) if property assert_exists element_call { @element.style property } else attribute_value("style").to_s.strip end end
Returns tag name of the element.
@return [String]
# File lib/watir-webdriver/elements/element.rb, line 91 def tag_name assert_exists element_call { @element.tag_name.downcase } end
Returns the text of the element.
@return [String]
# File lib/watir-webdriver/elements/element.rb, line 80 def text assert_exists element_call { @element.text } end
Cast this Element
instance to a more specific subtype.
@example
browser.element(xpath: "//input[@type='submit']").to_subtype #=> #<Watir::Button>
# File lib/watir-webdriver/elements/element.rb, line 460 def to_subtype elem = wd() tag_name = elem.tag_name.downcase klass = nil if tag_name == "input" klass = case elem.attribute(:type) when *Button::VALID_TYPES Button when 'checkbox' CheckBox when 'radio' Radio when 'file' FileField else TextField end else klass = Watir.element_class_for(tag_name) end klass.new(@parent, element: elem) end
Returns value of the element.
@return [String]
# File lib/watir-webdriver/elements/element.rb, line 253 def value attribute_value('value') || '' rescue Selenium::WebDriver::Error::InvalidElementStateError '' end
Returns true if this element is visible on the page.
@return [Boolean]
# File lib/watir-webdriver/elements/element.rb, line 401 def visible? assert_exists element_call { @element.displayed? } end
@api private
# File lib/watir-webdriver/elements/element.rb, line 390 def wd assert_exists @element end
Protected Instance Methods
# File lib/watir-webdriver/elements/element.rb, line 534 def assert_element_found unless @element raise UnknownObjectException, "unable to locate element, using #{selector_string}" end end
Ensure that the element exists, making sure that it is not stale and located if necessary
# File lib/watir-webdriver/elements/element.rb, line 499 def assert_exists @element ||= @selector[:element] if @element ensure_not_stale # ensure not stale else @element = locate end assert_element_found end
Ensure that the element isn't stale, by relocating if it is (unless always_locate = false)
# File lib/watir-webdriver/elements/element.rb, line 512 def ensure_not_stale # Performance shortcut; only need recursive call to ensure context if stale in current context return unless stale? ensure_context if stale? if Watir.always_locate? && !@selector[:element] @element = locate else reset! end end assert_element_found end
# File lib/watir-webdriver/elements/element.rb, line 544 def locate ensure_context element_validator = element_validator_class.new selector_builder = selector_builder_class.new(@parent, @selector, self.class.attribute_list) locator = locator_class.new(@parent, @selector, selector_builder, element_validator) locator.locate end
# File lib/watir-webdriver/elements/element.rb, line 540 def reset! @element = nil end
# File lib/watir-webdriver/elements/element.rb, line 527 def stale? @element.enabled? # any wire call will check for staleness false rescue Selenium::WebDriver::Error::ObsoleteElementError true end
Private Instance Methods
# File lib/watir-webdriver/elements/element.rb, line 594 def assert_enabled unless element_call { @element.enabled? } raise ObjectDisabledException, "object is disabled #{selector_string}" end end
# File lib/watir-webdriver/elements/element.rb, line 608 def assert_has_input_devices_for(name) unless driver.kind_of? Selenium::WebDriver::DriverExtensions::HasInputDevices raise NotImplementedError, "#{self.class}##{name} is not supported by this driver" end end
# File lib/watir-webdriver/elements/element.rb, line 614 def assert_is_element(obj) unless obj.kind_of? Watir::Element raise TypeError, "execpted Watir::Element, got #{obj.inspect}:#{obj.class}" end end
# File lib/watir-webdriver/elements/element.rb, line 600 def assert_writable assert_enabled if respond_to?(:readonly?) && readonly? raise ObjectReadOnlyException, "object is read only #{selector_string}" end end
# File lib/watir-webdriver/elements/element.rb, line 587 def attribute?(attribute) assert_exists element_call do !!execute_atom(:getAttribute, @element, attribute.to_s.downcase) end end
# File lib/watir-webdriver/elements/element.rb, line 620 def element_call yield rescue Selenium::WebDriver::Error::StaleElementReferenceError if Watir.always_locate? && !@selector[:element] @element = locate else reset! end assert_element_found retry end
# File lib/watir-webdriver/elements/element.rb, line 574 def element_class_name self.class.name.split('::').last end
# File lib/watir-webdriver/elements/element.rb, line 562 def element_validator_class Kernel.const_get("#{Watir.locator_namespace}::#{element_class_name}::Validator") rescue NameError Kernel.const_get("#{Watir.locator_namespace}::Element::Validator") end
Ensure the driver is in the desired browser context
# File lib/watir-webdriver/elements/element.rb, line 583 def ensure_context @parent.is_a?(IFrame) ? @parent.switch_to! : @parent.assert_exists end
# File lib/watir-webdriver/elements/element.rb, line 556 def locator_class Kernel.const_get("#{Watir.locator_namespace}::#{element_class_name}::Locator") rescue NameError Kernel.const_get("#{Watir.locator_namespace}::Element::Locator") end
# File lib/watir-webdriver/elements/element.rb, line 632 def method_missing(meth, *args, &blk) method = meth.to_s if method =~ Locators::Element::SelectorBuilder::WILDCARD_ATTRIBUTE attribute_value(method.tr('_', '-'), *args) else super end end
# File lib/watir-webdriver/elements/element.rb, line 641 def respond_to_missing?(meth, *) Locators::Element::SelectorBuilder::WILDCARD_ATTRIBUTE === meth.to_s || super end
# File lib/watir-webdriver/elements/element.rb, line 568 def selector_builder_class Kernel.const_get("#{Watir.locator_namespace}::#{element_class_name}::SelectorBuilder") rescue NameError Kernel.const_get("#{Watir.locator_namespace}::Element::SelectorBuilder") end
# File lib/watir-webdriver/elements/element.rb, line 578 def selector_string @selector.inspect end