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 ADDED
@@ -0,0 +1,5 @@
1
+ === 0.0.1 / 2008-08-28
2
+
3
+ * Created
4
+
5
+
data/README.txt ADDED
@@ -0,0 +1,11 @@
1
+ = vapir-common
2
+
3
+ * http://vapir.org
4
+
5
+ == DESCRIPTION:
6
+
7
+ Common code used by Vapir-IE and Vapir-Firefox
8
+
9
+ == INSTALL:
10
+
11
+ * sudo gem install vapir-common
@@ -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