| module Selenium |
| module WebDriver |
| class Element |
| include SearchContext |
| |
| # |
| # Creates a new Element |
| # |
| # @api private |
| # |
| |
| def initialize(bridge, id) |
| @bridge, @id = bridge, id |
| end |
| |
| def inspect |
| '#<%s:0x%x id=%s>' % [self.class, hash*2, @id.inspect] |
| end |
| |
| def ==(other) |
| other.kind_of?(self.class) && bridge.elementEquals(self, other) |
| end |
| alias_method :eql?, :== |
| |
| def hash |
| @id.hash ^ @bridge.hash |
| end |
| |
| # |
| # Click this element. If this causes a new page to load, this method will |
| # attempt to block until the page has loaded. At this point, you should |
| # discard all references to this element and any further operations |
| # performed on this element will raise a StaleElementReferenceError |
| # unless you know that the element and the page will still be present. If |
| # click() causes a new page to be loaded via an event or is done by |
| # sending a native event then the method will *not* wait for it to be |
| # loaded and the caller should verify that a new page has been loaded. |
| # |
| # There are some preconditions for an element to be clicked. The element |
| # must be visible and it must have a height and width greater then 0. |
| # |
| # Equivalent to: |
| # driver.action.click(element) |
| # |
| # @example Click on a button |
| # |
| # driver.find_element(:tag_name, "button").click |
| # |
| # @raise [StaleElementReferenceError] if the element no longer exists as |
| # defined |
| # |
| |
| def click |
| bridge.clickElement @id |
| end |
| |
| # |
| # Get the tag name of the element. |
| # |
| # @example Get the tagname of an INPUT element(returns "input") |
| # |
| # driver.find_element(:xpath, "//input").tag_name |
| # |
| # @return [String] The tag name of this element. |
| # |
| |
| def tag_name |
| bridge.getElementTagName @id |
| end |
| |
| # |
| # Get the value of a the given attribute of the element. Will return the current value, even if |
| # this has been modified after the page has been loaded. More exactly, this method will return |
| # the value of the given attribute, unless that attribute is not present, in which case the |
| # value of the property with the same name is returned. If neither value is set, nil is |
| # returned. The "style" attribute is converted as best can be to a text representation with a |
| # trailing semi-colon. The following are deemed to be "boolean" attributes, and will |
| # return either "true" or "false": |
| # |
| # async, autofocus, autoplay, checked, compact, complete, controls, declare, defaultchecked, |
| # defaultselected, defer, disabled, draggable, ended, formnovalidate, hidden, indeterminate, |
| # iscontenteditable, ismap, itemscope, loop, multiple, muted, nohref, noresize, noshade, novalidate, |
| # nowrap, open, paused, pubdate, readonly, required, reversed, scoped, seamless, seeking, |
| # selected, spellcheck, truespeed, willvalidate |
| # |
| # Finally, the following commonly mis-capitalized attribute/property names are evaluated as |
| # expected: |
| # |
| # class, readonly |
| # |
| # @param [String] |
| # attribute name |
| # @return [String,nil] |
| # attribute value |
| # |
| |
| def attribute(name) |
| bridge.getElementAttribute @id, name |
| end |
| |
| # |
| # Get the text content of this element |
| # |
| # @return [String] |
| # |
| |
| def text |
| bridge.getElementText @id |
| end |
| |
| # |
| # Send keystrokes to this element |
| # |
| # @param [String, Symbol, Array] |
| # |
| # Examples: |
| # |
| # element.send_keys "foo" #=> value: 'foo' |
| # element.send_keys "tet", :arrow_left, "s" #=> value: 'test' |
| # element.send_keys [:control, 'a'], :space #=> value: ' ' |
| # |
| # @see Keys::KEYS |
| # |
| |
| def send_keys(*args) |
| bridge.sendKeysToElement @id, Keys.encode(args) |
| end |
| alias_method :send_key, :send_keys |
| |
| # |
| # If this element is a text entry element, this will clear the value. Has no effect on other |
| # elements. Text entry elements are INPUT and TEXTAREA elements. |
| # |
| # Note that the events fired by this event may not be as you'd expect. In particular, we don't |
| # fire any keyboard or mouse events. If you want to ensure keyboard events are |
| # fired, consider using #send_keys with the backspace key. To ensure you get a change event, |
| # consider following with a call to #send_keys with the tab key. |
| # |
| |
| def clear |
| bridge.clearElement @id |
| end |
| |
| # |
| # Is the element enabled? |
| # |
| # @return [Boolean] |
| # |
| |
| def enabled? |
| bridge.isElementEnabled @id |
| end |
| |
| # |
| # Is the element selected? |
| # |
| # @return [Boolean] |
| # |
| |
| def selected? |
| bridge.isElementSelected @id |
| end |
| |
| # |
| # Is the element displayed? |
| # |
| # @return [Boolean] |
| # |
| |
| def displayed? |
| bridge.isElementDisplayed @id |
| end |
| |
| # |
| # Submit this element |
| # |
| |
| def submit |
| bridge.submitElement @id |
| end |
| |
| # |
| # Get the value of the given CSS property |
| # |
| # Note that shorthand CSS properties (e.g. background, font, border, border-top, margin, |
| # margin-top, padding, padding-top, list-style, outline, pause, cue) are not returned, |
| # in accordance with the DOM CSS2 specification - you should directly access the longhand |
| # properties (e.g. background-color) to access the desired values. |
| # |
| # @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration |
| # |
| |
| def css_value(prop) |
| bridge.getElementValueOfCssProperty @id, prop |
| end |
| alias_method :style, :css_value |
| |
| # |
| # Get the location of this element. |
| # |
| # @return [WebDriver::Point] |
| # |
| |
| def location |
| bridge.getElementLocation @id |
| end |
| |
| # |
| # Determine an element's location on the screen once it has been scrolled into view. |
| # |
| # @return [WebDriver::Point] |
| # |
| |
| def location_once_scrolled_into_view |
| bridge.getElementLocationOnceScrolledIntoView @id |
| end |
| |
| # |
| # Get the size of this element |
| # |
| # @return [WebDriver::Dimension] |
| # |
| |
| def size |
| bridge.getElementSize @id |
| end |
| |
| #-------------------------------- sugar -------------------------------- |
| |
| # |
| # element.first(:id, 'foo') |
| # |
| |
| alias_method :first, :find_element |
| |
| # |
| # element.all(:class, 'bar') |
| # |
| |
| alias_method :all, :find_elements |
| |
| # |
| # element['class'] or element[:class] #=> "someclass" |
| # |
| alias_method :[], :attribute |
| |
| # |
| # for SearchContext and execute_script |
| # |
| # @api private |
| # |
| |
| def ref |
| @id |
| end |
| |
| # |
| # Convert to a WebElement JSON Object for transmission over the wire. |
| # @see http://code.google.com/p/selenium/wiki/JsonWireProtocol#Basic_Concepts_And_Terms |
| # |
| # @api private |
| # |
| |
| def to_json(*args) |
| WebDriver.json_dump as_json |
| end |
| |
| # |
| # For Rails 3 - http://jonathanjulian.com/2010/04/rails-to_json-or-as_json/ |
| # |
| # @api private |
| # |
| |
| def as_json(opts = nil) |
| { :ELEMENT => @id } |
| end |
| |
| private |
| |
| def bridge |
| @bridge |
| end |
| |
| def selectable? |
| tn = tag_name.downcase |
| type = attribute(:type).to_s.downcase |
| |
| tn == "option" || (tn == "input" && %w[radio checkbox].include?(type)) |
| end |
| |
| end # Element |
| end # WebDriver |
| end # Selenium |