vapir-common 1.7.0.rc1
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/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
|