watirloo 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +22 -0
- data/History.txt +44 -0
- data/Manifest.txt +59 -0
- data/README.rdoc +94 -0
- data/Rakefile +68 -0
- data/VERSION +1 -0
- data/lib/watirloo/browsers.rb +73 -0
- data/lib/watirloo/desktop.rb +44 -0
- data/lib/watirloo/extension/firewatir_ducktape.rb +194 -0
- data/lib/watirloo/extension/object.rb +32 -0
- data/lib/watirloo/extension/watir_ducktape.rb +552 -0
- data/lib/watirloo/extension/watir_reflector.rb +83 -0
- data/lib/watirloo/locker.rb +85 -0
- data/lib/watirloo/page.rb +140 -0
- data/lib/watirloo.rb +16 -0
- data/spec/browser_spec.rb +38 -0
- data/spec/browser_threads_spec.rb +45 -0
- data/spec/checkbox_group_spec.rb +136 -0
- data/spec/checkbox_groups_spec.rb +55 -0
- data/spec/checkboxes_value_spec.rb +35 -0
- data/spec/desktop_spec.rb +54 -0
- data/spec/extra/browser_events_spec.rb +76 -0
- data/spec/extra/page_objects_metrics.rb +139 -0
- data/spec/face_mixing_spec.rb +55 -0
- data/spec/firewatir/attach_instance_test.rb +38 -0
- data/spec/firewatir/spec_results.html +263 -0
- data/spec/firewatir/spec_results.txt +23 -0
- data/spec/firewatir/spec_results_failed.txt +3 -0
- data/spec/html/census.html +332 -0
- data/spec/html/checkbox_group1.html +33 -0
- data/spec/html/frameset1.html +17 -0
- data/spec/html/labels.html +53 -0
- data/spec/html/no_title.html +13 -0
- data/spec/html/person.html +37 -0
- data/spec/html/radio_group.html +35 -0
- data/spec/html/select_lists.html +82 -0
- data/spec/input_element_spec.rb +51 -0
- data/spec/label_spec.rb +65 -0
- data/spec/locker_spec.rb +49 -0
- data/spec/page_spec.rb +91 -0
- data/spec/person_def_wrappers_spec.rb +40 -0
- data/spec/radio_group_spec.rb +95 -0
- data/spec/radio_groups_spec.rb +55 -0
- data/spec/reflector_spec.rb +82 -0
- data/spec/select_list_options_spec.rb +40 -0
- data/spec/select_lists_spec.rb +151 -0
- data/spec/spec_helper.rb +20 -0
- data/spec/spec_helper_ff.rb +5 -0
- data/spec/spec_helper_runner.rb +13 -0
- data/spec/spec_results.html +556 -0
- data/spec/spec_results.txt +175 -0
- data/spec/spec_results_failed.txt +1 -0
- data/spec/text_fields_spec.rb +56 -0
- data/watirloo.gemspec +122 -0
- metadata +150 -0
@@ -0,0 +1,552 @@
|
|
1
|
+
gem 'watir', '>=1.6.2'
|
2
|
+
require 'watir'
|
3
|
+
require 'watir/ie'
|
4
|
+
|
5
|
+
module Watir
|
6
|
+
|
7
|
+
# for firefox and ie
|
8
|
+
module RadioCheckGroupCommonWatir
|
9
|
+
|
10
|
+
# size or count of controls in a group
|
11
|
+
def size
|
12
|
+
@o.size
|
13
|
+
end
|
14
|
+
alias count size
|
15
|
+
|
16
|
+
# sets control in a group by either position in a group
|
17
|
+
# or by hidden value attribute
|
18
|
+
def set(what)
|
19
|
+
if what.kind_of?(Array)
|
20
|
+
what.each {|thing| set thing } #calls itself with Fixnum or String
|
21
|
+
else
|
22
|
+
if what.kind_of?(Fixnum)
|
23
|
+
get_by_position(what).set
|
24
|
+
elsif what.kind_of?(String)
|
25
|
+
get_by_value(what).set
|
26
|
+
else
|
27
|
+
raise ::Watir::Exception::WatirException, "argument error #{what} not allowed"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# returns array of value attributes
|
33
|
+
def values
|
34
|
+
raise ::Watir::Exception::WatirException, "method should be implemented"
|
35
|
+
end
|
36
|
+
|
37
|
+
# returns Radio||Checkbox from a group that
|
38
|
+
# has specific value attribute
|
39
|
+
def get_by_value value
|
40
|
+
raise ::Watir::Exception::WatirException, "method should be implemented"
|
41
|
+
end
|
42
|
+
|
43
|
+
# returns Radio||Checkbox from a group that
|
44
|
+
# occupies specifi position in a group
|
45
|
+
# WARNING: it is 1-based NOT 0-based
|
46
|
+
# the intention is to enumerate position staring with 1, the way
|
47
|
+
# customer would enumerate items
|
48
|
+
def get_by_position position
|
49
|
+
if (1..self.size).member? position
|
50
|
+
@o[position-1]
|
51
|
+
else
|
52
|
+
raise ::Watir::Exception::WatirException, "positon #{position} is out of range of size"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# returns radio object in a group by position or by value
|
57
|
+
# in a collection. FIXME this is a hack
|
58
|
+
def [](accessor)
|
59
|
+
if accessor.kind_of? Fixnum
|
60
|
+
get_by_position(accessor+1)
|
61
|
+
elsif accessor.kind_of? String
|
62
|
+
get_by_value accessor
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
# for IE only
|
69
|
+
module RadioCheckGroup
|
70
|
+
|
71
|
+
def values
|
72
|
+
opts = []
|
73
|
+
@o.each {|rc| opts << rc.ole_object.invoke('value')}
|
74
|
+
return opts
|
75
|
+
end
|
76
|
+
|
77
|
+
def get_by_value value
|
78
|
+
if values.member? value
|
79
|
+
@o.find {|rc| rc.ole_object.invoke('value') == value}
|
80
|
+
else
|
81
|
+
raise ::Watir::Exception::WatirException, "value #{value} not found in hidden_values"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
#for firefox and ie
|
87
|
+
module RadioGroupCommonWatir
|
88
|
+
|
89
|
+
# Only one radio in RadioGroup can be selected just like
|
90
|
+
# only one option in single select list box can be selected.
|
91
|
+
# this method is a bit gratuitious because it will always return array
|
92
|
+
# with one item but it's here to keep the plural for compatibility with
|
93
|
+
# CheckboxGroup or SelectList. if at some point your page object gets changed from RadioGroup
|
94
|
+
# to SelectList your tests will not have to change
|
95
|
+
def selected_values
|
96
|
+
selected_value.to_a
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
# returns radio that is selected.
|
101
|
+
# there can only be one radio selected.
|
102
|
+
# in the event that none is selected it returns nil
|
103
|
+
# see selected_value commentary
|
104
|
+
def selected_radio
|
105
|
+
@o.find {|r| r.isSet?}
|
106
|
+
end
|
107
|
+
|
108
|
+
# if a radio button in a group is set then the group is set
|
109
|
+
# by default it should be set but many HTML implementations provide
|
110
|
+
# the radiogroup to the user with no default one set (Bad practice perhaps)
|
111
|
+
def set?
|
112
|
+
selected_radio ? true : false
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
# radios that share the same :name attribute form a RadioGroup.
|
118
|
+
# RadioGroup semantically behaves like single select list box
|
119
|
+
# usage: this class is accessed by Watir::Container#radio_group
|
120
|
+
# RadioGroup semantically behaves like single select list box.
|
121
|
+
#
|
122
|
+
# per HTML401: -
|
123
|
+
# "If no radio button in a set sharing the same control name
|
124
|
+
# is initially 'on', user agent behavior for choosing which
|
125
|
+
# control is initially 'on' is undefined
|
126
|
+
#
|
127
|
+
# The idea of having all radios off makes no sense but in the wild you can see lots of examples.
|
128
|
+
# it would be better to just have a single select list box with no items selected instead of radios.
|
129
|
+
# The point of having radios is that at least one radio is 'ON' providing a default value for the group
|
130
|
+
#
|
131
|
+
# @browser = Watir::IE.attach :url, //
|
132
|
+
# @browser.radio_group('food') # => RadioGroup with :name, 'food'
|
133
|
+
#
|
134
|
+
class RadioGroup
|
135
|
+
|
136
|
+
include RadioCheckGroupCommonWatir
|
137
|
+
include RadioCheckGroup
|
138
|
+
include RadioGroupCommonWatir
|
139
|
+
|
140
|
+
def initialize(container, how, what)
|
141
|
+
@container = container
|
142
|
+
@how = how
|
143
|
+
@what = what
|
144
|
+
@o = locate
|
145
|
+
end
|
146
|
+
|
147
|
+
def name
|
148
|
+
@name
|
149
|
+
end
|
150
|
+
|
151
|
+
def locate
|
152
|
+
@name = case @how
|
153
|
+
when :name then @what
|
154
|
+
when :index then
|
155
|
+
names = []
|
156
|
+
@container.radios.each do |r|
|
157
|
+
names << r.name
|
158
|
+
end
|
159
|
+
names.uniq.at(@what-1) # follow 1-based index addressing for Watir API
|
160
|
+
end
|
161
|
+
@container.radios.find_all {|r| r.name == @name}
|
162
|
+
end
|
163
|
+
private :locate
|
164
|
+
|
165
|
+
# which value is selected?. returns value text as string
|
166
|
+
# So per HTML401 spec I am not sure if we should ever have empyt array returned here
|
167
|
+
# if you do get empty array then I would speak with developers to fix this and explicity
|
168
|
+
# provide checked for one radio on page load.
|
169
|
+
def selected_value
|
170
|
+
selected_radio.ole_object.invoke('value')
|
171
|
+
end
|
172
|
+
|
173
|
+
# in the absence of visible text like in select list we treat value
|
174
|
+
# as a selected text invisible to the user
|
175
|
+
alias selected selected_value
|
176
|
+
|
177
|
+
end
|
178
|
+
|
179
|
+
class TextFields < ElementCollections
|
180
|
+
|
181
|
+
def reflect
|
182
|
+
ret = []
|
183
|
+
self.each do |item|
|
184
|
+
how, what = get_how_what get_attribs(item)
|
185
|
+
facename = suggest_def_name what
|
186
|
+
value = item.value
|
187
|
+
# this approach relies on doc element
|
188
|
+
ret << "face(:#{facename}) {doc.text_field(:#{how}, #{what.inspect})}"
|
189
|
+
ret << "#{facename}.value.should == #{value.inspect}"
|
190
|
+
end
|
191
|
+
ret
|
192
|
+
end
|
193
|
+
|
194
|
+
end
|
195
|
+
|
196
|
+
class RadioGroups < ElementCollections
|
197
|
+
|
198
|
+
def element_class; RadioGroup; end
|
199
|
+
def length
|
200
|
+
names = []
|
201
|
+
@container.radios.each do |r|
|
202
|
+
names << r.name
|
203
|
+
end
|
204
|
+
names.uniq.size #non repeating names
|
205
|
+
end
|
206
|
+
|
207
|
+
def reflect
|
208
|
+
ret = []
|
209
|
+
self.each do |item|
|
210
|
+
name = item.name
|
211
|
+
facename = suggest_def_name name
|
212
|
+
values = item.values
|
213
|
+
selected = item.selected
|
214
|
+
ret << "face(:#{facename}) {doc.radio_group(#{name.inspect})}"
|
215
|
+
ret << "#{facename}.values.should == #{values.inspect}"
|
216
|
+
ret << "#{facename}.selected.should == #{selected.inspect}"
|
217
|
+
end
|
218
|
+
ret
|
219
|
+
end
|
220
|
+
|
221
|
+
|
222
|
+
private
|
223
|
+
def iterator_object(i)
|
224
|
+
@container.radio_group(:index, i + 1)
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
module CheckboxGroupCommonWatir
|
229
|
+
|
230
|
+
# returns selected checkboxes as array
|
231
|
+
# when empty [] then nothing is selected
|
232
|
+
# when [checkbox, checkbox] = array of checkboxes that are selected
|
233
|
+
# that you can iterate over for tests.
|
234
|
+
def selected_checkboxes
|
235
|
+
@o.select {|cb| cb.isSet?}
|
236
|
+
end
|
237
|
+
|
238
|
+
# convenience method as a filter for selected_values
|
239
|
+
# returns:
|
240
|
+
# nil => when no checkbox is set
|
241
|
+
# 'value' => if one checkbox is set
|
242
|
+
# or bypass filter and return selected_values array
|
243
|
+
def selected_value
|
244
|
+
arr = selected_values
|
245
|
+
case arr.size
|
246
|
+
when 0 then nil
|
247
|
+
when 1 then arr[0]
|
248
|
+
else arr
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
# in case of checkbox there are no visible text items.
|
253
|
+
# We rely on value attributes that must be present
|
254
|
+
# to differentiate the checkbox in a group
|
255
|
+
# compare to SelectList where selected returns selected_item
|
256
|
+
alias selected selected_value
|
257
|
+
|
258
|
+
|
259
|
+
# if at least one checkbox is selected then the group is considered set
|
260
|
+
def set?
|
261
|
+
(selected_checkboxes != []) ? true : false
|
262
|
+
end
|
263
|
+
|
264
|
+
alias checked? set?
|
265
|
+
|
266
|
+
end
|
267
|
+
|
268
|
+
# Checkbox group semantically behaves like multi select list box.
|
269
|
+
# each checkbox is a menu item groupped by the common attribute :name
|
270
|
+
# each checkbox can be off initially (a bit different semantics than RadioGroup)
|
271
|
+
class CheckboxGroup
|
272
|
+
|
273
|
+
include RadioCheckGroupCommonWatir
|
274
|
+
include RadioCheckGroup
|
275
|
+
include CheckboxGroupCommonWatir
|
276
|
+
|
277
|
+
def initialize(container, how, what)
|
278
|
+
@container = container
|
279
|
+
@how = how
|
280
|
+
@what = what
|
281
|
+
@o = locate
|
282
|
+
end
|
283
|
+
|
284
|
+
def name
|
285
|
+
@name
|
286
|
+
end
|
287
|
+
|
288
|
+
def locate
|
289
|
+
@name = case @how
|
290
|
+
when :name then @what
|
291
|
+
when :index then
|
292
|
+
names = []
|
293
|
+
@container.checkboxes.each do |cb|
|
294
|
+
names << cb.name
|
295
|
+
end
|
296
|
+
names.uniq.at(@what-1) # follow 1-based index addressing for Watir API
|
297
|
+
end
|
298
|
+
@container.checkboxes.find_all {|cb| cb.name == @name}
|
299
|
+
end
|
300
|
+
private :locate
|
301
|
+
|
302
|
+
# returns array of value attributes. Each Checkbox in a group
|
303
|
+
# has a value which is invisible to the user
|
304
|
+
def selected_values
|
305
|
+
values = []
|
306
|
+
selected_checkboxes.each do |cb|
|
307
|
+
values << cb.ole_object.invoke('value')
|
308
|
+
end
|
309
|
+
return values
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
class CheckboxGroups < ElementCollections
|
314
|
+
def element_class; CheckboxGroup; end
|
315
|
+
def length
|
316
|
+
names = []
|
317
|
+
@container.checkboxes.each do |cb|
|
318
|
+
names << cb.name
|
319
|
+
end
|
320
|
+
names.uniq.size #non repeating names
|
321
|
+
end
|
322
|
+
|
323
|
+
def reflect
|
324
|
+
ret = []
|
325
|
+
self.each do |item|
|
326
|
+
name = item.name
|
327
|
+
facename = suggest_def_name(name)
|
328
|
+
values = item.values
|
329
|
+
selected = item.selected
|
330
|
+
ret << "face(:#{facename}) {doc.checkbox_group(#{name.inspect})}"
|
331
|
+
ret << "#{facename}.values.should == #{values.inspect}"
|
332
|
+
ret << "#{facename}.selected.should == #{selected.inspect}"
|
333
|
+
end
|
334
|
+
ret
|
335
|
+
end
|
336
|
+
|
337
|
+
private
|
338
|
+
def iterator_object(i)
|
339
|
+
@container.checkbox_group(:index, i + 1)
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
|
344
|
+
module Container
|
345
|
+
|
346
|
+
def radio_group(how, what=nil)
|
347
|
+
how, what = process_default :name, how, what
|
348
|
+
RadioGroup.new(self, how, what)
|
349
|
+
end
|
350
|
+
|
351
|
+
def radio_groups
|
352
|
+
RadioGroups.new(self)
|
353
|
+
end
|
354
|
+
|
355
|
+
def checkbox_group(how, what=nil)
|
356
|
+
how, what = process_default :name, how, what
|
357
|
+
CheckboxGroup.new(self, how, what)
|
358
|
+
end
|
359
|
+
|
360
|
+
def checkbox_groups
|
361
|
+
CheckboxGroups.new(self)
|
362
|
+
end
|
363
|
+
|
364
|
+
end
|
365
|
+
|
366
|
+
class RadioCheckCommon
|
367
|
+
alias set? isSet?
|
368
|
+
end
|
369
|
+
|
370
|
+
# these methods work for IE and for Firefox
|
371
|
+
module SelectListCommonWatir
|
372
|
+
|
373
|
+
# selected_items examples
|
374
|
+
# [] => nothing selected
|
375
|
+
# ['item'] => if one selected
|
376
|
+
# ['item1', 'item2', 'item3'] => several items selected
|
377
|
+
def selected_items
|
378
|
+
getSelectedItems
|
379
|
+
end
|
380
|
+
|
381
|
+
# selected_item is a convenience filter for selected_items
|
382
|
+
# returns
|
383
|
+
# nil if no options selected
|
384
|
+
# 'text' string if one option selected.
|
385
|
+
# or selected_items if more than one option selected
|
386
|
+
def selected_item
|
387
|
+
arr = selected_items # limit to one mehtod call
|
388
|
+
case arr.size
|
389
|
+
when 0 then nil
|
390
|
+
when 1 then arr[0]
|
391
|
+
else arr
|
392
|
+
end
|
393
|
+
end
|
394
|
+
|
395
|
+
|
396
|
+
# for selecte lists by default we return the text of an option
|
397
|
+
# compare to selected in RadioGroup or Checkbox group which return the
|
398
|
+
# value attributes since there is no visible text for the user
|
399
|
+
alias selected selected_item
|
400
|
+
|
401
|
+
# set :value or :text
|
402
|
+
def _set(how, what)
|
403
|
+
if what.kind_of? Array
|
404
|
+
what.each { |item| _set(how,item)} # call self with individual item
|
405
|
+
else
|
406
|
+
if what.kind_of? Fixnum # if by position then translate to set by text
|
407
|
+
if (0..items.size).member? what
|
408
|
+
_set :text, items[what-1]
|
409
|
+
else
|
410
|
+
raise ::Watir::Exception::WatirException, "number #{item} is out of range of item count"
|
411
|
+
end
|
412
|
+
else
|
413
|
+
select_item_in_select_list(how, what) #finally as :value or :text
|
414
|
+
end
|
415
|
+
end
|
416
|
+
|
417
|
+
end
|
418
|
+
private :_set
|
419
|
+
|
420
|
+
|
421
|
+
|
422
|
+
|
423
|
+
# similar to selected_items but returns array of option value attributes
|
424
|
+
def selected_values
|
425
|
+
assert_exists
|
426
|
+
arr = []
|
427
|
+
@o.each do |thisItem|
|
428
|
+
if thisItem.selected
|
429
|
+
arr << thisItem.value
|
430
|
+
end
|
431
|
+
end
|
432
|
+
return arr
|
433
|
+
end
|
434
|
+
|
435
|
+
# convinience method as a filter for select_values
|
436
|
+
# returns:
|
437
|
+
# nil for nothing selected.
|
438
|
+
# single value if only once selected or just
|
439
|
+
# or returns selected_values
|
440
|
+
def selected_value
|
441
|
+
arr = selected_values
|
442
|
+
case arr.size
|
443
|
+
when 0 then nil
|
444
|
+
when 1 then arr[0]
|
445
|
+
else arr
|
446
|
+
end
|
447
|
+
end
|
448
|
+
|
449
|
+
|
450
|
+
end
|
451
|
+
|
452
|
+
# SelectList acts like RadioGroup or CheckboxGroup
|
453
|
+
# They all have options to select
|
454
|
+
# There are two kinds of SelectLists. SingleSelect and MultiSelect
|
455
|
+
# SelectList presents user with visible items to select from.
|
456
|
+
# Each Item has a visible :text and invisible :value attributes
|
457
|
+
# (sometimes :value attributes are missing)
|
458
|
+
#
|
459
|
+
# In Watirloo
|
460
|
+
# The invisible :value attributes of options we call :values
|
461
|
+
# The visible :text of options we call :items
|
462
|
+
# The selected items as visible text we call :selected
|
463
|
+
# The selected items as values we call :selected_values
|
464
|
+
#
|
465
|
+
# example of single select list
|
466
|
+
#
|
467
|
+
# <select name="controlname">
|
468
|
+
# <option value="opt0"></option>
|
469
|
+
# <option value="opt1">item1</option>
|
470
|
+
# <option value="opt2" selected>item2</option>
|
471
|
+
# </select>
|
472
|
+
#
|
473
|
+
# items => ['', 'item1', 'item2']
|
474
|
+
# values => ['opt0','opt1', 'opt2']
|
475
|
+
# selected => ['item2']
|
476
|
+
# selected_values => ['opt2']
|
477
|
+
#
|
478
|
+
# example of multi select list
|
479
|
+
#
|
480
|
+
# <select name="controlname" multiple size=2>
|
481
|
+
# <option value="o1">item1
|
482
|
+
# <option value="o2" selected>item2
|
483
|
+
# <option value="o3" selected>item3
|
484
|
+
# </select>
|
485
|
+
#
|
486
|
+
# items => ['item1', 'item2', 'item3']
|
487
|
+
# values => ['o1','o2','o3']
|
488
|
+
# selected => ['item2', 'item3']
|
489
|
+
# selected_values => ['o2', 'o3']
|
490
|
+
#
|
491
|
+
class SelectList
|
492
|
+
|
493
|
+
include SelectListCommonWatir
|
494
|
+
|
495
|
+
|
496
|
+
# accepts one text item or array of text items. if array then sets one after another.
|
497
|
+
# For single select lists the last item in array wins
|
498
|
+
#
|
499
|
+
# examples
|
500
|
+
# select_list.set 'bla' # => single option text
|
501
|
+
# select_list.set ['bla','foo','gugu'] # => set 3 options by text. If
|
502
|
+
# this is a single select list box it will set each value in turn
|
503
|
+
# select_list set 1 # => set the first option in a list
|
504
|
+
# select_list.set [1,3,5] => set the first, third and fith options
|
505
|
+
def set(item)
|
506
|
+
_set(:text, item)
|
507
|
+
end
|
508
|
+
|
509
|
+
# set item by the option value attribute. if array then set one after anohter.
|
510
|
+
# see examples in set method
|
511
|
+
def set_value(value)
|
512
|
+
_set(:value, value)
|
513
|
+
end
|
514
|
+
|
515
|
+
# returns array of value attributes
|
516
|
+
# each option usually has a value attribute
|
517
|
+
# which is hidden to the person viewing the page
|
518
|
+
def values
|
519
|
+
a = []
|
520
|
+
attribute_value('options').each do |item|
|
521
|
+
a << item.value
|
522
|
+
end
|
523
|
+
return a
|
524
|
+
end
|
525
|
+
|
526
|
+
alias clear clearSelection
|
527
|
+
|
528
|
+
# alias, items or contents return the same visible text items
|
529
|
+
alias items getAllContents
|
530
|
+
|
531
|
+
|
532
|
+
|
533
|
+
def reflect
|
534
|
+
ret = []
|
535
|
+
self.each do |item|
|
536
|
+
name = item.name
|
537
|
+
facename = suggest_def_name name
|
538
|
+
values = item.values
|
539
|
+
items = item.items
|
540
|
+
selected_item = item.selected_item
|
541
|
+
selected_value = item.selected_value
|
542
|
+
|
543
|
+
ret << "face(:#{facename}) {doc.select_list(:name, #{name.inspect})}"
|
544
|
+
ret << "#{facename}.items.should == #{items.inspect}"
|
545
|
+
ret << "#{facename}.values.should == #{values.inspect}"
|
546
|
+
ret << "#{facename}.selected_item.should == #{selected_item.inspect}"
|
547
|
+
ret << "#{facename}.selected_value.should == #{selected_value.inspect}"
|
548
|
+
end
|
549
|
+
ret
|
550
|
+
end
|
551
|
+
end
|
552
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
=begin rdoc
|
2
|
+
Look Ma!, I can Has Reflect The Browser
|
3
|
+
|
4
|
+
Watir::Reflector module added to watir.
|
5
|
+
reflect watir element collections. reflections create wrapper methods
|
6
|
+
with suggested semantic naming based on id, name, value or combination.
|
7
|
+
the intention is to create a scaffolding for Watirloo::Page elements.
|
8
|
+
=end
|
9
|
+
|
10
|
+
module Watir
|
11
|
+
|
12
|
+
# Watirloo::Page objects scaffold creation. Talks to the current page and reflects
|
13
|
+
# the watir elements to be used for semantic test objects tests.
|
14
|
+
module Reflector
|
15
|
+
|
16
|
+
#cleanup the def name for some kind of semantic name
|
17
|
+
def suggest_def_name(how)
|
18
|
+
how.gsub!(/_+/,'_') # double underscores to one
|
19
|
+
how.gsub!(/^_/, '') # if it begins with undrscore kill it.
|
20
|
+
how.gsub!(/\s+/, '_') # kill spaces if for some strange reason they exist
|
21
|
+
how.underscore #Any CamelCase will be converted to camel_no_case
|
22
|
+
end
|
23
|
+
|
24
|
+
# glean(:text_fields, [:id, :name, :value]
|
25
|
+
# glean(:radios, [:id, :name, :value])
|
26
|
+
# glean and make a map of types and attributes needed for reflection
|
27
|
+
# this should be private I think
|
28
|
+
def get_attribs(item)
|
29
|
+
attribs = [:id, :name, :value]
|
30
|
+
h = {}
|
31
|
+
attribs.each do |k|
|
32
|
+
v = item.attribute_value k.to_s
|
33
|
+
h[k] = v
|
34
|
+
end
|
35
|
+
h
|
36
|
+
end
|
37
|
+
|
38
|
+
def get_how_what h
|
39
|
+
how, what = '', ''
|
40
|
+
if h[:id] != '' #First Choice: if id is not blank then we'll use it
|
41
|
+
how, what = :id, h[:id]
|
42
|
+
elsif h[:name] != '' #Second Choice: if name is not blank then we'll use it instead of id
|
43
|
+
how, what = :name, h[:name]
|
44
|
+
elsif h[:value] != ''
|
45
|
+
how, what = :value, h[:value]
|
46
|
+
end
|
47
|
+
[how, what]
|
48
|
+
end
|
49
|
+
|
50
|
+
# public interface for Reflector.
|
51
|
+
# ie.reflect # => returns object definitions for entire dom using ie as container
|
52
|
+
# ie.frame('main').select_lists.reflect# => returns definitions for select_lists
|
53
|
+
# only contained by the frame
|
54
|
+
# you can be as granular as needed
|
55
|
+
def reflect
|
56
|
+
puts "I has not exist. Implements me please"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
module Container
|
62
|
+
|
63
|
+
# container asks collections to reflect themselves
|
64
|
+
# each collection knows how to reflect itself and what to reflect
|
65
|
+
def reflect
|
66
|
+
ref = []
|
67
|
+
[:radio_groups, :checkbox_groups, :text_fields, :select_lists].each do |type|
|
68
|
+
ret << self.send(type).reflect
|
69
|
+
end
|
70
|
+
return ref
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
class ElementCollections
|
77
|
+
|
78
|
+
# adds reflect method to element collections
|
79
|
+
include ::Watir::Reflector
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module Watirloo
|
2
|
+
|
3
|
+
|
4
|
+
# manages references to browsers we care about to run tests agains.
|
5
|
+
# Saves references to window handles internall to yaml file so we can reuse the browser for tests by reattaching to it between tests.
|
6
|
+
# you put reference to a browser in storage. Next time you run a test you can restore the browser's reference instead fo staring a new one.
|
7
|
+
module Locker
|
8
|
+
|
9
|
+
@@locker_file = File.join(ENV['TEMP'], "watirloo_temp_locker.yml")
|
10
|
+
|
11
|
+
class << self
|
12
|
+
|
13
|
+
# hash of {key => IE.hwnd} to attach and reuse browsers
|
14
|
+
# example: mapping = {:default=> 234567, :bla => 234234}
|
15
|
+
def mapping
|
16
|
+
@mapping ||= read_mapping
|
17
|
+
end
|
18
|
+
|
19
|
+
def locker
|
20
|
+
@@locker_file
|
21
|
+
end
|
22
|
+
|
23
|
+
def locker=( locker )
|
24
|
+
@@locker_file = locker
|
25
|
+
end
|
26
|
+
|
27
|
+
# returns IE reference to a browser with a given key
|
28
|
+
def browser(key='default')
|
29
|
+
if key == 'default'
|
30
|
+
(@browser && @browser.exists?) ? @browser : @browser = attach_browser
|
31
|
+
else
|
32
|
+
attach_browser(key)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# add browser to storage for later reuse. by convention if you don't have any browsers it
|
37
|
+
# so you can later restore it and continue working with it.
|
38
|
+
# pass either browser referene or the hwnd Fixnum
|
39
|
+
def add(browser, key='default')
|
40
|
+
mapping[key] = browser.kind_of?(Watir::IE) ? browser.hwnd : browser
|
41
|
+
save_mapping
|
42
|
+
end
|
43
|
+
|
44
|
+
# remove browser from storage and from further reusing
|
45
|
+
def remove(key='default')
|
46
|
+
@browser = nil if key == 'default'
|
47
|
+
mapping.delete(key) if mapping[key]
|
48
|
+
save_mapping
|
49
|
+
end
|
50
|
+
|
51
|
+
# clear Storage
|
52
|
+
def clear
|
53
|
+
@browser = nil
|
54
|
+
mapping.clear
|
55
|
+
save_mapping
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
# TODO Change this all to Yaml::Store transaction mechanism. get rid of hand rolled stuff.
|
61
|
+
def read_mapping
|
62
|
+
if FileTest.exists?(locker)
|
63
|
+
loaded = YAML::load_file(locker)
|
64
|
+
#if file is empty or not well formed yaml
|
65
|
+
#or not a hash then return empty hash
|
66
|
+
loaded.kind_of?(Hash) ? loaded : {}
|
67
|
+
else
|
68
|
+
#empty hash if locker.yaml not there
|
69
|
+
#or malformed loaded not created yet
|
70
|
+
{}
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def save_mapping
|
75
|
+
File.open(locker,'w') {|f| YAML.dump(mapping, f)}
|
76
|
+
end
|
77
|
+
|
78
|
+
# throws exception if can't attach to the known handle.
|
79
|
+
def attach_browser(key='default')
|
80
|
+
Watir::IE.attach(:hwnd, mapping[key])
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|