watir-webdriver 0.0.1.dev
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/LICENSE +20 -0
- data/README.rdoc +32 -0
- data/Rakefile +107 -0
- data/TODO +15 -0
- data/VERSION +1 -0
- data/lib/watir-webdriver.rb +74 -0
- data/lib/watir-webdriver/base_element.rb +347 -0
- data/lib/watir-webdriver/browser.rb +130 -0
- data/lib/watir-webdriver/browserbot.js +34 -0
- data/lib/watir-webdriver/collections/buttons_collection.rb +13 -0
- data/lib/watir-webdriver/collections/element_collection.rb +45 -0
- data/lib/watir-webdriver/collections/table_rows_collection.rb +14 -0
- data/lib/watir-webdriver/collections/text_fields_collection.rb +13 -0
- data/lib/watir-webdriver/container.rb +24 -0
- data/lib/watir-webdriver/core_ext/string.rb +22 -0
- data/lib/watir-webdriver/elements/button.rb +27 -0
- data/lib/watir-webdriver/elements/checkbox.rb +23 -0
- data/lib/watir-webdriver/elements/file_field.rb +20 -0
- data/lib/watir-webdriver/elements/form.rb +11 -0
- data/lib/watir-webdriver/elements/generated.rb +941 -0
- data/lib/watir-webdriver/elements/headings.rb +48 -0
- data/lib/watir-webdriver/elements/hidden.rb +18 -0
- data/lib/watir-webdriver/elements/image.rb +33 -0
- data/lib/watir-webdriver/elements/input.rb +39 -0
- data/lib/watir-webdriver/elements/link.rb +13 -0
- data/lib/watir-webdriver/elements/option.rb +36 -0
- data/lib/watir-webdriver/elements/radio.rb +23 -0
- data/lib/watir-webdriver/elements/select_list.rb +73 -0
- data/lib/watir-webdriver/elements/shared_radio_checkbox.rb +13 -0
- data/lib/watir-webdriver/elements/table.rb +18 -0
- data/lib/watir-webdriver/elements/table_row.rb +17 -0
- data/lib/watir-webdriver/elements/text_field.rb +60 -0
- data/lib/watir-webdriver/exception.rb +20 -0
- data/lib/watir-webdriver/locators/button_locator.rb +57 -0
- data/lib/watir-webdriver/locators/element_locator.rb +269 -0
- data/lib/watir-webdriver/locators/table_row_locator.rb +25 -0
- data/lib/watir-webdriver/locators/text_field_locator.rb +61 -0
- data/lib/watir-webdriver/xpath_support.rb +23 -0
- data/spec/element_locator_spec.rb +11 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/watirspec/area_spec.rb +78 -0
- data/spec/watirspec/areas_spec.rb +31 -0
- data/spec/watirspec/browser_spec.rb +262 -0
- data/spec/watirspec/button_spec.rb +242 -0
- data/spec/watirspec/buttons_spec.rb +48 -0
- data/spec/watirspec/checkbox_spec.rb +272 -0
- data/spec/watirspec/checkboxes_spec.rb +32 -0
- data/spec/watirspec/dd_spec.rb +136 -0
- data/spec/watirspec/dds_spec.rb +31 -0
- data/spec/watirspec/div_spec.rb +222 -0
- data/spec/watirspec/divs_spec.rb +31 -0
- data/spec/watirspec/dl_spec.rb +136 -0
- data/spec/watirspec/dls_spec.rb +32 -0
- data/spec/watirspec/dt_spec.rb +136 -0
- data/spec/watirspec/dts_spec.rb +31 -0
- data/spec/watirspec/element_spec.rb +87 -0
- data/spec/watirspec/em_spec.rb +110 -0
- data/spec/watirspec/ems_spec.rb +32 -0
- data/spec/watirspec/filefield_spec.rb +119 -0
- data/spec/watirspec/filefields_spec.rb +32 -0
- data/spec/watirspec/form_spec.rb +63 -0
- data/spec/watirspec/forms_spec.rb +33 -0
- data/spec/watirspec/frame_spec.rb +140 -0
- data/spec/watirspec/frames_spec.rb +62 -0
- data/spec/watirspec/hidden_spec.rb +102 -0
- data/spec/watirspec/hiddens_spec.rb +32 -0
- data/spec/watirspec/hn_spec.rb +93 -0
- data/spec/watirspec/hns_spec.rb +38 -0
- data/spec/watirspec/image_spec.rb +207 -0
- data/spec/watirspec/images_spec.rb +31 -0
- data/spec/watirspec/label_spec.rb +75 -0
- data/spec/watirspec/labels_spec.rb +31 -0
- data/spec/watirspec/li_spec.rb +127 -0
- data/spec/watirspec/lib/guards.rb +59 -0
- data/spec/watirspec/lib/server.rb +127 -0
- data/spec/watirspec/lib/spec_helper.rb +79 -0
- data/spec/watirspec/lib/watirspec.rb +72 -0
- data/spec/watirspec/link_spec.rb +165 -0
- data/spec/watirspec/links_spec.rb +35 -0
- data/spec/watirspec/lis_spec.rb +31 -0
- data/spec/watirspec/map_spec.rb +92 -0
- data/spec/watirspec/maps_spec.rb +32 -0
- data/spec/watirspec/meta_spec.rb +22 -0
- data/spec/watirspec/metas_spec.rb +30 -0
- data/spec/watirspec/ol_spec.rb +78 -0
- data/spec/watirspec/ols_spec.rb +31 -0
- data/spec/watirspec/option_spec.rb +173 -0
- data/spec/watirspec/p_spec.rb +143 -0
- data/spec/watirspec/pre_spec.rb +125 -0
- data/spec/watirspec/pres_spec.rb +31 -0
- data/spec/watirspec/ps_spec.rb +31 -0
- data/spec/watirspec/radio_spec.rb +278 -0
- data/spec/watirspec/radios_spec.rb +32 -0
- data/spec/watirspec/select_list_spec.rb +318 -0
- data/spec/watirspec/select_lists_spec.rb +35 -0
- data/spec/watirspec/span_spec.rb +157 -0
- data/spec/watirspec/spans_spec.rb +57 -0
- data/spec/watirspec/spec_helper.rb +17 -0
- data/spec/watirspec/strong_spec.rb +89 -0
- data/spec/watirspec/strongs_spec.rb +32 -0
- data/spec/watirspec/table_bodies_spec.rb +45 -0
- data/spec/watirspec/table_body_spec.rb +98 -0
- data/spec/watirspec/table_cell_spec.rb +68 -0
- data/spec/watirspec/table_cells_spec.rb +47 -0
- data/spec/watirspec/table_footer_spec.rb +85 -0
- data/spec/watirspec/table_footers_spec.rb +47 -0
- data/spec/watirspec/table_header_spec.rb +85 -0
- data/spec/watirspec/table_headers_spec.rb +45 -0
- data/spec/watirspec/table_row_spec.rb +87 -0
- data/spec/watirspec/table_rows_spec.rb +50 -0
- data/spec/watirspec/table_spec.rb +166 -0
- data/spec/watirspec/tables_spec.rb +33 -0
- data/spec/watirspec/text_field_spec.rb +276 -0
- data/spec/watirspec/text_fields_spec.rb +35 -0
- data/spec/watirspec/ul_spec.rb +76 -0
- data/spec/watirspec/uls_spec.rb +33 -0
- data/spec/xpath_builder_spec.rb +49 -0
- data/support/html5/html5.idl +815 -0
- data/support/html5/html5_extras.idl +147 -0
- data/support/html5/idl_extractor.rb +73 -0
- data/support/html5/watir_visitor.rb +169 -0
- metadata +220 -0
data/.document
ADDED
data/.gitmodules
ADDED
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
|