watirloo 0.0.7
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/.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
|