watir 1.6.2 → 1.6.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (178) hide show
  1. data/CHANGES +326 -188
  2. data/bin/watir-console +7 -8
  3. data/lib/changes.rb +3 -3
  4. data/lib/license.rb +38 -38
  5. data/lib/readme.rb +140 -140
  6. data/lib/watir/WindowHelper.rb +49 -49
  7. data/lib/watir/camel_case.rb +66 -45
  8. data/lib/watir/clickJSDialog.rb +19 -19
  9. data/lib/watir/close_all.rb +37 -37
  10. data/lib/watir/collections.rb +344 -312
  11. data/lib/watir/container.rb +815 -753
  12. data/lib/watir/contrib/enabled_popup.rb +20 -20
  13. data/lib/watir/contrib/ie-new-process.rb +27 -27
  14. data/lib/watir/contrib/page_checker.rb +29 -29
  15. data/lib/watir/cookiemanager.rb +55 -55
  16. data/lib/watir/core_ext.rb +18 -0
  17. data/lib/watir/datahandler.rb +107 -107
  18. data/lib/watir/dialog.rb +46 -46
  19. data/lib/watir/element.rb +343 -312
  20. data/lib/watir/element_collections.rb +97 -81
  21. data/lib/watir/form.rb +170 -170
  22. data/lib/watir/frame.rb +59 -59
  23. data/lib/watir/ie-class.rb +1009 -1003
  24. data/lib/watir/ie-process.rb +39 -39
  25. data/lib/watir/ie.rb +133 -132
  26. data/lib/watir/image.rb +130 -130
  27. data/lib/watir/input_elements.rb +572 -539
  28. data/lib/watir/irb-history.rb +30 -30
  29. data/lib/watir/link.rb +64 -64
  30. data/lib/watir/locator.rb +176 -161
  31. data/lib/watir/logger.rb +19 -19
  32. data/lib/watir/modal_dialog.rb +122 -122
  33. data/lib/watir/non_control_elements.rb +145 -127
  34. data/lib/watir/page-container.rb +107 -105
  35. data/lib/watir/popup.rb +29 -29
  36. data/lib/watir/process.rb +19 -19
  37. data/lib/watir/screen_capture.rb +115 -115
  38. data/lib/watir/setFileDialog.rb +16 -16
  39. data/lib/watir/table.rb +362 -362
  40. data/lib/watir/utils.rb +19 -19
  41. data/lib/watir/version.rb +5 -5
  42. data/lib/watir/watir_simple.rb +475 -475
  43. data/lib/watir/win32.rb +35 -28
  44. data/lib/watir/win32ole.rb +14 -6
  45. data/lib/watir/winClicker.rb +496 -479
  46. data/unittests/all_tests.rb +10 -10
  47. data/unittests/buttons_xpath_test.rb +69 -69
  48. data/unittests/checkbox_test.rb +179 -176
  49. data/unittests/checkbox_xpath_test.rb +107 -107
  50. data/unittests/core_tests.rb +17 -16
  51. data/unittests/css_test.rb +35 -35
  52. data/unittests/defer_test.rb +46 -46
  53. data/unittests/dialog_test.rb +77 -77
  54. data/unittests/div2_xpath_test.rb +21 -21
  55. data/unittests/div_test.rb +188 -183
  56. data/unittests/div_xpath_test.rb +96 -96
  57. data/unittests/errorchecker_test.rb +22 -22
  58. data/unittests/filefield_test.rb +39 -40
  59. data/unittests/filefield_xpath_test.rb +33 -33
  60. data/unittests/form_test.rb +280 -293
  61. data/unittests/form_xpath_test.rb +252 -253
  62. data/unittests/frame_test.rb +155 -157
  63. data/unittests/google_form_test.rb +15 -15
  64. data/unittests/html/JavascriptClick.html +39 -39
  65. data/unittests/html/blankpage.html +11 -11
  66. data/unittests/html/buttons1.html +40 -40
  67. data/unittests/html/checkboxes1.html +89 -89
  68. data/unittests/html/complex_table.html +36 -36
  69. data/unittests/html/cssTest.html +42 -42
  70. data/unittests/html/depot_store.html +51 -51
  71. data/unittests/html/div.html +93 -93
  72. data/unittests/html/div_xml.html +20 -20
  73. data/unittests/html/fileupload.html +45 -45
  74. data/unittests/html/formTest1.html +38 -38
  75. data/unittests/html/forms2.html +44 -44
  76. data/unittests/html/forms3.html +131 -131
  77. data/unittests/html/forms4.html +27 -27
  78. data/unittests/html/frame_buttons.html +3 -3
  79. data/unittests/html/frame_links.html +3 -3
  80. data/unittests/html/frame_multi.html +4 -4
  81. data/unittests/html/google_india.html +107 -107
  82. data/unittests/html/iframeTest.html +12 -12
  83. data/unittests/html/iframeTest1.html +6 -6
  84. data/unittests/html/iframeTest2.html +5 -5
  85. data/unittests/html/images1.html +66 -66
  86. data/unittests/html/javascriptevents.html +35 -35
  87. data/unittests/html/link_pass.html +10 -10
  88. data/unittests/html/links1.html +38 -38
  89. data/unittests/html/links2.html +10 -10
  90. data/unittests/html/links_multi.html +14 -14
  91. data/unittests/html/list_matters.html +720 -720
  92. data/unittests/html/lists.html +17 -17
  93. data/unittests/html/map_test.html +31 -31
  94. data/unittests/html/modal_dialog.html +10 -10
  95. data/unittests/html/modal_dialog_launcher.html +11 -11
  96. data/unittests/html/nestedFrames.html +6 -6
  97. data/unittests/html/new_browser.html +16 -16
  98. data/unittests/html/pass.html +12 -12
  99. data/unittests/html/popups1.html +59 -59
  100. data/unittests/html/pre.html +27 -27
  101. data/unittests/html/radioButtons1.html +71 -71
  102. data/unittests/html/select_tealeaf.html +54 -54
  103. data/unittests/html/selectboxes1.html +52 -55
  104. data/unittests/html/simple_table.html +26 -26
  105. data/unittests/html/simple_table_buttons.html +104 -104
  106. data/unittests/html/simple_table_columns.html +76 -76
  107. data/unittests/html/table1.html +181 -181
  108. data/unittests/html/tableCell_using_xpath.html +19 -19
  109. data/unittests/html/textarea.html +30 -30
  110. data/unittests/html/textfields1.html +88 -88
  111. data/unittests/html/textsearch.html +44 -44
  112. data/unittests/html/wallofcheckboxes.html +1003 -1003
  113. data/unittests/html/xpath_nbsp.html +12 -12
  114. data/unittests/ie_exists_test.rb +33 -33
  115. data/unittests/ie_mock.rb +94 -94
  116. data/unittests/ie_test.rb +51 -50
  117. data/unittests/images_test.rb +157 -157
  118. data/unittests/images_xpath_test.rb +91 -91
  119. data/unittests/links_multi_test.rb +48 -48
  120. data/unittests/links_test.rb +175 -177
  121. data/unittests/links_xpath_test.rb +39 -39
  122. data/unittests/map_test.rb +98 -98
  123. data/unittests/minmax_test.rb +31 -31
  124. data/unittests/navigate_test.rb +39 -39
  125. data/unittests/nbsp_xpath_test.rb +16 -16
  126. data/unittests/non_core_tests.rb +12 -12
  127. data/unittests/other/WindowLogonExample.rb +27 -27
  128. data/unittests/other/WindowLogonExtra.rb +6 -6
  129. data/unittests/other/all_tests_concurrent.rb +57 -57
  130. data/unittests/{windows → other}/jscriptExtraAlert.rb +6 -6
  131. data/unittests/{windows → other}/jscriptExtraConfirmCancel.rb +6 -6
  132. data/unittests/{windows → other}/jscriptExtraConfirmOk.rb +6 -6
  133. data/unittests/{windows → other}/jscriptPushButton.rb +6 -6
  134. data/unittests/{windows → other}/jscript_test.rb +63 -63
  135. data/unittests/other/navigate_exception_test.rb +24 -24
  136. data/unittests/other/rexml_unit_test.rb +27 -24
  137. data/unittests/other/screen_capture_test.rb +54 -54
  138. data/unittests/other/testcase_method_order_test.rb +35 -35
  139. data/unittests/other/testcase_verify_test.rb +24 -24
  140. data/unittests/other/wait_until_test.rb +99 -99
  141. data/unittests/pagecontainstext_test.rb +69 -69
  142. data/unittests/parent_child_test.rb +43 -43
  143. data/unittests/perf_test.rb +20 -20
  144. data/unittests/popups_test.rb +43 -43
  145. data/unittests/pre_test.rb +53 -53
  146. data/unittests/radios_test.rb +212 -212
  147. data/unittests/radios_xpath_test.rb +101 -101
  148. data/unittests/security_setting_test.rb +23 -23
  149. data/unittests/selectbox_test.rb +148 -139
  150. data/unittests/selectbox_xpath_test.rb +113 -113
  151. data/unittests/setup.rb +77 -75
  152. data/unittests/speed_settings_test.rb +67 -65
  153. data/unittests/table_cell_using_xpath_test.rb +35 -35
  154. data/unittests/table_test.rb +376 -362
  155. data/unittests/table_xpath_test.rb +110 -110
  156. data/unittests/test_tests.rb +9 -9
  157. data/unittests/textarea_test.rb +92 -92
  158. data/unittests/textarea_xpath_test.rb +78 -78
  159. data/unittests/textfield_for_ch_char_test.rb +31 -29
  160. data/unittests/textfields_test.rb +218 -218
  161. data/unittests/textfields_xpath_test.rb +111 -111
  162. data/unittests/window_tests.rb +10 -7
  163. data/unittests/windows/attach_to_existing_window_test.rb +53 -52
  164. data/unittests/windows/attach_to_new_window_test.rb +83 -82
  165. data/unittests/windows/close_window_test.rb +20 -20
  166. data/unittests/windows/frame_links_test.rb +25 -25
  167. data/unittests/windows/ie-each_test.rb +47 -47
  168. data/unittests/windows/iedialog_test.rb +54 -54
  169. data/unittests/windows/js_events_test.rb +55 -55
  170. data/unittests/windows/modal_dialog_test.rb +128 -126
  171. data/unittests/windows/new_test.rb +57 -55
  172. data/unittests/windows/open_close_test.rb +18 -18
  173. data/unittests/windows/send_keys_test.rb +33 -32
  174. data/unittests/xpath_tests.rb +10 -10
  175. metadata +20 -20
  176. data/lib/watir/contrib/visible.rb +0 -47
  177. data/unittests/iostring.rb +0 -30
  178. data/unittests/iostring_test.rb +0 -48
