ayanko-watir-webdriver 0.1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
- data/.gitignore +5 -0
- data/.gitmodules +3 -0
- data/Gemfile +4 -0
- data/LICENSE +20 -0
- data/README.rdoc +55 -0
- data/Rakefile +139 -0
- data/VERSION +1 -0
- data/lib/watir-webdriver.rb +71 -0
- data/lib/watir-webdriver/attribute_helper.rb +128 -0
- data/lib/watir-webdriver/browser.rb +164 -0
- data/lib/watir-webdriver/browserbot.js +49 -0
- data/lib/watir-webdriver/cell_container.rb +19 -0
- data/lib/watir-webdriver/container.rb +40 -0
- data/lib/watir-webdriver/core_ext/string.rb +22 -0
- data/lib/watir-webdriver/element_collection.rb +96 -0
- data/lib/watir-webdriver/elements/button.rb +75 -0
- data/lib/watir-webdriver/elements/checkbox.rb +73 -0
- data/lib/watir-webdriver/elements/element.rb +265 -0
- data/lib/watir-webdriver/elements/file_field.rb +69 -0
- data/lib/watir-webdriver/elements/font.rb +11 -0
- data/lib/watir-webdriver/elements/form.rb +17 -0
- data/lib/watir-webdriver/elements/frame.rb +110 -0
- data/lib/watir-webdriver/elements/generated.rb +2541 -0
- data/lib/watir-webdriver/elements/hidden.rb +24 -0
- data/lib/watir-webdriver/elements/image.rb +51 -0
- data/lib/watir-webdriver/elements/input.rb +42 -0
- data/lib/watir-webdriver/elements/link.rb +7 -0
- data/lib/watir-webdriver/elements/option.rb +55 -0
- data/lib/watir-webdriver/elements/radio.rb +49 -0
- data/lib/watir-webdriver/elements/select.rb +216 -0
- data/lib/watir-webdriver/elements/table.rb +37 -0
- data/lib/watir-webdriver/elements/table_cell.rb +36 -0
- data/lib/watir-webdriver/elements/table_row.rb +45 -0
- data/lib/watir-webdriver/elements/table_section.rb +9 -0
- data/lib/watir-webdriver/elements/text_field.rb +97 -0
- data/lib/watir-webdriver/exception.rb +21 -0
- data/lib/watir-webdriver/extensions/alerts.rb +69 -0
- data/lib/watir-webdriver/extensions/cookies.rb +39 -0
- data/lib/watir-webdriver/extensions/firefox/webdriver.xpi +0 -0
- data/lib/watir-webdriver/extensions/nokogiri.rb +14 -0
- data/lib/watir-webdriver/extensions/performance.rb +54 -0
- data/lib/watir-webdriver/extensions/wait.rb +141 -0
- data/lib/watir-webdriver/html.rb +19 -0
- data/lib/watir-webdriver/html/generator.rb +112 -0
- data/lib/watir-webdriver/html/idl_sorter.rb +49 -0
- data/lib/watir-webdriver/html/spec_extractor.rb +111 -0
- data/lib/watir-webdriver/html/util.rb +22 -0
- data/lib/watir-webdriver/html/visitor.rb +174 -0
- data/lib/watir-webdriver/locators/button_locator.rb +74 -0
- data/lib/watir-webdriver/locators/child_cell_locator.rb +32 -0
- data/lib/watir-webdriver/locators/child_row_locator.rb +37 -0
- data/lib/watir-webdriver/locators/element_locator.rb +352 -0
- data/lib/watir-webdriver/locators/text_field_locator.rb +65 -0
- data/lib/watir-webdriver/row_container.rb +34 -0
- data/lib/watir-webdriver/window_switching.rb +105 -0
- data/lib/watir-webdriver/xpath_support.rb +28 -0
- data/lib/yard/handlers/watir.rb +57 -0
- data/spec/alert_spec.rb +49 -0
- data/spec/browser_spec.rb +42 -0
- data/spec/container_spec.rb +42 -0
- data/spec/element_locator_spec.rb +304 -0
- data/spec/element_spec.rb +13 -0
- data/spec/html/alerts.html +11 -0
- data/spec/html/keylogger.html +15 -0
- data/spec/html/wait.html +27 -0
- data/spec/implementation.rb +17 -0
- data/spec/input_spec.rb +39 -0
- data/spec/locator_spec_helper.rb +51 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/wait_spec.rb +98 -0
- data/support/html5.html +90243 -0
- data/watir-webdriver.gemspec +59 -0
- metadata +238 -0
@@ -0,0 +1,49 @@
|
|
1
|
+
// stolen from injectableSelenium.js in WebDriver
|
2
|
+
var browserbot = {
|
3
|
+
|
4
|
+
triggerEvent: function(element, eventType, canBubble, controlKeyDown, altKeyDown, shiftKeyDown, metaKeyDown) {
|
5
|
+
canBubble = (typeof(canBubble) == undefined) ? true: canBubble;
|
6
|
+
if (element.fireEvent && element.ownerDocument && element.ownerDocument.createEventObject) {
|
7
|
+
// IE
|
8
|
+
var evt = this.createEventObject(element, controlKeyDown, altKeyDown, shiftKeyDown, metaKeyDown);
|
9
|
+
element.fireEvent('on' + eventType, evt);
|
10
|
+
} else {
|
11
|
+
var evt = document.createEvent('HTMLEvents');
|
12
|
+
|
13
|
+
try {
|
14
|
+
evt.shiftKey = shiftKeyDown;
|
15
|
+
evt.metaKey = metaKeyDown;
|
16
|
+
evt.altKey = altKeyDown;
|
17
|
+
evt.ctrlKey = controlKeyDown;
|
18
|
+
} catch(e) {
|
19
|
+
// Nothing sane to do
|
20
|
+
}
|
21
|
+
|
22
|
+
evt.initEvent(eventType, canBubble, true);
|
23
|
+
return element.dispatchEvent(evt);
|
24
|
+
}
|
25
|
+
},
|
26
|
+
|
27
|
+
getVisibleText: function() {
|
28
|
+
var selection = getSelection();
|
29
|
+
var range = document.createRange();
|
30
|
+
range.selectNodeContents(document.documentElement);
|
31
|
+
selection.addRange(range);
|
32
|
+
var string = selection.toString();
|
33
|
+
selection.removeAllRanges();
|
34
|
+
|
35
|
+
return string;
|
36
|
+
},
|
37
|
+
|
38
|
+
getOuterHTML: function(element) {
|
39
|
+
if (element.outerHTML) {
|
40
|
+
return element.outerHTML;
|
41
|
+
} else if (typeof(XMLSerializer) != undefined) {
|
42
|
+
return new XMLSerializer().serializeToString(element);
|
43
|
+
} else {
|
44
|
+
throw "can't get outerHTML in this browser";
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
|
49
|
+
};
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Watir
|
2
|
+
module CellContainer
|
3
|
+
|
4
|
+
def cell(*args)
|
5
|
+
cell = TableCell.new(self, extract_selector(args).merge(:tag_name => /^(th|td)$/))
|
6
|
+
cell.locator_class = ChildCellLocator
|
7
|
+
|
8
|
+
cell
|
9
|
+
end
|
10
|
+
|
11
|
+
def cells(*args)
|
12
|
+
cells = TableCellCollection.new(self, extract_selector(args).merge(:tag_name => /^(th|td)$/))
|
13
|
+
cells.locator_class = ChildCellLocator
|
14
|
+
|
15
|
+
cells
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Watir
|
3
|
+
module Container
|
4
|
+
include XpathSupport
|
5
|
+
|
6
|
+
def element(*args)
|
7
|
+
HTMLElement.new(self, extract_selector(args))
|
8
|
+
end
|
9
|
+
|
10
|
+
def elements(*args)
|
11
|
+
HTMLElementCollection.new(self, extract_selector(args))
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def browserbot(function_name, *arguments)
|
17
|
+
script = browserbot_script + "return browserbot.#{function_name}.apply(browserbot, arguments);"
|
18
|
+
driver.execute_script(script, *arguments)
|
19
|
+
end
|
20
|
+
|
21
|
+
def browserbot_script
|
22
|
+
@browserbot_script ||= File.read("#{File.dirname(__FILE__)}/browserbot.js")
|
23
|
+
end
|
24
|
+
|
25
|
+
def extract_selector(selectors)
|
26
|
+
case selectors.size
|
27
|
+
when 2
|
28
|
+
return { selectors[0] => selectors[1] }
|
29
|
+
when 1
|
30
|
+
obj = selectors.first
|
31
|
+
return obj if obj.kind_of? Hash
|
32
|
+
when 0
|
33
|
+
return {}
|
34
|
+
end
|
35
|
+
|
36
|
+
raise ArgumentError, "expected Hash or (:how, 'what'), got #{selectors.inspect}"
|
37
|
+
end
|
38
|
+
|
39
|
+
end # Container
|
40
|
+
end # Watir
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
class String
|
3
|
+
#
|
4
|
+
# Convert from camel case to snake case
|
5
|
+
#
|
6
|
+
# 'FooBar'.snake_case # => "foo_bar"
|
7
|
+
#
|
8
|
+
|
9
|
+
def snake_case
|
10
|
+
gsub(/\B[A-Z][^A-Z]/, '_\&').downcase.gsub(' ', '_')
|
11
|
+
end
|
12
|
+
|
13
|
+
#
|
14
|
+
# Convert from snake case to camel case
|
15
|
+
#
|
16
|
+
# 'foo_bar'.camel_case # => "FooBar"
|
17
|
+
#
|
18
|
+
|
19
|
+
def camel_case
|
20
|
+
split('_').map { |e| e.capitalize }.join
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Watir
|
3
|
+
|
4
|
+
#
|
5
|
+
# Base class for element collections.
|
6
|
+
#
|
7
|
+
|
8
|
+
class ElementCollection
|
9
|
+
include Enumerable
|
10
|
+
|
11
|
+
def initialize(parent, selector)
|
12
|
+
@parent = parent
|
13
|
+
@selector = selector
|
14
|
+
end
|
15
|
+
|
16
|
+
#
|
17
|
+
# @yieldparam [Watir::Element] element Iterate through the elements in this collection.
|
18
|
+
#
|
19
|
+
|
20
|
+
def each(&blk)
|
21
|
+
to_a.each(&blk)
|
22
|
+
end
|
23
|
+
|
24
|
+
#
|
25
|
+
# @return [Fixnum] The number of elements in this collection.
|
26
|
+
#
|
27
|
+
|
28
|
+
def length
|
29
|
+
elements.length
|
30
|
+
end
|
31
|
+
alias_method :size, :length
|
32
|
+
|
33
|
+
#
|
34
|
+
# Get the element at the given index.
|
35
|
+
# Note that this is 0-indexed and not compatible with older Watir implementations.
|
36
|
+
#
|
37
|
+
# Also note that because of Watir's lazy loading, this will return an Element
|
38
|
+
# instance even if the index is out of bounds.
|
39
|
+
#
|
40
|
+
# @param [Fixnum] n Index of wanted element, 0-indexed
|
41
|
+
# @return [Watir::Element] Returns an instance of a Watir::Element subclass
|
42
|
+
#
|
43
|
+
|
44
|
+
|
45
|
+
def [](idx)
|
46
|
+
to_a[idx] || element_class.new(@parent, :index => idx)
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
# First element of this collection
|
51
|
+
#
|
52
|
+
# @return [Watir::Element] Returns an instance of a Watir::Element subclass
|
53
|
+
#
|
54
|
+
|
55
|
+
def first
|
56
|
+
self[0]
|
57
|
+
end
|
58
|
+
|
59
|
+
#
|
60
|
+
# Last element of the collection
|
61
|
+
#
|
62
|
+
# @return [Watir::Element] Returns an instance of a Watir::Element subclass
|
63
|
+
#
|
64
|
+
|
65
|
+
def last
|
66
|
+
self[-1]
|
67
|
+
end
|
68
|
+
|
69
|
+
#
|
70
|
+
# This collection as an Array
|
71
|
+
#
|
72
|
+
# @return [Array<Watir::Element>]
|
73
|
+
#
|
74
|
+
|
75
|
+
def to_a
|
76
|
+
# TODO: optimize - lazy element_class instance?
|
77
|
+
@to_a ||= elements.map { |e| element_class.new(@parent, :element => e) }
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def elements
|
83
|
+
@elements ||= locator_class.new(
|
84
|
+
@parent.wd,
|
85
|
+
@selector,
|
86
|
+
element_class.attribute_list
|
87
|
+
).locate_all
|
88
|
+
end
|
89
|
+
|
90
|
+
# overridable by subclasses
|
91
|
+
def locator_class
|
92
|
+
ElementLocator
|
93
|
+
end
|
94
|
+
|
95
|
+
end # ElementCollection
|
96
|
+
end # Watir
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Watir
|
3
|
+
|
4
|
+
#
|
5
|
+
# Class representing button elements.
|
6
|
+
#
|
7
|
+
# This class covers both <button> and <input type="submit|reset|image|button" /> elements.
|
8
|
+
#
|
9
|
+
|
10
|
+
class Button < HTMLElement
|
11
|
+
|
12
|
+
# add the attributes from <input>
|
13
|
+
attributes Watir::Input.typed_attributes
|
14
|
+
|
15
|
+
VALID_TYPES = %w[button reset submit image]
|
16
|
+
|
17
|
+
def self.from(parent, element)
|
18
|
+
if element.tag_name == "button" ||
|
19
|
+
element.tag_name == "input" && VALID_TYPES.include?(element.attribute(:type))
|
20
|
+
Button.new(parent, :element => element)
|
21
|
+
else
|
22
|
+
raise TypeError, "expected button or input[@type=#{VALID_TYPES.join("|")}] for #{element.inspect}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
#
|
27
|
+
# Returns the text of the button.
|
28
|
+
#
|
29
|
+
# For input elements, returns the "value" attribute.
|
30
|
+
# For button elements, returns the inner text.
|
31
|
+
#
|
32
|
+
|
33
|
+
def text
|
34
|
+
assert_exists
|
35
|
+
case @element.tag_name
|
36
|
+
when 'input'
|
37
|
+
@element.attribute(:value)
|
38
|
+
when 'button'
|
39
|
+
@element.text
|
40
|
+
else
|
41
|
+
raise Exception::Error, "unknown tag name for button: #{@element.tag_name}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
#
|
46
|
+
# Returns true if this element is enabled
|
47
|
+
#
|
48
|
+
# @return [Boolean]
|
49
|
+
#
|
50
|
+
|
51
|
+
def enabled?
|
52
|
+
!disabled?
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def locate
|
58
|
+
@parent.assert_exists
|
59
|
+
ButtonLocator.new(@parent.wd, @selector, self.class.attribute_list).locate
|
60
|
+
end
|
61
|
+
|
62
|
+
end # Button
|
63
|
+
|
64
|
+
class ButtonCollection < ElementCollection
|
65
|
+
private
|
66
|
+
|
67
|
+
def locator_class
|
68
|
+
ButtonLocator
|
69
|
+
end
|
70
|
+
|
71
|
+
def element_class
|
72
|
+
Button
|
73
|
+
end
|
74
|
+
end # ButtonsCollection
|
75
|
+
end # Watir
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Watir
|
4
|
+
class CheckBox < Input
|
5
|
+
|
6
|
+
def self.from(parent, element)
|
7
|
+
if element.attribute(:type) != "checkbox"
|
8
|
+
raise TypeError, "expected type=checkbox for #{element.inspect}"
|
9
|
+
end
|
10
|
+
|
11
|
+
super
|
12
|
+
end
|
13
|
+
|
14
|
+
#
|
15
|
+
# Set this checkbox to the given value
|
16
|
+
#
|
17
|
+
# Example:
|
18
|
+
#
|
19
|
+
# checkbox.set? #=> false
|
20
|
+
# checkbox.set
|
21
|
+
# checkbox.set? #=> true
|
22
|
+
# checkbox.set(false)
|
23
|
+
# checkbox.set? #=> false
|
24
|
+
#
|
25
|
+
|
26
|
+
def set(bool = true)
|
27
|
+
assert_exists
|
28
|
+
assert_enabled
|
29
|
+
|
30
|
+
if @element.selected?
|
31
|
+
@element.click unless bool
|
32
|
+
else
|
33
|
+
@element.click if bool
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
#
|
38
|
+
# returns true if the element is checked
|
39
|
+
# @return [Boolean]
|
40
|
+
#
|
41
|
+
|
42
|
+
def set?
|
43
|
+
assert_exists
|
44
|
+
@element.selected?
|
45
|
+
end
|
46
|
+
|
47
|
+
#
|
48
|
+
# Unset this checkbox.
|
49
|
+
#
|
50
|
+
# Same as +set(false)+
|
51
|
+
#
|
52
|
+
|
53
|
+
def clear
|
54
|
+
set false
|
55
|
+
end
|
56
|
+
end # CheckBox
|
57
|
+
|
58
|
+
module Container
|
59
|
+
def checkbox(*args)
|
60
|
+
CheckBox.new(self, extract_selector(args).merge(:tag_name => "input", :type => "checkbox"))
|
61
|
+
end
|
62
|
+
|
63
|
+
def checkboxes(*args)
|
64
|
+
CheckBoxCollection.new(self, extract_selector(args).merge(:tag_name => "input", :type => "checkbox"))
|
65
|
+
end
|
66
|
+
end # Container
|
67
|
+
|
68
|
+
class CheckBoxCollection < InputCollection
|
69
|
+
def element_class
|
70
|
+
CheckBox
|
71
|
+
end
|
72
|
+
end # CheckBoxCollection
|
73
|
+
end
|
@@ -0,0 +1,265 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Watir
|
4
|
+
|
5
|
+
#
|
6
|
+
# Base class for HTML elements.
|
7
|
+
#
|
8
|
+
|
9
|
+
class Element
|
10
|
+
include Exception
|
11
|
+
include Container
|
12
|
+
include Selenium
|
13
|
+
extend AttributeHelper
|
14
|
+
|
15
|
+
def initialize(parent, selector)
|
16
|
+
@parent = parent
|
17
|
+
@selector = selector
|
18
|
+
|
19
|
+
unless @selector.kind_of? Hash
|
20
|
+
raise ArgumentError, "invalid argument: #{selector.inspect}"
|
21
|
+
end
|
22
|
+
|
23
|
+
if @selector.has_key?(:element)
|
24
|
+
@element = @selector[:element]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def exists?
|
29
|
+
assert_exists
|
30
|
+
true
|
31
|
+
rescue UnknownObjectException, UnknownFrameException
|
32
|
+
false
|
33
|
+
end
|
34
|
+
alias_method :exist?, :exists?
|
35
|
+
|
36
|
+
def inspect
|
37
|
+
if @selector.has_key?(:element)
|
38
|
+
'#<%s:0x%x located=%s selector=%s>' % [self.class, hash*2, !!@element, '{:element=>(webdriver element)}']
|
39
|
+
else
|
40
|
+
'#<%s:0x%x located=%s selector=%s>' % [self.class, hash*2, !!@element, selector_string]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def ==(other)
|
45
|
+
return false unless other.kind_of? self.class
|
46
|
+
|
47
|
+
assert_exists
|
48
|
+
@element == other.element
|
49
|
+
end
|
50
|
+
alias_method :eql?, :==
|
51
|
+
|
52
|
+
def hash
|
53
|
+
@element ? @element.hash : super
|
54
|
+
end
|
55
|
+
|
56
|
+
def text
|
57
|
+
assert_exists
|
58
|
+
@element.text
|
59
|
+
end
|
60
|
+
|
61
|
+
def tag_name
|
62
|
+
assert_exists
|
63
|
+
@element.tag_name
|
64
|
+
end
|
65
|
+
|
66
|
+
def click
|
67
|
+
assert_exists
|
68
|
+
assert_enabled
|
69
|
+
@element.click
|
70
|
+
run_checkers
|
71
|
+
end
|
72
|
+
|
73
|
+
def double_click
|
74
|
+
assert_exists
|
75
|
+
raise NotImplementedError, "need support in WebDriver"
|
76
|
+
|
77
|
+
@element.double_click
|
78
|
+
run_checkers
|
79
|
+
end
|
80
|
+
|
81
|
+
def right_click
|
82
|
+
assert_exists
|
83
|
+
raise NotImplementedError, "need support in WebDriver"
|
84
|
+
|
85
|
+
@element.right_click
|
86
|
+
run_checkers
|
87
|
+
end
|
88
|
+
|
89
|
+
def flash
|
90
|
+
original_color = style("backgroundColor")
|
91
|
+
|
92
|
+
10.times do |n|
|
93
|
+
color = (n % 2 == 0) ? "red" : original_color
|
94
|
+
driver.execute_script("arguments[0].style.backgroundColor = '#{color}'", @element)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def value
|
99
|
+
assert_exists
|
100
|
+
|
101
|
+
begin
|
102
|
+
@element.value || ''
|
103
|
+
rescue WebDriver::Error::ElementNotEnabledError
|
104
|
+
""
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def attribute_value(attribute_name)
|
109
|
+
assert_exists
|
110
|
+
@element.attribute attribute_name
|
111
|
+
end
|
112
|
+
|
113
|
+
def html
|
114
|
+
assert_exists
|
115
|
+
browserbot('getOuterHTML', @element).strip
|
116
|
+
end
|
117
|
+
|
118
|
+
def send_keys(*args)
|
119
|
+
assert_exists
|
120
|
+
@element.send_keys(*args)
|
121
|
+
end
|
122
|
+
|
123
|
+
#
|
124
|
+
# Note: Firefox queues focus events until the window actually has focus.
|
125
|
+
#
|
126
|
+
# See http://code.google.com/p/selenium/issues/detail?id=157
|
127
|
+
#
|
128
|
+
|
129
|
+
def focus
|
130
|
+
assert_exists
|
131
|
+
driver.execute_script "return arguments[0].focus()", @element
|
132
|
+
end
|
133
|
+
|
134
|
+
def fire_event(event_name, bubble = false)
|
135
|
+
assert_exists
|
136
|
+
event_name = event_name.to_s.sub(/^on/, '')
|
137
|
+
browserbot('triggerEvent', @element, event_name, bubble)
|
138
|
+
end
|
139
|
+
|
140
|
+
def parent
|
141
|
+
assert_exists
|
142
|
+
|
143
|
+
e = driver.execute_script "return arguments[0].parentNode", @element
|
144
|
+
|
145
|
+
if e.kind_of?(WebDriver::Element)
|
146
|
+
Watir.element_class_for(e.tag_name).new(@parent, :element => e)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def driver
|
151
|
+
@parent.driver
|
152
|
+
end
|
153
|
+
|
154
|
+
def element
|
155
|
+
assert_exists
|
156
|
+
@element
|
157
|
+
end
|
158
|
+
alias_method :wd, :element # ensures duck typing with Browser
|
159
|
+
|
160
|
+
def visible?
|
161
|
+
assert_exists
|
162
|
+
@element.displayed?
|
163
|
+
end
|
164
|
+
|
165
|
+
def style(property = nil)
|
166
|
+
if property
|
167
|
+
assert_exists
|
168
|
+
@element.style property
|
169
|
+
else
|
170
|
+
attribute_value("style") || ''
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def run_checkers
|
175
|
+
@parent.run_checkers
|
176
|
+
end
|
177
|
+
|
178
|
+
#
|
179
|
+
# Cast this Element instance to a more specific subtype.
|
180
|
+
#
|
181
|
+
# Example:
|
182
|
+
#
|
183
|
+
# browser.element(:xpath => "//input[@type='submit']").to_subtype #=> #<Watir::Button>
|
184
|
+
#
|
185
|
+
|
186
|
+
def to_subtype
|
187
|
+
elem = element()
|
188
|
+
tag_name = elem.tag_name
|
189
|
+
|
190
|
+
klass = nil
|
191
|
+
|
192
|
+
if tag_name == "input"
|
193
|
+
klass = case elem.attribute(:type)
|
194
|
+
when *Button::VALID_TYPES
|
195
|
+
Button
|
196
|
+
when 'checkbox'
|
197
|
+
CheckBox
|
198
|
+
when 'radio'
|
199
|
+
Radio
|
200
|
+
when 'file'
|
201
|
+
FileField
|
202
|
+
else
|
203
|
+
TextField
|
204
|
+
end
|
205
|
+
else
|
206
|
+
klass = Watir.element_class_for(tag_name)
|
207
|
+
end
|
208
|
+
|
209
|
+
klass.new(@parent, :element => elem)
|
210
|
+
end
|
211
|
+
|
212
|
+
protected
|
213
|
+
|
214
|
+
def assert_exists
|
215
|
+
@element ||= locate
|
216
|
+
|
217
|
+
unless @element
|
218
|
+
raise UnknownObjectException, "unable to locate element, using #{selector_string}"
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
def browser
|
223
|
+
@parent.browser
|
224
|
+
end
|
225
|
+
|
226
|
+
def locate
|
227
|
+
@parent.assert_exists
|
228
|
+
locator_class.new(@parent.wd, @selector, self.class.attribute_list).locate
|
229
|
+
end
|
230
|
+
|
231
|
+
private
|
232
|
+
|
233
|
+
def locator_class
|
234
|
+
ElementLocator
|
235
|
+
end
|
236
|
+
|
237
|
+
def selector_string
|
238
|
+
@selector.inspect
|
239
|
+
end
|
240
|
+
|
241
|
+
def attribute?(attribute)
|
242
|
+
assert_exists
|
243
|
+
driver.execute_script "return !!arguments[0].getAttributeNode(arguments[1]);", @element, attribute.to_s.downcase
|
244
|
+
end
|
245
|
+
|
246
|
+
def assert_enabled
|
247
|
+
raise ObjectDisabledException, "object is disabled #{selector_string}" unless @element.enabled?
|
248
|
+
end
|
249
|
+
|
250
|
+
def assert_writable
|
251
|
+
assert_enabled
|
252
|
+
raise ObjectReadOnlyException if respond_to?(:readonly?) && readonly?
|
253
|
+
end
|
254
|
+
|
255
|
+
def method_missing(meth, *args, &blk)
|
256
|
+
method = meth.to_s
|
257
|
+
if method =~ /^data_(.+)$/
|
258
|
+
attribute_value(method.gsub(/_/, '-'), *args)
|
259
|
+
else
|
260
|
+
super
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
end # Element
|
265
|
+
end # Watir
|