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.
- data/CHANGES +721 -0
- data/LICENSE +34 -0
- data/README.rdoc +78 -0
- data/VERSION +1 -0
- data/bin/watir-console +5 -0
- data/lib/watir-classic.rb +14 -0
- data/lib/watir-classic/IEDialog/Release/IEDialog.dll +0 -0
- data/lib/watir-classic/assertions.rb +44 -0
- data/lib/watir-classic/browser.rb +149 -0
- data/lib/watir-classic/browsers.rb +7 -0
- data/lib/watir-classic/close_all.rb +31 -0
- data/lib/watir-classic/container.rb +110 -0
- data/lib/watir-classic/contrib/enabled_popup.rb +21 -0
- data/lib/watir-classic/contrib/ie-new-process.rb +27 -0
- data/lib/watir-classic/contrib/page_checker.rb +29 -0
- data/lib/watir-classic/cookies.rb +80 -0
- data/lib/watir-classic/core.rb +43 -0
- data/lib/watir-classic/dialogs/file_field.rb +34 -0
- data/lib/watir-classic/dialogs/javascript.rb +43 -0
- data/lib/watir-classic/drag_and_drop_helper.rb +68 -0
- data/lib/watir-classic/element.rb +438 -0
- data/lib/watir-classic/element_collection.rb +109 -0
- data/lib/watir-classic/element_extensions.rb +69 -0
- data/lib/watir-classic/exceptions.rb +50 -0
- data/lib/watir-classic/form.rb +96 -0
- data/lib/watir-classic/frame.rb +47 -0
- data/lib/watir-classic/ie-class.rb +767 -0
- data/lib/watir-classic/ie-process.rb +47 -0
- data/lib/watir-classic/ie.rb +20 -0
- data/lib/watir-classic/image.rb +111 -0
- data/lib/watir-classic/input_elements.rb +480 -0
- data/lib/watir-classic/irb-history.rb +31 -0
- data/lib/watir-classic/link.rb +46 -0
- data/lib/watir-classic/locator.rb +243 -0
- data/lib/watir-classic/logger.rb +19 -0
- data/lib/watir-classic/matches.rb +23 -0
- data/lib/watir-classic/modal_dialog.rb +72 -0
- data/lib/watir-classic/module.rb +12 -0
- data/lib/watir-classic/non_control_elements.rb +114 -0
- data/lib/watir-classic/options.rb +56 -0
- data/lib/watir-classic/page-container.rb +114 -0
- data/lib/watir-classic/process.rb +20 -0
- data/lib/watir-classic/screen_capture.rb +115 -0
- data/lib/watir-classic/supported_elements.rb +172 -0
- data/lib/watir-classic/table.rb +224 -0
- data/lib/watir-classic/testcase.rb +97 -0
- data/lib/watir-classic/util.rb +35 -0
- data/lib/watir-classic/version.rb +4 -0
- data/lib/watir-classic/wait.rb +41 -0
- data/lib/watir-classic/wait_helper.rb +12 -0
- data/lib/watir-classic/waiter.rb +98 -0
- data/lib/watir-classic/win32.rb +40 -0
- data/lib/watir-classic/win32ole.rb +16 -0
- data/lib/watir-classic/win32ole/1.8.7/win32ole.so +0 -0
- data/lib/watir-classic/win32ole/1.9.3/win32ole.so +0 -0
- data/lib/watir-classic/window.rb +68 -0
- data/lib/watir-classic/xpath_locator.rb +52 -0
- data/rakefile.rb +54 -0
- data/unittests/all_tests.rb +10 -0
- data/unittests/buttons_xpath_test.rb +68 -0
- data/unittests/checkbox_test.rb +163 -0
- data/unittests/checkbox_xpath_test.rb +106 -0
- data/unittests/click_no_wait_test.rb +23 -0
- data/unittests/close_all_test.rb +17 -0
- data/unittests/core_tests.rb +17 -0
- data/unittests/css_selector_test.rb +44 -0
- data/unittests/css_test.rb +38 -0
- data/unittests/dialog_test.rb +64 -0
- data/unittests/div2_xpath_test.rb +21 -0
- data/unittests/div_test.rb +170 -0
- data/unittests/div_xpath_test.rb +95 -0
- data/unittests/document_standards.rb +63 -0
- data/unittests/element_collection_indexes_test.rb +57 -0
- data/unittests/element_collections_test.rb +100 -0
- data/unittests/element_test.rb +47 -0
- data/unittests/errorchecker_test.rb +31 -0
- data/unittests/filefield_test.rb +43 -0
- data/unittests/filefield_xpath_test.rb +35 -0
- data/unittests/form_test.rb +282 -0
- data/unittests/form_xpath_test.rb +254 -0
- data/unittests/frame_test.rb +165 -0
- data/unittests/google_form_test.rb +15 -0
- data/unittests/html/JavascriptClick.html +39 -0
- data/unittests/html/blankpage.html +11 -0
- data/unittests/html/buttons1.html +40 -0
- data/unittests/html/checkboxes1.html +89 -0
- data/unittests/html/click_no_wait.html +14 -0
- data/unittests/html/complex_table.html +35 -0
- data/unittests/html/cssTest.html +42 -0
- data/unittests/html/depot_store.html +59 -0
- data/unittests/html/div.html +92 -0
- data/unittests/html/div_xml.html +21 -0
- data/unittests/html/fileupload.html +44 -0
- data/unittests/html/formTest1.html +38 -0
- data/unittests/html/forms2.html +44 -0
- data/unittests/html/forms3.html +131 -0
- data/unittests/html/forms4.html +26 -0
- data/unittests/html/frame_buttons.html +4 -0
- data/unittests/html/frame_links.html +4 -0
- data/unittests/html/frame_multi.html +5 -0
- data/unittests/html/google_india.html +119 -0
- data/unittests/html/ie7_document_standards.html +9 -0
- data/unittests/html/ie8_document_standards.html +9 -0
- data/unittests/html/ie9_document_standards.html +9 -0
- data/unittests/html/iframe.html +3 -0
- data/unittests/html/iframeTest.html +17 -0
- data/unittests/html/iframeTest1.html +7 -0
- data/unittests/html/iframeTest2.html +5 -0
- data/unittests/html/images/1.gif +0 -0
- data/unittests/html/images/2.GIF +0 -0
- data/unittests/html/images/3.GIF +0 -0
- data/unittests/html/images/button.jpg +0 -0
- data/unittests/html/images/circle.jpg +0 -0
- data/unittests/html/images/map.GIF +0 -0
- data/unittests/html/images/map2.gif +0 -0
- data/unittests/html/images/minus.GIF +0 -0
- data/unittests/html/images/originaltriangle.jpg +0 -0
- data/unittests/html/images/plus.gif +0 -0
- data/unittests/html/images/square.jpg +0 -0
- data/unittests/html/images/triangle.jpg +0 -0
- data/unittests/html/images1.html +65 -0
- data/unittests/html/javascriptevents.html +33 -0
- data/unittests/html/link_pass.html +11 -0
- data/unittests/html/links1.html +37 -0
- data/unittests/html/links2.html +11 -0
- data/unittests/html/links_multi.html +12 -0
- data/unittests/html/list_matters.html +720 -0
- data/unittests/html/lists.html +18 -0
- data/unittests/html/map_test.html +30 -0
- data/unittests/html/modal_dialog.html +10 -0
- data/unittests/html/modal_dialog_launcher.html +12 -0
- data/unittests/html/multiple_specifiers.html +64 -0
- data/unittests/html/nestedFrames.html +6 -0
- data/unittests/html/new_browser.html +17 -0
- data/unittests/html/pass.html +13 -0
- data/unittests/html/popups1.html +59 -0
- data/unittests/html/pre.html +29 -0
- data/unittests/html/quirks_document_standards.html +8 -0
- data/unittests/html/radioButtons1.html +71 -0
- data/unittests/html/select_tealeaf.html +54 -0
- data/unittests/html/selectboxes1.html +52 -0
- data/unittests/html/simple_table.html +25 -0
- data/unittests/html/simple_table_buttons.html +104 -0
- data/unittests/html/simple_table_columns.html +75 -0
- data/unittests/html/table1.html +179 -0
- data/unittests/html/tableCell_using_xpath.html +19 -0
- data/unittests/html/table_and_tablerow_to_a.html +174 -0
- data/unittests/html/textarea.html +30 -0
- data/unittests/html/textfields1.html +100 -0
- data/unittests/html/textsearch.html +44 -0
- data/unittests/html/wallofcheckboxes.html +1003 -0
- data/unittests/html/xpath_nbsp.html +11 -0
- data/unittests/html/zeroindex.html +11 -0
- data/unittests/ie_exists_test.rb +16 -0
- data/unittests/ie_mock.rb +94 -0
- data/unittests/ie_test.rb +54 -0
- data/unittests/images_test.rb +156 -0
- data/unittests/images_xpath_test.rb +90 -0
- data/unittests/index_specifier_test.rb +31 -0
- data/unittests/js_events_test.rb +31 -0
- data/unittests/links_multi_test.rb +34 -0
- data/unittests/links_test.rb +131 -0
- data/unittests/links_xpath_test.rb +38 -0
- data/unittests/lists_test.rb +23 -0
- data/unittests/map_test.rb +98 -0
- data/unittests/minmax_test.rb +37 -0
- data/unittests/navigate_test.rb +38 -0
- data/unittests/nbsp_xpath_test.rb +16 -0
- data/unittests/no_wait_test.rb +28 -0
- data/unittests/non_core_tests.rb +12 -0
- data/unittests/other/all_tests_concurrent.rb +57 -0
- data/unittests/other/navigate_exception_test.rb +24 -0
- data/unittests/other/rexml_unit_test.rb +27 -0
- data/unittests/other/screen_capture_test.rb +53 -0
- data/unittests/other/testcase_method_order_test.rb +36 -0
- data/unittests/other/testcase_verify_test.rb +25 -0
- data/unittests/other/wait_until_test.rb +102 -0
- data/unittests/pagecontainstext_test.rb +69 -0
- data/unittests/parent_child_test.rb +27 -0
- data/unittests/perf_test.rb +20 -0
- data/unittests/pre_test.rb +49 -0
- data/unittests/radios_test.rb +181 -0
- data/unittests/radios_xpath_test.rb +100 -0
- data/unittests/security_setting_test.rb +24 -0
- data/unittests/selectbox_test.rb +144 -0
- data/unittests/selectbox_xpath_test.rb +102 -0
- data/unittests/setup.rb +69 -0
- data/unittests/speed_settings_test.rb +67 -0
- data/unittests/table_cell_using_xpath_test.rb +34 -0
- data/unittests/table_test.rb +296 -0
- data/unittests/table_xpath_test.rb +109 -0
- data/unittests/test_tests.rb +9 -0
- data/unittests/textarea_test.rb +92 -0
- data/unittests/textarea_xpath_test.rb +77 -0
- data/unittests/textfield_for_ch_char_test.rb +32 -0
- data/unittests/textfields_test.rb +184 -0
- data/unittests/textfields_xpath_test.rb +110 -0
- data/unittests/version_test.rb +15 -0
- data/unittests/win32ole_so_test.rb +35 -0
- data/unittests/window_tests.rb +10 -0
- data/unittests/windows/attach_to_existing_window_test.rb +52 -0
- data/unittests/windows/attach_to_new_window_test.rb +74 -0
- data/unittests/windows/close_window_test.rb +20 -0
- data/unittests/windows/frame_links_test.rb +23 -0
- data/unittests/windows/ie-each_test.rb +46 -0
- data/unittests/windows/modal_dialog_test.rb +95 -0
- data/unittests/windows/new_process_test.rb +24 -0
- data/unittests/windows/new_test.rb +58 -0
- data/unittests/windows/open_close_test.rb +19 -0
- data/unittests/windows/send_keys_test.rb +26 -0
- data/unittests/xpath_tests.rb +11 -0
- data/watir-rdoc.rb +7 -0
- 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
|