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 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