@@ -1,82 +1,98 @@
1
- module Watir
2
- # this class is the super class for the iterator classes (buttons, links, spans etc
3
- # it would normally only be accessed by the iterator methods (spans, links etc) of IE
4
- class ElementCollections
5
- include Enumerable
6
-
7
- # Super class for all the iteractor classes
8
- # * container - an instance of an IE object
9
- def initialize(container)
10
- @container = container
11
- @page_container = container.page_container
12
- @length = length # defined by subclasses
13
-
14
- # set up the items we want to display when the show method is used
15
- set_show_items
16
- end
17
-
18
- private
19
- def set_show_items
20
- @show_attributes = AttributeLengthPairs.new("id", 20)
21
- @show_attributes.add("name", 20)
22
- end
23
-
24
- public
25
- def get_length_of_input_objects(object_type)
26
- object_types =
27
- if object_type.kind_of? Array
28
- object_type
29
- else
30
- [object_type]
31
- end
32
-
33
- length = 0
34
- objects = @container.document.getElementsByTagName("INPUT")
35
- if objects.length > 0
36
- objects.each do |o|
37
- length += 1 if object_types.include?(o.invoke("type").downcase)
38
- end
39
- end
40
- return length
41
- end
42
-
43
- # iterate through each of the elements in the collection in turn
44
- def each
45
- 0.upto(@length-1) { |i| yield iterator_object(i) }
46
- end
47
-
48
- # allows access to a specific item in the collection
49
- def [](n)
50
- return iterator_object(n-1)
51
- end
52
-
53
- # this method is the way to show the objects, normally used from irb
54
- def show
55
- s = "index".ljust(6)
56
- @show_attributes.each do |attribute_length_pair|
57
- s += attribute_length_pair.attribute.ljust(attribute_length_pair.length)
58
- end
59
-
60
- index = 1
61
- self.each do |o|
62
- s += "\n"
63
- s += index.to_s.ljust(6)
64
- @show_attributes.each do |attribute_length_pair|
65
- begin
66
- s += eval('o.ole_object.invoke("#{attribute_length_pair.attribute}")').to_s.ljust(attribute_length_pair.length)
67
- rescue => e
68
- s += " ".ljust(attribute_length_pair.length)
69
- end
70
- end
71
- index += 1
72
- end
73
- puts s
74
- end
75
-
76
- # this method creates an object of the correct type that the iterators use
77
- private
78
- def iterator_object(i)
79
- element_class.new(@container, :index, i + 1)
80
- end
81
- end
1
+ module Watir
2
+ # this class is the super class for the iterator classes (buttons, links, spans etc
3
+ # it would normally only be accessed by the iterator methods (spans, links etc) of IE
4
+ class ElementCollections
5
+ include Enumerable
6
+
7
+ # Super class for all the iteractor classes
8
+ # * container - an instance of an IE object
9
+ def initialize(container)
10
+ @container = container
11
+ @page_container = container.page_container
12
+ @length = length # defined by subclasses
13
+
14
+ # set up the items we want to display when the show method is used
15
+ set_show_items
16
+ end
17
+
18
+ private
19
+ def set_show_items
20
+ @show_attributes = AttributeLengthPairs.new("id", 20)
21
+ @show_attributes.add("name", 20)
22
+ end
23
+
24
+ public
25
+ def get_length_of_input_objects(object_type)
26
+ object_types =
27
+ if object_type.kind_of? Array
28
+ object_type
29
+ else
30
+ [object_type]
31
+ end
32
+
33
+ length = 0
34
+ objects = @container.document.getElementsByTagName("INPUT")
35
+ if objects.length > 0
36
+ objects.each do |o|
37
+ length += 1 if object_types.include?(o.invoke("type").downcase)
38
+ end
39
+ end
40
+ return length
41
+ end
42
+
43
+ # iterate through each of the elements in the collection in turn
44
+ def each
45
+ 0.upto(@length-1) { |i| yield iterator_object(i) }
46
+ end
47
+
48
+ # allows access to a specific item in the collection
49
+ def [](n)
50
+ return iterator_object(n-1)
51
+ end
52
+
53
+ def first
54
+ iterator_object(0)
55
+ end
56
+
57
+ def last
58
+ iterator_object(length - 1)
59
+ end
60
+
61
+ # this method is the way to show the objects, normally used from irb
62
+ def show
63
+ s = "index".ljust(6)
64
+ @show_attributes.each do |attribute_length_pair|
65
+ s += attribute_length_pair.attribute.ljust(attribute_length_pair.length)
66
+ end
67
+
68
+ index = 1
69
+ self.each do |o|
70
+ s += "\n"
71
+ s += index.to_s.ljust(6)
72
+ @show_attributes.each do |attribute_length_pair|
73
+ begin
74
+ s += eval('o.ole_object.invoke("#{attribute_length_pair.attribute}")').to_s.ljust(attribute_length_pair.length)
75
+ rescue => e
76
+ s += " ".ljust(attribute_length_pair.length)
77
+ end
78
+ end
79
+ index += 1
80
+ end
81
+ puts s
82
+ end
83
+
84
+ def to_s
85
+ map { |e| e.to_s }.join("\n")
86
+ end
87
+
88
+ def inspect
89
+ '#<%s:0x%x length=%s container=%s>' % [self.class, hash*2, @length.inspect, @container.inspect]
90
+ end
91
+
92
+ # this method creates an object of the correct type that the iterators use
93
+ private
94
+ def iterator_object(i)
95
+ element_class.new(@container, :index, i + 1)
96
+ end
97
+ end
82
98
  end
