watir-webdriver 0.0.1.dev

Sign up to get free protection for your applications and to get access to all the features.
Files changed (125) hide show
  1. data/.document +5 -0
  2. data/.gitignore +5 -0
  3. data/.gitmodules +3 -0
  4. data/LICENSE +20 -0
  5. data/README.rdoc +32 -0
  6. data/Rakefile +107 -0
  7. data/TODO +15 -0
  8. data/VERSION +1 -0
  9. data/lib/watir-webdriver.rb +74 -0
  10. data/lib/watir-webdriver/base_element.rb +347 -0
  11. data/lib/watir-webdriver/browser.rb +130 -0
  12. data/lib/watir-webdriver/browserbot.js +34 -0
  13. data/lib/watir-webdriver/collections/buttons_collection.rb +13 -0
  14. data/lib/watir-webdriver/collections/element_collection.rb +45 -0
  15. data/lib/watir-webdriver/collections/table_rows_collection.rb +14 -0
  16. data/lib/watir-webdriver/collections/text_fields_collection.rb +13 -0
  17. data/lib/watir-webdriver/container.rb +24 -0
  18. data/lib/watir-webdriver/core_ext/string.rb +22 -0
  19. data/lib/watir-webdriver/elements/button.rb +27 -0
  20. data/lib/watir-webdriver/elements/checkbox.rb +23 -0
  21. data/lib/watir-webdriver/elements/file_field.rb +20 -0
  22. data/lib/watir-webdriver/elements/form.rb +11 -0
  23. data/lib/watir-webdriver/elements/generated.rb +941 -0
  24. data/lib/watir-webdriver/elements/headings.rb +48 -0
  25. data/lib/watir-webdriver/elements/hidden.rb +18 -0
  26. data/lib/watir-webdriver/elements/image.rb +33 -0
  27. data/lib/watir-webdriver/elements/input.rb +39 -0
  28. data/lib/watir-webdriver/elements/link.rb +13 -0
  29. data/lib/watir-webdriver/elements/option.rb +36 -0
  30. data/lib/watir-webdriver/elements/radio.rb +23 -0
  31. data/lib/watir-webdriver/elements/select_list.rb +73 -0
  32. data/lib/watir-webdriver/elements/shared_radio_checkbox.rb +13 -0
  33. data/lib/watir-webdriver/elements/table.rb +18 -0
  34. data/lib/watir-webdriver/elements/table_row.rb +17 -0
  35. data/lib/watir-webdriver/elements/text_field.rb +60 -0
  36. data/lib/watir-webdriver/exception.rb +20 -0
  37. data/lib/watir-webdriver/locators/button_locator.rb +57 -0
  38. data/lib/watir-webdriver/locators/element_locator.rb +269 -0
  39. data/lib/watir-webdriver/locators/table_row_locator.rb +25 -0
  40. data/lib/watir-webdriver/locators/text_field_locator.rb +61 -0
  41. data/lib/watir-webdriver/xpath_support.rb +23 -0
  42. data/spec/element_locator_spec.rb +11 -0
  43. data/spec/spec_helper.rb +16 -0
  44. data/spec/watirspec/area_spec.rb +78 -0
  45. data/spec/watirspec/areas_spec.rb +31 -0
  46. data/spec/watirspec/browser_spec.rb +262 -0
  47. data/spec/watirspec/button_spec.rb +242 -0
  48. data/spec/watirspec/buttons_spec.rb +48 -0
  49. data/spec/watirspec/checkbox_spec.rb +272 -0
  50. data/spec/watirspec/checkboxes_spec.rb +32 -0
  51. data/spec/watirspec/dd_spec.rb +136 -0
  52. data/spec/watirspec/dds_spec.rb +31 -0
  53. data/spec/watirspec/div_spec.rb +222 -0
  54. data/spec/watirspec/divs_spec.rb +31 -0
  55. data/spec/watirspec/dl_spec.rb +136 -0
  56. data/spec/watirspec/dls_spec.rb +32 -0
  57. data/spec/watirspec/dt_spec.rb +136 -0
  58. data/spec/watirspec/dts_spec.rb +31 -0
  59. data/spec/watirspec/element_spec.rb +87 -0
  60. data/spec/watirspec/em_spec.rb +110 -0
  61. data/spec/watirspec/ems_spec.rb +32 -0
  62. data/spec/watirspec/filefield_spec.rb +119 -0
  63. data/spec/watirspec/filefields_spec.rb +32 -0
  64. data/spec/watirspec/form_spec.rb +63 -0
  65. data/spec/watirspec/forms_spec.rb +33 -0
  66. data/spec/watirspec/frame_spec.rb +140 -0
  67. data/spec/watirspec/frames_spec.rb +62 -0
  68. data/spec/watirspec/hidden_spec.rb +102 -0
  69. data/spec/watirspec/hiddens_spec.rb +32 -0
  70. data/spec/watirspec/hn_spec.rb +93 -0
  71. data/spec/watirspec/hns_spec.rb +38 -0
  72. data/spec/watirspec/image_spec.rb +207 -0
  73. data/spec/watirspec/images_spec.rb +31 -0
  74. data/spec/watirspec/label_spec.rb +75 -0
  75. data/spec/watirspec/labels_spec.rb +31 -0
  76. data/spec/watirspec/li_spec.rb +127 -0
  77. data/spec/watirspec/lib/guards.rb +59 -0
  78. data/spec/watirspec/lib/server.rb +127 -0
  79. data/spec/watirspec/lib/spec_helper.rb +79 -0
  80. data/spec/watirspec/lib/watirspec.rb +72 -0
  81. data/spec/watirspec/link_spec.rb +165 -0
  82. data/spec/watirspec/links_spec.rb +35 -0
  83. data/spec/watirspec/lis_spec.rb +31 -0
  84. data/spec/watirspec/map_spec.rb +92 -0
  85. data/spec/watirspec/maps_spec.rb +32 -0
  86. data/spec/watirspec/meta_spec.rb +22 -0
  87. data/spec/watirspec/metas_spec.rb +30 -0
  88. data/spec/watirspec/ol_spec.rb +78 -0
  89. data/spec/watirspec/ols_spec.rb +31 -0
  90. data/spec/watirspec/option_spec.rb +173 -0
  91. data/spec/watirspec/p_spec.rb +143 -0
  92. data/spec/watirspec/pre_spec.rb +125 -0
  93. data/spec/watirspec/pres_spec.rb +31 -0
  94. data/spec/watirspec/ps_spec.rb +31 -0
  95. data/spec/watirspec/radio_spec.rb +278 -0
  96. data/spec/watirspec/radios_spec.rb +32 -0
  97. data/spec/watirspec/select_list_spec.rb +318 -0
  98. data/spec/watirspec/select_lists_spec.rb +35 -0
  99. data/spec/watirspec/span_spec.rb +157 -0
  100. data/spec/watirspec/spans_spec.rb +57 -0
  101. data/spec/watirspec/spec_helper.rb +17 -0
  102. data/spec/watirspec/strong_spec.rb +89 -0
  103. data/spec/watirspec/strongs_spec.rb +32 -0
  104. data/spec/watirspec/table_bodies_spec.rb +45 -0
  105. data/spec/watirspec/table_body_spec.rb +98 -0
  106. data/spec/watirspec/table_cell_spec.rb +68 -0
  107. data/spec/watirspec/table_cells_spec.rb +47 -0
  108. data/spec/watirspec/table_footer_spec.rb +85 -0
  109. data/spec/watirspec/table_footers_spec.rb +47 -0
  110. data/spec/watirspec/table_header_spec.rb +85 -0
  111. data/spec/watirspec/table_headers_spec.rb +45 -0
  112. data/spec/watirspec/table_row_spec.rb +87 -0
  113. data/spec/watirspec/table_rows_spec.rb +50 -0
  114. data/spec/watirspec/table_spec.rb +166 -0
  115. data/spec/watirspec/tables_spec.rb +33 -0
  116. data/spec/watirspec/text_field_spec.rb +276 -0
  117. data/spec/watirspec/text_fields_spec.rb +35 -0
  118. data/spec/watirspec/ul_spec.rb +76 -0
  119. data/spec/watirspec/uls_spec.rb +33 -0
  120. data/spec/xpath_builder_spec.rb +49 -0
  121. data/support/html5/html5.idl +815 -0
  122. data/support/html5/html5_extras.idl +147 -0
  123. data/support/html5/idl_extractor.rb +73 -0
  124. data/support/html5/watir_visitor.rb +169 -0
  125. metadata +220 -0
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
data/.gitmodules ADDED
@@ -0,0 +1,3 @@
1
+ [submodule "spec/watirspec"]
2
+ path = spec/watirspec
3
+ url = git://github.com/jarib/watirspec.git
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Jari Bakken
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,32 @@
1
+ = watir-webdriver
2
+
3
+ Watir implementation built on WebDriver's Ruby bindings.
4
+ See http://rubyforge.org/pipermail/wtr-development/2009-October/001313.html.
5
+
6
+ = Description
7
+
8
+ The file in lib/watir/elements/generated.rb is autogenerated from the HTML5 spec. This is done by extracting the IDL parts from the spec and processing them with the WebIDL gem (link below).
9
+
10
+ = See also
11
+
12
+ * http://github.com/jarib/webidl
13
+ * http://webdriver.googlecode.com
14
+ * http://selenium.googlecode.com
15
+
16
+ = Dependencies
17
+
18
+ * selenium-webdriver
19
+
20
+ == Note on Patches/Pull Requests
21
+
22
+ * Fork the project.
23
+ * Make your feature addition or bug fix.
24
+ * Add tests for it. This is important so I don't break it in a
25
+ future version unintentionally.
26
+ * Commit, do not mess with rakefile, version, or history.
27
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
28
+ * Send me a pull request. Bonus points for topic branches.
29
+
30
+ == Copyright
31
+
32
+ Copyright (c) 2009 Jari Bakken. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,107 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "watir-webdriver"
8
+ gem.summary = %Q{Watir on WebDriver}
9
+ gem.description = %Q{WebDriver-backed Watir}
10
+ gem.email = "jari.bakken@gmail.com"
11
+ gem.homepage = "http://github.com/jarib/watir-webdriver"
12
+ gem.authors = ["Jari Bakken"]
13
+
14
+ gem.add_dependency "selenium-webdriver", ">= 0.0.10"
15
+
16
+ gem.add_development_dependency "rspec"
17
+ gem.add_development_dependency "webidl"
18
+ gem.add_development_dependency "sinatra"
19
+ end
20
+ Jeweler::GemcutterTasks.new
21
+ rescue LoadError
22
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
23
+ end
24
+
25
+ require 'spec/rake/spectask'
26
+ Spec::Rake::SpecTask.new(:spec) do |spec|
27
+ spec.libs << 'lib' << 'spec'
28
+ spec.spec_files = FileList['spec/**/*_spec.rb']
29
+ end
30
+
31
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
32
+ spec.libs << 'lib' << 'spec'
33
+ spec.pattern = 'spec/**/*_spec.rb'
34
+ spec.rcov = true
35
+ end
36
+
37
+ task :spec => :check_dependencies
38
+
39
+ namespace :html5 do
40
+ IDL_PATH = "support/html5/html5.idl"
41
+ EXTRAS_PATH = "support/html5/html5_extras.idl"
42
+ SPEC_URI = "http://dev.w3.org/html5/spec/Overview.html" # TODO: use http://www.whatwg.org/specs/web-apps/current-work/source
43
+
44
+ task :extract do
45
+ require 'support/html5/idl_extractor'
46
+
47
+ idl = IdlExtractor.new(SPEC_URI)
48
+ idl.write_idl_to IDL_PATH
49
+ idl.write_extras_to "#{EXTRAS_PATH}.txt"
50
+
51
+ puts "\n\n"
52
+ puts "Some HTML elements does not have an interface declaration defined in the spec."
53
+ puts "You will need to create the IDL by hand and remove the .txt extension from #{EXTRAS_PATH}.txt before running the html5:generate task."
54
+ puts "We're also adding an extended attribute to specify TagName - you may need to look through #{IDL_PATH} to make sure the syntax is correct."
55
+ end
56
+
57
+ desc 'Re-enerate the base Watir element classes from the spec '
58
+ task :generate do
59
+ require "support/html5/watir_visitor"
60
+ raise Errno::ENOENT, EXTRAS_PATH unless File.exist?(EXTRAS_PATH)
61
+
62
+ code = WatirVisitor.generate_from(IDL_PATH)
63
+ code << "# from extras: \n\n"
64
+ code << WatirVisitor.generate_from(EXTRAS_PATH)
65
+
66
+ old_file = "lib/watir/elements/generated.rb"
67
+
68
+ File.open("#{old_file}.new", "w") { |file| file << code }
69
+ if File.exist?(old_file)
70
+ system "diff -Naut #{old_file} #{old_file}.new | less"
71
+ end
72
+ end
73
+
74
+ desc 'Check the syntax of support/html5/*.idl'
75
+ task :syntax do
76
+ require 'webidl'
77
+ parser = WebIDL::Parser::IDLParser.new
78
+ failures = []
79
+ Dir['support/html5/*.idl'].each do |path|
80
+ unless parser.parse(File.read(path))
81
+ failures << [path, parser.failure_reason]
82
+ end
83
+ end
84
+
85
+ if failures.any?
86
+ puts "Parse errors!"
87
+ failures.each { |path, reason| puts "#{path.ljust(40)}: #{reason}" }
88
+ else
89
+ puts "Syntax OK."
90
+ end
91
+ end
92
+
93
+ end # html5
94
+
95
+ task :default => :spec
96
+
97
+ begin
98
+ require 'yard'
99
+ require 'support/yard/handlers/attributes_handler'
100
+ YARD::Rake::YardocTask.new
101
+ rescue LoadError
102
+ task :yardoc do
103
+ abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
104
+ end
105
+ end
106
+
107
+ load "spec/watirspec/watirspec.rake" if File.exist?("spec/watirspec/watirspec.rake")
data/TODO ADDED
@@ -0,0 +1,15 @@
1
+ TODO:
2
+
3
+ - frames
4
+ - tables
5
+
6
+ MAYBE:
7
+
8
+ - support selector arg to collection methods? i.e. browser.buttons(class: "foo")
9
+
10
+ DONE:
11
+
12
+ - check if selector attributes are valid (BaseElement.attribute_list ?) to get MissingWayOfFindingObjectException
13
+ - fix watirspec to not be so picky about exception messages
14
+ - text_field should cover both <input type="whatever"> and <textarea>
15
+ - buttons should cover both <input type="button"> and <button>
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1.dev
@@ -0,0 +1,74 @@
1
+ # encoding: utf-8
2
+ require "selenium-webdriver"
3
+ require "json"
4
+
5
+ require "watir-webdriver/core_ext/string"
6
+ require "watir-webdriver/exception"
7
+ require "watir-webdriver/xpath_support"
8
+ require "watir-webdriver/container"
9
+ require "watir-webdriver/locators/element_locator"
10
+ require "watir-webdriver/locators/button_locator"
11
+ require "watir-webdriver/locators/text_field_locator"
12
+ require "watir-webdriver/locators/table_row_locator"
13
+ require "watir-webdriver/browser"
14
+
15
+ module Watir
16
+ include Selenium
17
+
18
+ class << self
19
+ def tag_to_class
20
+ @tag_to_class ||= {}
21
+ end
22
+
23
+ def element_class_for(tag_name)
24
+ tag_to_class[tag_name] || raise(Exception::Error, "no class found for #{tag_name.inspect}")
25
+ end
26
+ end
27
+
28
+ end
29
+
30
+ require "watir-webdriver/base_element"
31
+ require "watir-webdriver/collections/element_collection"
32
+ require "watir-webdriver/elements/generated"
33
+ require "watir-webdriver/elements/shared_radio_checkbox"
34
+ require "watir-webdriver/elements/input"
35
+ require "watir-webdriver/elements/button"
36
+ require "watir-webdriver/collections/buttons_collection"
37
+ require "watir-webdriver/elements/checkbox"
38
+ require "watir-webdriver/elements/file_field"
39
+ require "watir-webdriver/elements/headings"
40
+ require "watir-webdriver/elements/image"
41
+ require "watir-webdriver/elements/link"
42
+ require "watir-webdriver/elements/radio"
43
+ require "watir-webdriver/elements/text_field"
44
+ require "watir-webdriver/collections/text_fields_collection"
45
+ require "watir-webdriver/elements/hidden"
46
+ require "watir-webdriver/elements/select_list"
47
+ require "watir-webdriver/elements/form"
48
+ require "watir-webdriver/elements/option"
49
+ require "watir-webdriver/elements/table"
50
+ require "watir-webdriver/elements/table_row"
51
+ require "watir-webdriver/collections/table_rows_collection"
52
+
53
+ Watir.tag_to_class.freeze
54
+
55
+ module Watir
56
+ module Container
57
+
58
+ # TODO: proper frame support
59
+ alias_method :frame, :iframe
60
+ alias_method :frames, :iframes
61
+
62
+ # TODO: deprecate cell/row in favor of td/tr?
63
+ alias_method :cell, :td
64
+ alias_method :cells, :tds
65
+ alias_method :row, :tr
66
+ alias_method :rows, :trs
67
+
68
+ end # Container
69
+ end # Watir
70
+
71
+
72
+ # undefine deprecated methods to use them for Element attributes
73
+ Object.send :undef_method, :id if Object.method_defined? "id"
74
+ Object.send :undef_method, :type if Object.method_defined? "type"
@@ -0,0 +1,347 @@
1
+ # encoding: utf-8
2
+
3
+ module Watir
4
+ class BaseElement
5
+ include Exception
6
+ include Container
7
+ include Selenium
8
+
9
+ class << self
10
+ attr_writer :default_selector
11
+
12
+ def inherited(klass)
13
+ klass.default_selector = default_selector.dup
14
+ end
15
+
16
+ def attributes(attribute_map = nil)
17
+ if attribute_map.nil?
18
+ return attribute_list
19
+ end
20
+
21
+ add_attributes attribute_map
22
+
23
+ attribute_map.each do |type, attribs|
24
+ attribs.each { |name| define_attribute(type, name) }
25
+ end
26
+ end
27
+
28
+ def define_attribute(type, name)
29
+ method_name = method_name_for(type, name)
30
+ attribute_name = attribute_for_method(name)
31
+
32
+ (@attributes ||= []) << attribute_name
33
+
34
+ case type
35
+ when :string
36
+ define_string_attribute(method_name, attribute_name)
37
+ when :bool
38
+ define_boolean_attribute(method_name, attribute_name)
39
+ when :int
40
+ define_int_attribute(method_name, attribute_name)
41
+ else
42
+ # $stderr.puts "treating #{type.inspect} as string for now"
43
+ end
44
+ end
45
+
46
+ def define_string_attribute(mname, aname)
47
+ define_method mname do
48
+ assert_exists
49
+ rescue_no_match { @element.attribute(aname).to_s }
50
+ end
51
+ end
52
+
53
+ def define_boolean_attribute(mname, aname)
54
+ define_method mname do
55
+ assert_exists
56
+ rescue_no_match(false) { !!@element.attribute(aname) }
57
+ end
58
+ end
59
+
60
+ def define_int_attribute(mname, aname)
61
+ define_method mname do
62
+ assert_exists
63
+ rescue_no_match(-1) { @element.attribute(aname).to_i }
64
+ end
65
+ end
66
+
67
+ def container_method(name)
68
+ klass = self
69
+ Container.add name do |*args|
70
+ klass.new(self, *args)
71
+ end
72
+ end
73
+
74
+ def collection_method(name)
75
+ element_class = self
76
+ klass = Watir.const_set(
77
+ "#{name.to_s.camel_case}Collection",
78
+ Class.new(ElementCollection)
79
+ )
80
+
81
+ Container.add name do
82
+ klass.new(self, element_class)
83
+ end
84
+ end
85
+
86
+ def add_attributes(attributes)
87
+ attributes.each do |type, attr_list|
88
+ typed_attributes[type] += attr_list
89
+ end
90
+ end
91
+
92
+ def typed_attributes
93
+ @typed_attributes ||= Hash.new { |hash, type| hash[type] = [] }
94
+ end
95
+
96
+ def identifier(selector)
97
+ Watir.tag_to_class[selector[:tag_name]] = self
98
+ default_selector.merge! selector
99
+ end
100
+
101
+ def default_selector
102
+ @default_selector ||= {}
103
+ end
104
+
105
+ def attribute_list
106
+ @attribute_list ||= begin
107
+ list = typed_attributes.values.flatten
108
+ list += ancestors[1..-1].map do |e|
109
+ e.attribute_list if e.respond_to?(:attribute_list)
110
+ end.compact.flatten
111
+ end
112
+ end
113
+
114
+ def method_name_for(type, attribute)
115
+ # TODO: rethink this - this list could get pretty long...
116
+ name = case attribute
117
+ when :hash
118
+ 'hash_attribute'
119
+ when :html_for
120
+ 'for'
121
+ when :col_span
122
+ 'colspan'
123
+ when :row_span
124
+ 'rowspan'
125
+ else
126
+ attribute.to_s
127
+ end
128
+
129
+ name << "?" if type == :bool
130
+
131
+ name
132
+ end
133
+
134
+ def attribute_for_method(method)
135
+ case method.to_sym
136
+ when :class_name
137
+ 'class'
138
+ when :hash_attribute
139
+ 'hash'
140
+ when :html_for
141
+ 'for'
142
+ when :read_only
143
+ 'readonly'
144
+ else
145
+ method.to_s
146
+ end
147
+ end
148
+ end # class << self
149
+
150
+ def initialize(parent, *selectors)
151
+ @parent = parent
152
+ @selector = extract_selector(selectors).merge(self.class.default_selector)
153
+
154
+ if @selector.has_key?(:element)
155
+ @element = @selector[:element]
156
+ end
157
+ end
158
+
159
+ def exists?
160
+ assert_exists
161
+ true
162
+ rescue UnknownObjectException
163
+ false
164
+ end
165
+ alias_method :exist?, :exists?
166
+
167
+ def inspect
168
+ if @selector.has_key?(:element)
169
+ '#<%s:0x%x located=%s selector=%s>' % [self.class, hash*2, !!@element, '{:element=>(webdriver element)}']
170
+ else
171
+ '#<%s:0x%x located=%s selector=%s>' % [self.class, hash*2, !!@element, @selector.inspect]
172
+ end
173
+ end
174
+
175
+ def text
176
+ assert_exists
177
+ @element.text
178
+ end
179
+
180
+ def tag_name
181
+ assert_exists
182
+ @element.tag_name
183
+ end
184
+
185
+ def click
186
+ assert_exists
187
+ assert_enabled
188
+ @element.click
189
+ run_checkers
190
+ end
191
+
192
+ def double_click
193
+ assert_exists
194
+ raise NotImplementedError, "need support in WebDriver"
195
+
196
+ @element.double_click
197
+ run_checkers
198
+ end
199
+
200
+ def right_click
201
+ assert_exists
202
+ raise NotImplementedError, "need support in WebDriver"
203
+
204
+ @element.right_click
205
+ run_checkers
206
+ end
207
+
208
+ def flash
209
+ assert_exists
210
+ original_color = driver.execute_script("arguments[0].style.backgroundColor", @element)
211
+ 10.times do |n|
212
+ color = (n % 2 == 0) ? "red" : original_color
213
+ driver.execute_script("arguments[0].style.backgroundColor = '#{color}'", @element)
214
+ end
215
+ end
216
+
217
+ def value
218
+ assert_exists
219
+ rescue_no_match { @element.value }
220
+ end
221
+
222
+ def attribute_value(attribute_name)
223
+ assert_exists
224
+ # should rescue?
225
+ @element.attribute attribute_name
226
+ end
227
+
228
+ def html
229
+ assert_exists
230
+
231
+ driver.execute_script(<<-JAVASCRIPT, @element)
232
+ var e = arguments[0];
233
+ if(e.outerHTML) {
234
+ return e.outerHTML;
235
+ } else {
236
+ return e.parentNode.innerHTML;
237
+ }
238
+ JAVASCRIPT
239
+ end
240
+
241
+ def focus
242
+ fire_event :focus
243
+ end
244
+
245
+ def fire_event(event_name)
246
+ assert_exists
247
+ event_name = event_name.to_s.sub!(/^on/, '')
248
+ browserbot('triggerEvent', @element, event_name, false)
249
+ end
250
+
251
+ def parent
252
+ assert_exists
253
+
254
+ e = driver.execute_script "return arguments[0].parentNode", @element
255
+
256
+ if e.kind_of?(WebDriver::Element)
257
+ Watir.element_class_for(e.tag_name).new(@parent, :element, e)
258
+ end
259
+ end
260
+
261
+ def driver
262
+ @parent.driver
263
+ end
264
+
265
+ def element
266
+ assert_exists
267
+ @element
268
+ end
269
+ alias_method :wd, :element # ensures duck typing with Browser
270
+
271
+ def visible?
272
+ assert_exists
273
+ @element.displayed?
274
+ end
275
+
276
+ def style(property = nil)
277
+ if property
278
+ assert_exists
279
+ @element.style property
280
+ else
281
+ rescue_no_match { attribute_value "style" } || ''
282
+ end
283
+ end
284
+
285
+ def run_checkers
286
+ @parent.run_checkers
287
+ end
288
+
289
+ protected
290
+
291
+ def assert_exists
292
+ @element ||= locate
293
+
294
+ unless @element
295
+ raise UnknownObjectException, "unable to locate element, using #{selector_string}"
296
+ end
297
+ end
298
+
299
+ private
300
+
301
+ def selector_string
302
+ @selector.inspect
303
+ end
304
+
305
+ def attribute?(a)
306
+ assert_exists
307
+ rescue_no_match(false) { !!@element.attribute(a) }
308
+ end
309
+
310
+ def locate
311
+ @parent.assert_exists
312
+ ElementLocator.new(@parent.wd, @selector, self.class.attribute_list).locate
313
+ end
314
+
315
+ def assert_enabled
316
+ raise ObjectDisabledException, "object is disabled #{selector_string}" unless @element.enabled?
317
+ end
318
+
319
+ def assert_writable
320
+ assert_enabled
321
+ raise ObjectReadOnlyException if respond_to?(:readonly?) && readonly?
322
+ end
323
+
324
+ def rescue_no_match(returned = "", &blk)
325
+ yield
326
+ rescue WebDriver::Error::WebDriverError => e # webdriver needs a MissingAttributeError or similar
327
+ raise unless e.message == "No match"
328
+ returned
329
+ end
330
+
331
+ def extract_selector(selectors)
332
+ case selectors.size
333
+ when 2
334
+ { selectors[0] => selectors[1] }
335
+ when 1
336
+ unless selectors.first.is_a? Hash
337
+ raise ArgumentError, "expected Hash or (:how, 'what')"
338
+ end
339
+
340
+ selectors.first
341
+ else
342
+ raise ArgumentError, "wrong number of arguments (#{selectors.size} for 2)"
343
+ end
344
+ end
345
+
346
+ end # BaseElement
347
+ end # Watir