watir-classic 3.0.0

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.
Files changed (213) hide show
  1. data/CHANGES +721 -0
  2. data/LICENSE +34 -0
  3. data/README.rdoc +78 -0
  4. data/VERSION +1 -0
  5. data/bin/watir-console +5 -0
  6. data/lib/watir-classic.rb +14 -0
  7. data/lib/watir-classic/IEDialog/Release/IEDialog.dll +0 -0
  8. data/lib/watir-classic/assertions.rb +44 -0
  9. data/lib/watir-classic/browser.rb +149 -0
  10. data/lib/watir-classic/browsers.rb +7 -0
  11. data/lib/watir-classic/close_all.rb +31 -0
  12. data/lib/watir-classic/container.rb +110 -0
  13. data/lib/watir-classic/contrib/enabled_popup.rb +21 -0
  14. data/lib/watir-classic/contrib/ie-new-process.rb +27 -0
  15. data/lib/watir-classic/contrib/page_checker.rb +29 -0
  16. data/lib/watir-classic/cookies.rb +80 -0
  17. data/lib/watir-classic/core.rb +43 -0
  18. data/lib/watir-classic/dialogs/file_field.rb +34 -0
  19. data/lib/watir-classic/dialogs/javascript.rb +43 -0
  20. data/lib/watir-classic/drag_and_drop_helper.rb +68 -0
  21. data/lib/watir-classic/element.rb +438 -0
  22. data/lib/watir-classic/element_collection.rb +109 -0
  23. data/lib/watir-classic/element_extensions.rb +69 -0
  24. data/lib/watir-classic/exceptions.rb +50 -0
  25. data/lib/watir-classic/form.rb +96 -0
  26. data/lib/watir-classic/frame.rb +47 -0
  27. data/lib/watir-classic/ie-class.rb +767 -0
  28. data/lib/watir-classic/ie-process.rb +47 -0
  29. data/lib/watir-classic/ie.rb +20 -0
  30. data/lib/watir-classic/image.rb +111 -0
  31. data/lib/watir-classic/input_elements.rb +480 -0
  32. data/lib/watir-classic/irb-history.rb +31 -0
  33. data/lib/watir-classic/link.rb +46 -0
  34. data/lib/watir-classic/locator.rb +243 -0
  35. data/lib/watir-classic/logger.rb +19 -0
  36. data/lib/watir-classic/matches.rb +23 -0
  37. data/lib/watir-classic/modal_dialog.rb +72 -0
  38. data/lib/watir-classic/module.rb +12 -0
  39. data/lib/watir-classic/non_control_elements.rb +114 -0
  40. data/lib/watir-classic/options.rb +56 -0
  41. data/lib/watir-classic/page-container.rb +114 -0
  42. data/lib/watir-classic/process.rb +20 -0
  43. data/lib/watir-classic/screen_capture.rb +115 -0
  44. data/lib/watir-classic/supported_elements.rb +172 -0
  45. data/lib/watir-classic/table.rb +224 -0
  46. data/lib/watir-classic/testcase.rb +97 -0
  47. data/lib/watir-classic/util.rb +35 -0
  48. data/lib/watir-classic/version.rb +4 -0
  49. data/lib/watir-classic/wait.rb +41 -0
  50. data/lib/watir-classic/wait_helper.rb +12 -0
  51. data/lib/watir-classic/waiter.rb +98 -0
  52. data/lib/watir-classic/win32.rb +40 -0
  53. data/lib/watir-classic/win32ole.rb +16 -0
  54. data/lib/watir-classic/win32ole/1.8.7/win32ole.so +0 -0
  55. data/lib/watir-classic/win32ole/1.9.3/win32ole.so +0 -0
  56. data/lib/watir-classic/window.rb +68 -0
  57. data/lib/watir-classic/xpath_locator.rb +52 -0
  58. data/rakefile.rb +54 -0
  59. data/unittests/all_tests.rb +10 -0
  60. data/unittests/buttons_xpath_test.rb +68 -0
  61. data/unittests/checkbox_test.rb +163 -0
  62. data/unittests/checkbox_xpath_test.rb +106 -0
  63. data/unittests/click_no_wait_test.rb +23 -0
  64. data/unittests/close_all_test.rb +17 -0
  65. data/unittests/core_tests.rb +17 -0
  66. data/unittests/css_selector_test.rb +44 -0
  67. data/unittests/css_test.rb +38 -0
  68. data/unittests/dialog_test.rb +64 -0
  69. data/unittests/div2_xpath_test.rb +21 -0
  70. data/unittests/div_test.rb +170 -0
  71. data/unittests/div_xpath_test.rb +95 -0
  72. data/unittests/document_standards.rb +63 -0
  73. data/unittests/element_collection_indexes_test.rb +57 -0
  74. data/unittests/element_collections_test.rb +100 -0
  75. data/unittests/element_test.rb +47 -0
  76. data/unittests/errorchecker_test.rb +31 -0
  77. data/unittests/filefield_test.rb +43 -0
  78. data/unittests/filefield_xpath_test.rb +35 -0
  79. data/unittests/form_test.rb +282 -0
  80. data/unittests/form_xpath_test.rb +254 -0
  81. data/unittests/frame_test.rb +165 -0
  82. data/unittests/google_form_test.rb +15 -0
  83. data/unittests/html/JavascriptClick.html +39 -0
  84. data/unittests/html/blankpage.html +11 -0
  85. data/unittests/html/buttons1.html +40 -0
  86. data/unittests/html/checkboxes1.html +89 -0
  87. data/unittests/html/click_no_wait.html +14 -0
  88. data/unittests/html/complex_table.html +35 -0
  89. data/unittests/html/cssTest.html +42 -0
  90. data/unittests/html/depot_store.html +59 -0
  91. data/unittests/html/div.html +92 -0
  92. data/unittests/html/div_xml.html +21 -0
  93. data/unittests/html/fileupload.html +44 -0
  94. data/unittests/html/formTest1.html +38 -0
  95. data/unittests/html/forms2.html +44 -0
  96. data/unittests/html/forms3.html +131 -0
  97. data/unittests/html/forms4.html +26 -0
  98. data/unittests/html/frame_buttons.html +4 -0
  99. data/unittests/html/frame_links.html +4 -0
  100. data/unittests/html/frame_multi.html +5 -0
  101. data/unittests/html/google_india.html +119 -0
  102. data/unittests/html/ie7_document_standards.html +9 -0
  103. data/unittests/html/ie8_document_standards.html +9 -0
  104. data/unittests/html/ie9_document_standards.html +9 -0
  105. data/unittests/html/iframe.html +3 -0
  106. data/unittests/html/iframeTest.html +17 -0
  107. data/unittests/html/iframeTest1.html +7 -0
  108. data/unittests/html/iframeTest2.html +5 -0
  109. data/unittests/html/images/1.gif +0 -0
  110. data/unittests/html/images/2.GIF +0 -0
  111. data/unittests/html/images/3.GIF +0 -0
  112. data/unittests/html/images/button.jpg +0 -0
  113. data/unittests/html/images/circle.jpg +0 -0
  114. data/unittests/html/images/map.GIF +0 -0
  115. data/unittests/html/images/map2.gif +0 -0
  116. data/unittests/html/images/minus.GIF +0 -0
  117. data/unittests/html/images/originaltriangle.jpg +0 -0
  118. data/unittests/html/images/plus.gif +0 -0
  119. data/unittests/html/images/square.jpg +0 -0
  120. data/unittests/html/images/triangle.jpg +0 -0
  121. data/unittests/html/images1.html +65 -0
  122. data/unittests/html/javascriptevents.html +33 -0
  123. data/unittests/html/link_pass.html +11 -0
  124. data/unittests/html/links1.html +37 -0
  125. data/unittests/html/links2.html +11 -0
  126. data/unittests/html/links_multi.html +12 -0
  127. data/unittests/html/list_matters.html +720 -0
  128. data/unittests/html/lists.html +18 -0
  129. data/unittests/html/map_test.html +30 -0
  130. data/unittests/html/modal_dialog.html +10 -0
  131. data/unittests/html/modal_dialog_launcher.html +12 -0
  132. data/unittests/html/multiple_specifiers.html +64 -0
  133. data/unittests/html/nestedFrames.html +6 -0
  134. data/unittests/html/new_browser.html +17 -0
  135. data/unittests/html/pass.html +13 -0
  136. data/unittests/html/popups1.html +59 -0
  137. data/unittests/html/pre.html +29 -0
  138. data/unittests/html/quirks_document_standards.html +8 -0
  139. data/unittests/html/radioButtons1.html +71 -0
  140. data/unittests/html/select_tealeaf.html +54 -0
  141. data/unittests/html/selectboxes1.html +52 -0
  142. data/unittests/html/simple_table.html +25 -0
  143. data/unittests/html/simple_table_buttons.html +104 -0
  144. data/unittests/html/simple_table_columns.html +75 -0
  145. data/unittests/html/table1.html +179 -0
  146. data/unittests/html/tableCell_using_xpath.html +19 -0
  147. data/unittests/html/table_and_tablerow_to_a.html +174 -0
  148. data/unittests/html/textarea.html +30 -0
  149. data/unittests/html/textfields1.html +100 -0
  150. data/unittests/html/textsearch.html +44 -0
  151. data/unittests/html/wallofcheckboxes.html +1003 -0
  152. data/unittests/html/xpath_nbsp.html +11 -0
  153. data/unittests/html/zeroindex.html +11 -0
  154. data/unittests/ie_exists_test.rb +16 -0
  155. data/unittests/ie_mock.rb +94 -0
  156. data/unittests/ie_test.rb +54 -0
  157. data/unittests/images_test.rb +156 -0
  158. data/unittests/images_xpath_test.rb +90 -0
  159. data/unittests/index_specifier_test.rb +31 -0
  160. data/unittests/js_events_test.rb +31 -0
  161. data/unittests/links_multi_test.rb +34 -0
  162. data/unittests/links_test.rb +131 -0
  163. data/unittests/links_xpath_test.rb +38 -0
  164. data/unittests/lists_test.rb +23 -0
  165. data/unittests/map_test.rb +98 -0
  166. data/unittests/minmax_test.rb +37 -0
  167. data/unittests/navigate_test.rb +38 -0
  168. data/unittests/nbsp_xpath_test.rb +16 -0
  169. data/unittests/no_wait_test.rb +28 -0
  170. data/unittests/non_core_tests.rb +12 -0
  171. data/unittests/other/all_tests_concurrent.rb +57 -0
  172. data/unittests/other/navigate_exception_test.rb +24 -0
  173. data/unittests/other/rexml_unit_test.rb +27 -0
  174. data/unittests/other/screen_capture_test.rb +53 -0
  175. data/unittests/other/testcase_method_order_test.rb +36 -0
  176. data/unittests/other/testcase_verify_test.rb +25 -0
  177. data/unittests/other/wait_until_test.rb +102 -0
  178. data/unittests/pagecontainstext_test.rb +69 -0
  179. data/unittests/parent_child_test.rb +27 -0
  180. data/unittests/perf_test.rb +20 -0
  181. data/unittests/pre_test.rb +49 -0
  182. data/unittests/radios_test.rb +181 -0
  183. data/unittests/radios_xpath_test.rb +100 -0
  184. data/unittests/security_setting_test.rb +24 -0
  185. data/unittests/selectbox_test.rb +144 -0
  186. data/unittests/selectbox_xpath_test.rb +102 -0
  187. data/unittests/setup.rb +69 -0
  188. data/unittests/speed_settings_test.rb +67 -0
  189. data/unittests/table_cell_using_xpath_test.rb +34 -0
  190. data/unittests/table_test.rb +296 -0
  191. data/unittests/table_xpath_test.rb +109 -0
  192. data/unittests/test_tests.rb +9 -0
  193. data/unittests/textarea_test.rb +92 -0
  194. data/unittests/textarea_xpath_test.rb +77 -0
  195. data/unittests/textfield_for_ch_char_test.rb +32 -0
  196. data/unittests/textfields_test.rb +184 -0
  197. data/unittests/textfields_xpath_test.rb +110 -0
  198. data/unittests/version_test.rb +15 -0
  199. data/unittests/win32ole_so_test.rb +35 -0
  200. data/unittests/window_tests.rb +10 -0
  201. data/unittests/windows/attach_to_existing_window_test.rb +52 -0
  202. data/unittests/windows/attach_to_new_window_test.rb +74 -0
  203. data/unittests/windows/close_window_test.rb +20 -0
  204. data/unittests/windows/frame_links_test.rb +23 -0
  205. data/unittests/windows/ie-each_test.rb +46 -0
  206. data/unittests/windows/modal_dialog_test.rb +95 -0
  207. data/unittests/windows/new_process_test.rb +24 -0
  208. data/unittests/windows/new_test.rb +58 -0
  209. data/unittests/windows/open_close_test.rb +19 -0
  210. data/unittests/windows/send_keys_test.rb +26 -0
  211. data/unittests/xpath_tests.rb +11 -0
  212. data/watir-rdoc.rb +7 -0
  213. metadata +370 -0