@@ -1,171 +1,171 @@
1
- module Watir
2
-
3
- # Forms
4
-
5
- module FormAccess
6
- def name
7
- @ole_object.getAttributeNode('name').value
8
- end
9
- def action
10
- @ole_object.action
11
- end
12
- def method
13
- @ole_object.invoke('method')
14
- end
15
- def id
16
- @ole_object.invoke('id')
17
- end
18
- end
19
-
20
- # wraps around a form OLE object
21
- class FormWrapper
22
- include FormAccess
23
- def initialize ole_object
24
- @ole_object = ole_object
25
- end
26
- end
27
-
28
- # Form Factory object
29
- class Form < Element
30
- include FormAccess
31
- include Container
32
-
33
- attr_accessor :form, :ole_object
34
-
35
- # * container - the containing object, normally an instance of IE
36
- # * how - symbol - how we access the form (:name, :id, :index, :action, :method)
37
- # * what - what we use to access the form
38
- def initialize(container, how, what)
39
- set_container container
40
- @how = how
41
- @what = what
42
-
43
- log "Get form how is #{@how} what is #{@what} "
44
-
45
- # Get form using xpath.
46
- if @how == :xpath
47
- @ole_object = @container.element_by_xpath(@what)
48
- else
49
- count = 1
50
- doc = @container.document
51
- doc.forms.each do |thisForm|
52
- next unless @ole_object == nil
53
-
54
- wrapped = FormWrapper.new(thisForm)
55
- @ole_object =
56
- case @how
57
- when :name, :id, :method, :action
58
- @what.matches(wrapped.send(@how)) ? thisForm : nil
59
- when :index
60
- count == @what ? thisForm : nil
61
- else
62
- raise MissingWayOfFindingObjectException, "#{how} is an unknown way of finding a form (#{what})"
63
- end
64
- count += 1
65
- end
66
- end
67
- super(@ole_object)
68
-
69
- copy_test_config container
70
- end
71
-
72
- def exists?
73
- @ole_object ? true : false
74
- end
75
- alias :exist? :exists?
76
-
77
- def assert_exists
78
- unless exists?
79
- raise UnknownFormException,
80
- "Unable to locate a form using #{@how} and #{@what}"
81
- end
82
- end
83
-
84
- # Submit the data -- equivalent to pressing Enter or Return to submit a form.
85
- def submit
86
- assert_exists
87
- @ole_object.invoke('submit')
88
- @container.wait
89
- end
90
-
91
- def ole_inner_elements
92
- assert_exists
93
- @ole_object.elements
94
- end
95
- private :ole_inner_elements
96
-
97
- def document
98
- return @ole_object
99
- end
100
-
101
- def wait(no_sleep=false)
102
- @container.wait(no_sleep)
103
- end
104
-
105
- # This method is responsible for setting and clearing the colored highlighting on the specified form.
106
- # use :set to set the highlight
107
- # :clear to clear the highlight
108
- def highlight(set_or_clear, element, count)
109
-
110
- if set_or_clear == :set
111
- begin
112
- original_color = element.style.backgroundColor
113
- original_color = "" if original_color==nil
114
- element.style.backgroundColor = activeObjectHighLightColor
115
- rescue => e
116
- puts e
117
- puts e.backtrace.join("\n")
118
- original_color = ""
119
- end
120
- @original_styles[count] = original_color
121
- else
122
- begin
123
- element.style.backgroundColor = @original_styles[ count]
124
- rescue => e
125
- puts e
126
- # we could be here for a number of reasons...
127
- ensure
128
- end
129
- end
130
- end
131
- private :highlight
132
-
133
- # causes the object to flash. Normally used in IRB when creating scripts
134
- # Default is 10
135
- def flash number=10
136
- @original_styles = {}
137
- number.times do
138
- count = 0
139
- @ole_object.elements.each do |element|
140
- highlight(:set, element, count)
141
- count += 1
142
- end
143
- sleep 0.05
144
- count = 0
145
- @ole_object.elements.each do |element|
146
- highlight(:clear, element, count)
147
- count += 1
148
- end
149
- sleep 0.05
150
- end
151
- end
152
-
153
- end # class Form
154
-
155
- end
156
-
157
- module Watir
158
- class Forms < ElementCollections
159
- def element_class; Form; end
160
- def element_tag; 'FORM'; end
161
- def length
162
- @container.document.getElementsByTagName("FORM").length
163
- end
164
- end
165
-
166
- module Container
167
- def forms
168
- Forms.new(self)
169
- end
170
- end
1
+ module Watir
2
+
3
+ # Forms
4
+
5
+ module FormAccess
6
+ def name
7
+ @ole_object.getAttributeNode('name').value
8
+ end
9
+ def action
10
+ @ole_object.action
11
+ end
12
+ def method
13
+ @ole_object.invoke('method')
14
+ end
15
+ def id
16
+ @ole_object.invoke('id')
17
+ end
18
+ end
19
+
20
+ # wraps around a form OLE object
21
+ class FormWrapper
22
+ include FormAccess
23
+ def initialize ole_object
24
+ @ole_object = ole_object
25
+ end
26
+ end
27
+
28
+ # Form Factory object
29
+ class Form < Element
30
+ include FormAccess
31
+ include Container
32
+
33
+ attr_accessor :form, :ole_object
34
+
35
+ # * container - the containing object, normally an instance of IE
36
+ # * how - symbol - how we access the form (:name, :id, :index, :action, :method)
37
+ # * what - what we use to access the form
38
+ def initialize(container, how, what)
39
+ set_container container
40
+ @how = how
41
+ @what = what
42
+
43
+ log "Get form how is #{@how} what is #{@what} "
44
+
45
+ # Get form using xpath.
46
+ if @how == :xpath
47
+ @ole_object = @container.element_by_xpath(@what)
48
+ else
49
+ count = 1
50
+ doc = @container.document
51
+ doc.forms.each do |thisForm|
52
+ next unless @ole_object == nil
53
+
54
+ wrapped = FormWrapper.new(thisForm)
55
+ @ole_object =
56
+ case @how
57
+ when :name, :id, :method, :action
58
+ @what.matches(wrapped.send(@how)) ? thisForm : nil
59
+ when :index
60
+ count == @what ? thisForm : nil
61
+ else
62
+ raise MissingWayOfFindingObjectException, "#{how} is an unknown way of finding a form (#{what})"
63
+ end
64
+ count += 1
65
+ end
66
+ end
67
+ super(@ole_object)
68
+
69
+ copy_test_config container
70
+ end
71
+
72
+ def exists?
73
+ @ole_object ? true : false
74
+ end
75
+ alias :exist? :exists?
76
+
77
+ def assert_exists
78
+ unless exists?
79
+ raise UnknownFormException,
80
+ "Unable to locate a form using #{@how} and #{@what}"
81
+ end
82
+ end
83
+
84
+ # Submit the data -- equivalent to pressing Enter or Return to submit a form.
85
+ def submit
86
+ assert_exists
87
+ @ole_object.invoke('submit')
88
+ @container.wait
89
+ end
90
+
91
+ def ole_inner_elements
92
+ assert_exists
93
+ @ole_object.elements
94
+ end
95
+ private :ole_inner_elements
96
+
97
+ def document
98
+ return @ole_object
99
+ end
100
+
101
+ def wait(no_sleep=false)
102
+ @container.wait(no_sleep)
103
+ end
104
+
105
+ # This method is responsible for setting and clearing the colored highlighting on the specified form.
106
+ # use :set to set the highlight
107
+ # :clear to clear the highlight
108
+ def highlight(set_or_clear, element, count)
109
+
110
+ if set_or_clear == :set
111
+ begin
112
+ original_color = element.style.backgroundColor
113
+ original_color = "" if original_color==nil
114
+ element.style.backgroundColor = activeObjectHighLightColor
115
+ rescue => e
116
+ puts e
117
+ puts e.backtrace.join("\n")
118
+ original_color = ""
119
+ end
120
+ @original_styles[count] = original_color
121
+ else
122
+ begin
123
+ element.style.backgroundColor = @original_styles[ count]
124
+ rescue => e
125
+ puts e
126
+ # we could be here for a number of reasons...
127
+ ensure
128
+ end
129
+ end
130
+ end
131
+ private :highlight
132
+
133
+ # causes the object to flash. Normally used in IRB when creating scripts
134
+ # Default is 10
135
+ def flash number=10
136
+ @original_styles = {}
137
+ number.times do
138
+ count = 0
139
+ @ole_object.elements.each do |element|
140
+ highlight(:set, element, count)
141
+ count += 1
142
+ end
143
+ sleep 0.05
144
+ count = 0
145
+ @ole_object.elements.each do |element|
146
+ highlight(:clear, element, count)
147
+ count += 1
148
+ end
149
+ sleep 0.05
150
+ end
151
+ end
152
+
153
+ end # class Form
154
+
155
+ end
156
+
157
+ module Watir
158
+ class Forms < ElementCollections
159
+ def element_class; Form; end
160
+ def element_tag; 'FORM'; end
161
+ def length
162
+ @container.document.getElementsByTagName("FORM").length
163
+ end
164
+ end
165
+
166
+ module Container
167
+ def forms
168
+ Forms.new(self)
169
+ end
170
+ end
171
171
  end