Path: blob/trunk/rb/lib/selenium/webdriver/common/element.rb
1865 views
# frozen_string_literal: true12# Licensed to the Software Freedom Conservancy (SFC) under one3# or more contributor license agreements. See the NOTICE file4# distributed with this work for additional information5# regarding copyright ownership. The SFC licenses this file6# to you under the Apache License, Version 2.0 (the7# "License"); you may not use this file except in compliance8# with the License. You may obtain a copy of the License at9#10# http://www.apache.org/licenses/LICENSE-2.011#12# Unless required by applicable law or agreed to in writing,13# software distributed under the License is distributed on an14# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY15# KIND, either express or implied. See the License for the16# specific language governing permissions and limitations17# under the License.1819module Selenium20module WebDriver21class Element22ELEMENT_KEY = 'element-6066-11e4-a52e-4f735466cecf'2324include SearchContext25include TakesScreenshot2627#28# Creates a new Element29#30# @api private31#3233def initialize(bridge, id)34@bridge = bridge35@id = id36end3738def inspect39format '#<%<class>s:0x%<hash>x id=%<id>s>', class: self.class, hash: hash * 2, id: @id.inspect40end4142def ==(other)43other.is_a?(self.class) && ref == other.ref44end45alias eql? ==4647def hash48[@id, @bridge].hash49end5051#52# Click this element. If this causes a new page to load, this method will53# attempt to block until the page has loaded. At this point, you should54# discard all references to this element and any further operations55# performed on this element will raise a StaleElementReferenceError56# unless you know that the element and the page will still be present. If57# click() causes a new page to be loaded via an event or is done by58# sending a native event then the method will *not* wait for it to be59# loaded and the caller should verify that a new page has been loaded.60#61# There are some preconditions for an element to be clicked. The element62# must be visible and it must have a height and width greater then 0.63#64# Equivalent to:65# driver.action.click(element)66#67# @example Click on a button68#69# driver.find_element(tag_name: "button").click70#71# @raise [StaleElementReferenceError] if the element no longer exists as72# defined73#7475def click76bridge.click_element @id77end7879#80# Get the tag name of the element.81#82# @example Get the tagname of an INPUT element(returns "input")83#84# driver.find_element(xpath: "//input").tag_name85#86# @return [String] The tag name of this element.87#8889def tag_name90bridge.element_tag_name @id91end9293#94# This method attempts to provide the most likely desired current value for the attribute95# of the element, even when that desired value is actually a JavaScript property.96# It is implemented with a custom JavaScript atom. To obtain the exact value of the attribute or property,97# use #dom_attribute or #property methods respectively.98#99# More exactly, this method will return the value of the property with the given name,100# if it exists. If it does not, then the value of the attribute with the given name is returned.101# If neither exists, null is returned.102#103# The "style" attribute is converted as best can be to a text representation with a trailing semicolon.104#105# The following are deemed to be "boolean" attributes, and will return either "true" or "false":106#107# async, autofocus, autoplay, checked, compact, complete, controls, declare, defaultchecked,108# defaultselected, defer, disabled, draggable, ended, formnovalidate, hidden, indeterminate,109# iscontenteditable, ismap, itemscope, loop, multiple, muted, nohref, noresize, noshade, novalidate,110# nowrap, open, paused, pubdate, readonly, required, reversed, scoped, seamless, seeking,111# selected, spellcheck, truespeed, willvalidate112#113# Finally, the following commonly mis-capitalized attribute/property names are evaluated as expected:114#115# When the value of "class" is requested, the "className" property is returned.116# When the value of "readonly" is requested, the "readOnly" property is returned.117#118# @param [String] name attribute name119# @return [String, nil] attribute value120#121# @see #dom_attribute122# @see #property123#124125def attribute(name)126bridge.element_attribute self, name127end128129#130# Gets the value of a declared HTML attribute of this element.131#132# As opposed to the #attribute method, this method133# only returns attributes declared in the element's HTML markup.134#135# If the attribute is not set, nil is returned.136#137# @param [String] name attribute name138# @return [String, nil] attribute value139#140# @see #attribute141# @see #property142#143144def dom_attribute(name)145bridge.element_dom_attribute @id, name146end147148#149# Gets the value of a JavaScript property of this element150# This will return the current value,151# even if this has been modified after the page has been loaded.152# If the value is not set, nil is returned.153#154# @param [String] name property name155# @return [String, nil] property value156#157158def property(name)159bridge.element_property @id, name160end161162#163# Gets the computed WAI-ARIA role of element164#165# @return [String]166#167168def aria_role169bridge.element_aria_role @id170end171172#173# Gets the computed WAI-ARIA label of element.174#175# @return [String]176#177178def accessible_name179bridge.element_aria_label @id180end181182#183# Get the text content of this element184#185# @return [String]186#187188def text189bridge.element_text @id190end191192#193# Send keystrokes to this element194#195# @param [String, Symbol, Array] args keystrokes to send196#197# Examples:198#199# element.send_keys "foo" #=> value: 'foo'200# element.send_keys "tet", :arrow_left, "s" #=> value: 'test'201# element.send_keys [:control, 'a'], :space #=> value: ' '202#203# @see Keys::KEYS204#205206def send_keys(*args)207bridge.send_keys_to_element @id, Keys.encode(args)208end209alias send_key send_keys210211#212# If this element is a text entry element, this will clear the value. Has no effect on other213# elements. Text entry elements are INPUT and TEXTAREA elements.214#215# Note that the events fired by this event may not be as you'd expect. In particular, we don't216# fire any keyboard or mouse events. If you want to ensure keyboard events are217# fired, consider using #send_keys with the backspace key. To ensure you get a change event,218# consider following with a call to #send_keys with the tab key.219#220221def clear222bridge.clear_element @id223end224225#226# Is the element enabled?227#228# @return [Boolean]229#230231def enabled?232bridge.element_enabled? @id233end234235#236# Is the element selected?237#238# @return [Boolean]239#240241def selected?242bridge.element_selected? @id243end244245#246# Is the element displayed?247#248# @return [Boolean]249#250251def displayed?252bridge.element_displayed? self253end254255#256# Submit this element257#258259def submit260bridge.submit_element @id261end262263#264# Get the value of the given CSS property265#266# Note that shorthand CSS properties (e.g. background, font, border, border-top, margin,267# margin-top, padding, padding-top, list-style, outline, pause, cue) are not returned,268# in accordance with the DOM CSS2 specification - you should directly access the longhand269# properties (e.g. background-color) to access the desired values.270#271# @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration272#273274def css_value(prop)275bridge.element_value_of_css_property @id, prop276end277alias style css_value278279#280# Get the location of this element.281#282# @return [WebDriver::Point]283#284285def location286bridge.element_location @id287end288289#290# Get the dimensions and coordinates of this element.291#292# @return [WebDriver::Rectangle]293#294295def rect296bridge.element_rect @id297end298299#300# Determine an element's location on the screen once it has been scrolled into view.301#302# @return [WebDriver::Point]303#304305def location_once_scrolled_into_view306bridge.element_location_once_scrolled_into_view @id307end308309#310# Get the size of this element311#312# @return [WebDriver::Dimension]313#314315def size316bridge.element_size @id317end318319#320# Returns the shadow root of an element.321#322# @return [WebDriver::ShadowRoot]323#324325def shadow_root326bridge.shadow_root @id327end328329#-------------------------------- sugar --------------------------------330331#332# element.first(id: 'foo')333#334335alias first find_element336337#338# element.all(class: 'bar')339#340341alias all find_elements342343#344# element['class'] or element[:class] #=> "someclass"345#346alias [] attribute347348#349# @api private350# @see SearchContext351#352353def ref354[:element, @id]355end356357#358# Convert to a WebElement JSON Object for transmission over the wire.359# @see https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol#basic-terms-and-concepts360#361# @api private362#363364def to_json(*)365JSON.generate as_json366end367368#369# For Rails 3 - http://jonathanjulian.com/2010/04/rails-to_json-or-as_json/370#371# @api private372#373374def as_json(*)375@id.is_a?(Hash) ? @id : {ELEMENT_KEY => @id}376end377378private379380attr_reader :bridge381382def selectable?383tn = tag_name.downcase384type = attribute(:type).to_s.downcase385386tn == 'option' || (tn == 'input' && %w[radio checkbox].include?(type))387end388389def screenshot390bridge.element_screenshot(@id)391end392end # Element393end # WebDriver394end # Selenium395396397