@@ -0,0 +1,47 @@
1
+ require 'win32/process'
2
+
3
+ module Watir
4
+ class IE
5
+ class Process
6
+ def self.start
7
+ program_files = ENV['ProgramFiles'] || "c:\\Program Files"
8
+ startup_command = "#{program_files}\\Internet Explorer\\iexplore.exe"
9
+ startup_command << " -nomerge" if IE.version_parts.first.to_i == 8
10
+ startup_command << " -noframemerging" if IE.version_parts.first.to_i >= 9
11
+ process_info = ::Process.create('app_name' => "#{startup_command} about:blank")
12
+ process_id = process_info.process_id
13
+ new process_id
14
+ end
15
+
16
+ def initialize process_id
17
+ @process_id = process_id
18
+ end
19
+ attr_reader :process_id
20
+
21
+ def window
22
+ Wait.until do
23
+ found_window = nil
24
+ IE.each do | ie |
25
+ window = ie.ie
26
+ hwnd = ie.hwnd
27
+ process_id = Process.process_id_from_hwnd hwnd
28
+ if process_id == @process_id
29
+ found_window = window
30
+ break
31
+ end
32
+ end
33
+ found_window
34
+ end
35
+ end
36
+
37
+ # Returns the process id for the specifed hWnd.
38
+ def self.process_id_from_hwnd hwnd
39
+ pid_info = ' ' * 32
40
+ Win32API.new('user32', 'GetWindowThreadProcessId', 'ip', 'i').
41
+ call(hwnd, pid_info)
42
+ process_id = pid_info.unpack("L")[0]
43
+ end
44
+
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,20 @@
1
+ require 'watir-classic'
2
+ require 'watir-classic/core'
3
+ require 'watir-classic/close_all'
4
+ require 'watir-classic/ie-process'
5
+
6
+ # these switches need to be deleted from ARGV to enable the Test::Unit
7
+ # functionality that grabs
8
+ # the remaining ARGV as a filter on what tests to run.
9
+ # Note: this means that watir-classic must be require'd BEFORE test/unit.
10
+ # (Alternatively, you could require test/unit first and then put the Watir::IE
11
+ # arguments after the '--'.)
12
+
13
+ # Make Internet Explorer invisible. -b stands for background
14
+ $HIDE_IE ||= ARGV.delete('-b')
15
+
16
+ # Run fast
17
+ $FAST_SPEED = ARGV.delete('-f')
18
+
19
+ # Eat the -s command line switch (deprecated)
20
+ ARGV.delete('-s')
@@ -0,0 +1,111 @@
1
+ module Watir
2
+
3
+ # This class is the means of accessing an image on a page.
4
+ # Normally a user would not need to create this object as it is returned by the Watir::Container#image method
5
+ #
6
+ # many of the methods available to this object are inherited from the Element class
7
+ #
8
+ class Image < Element
9
+ attr_ole :alt
10
+ attr_ole :src
11
+ attr_ole :file_created_date, :fileCreatedDate
12
+
13
+ # this method produces the properties for an image as an array
14
+ def image_string_creator
15
+ n = []
16
+ n << "src:".ljust(TO_S_SIZE) + self.src.to_s
17
+ n << "file date:".ljust(TO_S_SIZE) + self.fileCreatedDate.to_s
18
+ n << "file size:".ljust(TO_S_SIZE) + self.fileSize.to_s
19
+ n << "width:".ljust(TO_S_SIZE) + self.width.to_s
20
+ n << "height:".ljust(TO_S_SIZE) + self.height.to_s
21
+ n << "alt:".ljust(TO_S_SIZE) + self.alt.to_s
22
+ return n
23
+ end
24
+ private :image_string_creator
25
+
26
+ # returns a string representation of the object
27
+ def to_s
28
+ assert_exists
29
+ r = string_creator
30
+ r += image_string_creator
31
+ return r.join("\n")
32
+ end
33
+
34
+ # this method returns the filesize of the image, as an int
35
+ def file_size
36
+ assert_exists
37
+ @o.invoke("fileSize").to_i
38
+ end
39
+
40
+ # returns the width in pixels of the image, as an int
41
+ def width
42
+ assert_exists
43
+ @o.invoke("width").to_i
44
+ end
45
+
46
+ # returns the height in pixels of the image, as an int
47
+ def height
48
+ assert_exists
49
+ @o.invoke("height").to_i
50
+ end
51
+
52
+ # This method attempts to find out if the image was actually loaded by the web browser.
53
+ # If the image was not loaded, the browser is unable to determine some of the properties.
54
+ # We look for these missing properties to see if the image is really there or not.
55
+ # If the Disk cache is full (tools menu -> Internet options -> Temporary Internet Files), it may produce incorrect responses.
56
+ def loaded?
57
+ assert_exists
58
+ !file_created_date.empty? && file_size != -1
59
+ end
60
+
61
+ # this method highlights the image (in fact it adds or removes a border around the image)
62
+ # * set_or_clear - symbol - :set to set the border, :clear to remove it
63
+ def highlight(set_or_clear)
64
+ if set_or_clear == :set
65
+ begin
66
+ @original_border = @o.border
67
+ @o.border = 1
68
+ rescue
69
+ @original_border = nil
70
+ end
71
+ else
72
+ begin
73
+ @o.border = @original_border
74
+ @original_border = nil
75
+ rescue
76
+ # we could be here for a number of reasons...
77
+ ensure
78
+ @original_border = nil
79
+ end
80
+ end
81
+ end
82
+ private :highlight
83
+
84
+ # This method saves the image to the file path that is given. The
85
+ # path must be in windows format (c:\\dirname\\somename.gif). This method
86
+ # will not overwrite a previously existing image. If an image already
87
+ # exists at the given path then a dialog will be displayed prompting
88
+ # for overwrite.
89
+ # path - directory path and file name of where image should be saved
90
+ def save(path)
91
+ @container.goto(src)
92
+ begin
93
+ fill_save_image_dialog(path)
94
+ @container.document.execCommand("SaveAs")
95
+ ensure
96
+ @container.back
97
+ end
98
+ end
99
+
100
+ def fill_save_image_dialog(path)
101
+ command = "require 'rubygems';require 'rautomation';" <<
102
+ "window=::RAutomation::Window.new(:title => 'Save Picture');" <<
103
+ "window.text_field(:class => 'Edit', :index => 0).set('#{path.gsub(File::SEPARATOR, File::ALT_SEPARATOR)}');" <<
104
+ "window.button(:value => '&Save').click"
105
+ IO.popen("ruby -e \"#{command}\"")
106
+ end
107
+ private :fill_save_image_dialog
108
+
109
+ end
110
+
111
+ end
@@ -0,0 +1,480 @@
1
+ module Watir
2
+
3
+ class InputElement < Element #:nodoc:all
4
+ def locate
5
+ @o = @container.locator_for(InputElementLocator, @specifiers, self.class).locate
6
+ end
7
+
8
+ attr_ole :disabled?
9
+ attr_ole :name
10
+ attr_ole :value
11
+ attr_ole :alt
12
+ attr_ole :src
13
+ attr_ole :type
14
+ end
15
+
16
+ #
17
+ # Input: Select
18
+ #
19
+
20
+ # This class is the way in which select boxes are manipulated.
21
+ # Normally a user would not need to create this object as it is returned by the Watir::Container#select_list method
22
+ class SelectList < InputElement
23
+ attr_ole :multiple?
24
+
25
+ # This method clears the selected items in the select box
26
+ def clear
27
+ perform_action do
28
+ options.each {|option| option.clear}
29
+ end
30
+ end
31
+
32
+ # This method selects an item, or items in a select box, by text.
33
+ # Raises NoValueFoundException if the specified value is not found.
34
+ # * item - the thing to select, string or reg exp
35
+ def select(item)
36
+ matching_options = []
37
+ perform_action do
38
+ matching_options = matching_items_in_select_list(:text, item) +
39
+ matching_items_in_select_list(:label, item) +
40
+ matching_items_in_select_list(:value, item)
41
+ raise NoValueFoundException, "No option with :text, :label or :value of #{item.inspect} in this select element" if matching_options.empty?
42
+ matching_options.each(&:select)
43
+ end
44
+ matching_options.first.text
45
+ end
46
+
47
+ # Selects an item, or items in a select box, by value.
48
+ # Raises NoValueFoundException if the specified value is not found.
49
+ # * item - the value of the thing to select, string or reg exp
50
+ def select_value(item)
51
+ matching_options = matching_items_in_select_list(:value, item)
52
+ raise NoValueFoundException, "No option with :value of #{item.inspect} in this select element" if matching_options.empty?
53
+ matching_options.each(&:select)
54
+ matching_options.first.value
55
+ end
56
+
57
+ # Returns array of the selected text items in a select box
58
+ # Raises UnknownObjectException if the select box is not found.
59
+ def selected_options
60
+ options.select(&:selected?)
61
+ end
62
+
63
+ # Does the SelectList include the specified option (text)?
64
+ def include? text_or_regexp
65
+ !options.map(&:text).grep(text_or_regexp).empty?
66
+ end
67
+
68
+ # Is the specified option (text) selected? Raises exception of option does not exist.
69
+ def selected? text_or_regexp
70
+ raise UnknownObjectException, "Option #{text_or_regexp.inspect} not found." unless include? text_or_regexp
71
+ !selected_options.map(&:text).grep(text_or_regexp).empty?
72
+ end
73
+
74
+ private
75
+
76
+ def matching_items_in_select_list(attribute, value)
77
+ options.select do |opt|
78
+ if value.is_a?(Regexp)
79
+ opt.send(attribute) =~ value
80
+ elsif value.is_a?(String) || value.is_a?(Numeric)
81
+ opt.send(attribute) == value.to_s
82
+ else
83
+ raise TypeError, "#{value.inspect} can be only String, Regexp or Numeric!"
84
+ end
85
+ end
86
+ end
87
+ end
88
+
89
+ class Option < Element
90
+ attr_ole :disabled?
91
+ attr_ole :name
92
+ attr_ole :value
93
+ attr_ole :label
94
+
95
+ def select
96
+ perform_action do
97
+ unless selected?
98
+ ole_object.selected = true
99
+ select_list.dispatch_event("onChange")
100
+ @container.wait
101
+ end
102
+ end
103
+ end
104
+
105
+ def clear
106
+ raise TypeError, "you can only clear multi-selects" unless select_list.multiple?
107
+
108
+ perform_action do
109
+ if selected?
110
+ ole_object.selected = false
111
+ select_list.dispatch_event("onChange")
112
+ @container.wait
113
+ end
114
+ end
115
+ end
116
+
117
+ def selected?
118
+ assert_exists
119
+ ole_object.selected
120
+ end
121
+
122
+ def text
123
+ l = label
124
+ l.empty? ? super : l rescue ''
125
+ end
126
+
127
+ private
128
+
129
+ def select_list
130
+ return @select_list if @select_list
131
+ el = parent
132
+ el = el.parent until el.is_a?(SelectList)
133
+
134
+ raise "SELECT element was not found for #{self}!" unless el
135
+ @select_list = el
136
+ end
137
+ end
138
+
139
+ #
140
+ # Input: Button
141
+ #
142
+
143
+ # Returned by the Watir::Container#button method
144
+ class Button < InputElement
145
+ alias_method :__value, :value
146
+
147
+ def text
148
+ val = __value
149
+ val.empty? ? super : val
150
+ end
151
+
152
+ alias_method :value, :text
153
+ end
154
+
155
+ #
156
+ # Input: Text
157
+ #
158
+
159
+ # This class is the main class for Text Fields
160
+ # Normally a user would not need to create this object as it is returned by the Watir::Container#text_field method
161
+ class TextField < InputElement
162
+ attr_ole :size
163
+ attr_ole :readonly?
164
+ alias_method :text, :value
165
+
166
+ #:startdoc:
167
+
168
+ # return number of maxlength attribute
169
+ def maxlength
170
+ assert_exists unless @o
171
+ begin
172
+ ole_object.invoke('maxlength').to_i
173
+ rescue WIN32OLERuntimeError
174
+ 0
175
+ end
176
+ end
177
+
178
+ def text_string_creator
179
+ n = []
180
+ n << "length:".ljust(TO_S_SIZE) + self.size.to_s
181
+ n << "max length:".ljust(TO_S_SIZE) + self.maxlength.to_s
182
+ n << "read only:".ljust(TO_S_SIZE) + self.readonly?.to_s
183
+ n
184
+ end
185
+ private :text_string_creator
186
+
187
+ def to_s
188
+ assert_exists
189
+ r = string_creator
190
+ r += text_string_creator
191
+ r.join("\n")
192
+ end
193
+
194
+ def assert_not_readonly #:nodoc:
195
+ if self.readonly?
196
+ raise ObjectReadOnlyException,
197
+ "Textfield #{@specifiers.inspect} is read only."
198
+ end
199
+ end
200
+
201
+ # Returns true if the text field contents is matches the specified target,
202
+ # which can be either a string or a regular expression.
203
+ # Raises UnknownObjectException if the object can't be found
204
+ #--
205
+ # I vote for deprecating this
206
+ # we should use text_field().text.include?(some) or text.match(/some/) instead of this method
207
+ def verify_contains(target) #:nodoc:
208
+ assert_exists
209
+ if target.kind_of? String
210
+ return true if self.value == target
211
+ elsif target.kind_of? Regexp
212
+ return true if self.value.match(target) != nil
213
+ end
214
+ return false
215
+ end
216
+
217
+ # Drag the entire contents of the text field to another text field
218
+ # 19 Jan 2005 - It is added as prototype functionality, and may change
219
+ # * destination_how - symbol, :id, :name how we identify the drop target
220
+ # * destination_what - string or regular expression, the name, id, etc of the text field that will be the drop target
221
+ def drag_contents_to(destination_how, destination_what)
222
+ assert_exists
223
+ destination = @container.text_field(destination_how, destination_what)
224
+ unless destination.exists?
225
+ raise UnknownObjectException, "Unable to locate destination using #{destination_how } and #{destination_what } "
226
+ end
227
+
228
+ @o.focus(0)
229
+ @o.select(0)
230
+ value = self.value
231
+
232
+ dispatch_event("onSelect")
233
+ dispatch_event("ondragstart")
234
+ dispatch_event("ondrag")
235
+ destination.dispatch_event("onDragEnter")
236
+ destination.dispatch_event("onDragOver")
237
+ destination.dispatch_event("ondrop")
238
+
239
+ dispatch_event("ondragend")
240
+ destination.value = destination.value + value.to_s
241
+ self.value = ""
242
+ end
243
+
244
+ # Clears the contents of the text box.
245
+ # Raises UnknownObjectException if the object can't be found
246
+ # Raises ObjectDisabledException if the object is disabled
247
+ # Raises ObjectReadOnlyException if the object is read only
248
+ def clear
249
+ assert_exists
250
+ assert_enabled
251
+ assert_not_readonly
252
+
253
+ highlight(:set)
254
+
255
+ @o.scrollIntoView
256
+ @o.focus(0)
257
+ @o.select(0)
258
+ dispatch_event("onSelect")
259
+ @o.value = ""
260
+ dispatch_event("onKeyPress")
261
+ dispatch_event("onChange")
262
+ @container.wait
263
+ highlight(:clear)
264
+ end
265
+
266
+ # Appends the specified string value to the contents of the text box.
267
+ # Raises UnknownObjectException if the object cant be found
268
+ # Raises ObjectDisabledException if the object is disabled
269
+ # Raises ObjectReadOnlyException if the object is read only
270
+ def append(value)
271
+ assert_exists
272
+ assert_enabled
273
+ assert_not_readonly
274
+
275
+ highlight(:set)
276
+ @o.scrollIntoView
277
+ @o.focus(0)
278
+ type_by_character(value)
279
+ highlight(:clear)
280
+ end
281
+
282
+ # Sets the contents of the text box to the specified text value
283
+ # Raises UnknownObjectException if the object cant be found
284
+ # Raises ObjectDisabledException if the object is disabled
285
+ # Raises ObjectReadOnlyException if the object is read only
286
+ def set(value)
287
+ assert_exists
288
+ assert_enabled
289
+ assert_not_readonly
290
+
291
+ highlight(:set)
292
+ @o.scrollIntoView
293
+ if type_keys
294
+ @o.focus(0)
295
+ @o.select(0)
296
+ dispatch_event("onSelect")
297
+ dispatch_event("onKeyPress")
298
+ @o.value = ""
299
+ type_by_character(value)
300
+ dispatch_event("onChange")
301
+ dispatch_event("onBlur")
302
+ else
303
+ @o.value = limit_to_maxlength(value)
304
+ end
305
+ highlight(:clear)
306
+ end
307
+
308
+ # Sets the value of the text field directly.
309
+ # It causes no events to be fired or exceptions to be raised,
310
+ # so generally shouldn't be used.
311
+ # It is preffered to use the set method.
312
+ def value=(v)
313
+ assert_exists
314
+ @o.value = v.to_s
315
+ end
316
+
317
+ def requires_typing #:nodoc:
318
+ @type_keys = true
319
+ self
320
+ end
321
+ def abhors_typing #:nodoc:
322
+ @type_keys = false
323
+ self
324
+ end
325
+
326
+ def label
327
+ @container.label(:for => name).text
328
+ end
329
+
330
+ private
331
+
332
+ # Type the characters in the specified string (value) one by one.
333
+ # It should not be used externally.
334
+ # * value - string - The string to enter into the text field
335
+ def type_by_character(value)
336
+ value = limit_to_maxlength(value)
337
+ characters_in(value) do |c|
338
+ sleep @container.typingspeed
339
+ @o.value = @o.value.to_s + c
340
+ dispatch_event("onKeyDown")
341
+ dispatch_event("onKeyPress")
342
+ dispatch_event("onKeyUp")
343
+ end
344
+ end
345
+
346
+ # Supports double-byte characters
347
+ def characters_in(value, &blk)
348
+ if RUBY_VERSION =~ /^1\.8/
349
+ index = 0
350
+ while index < value.length
351
+ len = value[index] > 128 ? 2 : 1
352
+ yield value[index, len]
353
+ index += len
354
+ end
355
+ else
356
+ value.each_char(&blk)
357
+ end
358
+ end
359
+
360
+ # Return the value (a string), limited to the maxlength of the element.
361
+ def limit_to_maxlength(value)
362
+ return value if @o.invoke('type') =~ /textarea/i # text areas don't have maxlength
363
+ if value.length > maxlength
364
+ value = value[0 .. maxlength - 1]
365
+ @container.log " Supplied string is #{value.length} chars, which exceeds the max length (#{maxlength}) of the field. Using value: #{value}"
366
+ end
367
+ value
368
+ end
369
+
370
+ end
371
+
372
+ # this class can be used to access hidden field objects
373
+ # Normally a user would not need to create this object as it is returned by the Watir::Container#hidden method
374
+ class Hidden < TextField
375
+ # set is overriden in this class, as there is no way to set focus to a hidden field
376
+ def set(n)
377
+ self.value = n
378
+ end
379
+
380
+ # override the append method, so that focus isnt set to the hidden object
381
+ def append(n)
382
+ self.value = self.value.to_s + n.to_s
383
+ end
384
+
385
+ # override the clear method, so that focus isnt set to the hidden object
386
+ def clear
387
+ self.value = ""
388
+ end
389
+
390
+ # this method will do nothing, as you cant set focus to a hidden field
391
+ def focus
392
+ end
393
+
394
+ # Hidden element is never visible - returns false.
395
+ def visible?
396
+ assert_exists
397
+ false
398
+ end
399
+ end
400
+
401
+ # This module contains common methods to both radio buttons and check boxes.
402
+ # Normally a user would not need to create this object as it is returned by the Watir::Container#checkbox or by Watir::Container#radio methods
403
+ module RadioCheckCommon
404
+ def self.included(base)
405
+ base.instance_eval do
406
+ attr_ole :set?, :checked
407
+ alias_method :checked?, :set?
408
+ end
409
+ end
410
+
411
+ def inspect
412
+ '#<%s:0x%x located=%s specifiers=%s value=%s>' % [self.class, hash*2, !!ole_object, @specifiers.inspect, @value.inspect]
413
+ end
414
+ end
415
+
416
+ #--
417
+ # this class makes the docs better
418
+ #++
419
+ # This class is the watir representation of a radio button.
420
+ # Normally a user would not need to create this object as it is returned by the Watir::Container#radio method
421
+ class Radio < InputElement
422
+ include RadioCheckCommon
423
+ # This method clears a radio button. One of them will almost always be set.
424
+ # Returns true if set or false if not set.
425
+ # Raises UnknownObjectException if its unable to locate an object
426
+ # ObjectDisabledException IF THE OBJECT IS DISABLED
427
+ def clear
428
+ assert_exists
429
+ assert_enabled
430
+ highlight(:set)
431
+ @o.checked = false
432
+ highlight(:clear)
433
+ highlight(:clear)
434
+ end
435
+
436
+ # This method sets the radio list item.
437
+ # Raises UnknownObjectException if it's unable to locate an object
438
+ # ObjectDisabledException if the object is disabled
439
+ def set
440
+ assert_exists
441
+ assert_enabled
442
+ highlight(:set)
443
+ @o.scrollIntoView
444
+ @o.checked = true
445
+ click
446
+ highlight(:clear)
447
+ end
448
+
449
+ end
450
+
451
+ # This class is the watir representation of a check box.
452
+ # Normally a user would not need to create this object as it is returned by the Watir::Container#checkbox method
453
+ class CheckBox < InputElement
454
+ include RadioCheckCommon
455
+ # This method checks or unchecks the checkbox.
456
+ # With no arguments supplied it sets the checkbox.
457
+ # Setting false argument unchecks/clears the checkbox.
458
+ # Raises UnknownObjectException if it's unable to locate an object
459
+ # ObjectDisabledException if the object is disabled
460
+ def set(value=true)
461
+ assert_exists
462
+ assert_enabled
463
+ highlight :set
464
+ current_value = @o.checked
465
+ unless value == current_value
466
+ click
467
+ end
468
+ highlight :clear
469
+ end
470
+
471
+ # Clears a check box.
472
+ # Raises UnknownObjectException if its unable to locate an object
473
+ # ObjectDisabledException if the object is disabled
474
+ def clear
475
+ set false
476
+ end
477
+
478
+ end
479
+
480
+ end