vapir-common 1.7.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +5 -0
- data/README.txt +11 -0
- data/lib/vapir/common.rb +1 -0
- data/lib/vapir-common/browser.rb +184 -0
- data/lib/vapir-common/browsers.rb +9 -0
- data/lib/vapir-common/container.rb +163 -0
- data/lib/vapir-common/element.rb +1078 -0
- data/lib/vapir-common/element_collection.rb +83 -0
- data/lib/vapir-common/elements/elements.rb +858 -0
- data/lib/vapir-common/elements.rb +2 -0
- data/lib/vapir-common/exceptions.rb +56 -0
- data/lib/vapir-common/handle_options.rb +15 -0
- data/lib/vapir-common/modal_dialog.rb +27 -0
- data/lib/vapir-common/options.rb +49 -0
- data/lib/vapir-common/specifier.rb +322 -0
- data/lib/vapir-common/testcase.rb +89 -0
- data/lib/vapir-common/waiter.rb +141 -0
- data/lib/vapir-common/win_window.rb +1227 -0
- data/lib/vapir-common.rb +7 -0
- data/lib/vapir.rb +1 -0
- data/lib/watir-vapir.rb +15 -0
- metadata +89 -0
data/README.txt
ADDED
data/lib/vapir/common.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'vapir-common'
|
@@ -0,0 +1,184 @@
|
|
1
|
+
# vapir-common/browser
|
2
|
+
require 'vapir-common/options'
|
3
|
+
module Vapir
|
4
|
+
|
5
|
+
=begin rdoc
|
6
|
+
|
7
|
+
Watir is a family of open-source drivers for automating web browsers. You
|
8
|
+
can use it to write tests that are easy to read and maintain.
|
9
|
+
|
10
|
+
Watir drives browsers the same way people do. It clicks links, fills in forms,
|
11
|
+
presses buttons. Watir also checks results, such as whether expected text
|
12
|
+
appears on a page.
|
13
|
+
|
14
|
+
The Watir family currently includes support for Internet Explorer (on Windows),
|
15
|
+
Firefox (on Windows, Mac and Linux) and Safari (on Mac).
|
16
|
+
|
17
|
+
Project Homepage: http://wtr.rubyforge.org
|
18
|
+
|
19
|
+
This Browser module provides a generic interface
|
20
|
+
that tests can use to access any browser. The actual browser (and thus
|
21
|
+
the actual Watir driver) is determined at runtime based on configuration
|
22
|
+
settings.
|
23
|
+
|
24
|
+
require 'vapir'
|
25
|
+
browser = Watir::Browser.new
|
26
|
+
browser.goto 'http://google.com'
|
27
|
+
browser.text_field(:name, 'q').set 'pickaxe'
|
28
|
+
browser.button(:name, 'btnG').click
|
29
|
+
if browser.text.include? 'Programming Ruby'
|
30
|
+
puts 'Text was found'
|
31
|
+
else
|
32
|
+
puts 'Text was not found'
|
33
|
+
end
|
34
|
+
|
35
|
+
A comprehensive summary of the Watir API can be found here
|
36
|
+
http://wiki.openqa.org/display/WTR/Methods+supported+by+Element
|
37
|
+
|
38
|
+
There are two ways to configure the browser that will be used by your tests.
|
39
|
+
|
40
|
+
One is to set the +watir_browser+ environment variable to +ie+ or +firefox+.
|
41
|
+
(How you do this depends on your platform.)
|
42
|
+
|
43
|
+
The other is to create a file that looks like this.
|
44
|
+
|
45
|
+
browser: ie
|
46
|
+
|
47
|
+
And then to add this line to your script, after the require statement and
|
48
|
+
before you invoke Browser.new.
|
49
|
+
|
50
|
+
Watir.options_file = 'path/to/the/file/you/just/created'
|
51
|
+
|
52
|
+
=end rdoc
|
53
|
+
|
54
|
+
class Browser
|
55
|
+
@@browser_classes = {}
|
56
|
+
@@sub_options = {}
|
57
|
+
@@default = nil
|
58
|
+
class << self
|
59
|
+
alias __new__ new
|
60
|
+
def inherited(subclass)
|
61
|
+
class << subclass
|
62
|
+
alias new __new__
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Create a new instance of a browser driver, as determined by the
|
67
|
+
# configuration settings. (Don't be fooled: this is not actually
|
68
|
+
# an instance of Browser class.)
|
69
|
+
def new *args, &block
|
70
|
+
#set_sub_options
|
71
|
+
browser=klass.new *args, &block
|
72
|
+
#browser=klass.allocate
|
73
|
+
#browser.send :initialize, *args, &block
|
74
|
+
browser
|
75
|
+
end
|
76
|
+
# makes sure that the class methods of Browser that call to the class methods of klass
|
77
|
+
# are overridden so that Browser class methods aren't inherited causing infinite loop.
|
78
|
+
def ensure_overridden
|
79
|
+
if self==klass
|
80
|
+
raise NotImplementedError, "This method must be overridden by #{self}!"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Create a new instance as with #new and start the browser on the
|
85
|
+
# specified url.
|
86
|
+
def start url
|
87
|
+
ensure_overridden
|
88
|
+
set_sub_options
|
89
|
+
klass.start url
|
90
|
+
end
|
91
|
+
# Attach to an existing browser.
|
92
|
+
def attach(how, what)
|
93
|
+
ensure_overridden
|
94
|
+
set_sub_options
|
95
|
+
klass.attach(how, what)
|
96
|
+
end
|
97
|
+
def set_options options
|
98
|
+
#ensure_overridden
|
99
|
+
unless self==klass
|
100
|
+
klass.set_options options
|
101
|
+
end
|
102
|
+
end
|
103
|
+
def options
|
104
|
+
self==klass ? {} : klass.options
|
105
|
+
end
|
106
|
+
|
107
|
+
def klass
|
108
|
+
key = Vapir.options[:browser]
|
109
|
+
#eval(@@browser_classes[key]) # this triggers the autoload
|
110
|
+
browser_class_name=@@browser_classes[key]
|
111
|
+
klass=browser_class_name.split('::').inject(Object) do |namespace, name_part|
|
112
|
+
namespace.const_get(name_part)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
private :klass
|
116
|
+
# Add support for the browser option, using the specified class,
|
117
|
+
# provided as a string. Optionally, additional options supported by
|
118
|
+
# the class can be specified as an array of symbols. Options specified
|
119
|
+
# by the user and included in this list will be passed (as a hash) to
|
120
|
+
# the set_options class method (if defined) before creating an instance.
|
121
|
+
def support hash_args
|
122
|
+
option = hash_args[:name]
|
123
|
+
class_string = hash_args[:class]
|
124
|
+
additional_options = hash_args[:options]
|
125
|
+
library = hash_args[:library]
|
126
|
+
gem = hash_args[:gem] || library
|
127
|
+
|
128
|
+
@@browser_classes[option] = class_string
|
129
|
+
@@sub_options[option] = additional_options
|
130
|
+
|
131
|
+
autoload class_string, library
|
132
|
+
activate_gem gem, option
|
133
|
+
end
|
134
|
+
|
135
|
+
def default
|
136
|
+
@@default
|
137
|
+
end
|
138
|
+
# Specifies a default browser. Must be specified before options are parsed.
|
139
|
+
def default= option
|
140
|
+
@@default = option
|
141
|
+
end
|
142
|
+
# Returns the names of the browsers that are supported by this module.
|
143
|
+
# These are the options for 'watir_browser' (env var) or 'browser:' (yaml).
|
144
|
+
def browser_names
|
145
|
+
@@browser_classes.keys
|
146
|
+
end
|
147
|
+
|
148
|
+
private
|
149
|
+
def autoload class_string, library
|
150
|
+
mod, klass = class_string.split('::')
|
151
|
+
eval "module ::#{mod}; autoload :#{klass}, '#{library}'; end"
|
152
|
+
end
|
153
|
+
# Activate the gem (if installed). The default browser will be set
|
154
|
+
# to the first gem that activates.
|
155
|
+
def activate_gem gem_name, option
|
156
|
+
begin
|
157
|
+
gem gem_name
|
158
|
+
@@default ||= option
|
159
|
+
rescue Gem::LoadError
|
160
|
+
end
|
161
|
+
end
|
162
|
+
def set_sub_options
|
163
|
+
sub_options = @@sub_options[Vapir.options[:browser]]
|
164
|
+
return if sub_options.nil?
|
165
|
+
specified_options = Vapir.options.reject {|k, v| !sub_options.include? k}
|
166
|
+
self.set_options specified_options
|
167
|
+
end
|
168
|
+
end
|
169
|
+
# locate is used by stuff that uses container. this doesn't actually locate the browser
|
170
|
+
# but checks if it (still) exists.
|
171
|
+
def locate(options={})
|
172
|
+
exists?
|
173
|
+
end
|
174
|
+
def locate!(options={})
|
175
|
+
locate(options) || raise(Vapir::Exception::NoMatchingWindowFoundException, "The browser window seems to be gone")
|
176
|
+
end
|
177
|
+
def inspect
|
178
|
+
"#<#{self.class}:0x#{(self.hash*2).to_s(16)} " + (exists? ? "url=#{url.inspect} title=#{title.inspect}" : "exists?=false") + '>'
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
end
|
183
|
+
|
184
|
+
require 'vapir-common/browsers'
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# vapir-common/browsers
|
2
|
+
# Define browsers supported by Vapir
|
3
|
+
|
4
|
+
Vapir::Browser.support :name => 'ie', :class => 'Vapir::IE',
|
5
|
+
:library => 'vapir-ie', :gem => 'vapir-ie',
|
6
|
+
:options => [:speed, :visible]
|
7
|
+
|
8
|
+
Vapir::Browser.support :name => 'firefox', :class => 'Vapir::Firefox',
|
9
|
+
:library => 'vapir-firefox'
|
@@ -0,0 +1,163 @@
|
|
1
|
+
require 'vapir-common/specifier'
|
2
|
+
|
3
|
+
module Vapir
|
4
|
+
module Container
|
5
|
+
module_function
|
6
|
+
# returns an Element of the given class klass with the specified how & what, and
|
7
|
+
# with self as its container.
|
8
|
+
# takes options:
|
9
|
+
# - :locate => true, false, :assert, or :nil_unless_exists
|
10
|
+
# whether the element should locate itself.
|
11
|
+
# - false - will not attempt to locate element at all
|
12
|
+
# - true - will try to locate element but not complain if it can't
|
13
|
+
# - :assert - will raise UnkownObjectException if it can't locate.
|
14
|
+
# - :nil_unless_exists - will attempt to locate the element, and only return it if
|
15
|
+
# successful - returns nil otherwise.
|
16
|
+
# - :other_attributes => Hash, attributes other than the given how/what to look for. This is
|
17
|
+
# used by radio and checkbox to specify :value (the third argument).
|
18
|
+
#
|
19
|
+
# the arguments 'first' and 'second' (they are the first and second arguments given
|
20
|
+
# to the container method, not to this method) correspond to 'how' and 'what, after a fashion.
|
21
|
+
#
|
22
|
+
# see also #extra_for_contained on inheriting classes (IE::Element, Firefox::Element) for what this passes to the created
|
23
|
+
# element, in terms of browser, container, other things each element uses.
|
24
|
+
def element_by_howwhat(klass, first, second, other={})
|
25
|
+
other={:other_attributes => nil}.merge(other)
|
26
|
+
|
27
|
+
how, what, index= *normalize_how_what_index(first, second, klass)
|
28
|
+
|
29
|
+
if other[:other_attributes]
|
30
|
+
if how==:attributes
|
31
|
+
what.merge!(other[:other_attributes])
|
32
|
+
else
|
33
|
+
raise ArgumentError, "other attributes were given, but we are not locating by attributes. We are locating by how=#{how.inspect} what=#{what.inspect}. other attributes given were #{other[:other_attributes].inspect}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
extra=extra_for_contained.merge(:index => index)
|
37
|
+
case other[:locate]
|
38
|
+
when :assert, true, false
|
39
|
+
element=klass.new(how, what, extra.merge(:locate => other[:locate]))
|
40
|
+
when :nil_unless_exists
|
41
|
+
element=klass.new(how, what, extra.merge(:locate => true))
|
42
|
+
element.exists? ? element : nil
|
43
|
+
else
|
44
|
+
raise ArgumentError, "Unrecognized value given for :locate: #{other[:locate].inspect} (#{other[:locate].class})"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# figure out how and what from the form(s) that users give to the container methods, and translate
|
49
|
+
# that to real how and what where 'how' is one of Vapir::ElementObjectCandidates::HowList and
|
50
|
+
# 'what' corresponds.
|
51
|
+
# this also determines index, when appropriate.
|
52
|
+
def normalize_how_what_index(first, second, klass)
|
53
|
+
case first
|
54
|
+
when nil
|
55
|
+
raise Vapir::Exception::MissingWayOfFindingObjectException, "no first argument (how) was given!"
|
56
|
+
when Hash
|
57
|
+
how=:attributes
|
58
|
+
what=first.dup
|
59
|
+
index=what.delete(:index)
|
60
|
+
unless second==nil
|
61
|
+
raise(ArgumentError, "first argument was given as a Hash, so assumed to be the 'what' for how=:attributes, but a second argument was also given. arguments were #{first.inspect}, #{second.inspect}")
|
62
|
+
end
|
63
|
+
when String, Symbol
|
64
|
+
if Vapir::ElementObjectCandidates::HowList.include?(first)
|
65
|
+
how=first
|
66
|
+
what=second
|
67
|
+
index=nil
|
68
|
+
else
|
69
|
+
if second.nil?
|
70
|
+
if klass.default_how
|
71
|
+
how=:attributes
|
72
|
+
what={klass.default_how => first}
|
73
|
+
index=nil
|
74
|
+
else
|
75
|
+
raise Vapir::Exception::MissingWayOfFindingObjectException, "Cannot search using arguments #{first.inspect} (#{first.class}) and #{second.inspect} (#{second.class})"
|
76
|
+
end
|
77
|
+
elsif first==:index # this is different because the index number doesn't go in the 'what'
|
78
|
+
how=first
|
79
|
+
what=nil
|
80
|
+
index=second
|
81
|
+
else
|
82
|
+
if klass.all_dom_attr_aliases.any?{|(dom_attr, aliases)| aliases.include?(first.to_sym) || dom_attr==first.to_sym}
|
83
|
+
how=:attributes
|
84
|
+
what={first.to_sym => second}
|
85
|
+
index=nil
|
86
|
+
else
|
87
|
+
raise Vapir::Exception::MissingWayOfFindingObjectException, "Cannot search for a #{klass} using the given argument: #{first.inspect} (other argument was #{second.inspect})"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
else
|
92
|
+
raise Vapir::Exception::MissingWayOfFindingObjectException, "Locating with the given arguments is not recognized or supported: #{first.inspect}, #{second.inspect}"
|
93
|
+
end
|
94
|
+
return [how, what, index]
|
95
|
+
end
|
96
|
+
|
97
|
+
public
|
98
|
+
# asserts that this element exists - optionally, takes a block, and other calls to assert_exists
|
99
|
+
# over the course of the block will not cause redundant assertions.
|
100
|
+
def assert_exists(options={})
|
101
|
+
was_asserting_exists=@asserting_exists
|
102
|
+
if (!@asserting_exists || options[:force])
|
103
|
+
locate!
|
104
|
+
end
|
105
|
+
@asserting_exists=true
|
106
|
+
begin
|
107
|
+
if block_given?
|
108
|
+
result=yield
|
109
|
+
end
|
110
|
+
ensure
|
111
|
+
@asserting_exists=was_asserting_exists
|
112
|
+
end
|
113
|
+
result
|
114
|
+
end
|
115
|
+
|
116
|
+
def default_extra_for_contained
|
117
|
+
extra={:container => self}
|
118
|
+
extra[:browser]= browser if respond_to?(:browser)
|
119
|
+
extra[:page_container]= page_container if respond_to?(:page_container)
|
120
|
+
extra
|
121
|
+
end
|
122
|
+
alias extra_for_contained default_extra_for_contained
|
123
|
+
|
124
|
+
# Checks if this container's text includes the given regexp or string.
|
125
|
+
# Returns true if the container's #text matches the given String or Regexp; otherwise false.
|
126
|
+
#
|
127
|
+
# *Deprecated*
|
128
|
+
# Instead use
|
129
|
+
# Container#text.include? target
|
130
|
+
# or
|
131
|
+
# Container#text.match target
|
132
|
+
def contains_text?(match)
|
133
|
+
if match.kind_of? Regexp
|
134
|
+
!!(text =~ match)
|
135
|
+
elsif match.kind_of? String
|
136
|
+
text.include?(match)
|
137
|
+
else
|
138
|
+
raise TypeError, "Expected String or Regexp, got #{match.inspect} (#{match.class.name})"
|
139
|
+
end
|
140
|
+
end
|
141
|
+
alias contains_text contains_text?
|
142
|
+
|
143
|
+
# shows the available objects on the current container.
|
144
|
+
# This is usually only used for debugging or writing new test scripts.
|
145
|
+
# This is a nice feature to help find out what HTML objects are on a page
|
146
|
+
# when developing a test case using Vapir.
|
147
|
+
#
|
148
|
+
# Typical Usage:
|
149
|
+
# browser.show_all_objects
|
150
|
+
# browser.div(:id, 'foo').show_all_objects
|
151
|
+
#
|
152
|
+
# API: no
|
153
|
+
def show_all_objects(write_to=$stdout)
|
154
|
+
# this used to reject tagNames 'br', 'hr', 'doctype', 'meta', and elements with no tagName
|
155
|
+
elements.map do |element|
|
156
|
+
element=element.to_factory
|
157
|
+
write_to.write element.to_s+"\n"
|
158
|
+
write_to.write '-'*42+"\n"
|
159
|
+
element
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|