watir 1.9.2 → 2.0.0.rc2
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/CHANGES +27 -0
- data/VERSION +1 -1
- data/lib/watir/collections.rb +29 -387
- data/lib/watir/container.rb +14 -784
- data/lib/watir/dialogs/javascript.rb +7 -0
- data/lib/watir/element.rb +24 -4
- data/lib/watir/element_collections.rb +35 -57
- data/lib/watir/form.rb +13 -33
- data/lib/watir/frame.rb +14 -27
- data/lib/watir/html_element.rb +11 -3
- data/lib/watir/ie-class.rb +10 -1
- data/lib/watir/image.rb +3 -11
- data/lib/watir/input_elements.rb +11 -11
- data/lib/watir/link.rb +8 -15
- data/lib/watir/locator.rb +98 -73
- data/lib/watir/modal_dialog.rb +7 -1
- data/lib/watir/non_control_elements.rb +5 -89
- data/lib/watir/table.rb +46 -49
- data/unittests/checkbox_test.rb +39 -44
- data/unittests/checkbox_xpath_test.rb +2 -2
- data/unittests/css_test.rb +1 -1
- data/unittests/div_test.rb +43 -43
- data/unittests/div_xpath_test.rb +12 -12
- data/unittests/element_collections_test.rb +85 -0
- data/unittests/element_test.rb +4 -4
- data/unittests/form_test.rb +16 -19
- data/unittests/form_xpath_test.rb +6 -6
- data/unittests/frame_test.rb +114 -120
- data/unittests/html/multiple_specifiers.html +64 -0
- data/unittests/ie_test.rb +5 -5
- data/unittests/images_test.rb +12 -12
- data/unittests/index_specifier_test.rb +32 -0
- data/unittests/js_events_test.rb +3 -3
- data/unittests/links_multi_test.rb +4 -4
- data/unittests/links_test.rb +20 -20
- data/unittests/lists_test.rb +1 -1
- data/unittests/map_test.rb +1 -1
- data/unittests/multiple_specifiers_test.rb +29 -0
- data/unittests/no_wait_test.rb +2 -2
- data/unittests/pagecontainstext_test.rb +2 -2
- data/unittests/parent_child_test.rb +2 -2
- data/unittests/pre_test.rb +5 -5
- data/unittests/radios_test.rb +41 -60
- data/unittests/selectbox_test.rb +15 -15
- data/unittests/speed_settings_test.rb +2 -2
- data/unittests/table_and_tablerow_to_a_test.rb +7 -7
- data/unittests/table_test.rb +81 -94
- data/unittests/textfields_test.rb +26 -27
- data/unittests/windows/attach_to_new_window_test.rb +1 -1
- data/watir-rdoc.rb +1 -1
- data/watir.gemspec +1 -2
- metadata +34 -40
data/CHANGES
CHANGED
|
@@ -1,3 +1,30 @@
|
|
|
1
|
+
== Version 2.0.0 - 2011/07/XX
|
|
2
|
+
|
|
3
|
+
* RIP FireWatir - there won't be any new releases
|
|
4
|
+
* all elements are using 0-based indexing instead of old 1-based indexing:
|
|
5
|
+
- disable it temporarily: require "watir"; Watir.options[:zero_based_indexing] = false
|
|
6
|
+
* #radio and #checkbox methods doesn't allow 3 parameters anymore for locating with "value"
|
|
7
|
+
- use browser.radio(:name => "something", :value => "some value") syntax instead for locating with "value"
|
|
8
|
+
* all element methods accept now multiple-specifiers with hash syntax, for example:
|
|
9
|
+
- browser.element(:class => "someclass", :name => "somename")
|
|
10
|
+
* all elements are searchable by :xpath and :css now (note that it's usually slower than searching by other specifiers)
|
|
11
|
+
* #button, #form and #frame doesn't accept single string as a specifier anymore to search by name:
|
|
12
|
+
- use browser.frame(:name => "name") or browser.frame(:name, "name") syntax instead
|
|
13
|
+
* :index => 0 is used as a default specifier if nothing is specified:
|
|
14
|
+
- browser.div(:id => "id").table.tr is same as browser.div(:id => "id").table(:index => 0).tr(:index => 0)
|
|
15
|
+
* all collection methods accept now specifiers too:
|
|
16
|
+
- browser.divs(:class => "someclass").each {|div| puts div.class_name} # => "someclass"
|
|
17
|
+
* removed FormElement class
|
|
18
|
+
* renamed CheckBox class to Checkbox
|
|
19
|
+
* renamed CheckBoxes class to Checkboxes
|
|
20
|
+
* added aliases:
|
|
21
|
+
- tr => row
|
|
22
|
+
- trs => rows
|
|
23
|
+
- td => cell
|
|
24
|
+
- tds => cells
|
|
25
|
+
- a => link
|
|
26
|
+
- as => links
|
|
27
|
+
|
|
1
28
|
== Version 1.9.2 - 2011/07/11
|
|
2
29
|
|
|
3
30
|
=== IE improvements
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
2.0.0.rc2
|
data/lib/watir/collections.rb
CHANGED
|
@@ -1,409 +1,51 @@
|
|
|
1
1
|
module Watir
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
# for subclasses of ElementCollections
|
|
7
|
-
module CommonCollection #:nodoc:all
|
|
8
|
-
def element_tag
|
|
9
|
-
element_class::TAG
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def length
|
|
13
|
-
@container.document.getElementsByTagName(element_tag).length
|
|
14
|
-
end
|
|
15
|
-
alias_method :size, :length
|
|
2
|
+
class InputElementCollections < ElementCollections
|
|
3
|
+
def each
|
|
4
|
+
@container.input_element_locator(@how, @what, element_class::INPUT_TYPES, element_class).each {|element| yield element}
|
|
5
|
+
end
|
|
16
6
|
end
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
# it would not normally be used by a user
|
|
20
|
-
class AttributeLengthPairs #:nodoc:all
|
|
21
|
-
|
|
22
|
-
# This class is used as part of the .show method of the iterators class
|
|
23
|
-
# it would not normally be used by a user
|
|
24
|
-
class AttributeLengthHolder
|
|
25
|
-
attr_accessor :attribute
|
|
26
|
-
attr_accessor :length
|
|
27
|
-
|
|
28
|
-
def initialize(attrib, length)
|
|
29
|
-
@attribute = attrib
|
|
30
|
-
@length = length
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def initialize(attrib=nil, length=nil)
|
|
35
|
-
@attr=[]
|
|
36
|
-
add(attrib, length) if attrib
|
|
37
|
-
@index_counter = 0
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
# BUG: Untested. (Null implementation passes all tests.)
|
|
41
|
-
def add(attrib, length)
|
|
42
|
-
@attr << AttributeLengthHolder.new(attrib, length)
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def delete(attrib)
|
|
46
|
-
item_to_delete = nil
|
|
47
|
-
@attr.each_with_index do |e,i|
|
|
48
|
-
item_to_delete = i if e.attribute == attrib
|
|
49
|
-
end
|
|
50
|
-
@attr.delete_at(item_to_delete) unless item_to_delete == nil
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def next
|
|
54
|
-
temp = @attr[@index_counter]
|
|
55
|
-
@index_counter += 1
|
|
56
|
-
return temp
|
|
57
|
-
end
|
|
58
|
-
|
|
7
|
+
|
|
8
|
+
class Frames < ElementCollections
|
|
59
9
|
def each
|
|
60
|
-
|
|
10
|
+
@container.locator_for(FrameLocator, @how, @what).each {|element| yield element}
|
|
61
11
|
end
|
|
62
12
|
end
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
# it would normally only be accessed by the Watir::Container#buttons method
|
|
69
|
-
class Buttons < ElementCollections
|
|
70
|
-
def element_class; Button; end
|
|
71
|
-
# number of buttons
|
|
72
|
-
# browser.buttons.length
|
|
73
|
-
def length
|
|
74
|
-
get_length_of_input_objects(["button", "submit", "image"])
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
private
|
|
78
|
-
def set_show_items
|
|
79
|
-
super
|
|
80
|
-
@show_attributes.add("disabled", 9)
|
|
81
|
-
@show_attributes.add("value", 20)
|
|
82
|
-
end
|
|
13
|
+
|
|
14
|
+
class Forms < ElementCollections
|
|
15
|
+
def each
|
|
16
|
+
@container.locator_for(FormLocator, @how, @what).each {|element| yield element}
|
|
17
|
+
end
|
|
83
18
|
end
|
|
84
19
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
def element_class; FileField; end
|
|
89
|
-
# number of file_fields
|
|
90
|
-
# browser.file_fields.length
|
|
91
|
-
def length
|
|
92
|
-
get_length_of_input_objects(["file"])
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
private
|
|
96
|
-
def set_show_items
|
|
97
|
-
super
|
|
98
|
-
@show_attributes.add("disabled", 9)
|
|
99
|
-
@show_attributes.add("value", 20)
|
|
20
|
+
class HTMLElements < ElementCollections
|
|
21
|
+
def each
|
|
22
|
+
@container.locator_for(ElementLocator, @how, @what).each { |element| yield element }
|
|
100
23
|
end
|
|
101
24
|
end
|
|
102
|
-
|
|
25
|
+
|
|
103
26
|
# this class accesses the check boxes in the document as a collection
|
|
104
27
|
# Normally a user would not need to create this object as it is returned by the Watir::Container#checkboxes method
|
|
105
|
-
class
|
|
106
|
-
def element_class;
|
|
107
|
-
# number of checkboxes
|
|
108
|
-
# browser.checkboxes.length
|
|
109
|
-
def length
|
|
110
|
-
get_length_of_input_objects("checkbox")
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
private
|
|
114
|
-
def iterator_object(i)
|
|
115
|
-
@container.checkbox(:index, i + 1)
|
|
116
|
-
end
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
# this class accesses the radio buttons in the document as a collection
|
|
120
|
-
# Normally a user would not need to create this object as it is returned by the Watir::Container#radios method
|
|
121
|
-
class Radios < ElementCollections
|
|
122
|
-
def element_class; Radio; end
|
|
123
|
-
# number of radios
|
|
124
|
-
# browser.radios.length
|
|
125
|
-
def length
|
|
126
|
-
get_length_of_input_objects("radio")
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
private
|
|
130
|
-
def iterator_object(i)
|
|
131
|
-
@container.radio(:index, i + 1)
|
|
132
|
-
end
|
|
28
|
+
class Checkboxes < InputElementCollections
|
|
29
|
+
def element_class; Checkbox; end
|
|
133
30
|
end
|
|
134
31
|
|
|
135
32
|
# this class accesses the select boxes in the document as a collection
|
|
136
33
|
# Normally a user would not need to create this object as it is returned by the Watir::Container#select_lists method
|
|
137
|
-
class SelectLists <
|
|
138
|
-
include CommonCollection
|
|
139
|
-
def element_class; SelectList; end
|
|
34
|
+
class SelectLists < InputElementCollections
|
|
140
35
|
def element_tag; 'SELECT'; end
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
# this class accesses the links in the document as a collection
|
|
144
|
-
# Normally a user would not need to create this object as it is returned by the Watir::Container#links method
|
|
145
|
-
class Links < ElementCollections
|
|
146
|
-
include CommonCollection
|
|
147
|
-
def element_class; Link; end
|
|
148
|
-
def element_tag; 'A'; end
|
|
149
|
-
|
|
150
|
-
private
|
|
151
|
-
def set_show_items
|
|
152
|
-
super
|
|
153
|
-
@show_attributes.add("href", 60)
|
|
154
|
-
@show_attributes.add("innerText", 60)
|
|
155
|
-
end
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
class Lis < ElementCollections
|
|
159
|
-
include CommonCollection
|
|
160
|
-
def element_class; Li; end
|
|
161
|
-
|
|
162
|
-
private
|
|
163
|
-
def set_show_items
|
|
164
|
-
super
|
|
165
|
-
@show_attributes.delete( "name")
|
|
166
|
-
@show_attributes.add( "className" , 20)
|
|
167
|
-
end
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
# this class accesses the maps in the document as a collection
|
|
171
|
-
# Normally a user would not need to create this object as it is returned by the Watir::Container#maps method
|
|
172
|
-
class Maps < ElementCollections
|
|
173
|
-
include CommonCollection
|
|
174
|
-
def element_class; Map; end
|
|
175
|
-
def element_tag; 'MAP'; end
|
|
176
|
-
end
|
|
177
|
-
|
|
36
|
+
end
|
|
178
37
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
def element_class; Area; end
|
|
184
|
-
def element_tag; 'AREA'; end
|
|
38
|
+
%w[Buttons FileFields Radios TextFields Hiddens].each do |collection|
|
|
39
|
+
module_eval %Q{
|
|
40
|
+
class #{collection} < InputElementCollections; end
|
|
41
|
+
}
|
|
185
42
|
end
|
|
186
43
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
# browser.images.length
|
|
193
|
-
def length
|
|
194
|
-
all = @container.document.all
|
|
195
|
-
imgs = []
|
|
196
|
-
all.each{|n| imgs << n if n.nodeName == "IMG"}
|
|
197
|
-
imgs.length
|
|
198
|
-
end
|
|
199
|
-
|
|
200
|
-
private
|
|
201
|
-
def set_show_items
|
|
202
|
-
super
|
|
203
|
-
@show_attributes.add("src", 60)
|
|
204
|
-
@show_attributes.add("alt", 30)
|
|
205
|
-
end
|
|
206
|
-
end
|
|
207
|
-
|
|
208
|
-
# this class accesses the text fields in the document as a collection
|
|
209
|
-
# Normally a user would not need to create this object as it is returned by the Watir::Container#text_fields method
|
|
210
|
-
class TextFields < ElementCollections
|
|
211
|
-
def element_class; TextField; end
|
|
212
|
-
# number of text_fields
|
|
213
|
-
# browser.text_fields.length
|
|
214
|
-
def length
|
|
215
|
-
# text areas are also included in the TextFields, but we need to get them seperately
|
|
216
|
-
get_length_of_input_objects(["text", "password"]) +
|
|
217
|
-
@container.document.getElementsByTagName("textarea").length
|
|
218
|
-
end
|
|
219
|
-
end
|
|
220
|
-
|
|
221
|
-
# this class accesses the hidden fields in the document as a collection
|
|
222
|
-
# Normally a user would not need to create this object as it is returned by the Watir::Container#hiddens method
|
|
223
|
-
class Hiddens < ElementCollections
|
|
224
|
-
def element_class; Hidden; end
|
|
225
|
-
# number of hidden elements
|
|
226
|
-
# browser.hiddens.length
|
|
227
|
-
def length
|
|
228
|
-
get_length_of_input_objects("hidden")
|
|
229
|
-
end
|
|
230
|
-
end
|
|
231
|
-
|
|
232
|
-
# this class accesses the text fields in the document as a collection
|
|
233
|
-
# Normally a user would not need to create this object as it is returned by the Watir::Container#tables method
|
|
234
|
-
class Tables < ElementCollections
|
|
235
|
-
include CommonCollection
|
|
236
|
-
def element_class; Table; end
|
|
237
|
-
def element_tag; 'TABLE'; end
|
|
238
|
-
|
|
239
|
-
private
|
|
240
|
-
def set_show_items
|
|
241
|
-
super
|
|
242
|
-
@show_attributes.delete("name")
|
|
243
|
-
end
|
|
244
|
-
end
|
|
245
|
-
# this class accesses the table rows in the document as a collection
|
|
246
|
-
# Normally a user would not need to create this object as it is returned by the Watir::Container#rows method
|
|
247
|
-
class TableRows < ElementCollections
|
|
248
|
-
include CommonCollection
|
|
249
|
-
def element_class; TableRow; end
|
|
250
|
-
def element_tag; 'TR'; end
|
|
251
|
-
end
|
|
252
|
-
# this class accesses the table cells in the document as a collection
|
|
253
|
-
# Normally a user would not need to create this object as it is returned by the Watir::Container#cells method
|
|
254
|
-
class TableCells < ElementCollections
|
|
255
|
-
include CommonCollection
|
|
256
|
-
def element_class; TableCell; end
|
|
257
|
-
def element_tag; 'TD'; end
|
|
258
|
-
end
|
|
259
|
-
# this class accesses the labels in the document as a collection
|
|
260
|
-
# Normally a user would not need to create this object as it is returned by the Watir::Container#labels method
|
|
261
|
-
class Labels < ElementCollections
|
|
262
|
-
include CommonCollection
|
|
263
|
-
def element_class; Label; end
|
|
264
|
-
def element_tag; 'LABEL'; end
|
|
265
|
-
|
|
266
|
-
private
|
|
267
|
-
def set_show_items
|
|
268
|
-
super
|
|
269
|
-
@show_attributes.add("htmlFor", 20)
|
|
270
|
-
end
|
|
271
|
-
end
|
|
272
|
-
|
|
273
|
-
# this class accesses the pre tags in the document as a collection
|
|
274
|
-
# Normally a user would not need to create this object as it is returned by the Watir::Container#pres method
|
|
275
|
-
class Pres < ElementCollections
|
|
276
|
-
include CommonCollection
|
|
277
|
-
def element_class; Pre; end
|
|
278
|
-
|
|
279
|
-
private
|
|
280
|
-
def set_show_items
|
|
281
|
-
super
|
|
282
|
-
@show_attributes.delete("name")
|
|
283
|
-
@show_attributes.add("className", 20)
|
|
284
|
-
end
|
|
285
|
-
end
|
|
286
|
-
|
|
287
|
-
# this class accesses the p tags in the document as a collection
|
|
288
|
-
# Normally a user would not need to create this object as it is returned by the Watir::Container#ps method
|
|
289
|
-
class Ps < ElementCollections
|
|
290
|
-
include CommonCollection
|
|
291
|
-
def element_class; P; end
|
|
292
|
-
|
|
293
|
-
private
|
|
294
|
-
def set_show_items
|
|
295
|
-
super
|
|
296
|
-
@show_attributes.delete("name")
|
|
297
|
-
@show_attributes.add("className", 20)
|
|
298
|
-
end
|
|
299
|
-
|
|
300
|
-
end
|
|
301
|
-
# this class accesses the spans in the document as a collection
|
|
302
|
-
# Normally a user would not need to create this object as it is returned by the Watir::Container#spans method
|
|
303
|
-
class Spans < ElementCollections
|
|
304
|
-
include CommonCollection
|
|
305
|
-
def element_class; Span; end
|
|
306
|
-
|
|
307
|
-
private
|
|
308
|
-
def set_show_items
|
|
309
|
-
super
|
|
310
|
-
@show_attributes.delete("name")
|
|
311
|
-
@show_attributes.add("className", 20)
|
|
312
|
-
end
|
|
313
|
-
end
|
|
314
|
-
|
|
315
|
-
# this class accesses the divs in the document as a collection
|
|
316
|
-
# Normally a user would not need to create this object as it is returned by the Watir::Container#divs method
|
|
317
|
-
class Divs < ElementCollections
|
|
318
|
-
include CommonCollection
|
|
319
|
-
def element_class; Div; end
|
|
320
|
-
|
|
321
|
-
private
|
|
322
|
-
def set_show_items
|
|
323
|
-
super
|
|
324
|
-
@show_attributes.delete("name")
|
|
325
|
-
@show_attributes.add("className", 20)
|
|
326
|
-
end
|
|
327
|
-
end
|
|
328
|
-
|
|
329
|
-
class Dls < ElementCollections
|
|
330
|
-
include CommonCollection
|
|
331
|
-
def element_class; Dl; end
|
|
332
|
-
def element_tag; Dl::TAG; end
|
|
333
|
-
end
|
|
334
|
-
|
|
335
|
-
class Dts < ElementCollections
|
|
336
|
-
include CommonCollection
|
|
337
|
-
def element_class; Dt; end
|
|
338
|
-
def element_tag; Dt::TAG; end
|
|
339
|
-
end
|
|
340
|
-
|
|
341
|
-
class Dds < ElementCollections
|
|
342
|
-
include CommonCollection
|
|
343
|
-
def element_class; Dd; end
|
|
344
|
-
def element_tag; Dd::TAG; end
|
|
345
|
-
end
|
|
346
|
-
|
|
347
|
-
class Strongs < ElementCollections
|
|
348
|
-
include CommonCollection
|
|
349
|
-
def element_class; Strong; end
|
|
350
|
-
def element_tag; Strong::TAG; end
|
|
351
|
-
end
|
|
352
|
-
|
|
353
|
-
class Ems < ElementCollections
|
|
354
|
-
include CommonCollection
|
|
355
|
-
def element_class; Em; end
|
|
356
|
-
def element_tag; Em::TAG; end
|
|
357
|
-
end
|
|
358
|
-
|
|
359
|
-
class Frames < ElementCollections
|
|
360
|
-
def element_class; Frame; end
|
|
361
|
-
|
|
362
|
-
def length
|
|
363
|
-
@container.document.getElementsByTagName("FRAME").length +
|
|
364
|
-
@container.document.getElementsByTagName("IFRAME").length
|
|
365
|
-
end
|
|
366
|
-
end
|
|
367
|
-
|
|
368
|
-
class Forms < ElementCollections
|
|
369
|
-
def element_class; Form; end
|
|
370
|
-
def element_tag; 'FORM'; end
|
|
371
|
-
def length
|
|
372
|
-
@container.document.getElementsByTagName("FORM").length
|
|
373
|
-
end
|
|
374
|
-
end
|
|
375
|
-
|
|
376
|
-
class HTMLElements < ElementCollections
|
|
377
|
-
include CommonCollection
|
|
378
|
-
def element_class; HTMLElement; end
|
|
379
|
-
def element_tag; '*'; end
|
|
380
|
-
|
|
381
|
-
def initialize(container, how, what)
|
|
382
|
-
@how = how
|
|
383
|
-
@what = what
|
|
384
|
-
if how == :index
|
|
385
|
-
raise MissingWayOfFindingObjectException,
|
|
386
|
-
"#{self.class} does not support attribute #{@how}"
|
|
387
|
-
end
|
|
388
|
-
super(container)
|
|
389
|
-
end
|
|
390
|
-
|
|
391
|
-
def length
|
|
392
|
-
count = 0
|
|
393
|
-
each {|element| count += 1 }
|
|
394
|
-
count
|
|
395
|
-
end
|
|
396
|
-
alias :size :length
|
|
397
|
-
|
|
398
|
-
def each
|
|
399
|
-
@container.locate_all_elements(@how, @what).each { |element| yield element }
|
|
400
|
-
end
|
|
401
|
-
|
|
402
|
-
def iterator_object(i)
|
|
403
|
-
count = 0
|
|
404
|
-
each {|e| return e if count == i;count += 1;}
|
|
405
|
-
end
|
|
406
|
-
|
|
44
|
+
%w[Links Lis Maps Areas Images Tables TableRows TableCells
|
|
45
|
+
Labels Pres Ps Spans Divs Dls Dts Dds Strongs Ems].each do |collection|
|
|
46
|
+
module_eval %Q{
|
|
47
|
+
class #{collection} < ElementCollections; end
|
|
48
|
+
}
|
|
407
49
|
end
|
|
408
50
|
|
|
409
51
|
end
|