watir-classic 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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,109 @@
|
|
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 ElementCollection
|
5
|
+
include Enumerable
|
6
|
+
|
7
|
+
# Super class for all the iterator classes
|
8
|
+
# * container - an instance of an IE object
|
9
|
+
def initialize(container, specifiers)
|
10
|
+
if specifiers[:index]
|
11
|
+
raise Exception::MissingWayOfFindingObjectException,
|
12
|
+
"#{self.class} does not support attribute :index in #{specifiers.inspect}"
|
13
|
+
end
|
14
|
+
|
15
|
+
@container = container
|
16
|
+
@specifiers = specifiers
|
17
|
+
@page_container = container.page_container
|
18
|
+
end
|
19
|
+
|
20
|
+
def length
|
21
|
+
count = 0
|
22
|
+
each {|element| count += 1 }
|
23
|
+
count
|
24
|
+
end
|
25
|
+
|
26
|
+
alias_method :size, :length
|
27
|
+
|
28
|
+
# iterate through each of the elements in the collection in turn
|
29
|
+
def each
|
30
|
+
@container.locator_for(TaggedElementLocator, @specifiers, element_class).each {|element| yield element}
|
31
|
+
end
|
32
|
+
|
33
|
+
# allows access to a specific item in the collection
|
34
|
+
def [](n)
|
35
|
+
number = n - Watir::IE.base_index
|
36
|
+
offset = Watir::IE.zero_based_indexing ? (length - 1) : length
|
37
|
+
non_existing_element = element_class.new(@container, @specifiers.merge(:index => n))
|
38
|
+
def non_existing_element.locate; nil end
|
39
|
+
iterator_object(number) || non_existing_element
|
40
|
+
end
|
41
|
+
|
42
|
+
def first
|
43
|
+
iterator_object(0)
|
44
|
+
end
|
45
|
+
|
46
|
+
def last
|
47
|
+
iterator_object(length - 1)
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_s
|
51
|
+
map { |e| e.to_s }.join("\n")
|
52
|
+
end
|
53
|
+
|
54
|
+
def inspect
|
55
|
+
'#<%s:0x%x length=%s container=%s>' % [self.class, hash*2, length.inspect, @container.inspect]
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def iterator_object(i)
|
61
|
+
count = 0
|
62
|
+
each do |e|
|
63
|
+
return e if (i >= 0 && count == i) || (i < 0 && count == length + i)
|
64
|
+
count += 1
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def element_class
|
69
|
+
Watir.const_get self.class.name.split("::").last.scan(/(.*)Collection/).flatten.first
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
class TableElementCollection < ElementCollection
|
75
|
+
def initialize(container, specifiers, ole_collection=nil)
|
76
|
+
super container, specifiers
|
77
|
+
@ole_collection = ole_collection
|
78
|
+
end
|
79
|
+
|
80
|
+
def each
|
81
|
+
if @ole_collection
|
82
|
+
elements = []
|
83
|
+
@ole_collection.each {|element| elements << element_class.new(@container, :ole_object => element)}
|
84
|
+
super do |element|
|
85
|
+
yield element if elements.include?(element)
|
86
|
+
end
|
87
|
+
else
|
88
|
+
super
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
class TableRowCollection < TableElementCollection; end
|
94
|
+
|
95
|
+
class TableCellCollection < TableElementCollection; end
|
96
|
+
|
97
|
+
class InputElementCollection < ElementCollection
|
98
|
+
def each
|
99
|
+
@container.locator_for(InputElementLocator, @specifiers, element_class).each {|element| yield element}
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
class HTMLElementCollection < ElementCollection
|
104
|
+
def each
|
105
|
+
@container.locator_for(TaggedElementLocator, @specifiers, Element).each { |element| yield element }
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Watir
|
4
|
+
# This assumes that Element#visible? is defined
|
5
|
+
module ElementExtensions
|
6
|
+
|
7
|
+
#
|
8
|
+
# Wraps a {Celerity,Watir}::Element so that any subsequent method calls are
|
9
|
+
# put on hold until the element is present on the page.
|
10
|
+
#
|
11
|
+
|
12
|
+
class WhenPresentDecorator
|
13
|
+
def initialize(element, timeout)
|
14
|
+
@element = element
|
15
|
+
@timeout = timeout
|
16
|
+
end
|
17
|
+
|
18
|
+
def method_missing(m, *args, &block)
|
19
|
+
Watir::Wait.until(@timeout) { @element.present? }
|
20
|
+
@element.send(m, *args, &block)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns element id
|
24
|
+
def id
|
25
|
+
Watir::Wait.until(@timeout) { @element.present? }
|
26
|
+
@element.id
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
#
|
32
|
+
# Returns true if the element exists and is visible on the page
|
33
|
+
#
|
34
|
+
|
35
|
+
def present?
|
36
|
+
exists? && visible? rescue false
|
37
|
+
end
|
38
|
+
|
39
|
+
#
|
40
|
+
# Waits until the element is present.
|
41
|
+
#
|
42
|
+
# Optional argument:
|
43
|
+
#
|
44
|
+
# timeout - seconds to wait before timing out (default: 60)
|
45
|
+
#
|
46
|
+
# browser.button(:id, 'foo').when_present.click
|
47
|
+
# browser.div(:id, 'bar').when_present { |div| ... }
|
48
|
+
# browser.p(:id, 'baz').when_present(60).text
|
49
|
+
#
|
50
|
+
|
51
|
+
def when_present(timeout = 60)
|
52
|
+
if block_given?
|
53
|
+
Watir::Wait.until(timeout) { self.present? }
|
54
|
+
yield self
|
55
|
+
else
|
56
|
+
return WhenPresentDecorator.new(self, timeout)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def wait_until_present(timeout = 60)
|
61
|
+
Watir::Wait.until(timeout) { self.present? }
|
62
|
+
end
|
63
|
+
|
64
|
+
def wait_while_present(timeout = 60)
|
65
|
+
Watir::Wait.while(timeout) { self.present? }
|
66
|
+
end
|
67
|
+
|
68
|
+
end # module ElementExtensions
|
69
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Watir
|
2
|
+
module Exception
|
3
|
+
|
4
|
+
# Root class for all Watir Exceptions
|
5
|
+
class WatirException < RuntimeError
|
6
|
+
def initialize(message="")
|
7
|
+
super(message)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
# This exception is raised if an attempt is made to access an object that doesn't exist
|
12
|
+
class UnknownObjectException < WatirException; end
|
13
|
+
# This exception is raised if an attempt is made to access an object that is in a disabled state
|
14
|
+
class ObjectDisabledException < WatirException; end
|
15
|
+
# This exception is raised if an attempt is made to access a frame that cannot be found
|
16
|
+
class UnknownFrameException < WatirException; end
|
17
|
+
# This exception is raised if an attempt is made to access a frame that IE is denying access to
|
18
|
+
class FrameAccessDeniedException < WatirException; end
|
19
|
+
# This exception is raised if an attempt is made to access a form that cannot be found
|
20
|
+
class UnknownFormException< WatirException; end
|
21
|
+
# This exception is raised if an attempt is made to access an object that is in a read only state
|
22
|
+
class ObjectReadOnlyException < WatirException; end
|
23
|
+
# This exception is raised if an attempt is made to access an object when the specified value cannot be found
|
24
|
+
class NoValueFoundException < WatirException; end
|
25
|
+
# This exception gets raised if part of finding an object is missing
|
26
|
+
class MissingWayOfFindingObjectException < WatirException; end
|
27
|
+
# this exception is raised if an attempt is made to access a table cell that doesnt exist
|
28
|
+
class UnknownCellException < WatirException; end
|
29
|
+
# This exception is raised if the window cannot be found
|
30
|
+
class NoMatchingWindowFoundException < WatirException; end
|
31
|
+
# This exception is raised if an attemp is made to acces the status bar of the browser when it doesnt exist
|
32
|
+
class NoStatusBarException < WatirException; end
|
33
|
+
# This exception is raised if an http error, such as a 404, 500 etc is encountered while navigating
|
34
|
+
class NavigationException < WatirException; end
|
35
|
+
# This exception is raised when an event is fired that we don't know how to handle
|
36
|
+
class UnhandledEventException < WatirException; end
|
37
|
+
# This exception is raised if a timeout is exceeded
|
38
|
+
class TimeOutException < WatirException
|
39
|
+
def initialize(duration, timeout)
|
40
|
+
@duration, @timeout = duration, timeout
|
41
|
+
end
|
42
|
+
attr_reader :duration, :timeout
|
43
|
+
end
|
44
|
+
|
45
|
+
# Return an error message for when unable to locate the element
|
46
|
+
def self.message_for_unable_to_locate(specifiers)
|
47
|
+
"Unable to locate element, using #{specifiers.inspect}"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
module Watir
|
2
|
+
|
3
|
+
class Form < Element
|
4
|
+
def initialize(container, specifiers)
|
5
|
+
super
|
6
|
+
copy_test_config container
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_ole :action
|
10
|
+
|
11
|
+
def name
|
12
|
+
assert_exists
|
13
|
+
name = ole_object.getAttributeNode('name')
|
14
|
+
name ? name.value : ''
|
15
|
+
end
|
16
|
+
|
17
|
+
def form_method
|
18
|
+
assert_exists
|
19
|
+
ole_object.invoke('method')
|
20
|
+
end
|
21
|
+
|
22
|
+
def method(arg = nil)
|
23
|
+
if arg.nil?
|
24
|
+
form_method
|
25
|
+
else
|
26
|
+
super
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def locate
|
31
|
+
@o = @container.locator_for(FormLocator, @specifiers, self.class).locate
|
32
|
+
end
|
33
|
+
|
34
|
+
# Submit the data -- equivalent to pressing Enter or Return to submit a form.
|
35
|
+
def submit
|
36
|
+
assert_exists
|
37
|
+
@o.submit(0) if dispatch_event "onSubmit"
|
38
|
+
@container.wait
|
39
|
+
end
|
40
|
+
|
41
|
+
def __ole_inner_elements
|
42
|
+
assert_exists
|
43
|
+
@o.elements
|
44
|
+
end
|
45
|
+
|
46
|
+
# This method is responsible for setting and clearing the colored highlighting on the specified form.
|
47
|
+
# use :set to set the highlight
|
48
|
+
# :clear to clear the highlight
|
49
|
+
def highlight(set_or_clear, element, count)
|
50
|
+
if set_or_clear == :set
|
51
|
+
begin
|
52
|
+
original_color = element.style.backgroundColor
|
53
|
+
original_color = "" if original_color==nil
|
54
|
+
element.style.backgroundColor = activeObjectHighLightColor
|
55
|
+
rescue => e
|
56
|
+
puts e
|
57
|
+
puts e.backtrace.join("\n")
|
58
|
+
original_color = ""
|
59
|
+
end
|
60
|
+
@original_styles[count] = original_color
|
61
|
+
else
|
62
|
+
begin
|
63
|
+
element.style.backgroundColor = @original_styles[ count]
|
64
|
+
rescue => e
|
65
|
+
puts e
|
66
|
+
# we could be here for a number of reasons...
|
67
|
+
ensure
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
private :highlight
|
72
|
+
|
73
|
+
# causes the object to flash. Normally used in IRB when creating scripts
|
74
|
+
# Default is 10
|
75
|
+
def flash number=10
|
76
|
+
assert_exists
|
77
|
+
@original_styles = {}
|
78
|
+
number.times do
|
79
|
+
count = 0
|
80
|
+
@o.elements.each do |element|
|
81
|
+
highlight(:set, element, count)
|
82
|
+
count += 1
|
83
|
+
end
|
84
|
+
sleep 0.05
|
85
|
+
count = 0
|
86
|
+
@o.elements.each do |element|
|
87
|
+
highlight(:clear, element, count)
|
88
|
+
count += 1
|
89
|
+
end
|
90
|
+
sleep 0.05
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
end # class Form
|
95
|
+
|
96
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Watir
|
2
|
+
class Frame < Element
|
3
|
+
include PageContainer
|
4
|
+
attr_accessor :document
|
5
|
+
|
6
|
+
attr_ole :name
|
7
|
+
attr_ole :src
|
8
|
+
|
9
|
+
def initialize(container, specifiers)
|
10
|
+
super
|
11
|
+
copy_test_config container
|
12
|
+
end
|
13
|
+
|
14
|
+
# Find the frame denoted by specifiers in the container and return its ole_object
|
15
|
+
def locate
|
16
|
+
frame, document = @container.locator_for(FrameLocator, @specifiers, self.class).locate
|
17
|
+
if frame && document
|
18
|
+
@o = frame
|
19
|
+
begin
|
20
|
+
@document = document.document
|
21
|
+
rescue WIN32OLERuntimeError => e
|
22
|
+
# This frame's content is not directly accessible but let the
|
23
|
+
# user continue so they can access the frame properties
|
24
|
+
raise e unless e.message =~ /Access is denied/
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def __ole_inner_elements
|
30
|
+
document.body.all
|
31
|
+
end
|
32
|
+
|
33
|
+
def document
|
34
|
+
assert_exists
|
35
|
+
if @document
|
36
|
+
@document
|
37
|
+
else
|
38
|
+
raise FrameAccessDeniedException, "IE will not allow access to this frame for security reasons. You can work around this with ie.goto(frame.src)"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def attach_command
|
43
|
+
@container.page_container.attach_command + ".frame(#{@specifiers.inspect})".gsub('"','\'')
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,767 @@
|
|
1
|
+
module Watir
|
2
|
+
class IE
|
3
|
+
include WaitHelper
|
4
|
+
include Exception
|
5
|
+
include Container
|
6
|
+
include PageContainer
|
7
|
+
|
8
|
+
# Maximum number of seconds to wait when attaching to a window
|
9
|
+
@@attach_timeout = 2.0 # default value
|
10
|
+
def self.attach_timeout
|
11
|
+
@@attach_timeout
|
12
|
+
end
|
13
|
+
def self.attach_timeout=(timeout)
|
14
|
+
@@attach_timeout = timeout
|
15
|
+
end
|
16
|
+
|
17
|
+
# Return the options used when creating new instances of IE.
|
18
|
+
# BUG: this interface invites misunderstanding/misuse such as IE.options[:speed] = :zippy]
|
19
|
+
def self.options
|
20
|
+
{:speed => self.speed, :visible => self.visible, :attach_timeout => self.attach_timeout, :zero_based_indexing => self.zero_based_indexing}
|
21
|
+
end
|
22
|
+
# set values for options used when creating new instances of IE.
|
23
|
+
def self.set_options options
|
24
|
+
options.each do |name, value|
|
25
|
+
send "#{name}=", value
|
26
|
+
end
|
27
|
+
end
|
28
|
+
# The globals $FAST_SPEED and $HIDE_IE are checked both at initialization
|
29
|
+
# and later, because they
|
30
|
+
# might be set after initialization. Setting them beforehand (e.g. from
|
31
|
+
# the command line) will affect the class, otherwise it is only a temporary
|
32
|
+
# effect
|
33
|
+
@@speed = $FAST_SPEED ? :fast : :slow
|
34
|
+
def self.speed
|
35
|
+
return :fast if $FAST_SPEED
|
36
|
+
@@speed
|
37
|
+
end
|
38
|
+
def self.speed= x
|
39
|
+
$FAST_SPEED = nil
|
40
|
+
@@speed = x
|
41
|
+
end
|
42
|
+
@@visible = $HIDE_IE ? false : true
|
43
|
+
def self.visible
|
44
|
+
return false if $HIDE_IE
|
45
|
+
@@visible
|
46
|
+
end
|
47
|
+
def self.visible= x
|
48
|
+
$HIDE_IE = nil
|
49
|
+
@@visible = x
|
50
|
+
end
|
51
|
+
|
52
|
+
@@zero_based_indexing = true
|
53
|
+
def self.zero_based_indexing= enabled
|
54
|
+
@@zero_based_indexing = enabled
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.zero_based_indexing
|
58
|
+
@@zero_based_indexing
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.base_index
|
62
|
+
self.zero_based_indexing ? 0 : 1
|
63
|
+
end
|
64
|
+
|
65
|
+
# Used internally to determine when IE has finished loading a page
|
66
|
+
READYSTATES = {:complete => 4}
|
67
|
+
|
68
|
+
# The default color for highlighting objects as they are accessed.
|
69
|
+
HIGHLIGHT_COLOR = 'yellow'
|
70
|
+
|
71
|
+
# The time, in seconds, it took for the new page to load after executing the
|
72
|
+
# the last command
|
73
|
+
attr_reader :down_load_time
|
74
|
+
|
75
|
+
# the OLE Internet Explorer object
|
76
|
+
attr_accessor :ie
|
77
|
+
# access to the logger object
|
78
|
+
attr_accessor :logger
|
79
|
+
|
80
|
+
# this contains the list of unique urls that have been visited
|
81
|
+
attr_reader :url_list
|
82
|
+
|
83
|
+
# Create a new IE window. Works just like IE.new in Watir 1.4.
|
84
|
+
def self.new_window
|
85
|
+
ie = new true
|
86
|
+
ie._new_window_init
|
87
|
+
ie
|
88
|
+
end
|
89
|
+
|
90
|
+
# Create an IE browser.
|
91
|
+
def initialize suppress_new_window=nil
|
92
|
+
_new_window_init unless suppress_new_window
|
93
|
+
end
|
94
|
+
|
95
|
+
def _new_window_init
|
96
|
+
create_browser_window
|
97
|
+
initialize_options
|
98
|
+
goto 'about:blank' # this avoids numerous problems caused by lack of a document
|
99
|
+
end
|
100
|
+
|
101
|
+
# Create a new IE Window, starting at the specified url.
|
102
|
+
# If no url is given, start empty.
|
103
|
+
def self.start url=nil
|
104
|
+
start_window url
|
105
|
+
end
|
106
|
+
|
107
|
+
# Create a new IE window, starting at the specified url.
|
108
|
+
# If no url is given, start empty. Works like IE.start in Watir 1.4.
|
109
|
+
def self.start_window url=nil
|
110
|
+
ie = new_window
|
111
|
+
ie.goto url if url
|
112
|
+
ie
|
113
|
+
end
|
114
|
+
|
115
|
+
# Create a new IE window in a new process.
|
116
|
+
# This method will not work when
|
117
|
+
# Watir/Ruby is run under a service (instead of a user).
|
118
|
+
def self.new_process
|
119
|
+
ie = new true
|
120
|
+
ie._new_process_init
|
121
|
+
ie
|
122
|
+
end
|
123
|
+
|
124
|
+
def _new_process_init
|
125
|
+
iep = Process.start
|
126
|
+
@ie = iep.window
|
127
|
+
@process_id = iep.process_id
|
128
|
+
initialize_options
|
129
|
+
goto 'about:blank'
|
130
|
+
end
|
131
|
+
|
132
|
+
# Create a new IE window in a new process, starting at the specified URL.
|
133
|
+
# Same as IE.start.
|
134
|
+
def self.start_process url=nil
|
135
|
+
ie = new_process
|
136
|
+
ie.goto url if url
|
137
|
+
ie
|
138
|
+
end
|
139
|
+
|
140
|
+
# Return a Watir::IE object for an existing IE window. Window can be
|
141
|
+
# referenced by url, title, or window handle.
|
142
|
+
# Second argument can be either a string or a regular expression in the
|
143
|
+
# case of of :url or :title.
|
144
|
+
# IE.attach(:url, 'http://www.google.com')
|
145
|
+
# IE.attach(:title, 'Google')
|
146
|
+
# IE.attach(:hwnd, 528140)
|
147
|
+
# This method will not work when
|
148
|
+
# Watir/Ruby is run under a service (instead of a user).
|
149
|
+
def self.attach how, what
|
150
|
+
ie = new true # don't create window
|
151
|
+
ie._attach_init(how, what)
|
152
|
+
ie
|
153
|
+
end
|
154
|
+
|
155
|
+
# this method is used internally to attach to an existing window
|
156
|
+
def _attach_init how, what
|
157
|
+
attach_browser_window how, what
|
158
|
+
initialize_options
|
159
|
+
wait
|
160
|
+
end
|
161
|
+
|
162
|
+
# Return an IE object that wraps the given window, typically obtained from
|
163
|
+
# Shell.Application.windows.
|
164
|
+
def self.bind window
|
165
|
+
ie = new true
|
166
|
+
ie.ie = window
|
167
|
+
ie.initialize_options
|
168
|
+
ie
|
169
|
+
end
|
170
|
+
|
171
|
+
def initialize_options
|
172
|
+
self.visible = IE.visible
|
173
|
+
self.speed = IE.speed
|
174
|
+
|
175
|
+
@ole_object = nil
|
176
|
+
@page_container = self
|
177
|
+
@error_checkers = []
|
178
|
+
@activeObjectHighLightColor = HIGHLIGHT_COLOR
|
179
|
+
|
180
|
+
|
181
|
+
@logger = DefaultLogger.new
|
182
|
+
@url_list = []
|
183
|
+
end
|
184
|
+
|
185
|
+
# Specifies the speed that commands will be executed at. Choices are:
|
186
|
+
# * :slow (default)
|
187
|
+
# * :fast
|
188
|
+
# * :zippy
|
189
|
+
# With IE#speed= :zippy, text fields will be entered at once, instead of
|
190
|
+
# character by character (default).
|
191
|
+
def speed= how_fast
|
192
|
+
case how_fast
|
193
|
+
when :zippy then
|
194
|
+
@typingspeed = 0
|
195
|
+
@pause_after_wait = 0.01
|
196
|
+
@type_keys = false
|
197
|
+
@speed = :fast
|
198
|
+
when :fast then
|
199
|
+
@typingspeed = 0
|
200
|
+
@pause_after_wait = 0.01
|
201
|
+
@type_keys = true
|
202
|
+
@speed = :fast
|
203
|
+
when :slow then
|
204
|
+
@typingspeed = 0.08
|
205
|
+
@pause_after_wait = 0.1
|
206
|
+
@type_keys = true
|
207
|
+
@speed = :slow
|
208
|
+
else
|
209
|
+
raise ArgumentError, "Invalid speed: #{how_fast}"
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
def speed
|
214
|
+
return @speed if @speed == :slow
|
215
|
+
return @type_keys ? :fast : :zippy
|
216
|
+
end
|
217
|
+
|
218
|
+
# deprecated: use speed = :fast instead
|
219
|
+
def set_fast_speed
|
220
|
+
self.speed = :fast
|
221
|
+
end
|
222
|
+
|
223
|
+
# deprecated: use speed = :slow instead
|
224
|
+
def set_slow_speed
|
225
|
+
self.speed = :slow
|
226
|
+
end
|
227
|
+
|
228
|
+
def visible
|
229
|
+
@ie.visible
|
230
|
+
end
|
231
|
+
def visible=(boolean)
|
232
|
+
@ie.visible = boolean if boolean != @ie.visible
|
233
|
+
end
|
234
|
+
|
235
|
+
# Yields successively to each IE window on the current desktop. Takes a block.
|
236
|
+
# This method will not work when
|
237
|
+
# Watir/Ruby is run under a service (instead of a user).
|
238
|
+
# Yields to the window and its hwnd.
|
239
|
+
def self.each
|
240
|
+
shell = WIN32OLE.new('Shell.Application')
|
241
|
+
ie_browsers = []
|
242
|
+
shell.Windows.each do |window|
|
243
|
+
next unless (window.path =~ /Internet Explorer/ rescue false)
|
244
|
+
next unless (hwnd = window.hwnd rescue false)
|
245
|
+
ie = IE.bind(window)
|
246
|
+
ie.hwnd = hwnd
|
247
|
+
ie_browsers << ie
|
248
|
+
end
|
249
|
+
ie_browsers.each do |ie|
|
250
|
+
yield ie
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
def self.version
|
255
|
+
@ie_version ||= begin
|
256
|
+
require 'win32/registry'
|
257
|
+
::Win32::Registry::HKEY_LOCAL_MACHINE.open("SOFTWARE\\Microsoft\\Internet Explorer") do |ie_key|
|
258
|
+
ie_key.read('Version').last
|
259
|
+
end
|
260
|
+
# OR: ::WIN32OLE.new("WScript.Shell").RegRead("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Internet Explorer\\Version")
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
def self.version_parts
|
265
|
+
version.split('.')
|
266
|
+
end
|
267
|
+
|
268
|
+
# return internet explorer instance as specified. if none is found,
|
269
|
+
# return nil.
|
270
|
+
# arguments:
|
271
|
+
# :url, url -- the URL of the IE browser window
|
272
|
+
# :title, title -- the title of the browser page
|
273
|
+
# :hwnd, hwnd -- the window handle of the browser window.
|
274
|
+
# This method will not work when
|
275
|
+
# Watir/Ruby is run under a service (instead of a user).
|
276
|
+
def self.find(how, what)
|
277
|
+
ie_ole = IE._find(how, what)
|
278
|
+
IE.bind ie_ole if ie_ole
|
279
|
+
end
|
280
|
+
|
281
|
+
def self._find(how, what)
|
282
|
+
self._find_all(how, what).first
|
283
|
+
end
|
284
|
+
|
285
|
+
def self._find_all(how, what)
|
286
|
+
ies = []
|
287
|
+
count = -1
|
288
|
+
IE.each do |ie|
|
289
|
+
window = ie.ie
|
290
|
+
|
291
|
+
case how
|
292
|
+
when :url
|
293
|
+
ies << window if (what.matches(window.locationURL))
|
294
|
+
when :title
|
295
|
+
# normal windows explorer shells do not have document
|
296
|
+
# note window.document will fail for "new" browsers
|
297
|
+
begin
|
298
|
+
title = window.locationname
|
299
|
+
title = window.document.title
|
300
|
+
rescue WIN32OLERuntimeError
|
301
|
+
end
|
302
|
+
ies << window if what.matches(title)
|
303
|
+
when :hwnd
|
304
|
+
begin
|
305
|
+
ies << window if what == window.HWND
|
306
|
+
rescue WIN32OLERuntimeError
|
307
|
+
end
|
308
|
+
when :index
|
309
|
+
count += 1
|
310
|
+
if count == what
|
311
|
+
ies << window
|
312
|
+
break
|
313
|
+
end
|
314
|
+
when nil
|
315
|
+
ies << window
|
316
|
+
else
|
317
|
+
raise ArgumentError
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
ies
|
322
|
+
end
|
323
|
+
|
324
|
+
# Return the current window handle
|
325
|
+
def hwnd
|
326
|
+
raise "Not attached to a browser" if @ie.nil?
|
327
|
+
@hwnd ||= @ie.hwnd
|
328
|
+
end
|
329
|
+
attr_writer :hwnd
|
330
|
+
|
331
|
+
# Are we attached to an open browser?
|
332
|
+
def exists?
|
333
|
+
begin
|
334
|
+
!!(@ie.name =~ /Internet Explorer/)
|
335
|
+
rescue WIN32OLERuntimeError, NoMethodError
|
336
|
+
false
|
337
|
+
end
|
338
|
+
end
|
339
|
+
alias :exist? :exists?
|
340
|
+
|
341
|
+
# deprecated: use logger= instead
|
342
|
+
def set_logger(logger)
|
343
|
+
@logger = logger
|
344
|
+
end
|
345
|
+
|
346
|
+
def log(what)
|
347
|
+
@logger.debug(what) if @logger
|
348
|
+
end
|
349
|
+
|
350
|
+
#
|
351
|
+
# Accessing data outside the document
|
352
|
+
#
|
353
|
+
|
354
|
+
# Return the title of the document
|
355
|
+
def title
|
356
|
+
@ie.document.title
|
357
|
+
end
|
358
|
+
|
359
|
+
# Return the status of the window, typically from the status bar at the bottom.
|
360
|
+
def status
|
361
|
+
@ie.statusText
|
362
|
+
rescue WIN32OLERuntimeError
|
363
|
+
""
|
364
|
+
end
|
365
|
+
|
366
|
+
#
|
367
|
+
# Navigation
|
368
|
+
#
|
369
|
+
|
370
|
+
# Navigate to the specified URL.
|
371
|
+
# * url - string - the URL to navigate to
|
372
|
+
def goto(url)
|
373
|
+
url = "http://" + url unless url =~ %r{://} || url == "about:blank"
|
374
|
+
@ie.navigate(url)
|
375
|
+
wait
|
376
|
+
return @down_load_time
|
377
|
+
end
|
378
|
+
|
379
|
+
# Go to the previous page - the same as clicking the browsers back button
|
380
|
+
# an WIN32OLERuntimeError exception is raised if the browser cant go back
|
381
|
+
def back
|
382
|
+
@ie.GoBack
|
383
|
+
wait
|
384
|
+
end
|
385
|
+
|
386
|
+
# Go to the next page - the same as clicking the browsers forward button
|
387
|
+
# an WIN32OLERuntimeError exception is raised if the browser cant go forward
|
388
|
+
def forward
|
389
|
+
@ie.GoForward
|
390
|
+
wait
|
391
|
+
end
|
392
|
+
|
393
|
+
# Refresh the current page - the same as clicking the browsers refresh button
|
394
|
+
# an WIN32OLERuntimeError exception is raised if the browser cant refresh
|
395
|
+
def refresh
|
396
|
+
@ie.refresh2(3)
|
397
|
+
wait
|
398
|
+
end
|
399
|
+
|
400
|
+
def inspect
|
401
|
+
'#<%s:0x%x url=%s title=%s>' % [self.class, hash*2, url.inspect, title.inspect]
|
402
|
+
end
|
403
|
+
|
404
|
+
# clear the list of urls that we have visited
|
405
|
+
def clear_url_list
|
406
|
+
@url_list.clear
|
407
|
+
end
|
408
|
+
|
409
|
+
# Closes the Browser
|
410
|
+
def close
|
411
|
+
return unless exists?
|
412
|
+
@ie.stop
|
413
|
+
wait rescue nil
|
414
|
+
chwnd = @ie.hwnd.to_i
|
415
|
+
@ie.quit
|
416
|
+
t = ::Time.now
|
417
|
+
while exists?
|
418
|
+
# just in case to avoid possible endless loop if failing to close some
|
419
|
+
# window or tab
|
420
|
+
break if ::Time.now - t > 10
|
421
|
+
sleep 0.3
|
422
|
+
end
|
423
|
+
end
|
424
|
+
|
425
|
+
# Maximize the window (expands to fill the screen)
|
426
|
+
def maximize
|
427
|
+
rautomation.maximize
|
428
|
+
end
|
429
|
+
|
430
|
+
# Minimize the window (appears as icon on taskbar)
|
431
|
+
def minimize
|
432
|
+
rautomation.minimize
|
433
|
+
end
|
434
|
+
|
435
|
+
def minimized?
|
436
|
+
rautomation.minimized?
|
437
|
+
end
|
438
|
+
|
439
|
+
# Restore the window (after minimizing or maximizing)
|
440
|
+
def restore
|
441
|
+
rautomation.restore
|
442
|
+
end
|
443
|
+
|
444
|
+
# Make the window come to the front
|
445
|
+
def activate
|
446
|
+
rautomation.activate
|
447
|
+
end
|
448
|
+
alias :bring_to_front :activate
|
449
|
+
|
450
|
+
def active?
|
451
|
+
rautomation.active?
|
452
|
+
end
|
453
|
+
alias :front? :active?
|
454
|
+
|
455
|
+
def rautomation
|
456
|
+
@rautomation ||= ::RAutomation::Window.new(:hwnd => hwnd)
|
457
|
+
@rautomation
|
458
|
+
end
|
459
|
+
|
460
|
+
def autoit
|
461
|
+
Kernel.warn "Usage of Watir::IE#autoit method is DEPRECATED! Use Watir::IE#rautomation method instead. Refer to https://github.com/jarmo/RAutomation for updating your scripts."
|
462
|
+
@autoit ||= ::RAutomation::Window.new(:hwnd => hwnd, :adapter => :autoit)
|
463
|
+
@autoit
|
464
|
+
end
|
465
|
+
|
466
|
+
# Activates the window and sends keys to it.
|
467
|
+
#
|
468
|
+
# Example:
|
469
|
+
# browser.send_keys("Hello World{enter}")
|
470
|
+
#
|
471
|
+
# Refer to RAutomation::Adapter::WinFfi::KeystrokeConverter.convert_special_characters for
|
472
|
+
# special characters conversion.
|
473
|
+
# @see RAutomation::Window#send_keys
|
474
|
+
def send_keys(*keys)
|
475
|
+
rautomation.send_keys *keys
|
476
|
+
end
|
477
|
+
|
478
|
+
def dir
|
479
|
+
return File.expand_path(File.dirname(__FILE__))
|
480
|
+
end
|
481
|
+
|
482
|
+
#
|
483
|
+
# Document and Document Data
|
484
|
+
#
|
485
|
+
|
486
|
+
# Return the current document
|
487
|
+
def document
|
488
|
+
return @ie.document
|
489
|
+
end
|
490
|
+
|
491
|
+
# returns the current url, as displayed in the address bar of the browser
|
492
|
+
def url
|
493
|
+
return @ie.LocationURL
|
494
|
+
end
|
495
|
+
|
496
|
+
def window(specifiers={}, &blk)
|
497
|
+
win = Window.new(self, specifiers, &blk)
|
498
|
+
win.use &blk if blk
|
499
|
+
win
|
500
|
+
end
|
501
|
+
|
502
|
+
def windows(specifiers={}, &blk)
|
503
|
+
self.class._find_all(specifiers.keys.first, specifiers.values.first).map {|ie| Window.new(self, specifiers, IE.bind(ie), &blk)}
|
504
|
+
end
|
505
|
+
|
506
|
+
def cookies
|
507
|
+
Cookies.new(self)
|
508
|
+
end
|
509
|
+
|
510
|
+
#
|
511
|
+
# Synchronization
|
512
|
+
#
|
513
|
+
|
514
|
+
# Block execution until the page has loaded.
|
515
|
+
#
|
516
|
+
# Will raise Timeout::Error if page hasn't been loaded within 5 minutes.
|
517
|
+
# =nodoc
|
518
|
+
# Note: This code needs to be prepared for the ie object to be closed at
|
519
|
+
# any moment!
|
520
|
+
def wait(no_sleep=false)
|
521
|
+
@xml_parser_doc = nil
|
522
|
+
@down_load_time = 0.0
|
523
|
+
interval = 0.05
|
524
|
+
start_load_time = ::Time.now
|
525
|
+
|
526
|
+
Timeout::timeout(5*60) do
|
527
|
+
begin
|
528
|
+
while @ie.busy
|
529
|
+
sleep interval
|
530
|
+
end
|
531
|
+
|
532
|
+
until READYSTATES.has_value?(@ie.readyState)
|
533
|
+
sleep interval
|
534
|
+
end
|
535
|
+
|
536
|
+
until @ie.document
|
537
|
+
sleep interval
|
538
|
+
end
|
539
|
+
|
540
|
+
documents_to_wait_for = [@ie.document]
|
541
|
+
rescue WIN32OLERuntimeError # IE window must have been closed
|
542
|
+
@down_load_time = ::Time.now - start_load_time
|
543
|
+
return @down_load_time
|
544
|
+
end
|
545
|
+
|
546
|
+
while doc = documents_to_wait_for.shift
|
547
|
+
begin
|
548
|
+
until READYSTATES.has_key?(doc.readyState.to_sym)
|
549
|
+
sleep interval
|
550
|
+
end
|
551
|
+
@url_list << doc.location.href unless @url_list.include?(doc.location.href)
|
552
|
+
doc.frames.length.times do |n|
|
553
|
+
begin
|
554
|
+
documents_to_wait_for << doc.frames[n.to_s].document
|
555
|
+
rescue WIN32OLERuntimeError, NoMethodError
|
556
|
+
end
|
557
|
+
end
|
558
|
+
rescue WIN32OLERuntimeError
|
559
|
+
end
|
560
|
+
end
|
561
|
+
end
|
562
|
+
|
563
|
+
@down_load_time = ::Time.now - start_load_time
|
564
|
+
run_error_checks
|
565
|
+
sleep @pause_after_wait unless no_sleep
|
566
|
+
@down_load_time
|
567
|
+
end
|
568
|
+
|
569
|
+
# Error checkers
|
570
|
+
|
571
|
+
# this method runs the predefined error checks
|
572
|
+
def run_error_checks
|
573
|
+
@error_checkers.each { |e| e.call(self) }
|
574
|
+
end
|
575
|
+
|
576
|
+
# this method is used to add an error checker that gets executed on every page load
|
577
|
+
# * checker Proc Object, that contains the code to be run
|
578
|
+
def add_checker(checker)
|
579
|
+
@error_checkers << checker
|
580
|
+
end
|
581
|
+
|
582
|
+
# this allows a checker to be disabled
|
583
|
+
# * checker Proc Object, the checker that is to be disabled
|
584
|
+
def disable_checker(checker)
|
585
|
+
@error_checkers.delete(checker)
|
586
|
+
end
|
587
|
+
|
588
|
+
#
|
589
|
+
# Show me state
|
590
|
+
#
|
591
|
+
|
592
|
+
# Show all forms displays all the forms that are on a web page.
|
593
|
+
def show_forms
|
594
|
+
if all_forms = self.forms
|
595
|
+
count = all_forms.length
|
596
|
+
puts "There are #{count} forms"
|
597
|
+
all_forms.each do |form|
|
598
|
+
puts "Form name: #{form.name}"
|
599
|
+
puts " id: #{form.id}"
|
600
|
+
puts " method: #{form.method}"
|
601
|
+
puts " action: #{form.action}"
|
602
|
+
end
|
603
|
+
else
|
604
|
+
puts "No forms"
|
605
|
+
end
|
606
|
+
end
|
607
|
+
|
608
|
+
# this method shows all the images availble in the document
|
609
|
+
def show_images
|
610
|
+
doc = document
|
611
|
+
index = 1
|
612
|
+
doc.images.each do |l|
|
613
|
+
puts "image: name: #{l.name}"
|
614
|
+
puts " id: #{l.invoke("id")}"
|
615
|
+
puts " src: #{l.src}"
|
616
|
+
puts " index: #{index}"
|
617
|
+
index += 1
|
618
|
+
end
|
619
|
+
end
|
620
|
+
|
621
|
+
# this method shows all the links availble in the document
|
622
|
+
def show_links
|
623
|
+
props = ["name", "id", "href"]
|
624
|
+
print_sizes = [12, 12, 60]
|
625
|
+
doc = document
|
626
|
+
index = 0
|
627
|
+
text_size = 60
|
628
|
+
# draw the table header
|
629
|
+
s = "index".ljust(6)
|
630
|
+
props.each_with_index do |p, i|
|
631
|
+
s += p.ljust(print_sizes[i])
|
632
|
+
end
|
633
|
+
s += "text/src".ljust(text_size)
|
634
|
+
s += "\n"
|
635
|
+
|
636
|
+
# now get the details of the links
|
637
|
+
doc.links.each do |n|
|
638
|
+
index += 1
|
639
|
+
s = s + index.to_s.ljust(6)
|
640
|
+
props.each_with_index do |prop, i|
|
641
|
+
printsize = print_sizes[i]
|
642
|
+
begin
|
643
|
+
p = n.invoke(prop)
|
644
|
+
temp_var = "#{p}".to_s.ljust(printsize)
|
645
|
+
rescue
|
646
|
+
# this object probably doesnt have this property
|
647
|
+
temp_var = "".to_s.ljust(printsize)
|
648
|
+
end
|
649
|
+
s += temp_var
|
650
|
+
end
|
651
|
+
s += n.innerText
|
652
|
+
if n.getElementsByTagName("IMG").length > 0
|
653
|
+
s += " / " + n.getElementsByTagName("IMG").item(0).src
|
654
|
+
end
|
655
|
+
s += "\n"
|
656
|
+
end
|
657
|
+
puts s
|
658
|
+
end
|
659
|
+
|
660
|
+
# this method shows the name, id etc of the object that is currently active - ie the element that has focus
|
661
|
+
# its mostly used in irb when creating a script
|
662
|
+
def show_active
|
663
|
+
s = ""
|
664
|
+
|
665
|
+
current = document.activeElement
|
666
|
+
begin
|
667
|
+
s += current.invoke("type").to_s.ljust(16)
|
668
|
+
rescue
|
669
|
+
end
|
670
|
+
props = ["name", "id", "value", "alt", "src", "innerText", "href"]
|
671
|
+
props.each do |prop|
|
672
|
+
begin
|
673
|
+
p = current.invoke(prop)
|
674
|
+
s += " " + "#{prop}=#{p}".to_s.ljust(18)
|
675
|
+
rescue
|
676
|
+
#this object probably doesnt have this property
|
677
|
+
end
|
678
|
+
end
|
679
|
+
s += "\n"
|
680
|
+
end
|
681
|
+
|
682
|
+
# this method shows all the divs availble in the document
|
683
|
+
def show_divs
|
684
|
+
divs = document.getElementsByTagName("DIV")
|
685
|
+
puts "Found #{divs.length} div tags"
|
686
|
+
index = 1
|
687
|
+
divs.each do |d|
|
688
|
+
puts "#{index} id=#{d.invoke('id')} class=#{d.invoke("className")}"
|
689
|
+
index += 1
|
690
|
+
end
|
691
|
+
end
|
692
|
+
|
693
|
+
# this method is used to show all the tables that are available
|
694
|
+
def show_tables
|
695
|
+
tables = document.getElementsByTagName("TABLE")
|
696
|
+
puts "Found #{tables.length} tables"
|
697
|
+
index = 1
|
698
|
+
tables.each do |d|
|
699
|
+
puts "#{index} id=#{d.invoke('id')} rows=#{d.rows.length} columns=#{begin d.rows["0"].cells.length; rescue; end}"
|
700
|
+
index += 1
|
701
|
+
end
|
702
|
+
end
|
703
|
+
|
704
|
+
def show_pres
|
705
|
+
pres = document.getElementsByTagName("PRE")
|
706
|
+
puts "Found #{ pres.length } pre tags"
|
707
|
+
index = 1
|
708
|
+
pres.each do |d|
|
709
|
+
puts "#{index} id=#{d.invoke('id')} class=#{d.invoke("className")}"
|
710
|
+
index+=1
|
711
|
+
end
|
712
|
+
end
|
713
|
+
|
714
|
+
# this method shows all the spans availble in the document
|
715
|
+
def show_spans
|
716
|
+
spans = document.getElementsByTagName("SPAN")
|
717
|
+
puts "Found #{spans.length} span tags"
|
718
|
+
index = 1
|
719
|
+
spans.each do |d|
|
720
|
+
puts "#{index} id=#{d.invoke('id')} class=#{d.invoke("className")}"
|
721
|
+
index += 1
|
722
|
+
end
|
723
|
+
end
|
724
|
+
|
725
|
+
def show_labels
|
726
|
+
labels = document.getElementsByTagName("LABEL")
|
727
|
+
puts "Found #{labels.length} label tags"
|
728
|
+
index = 1
|
729
|
+
labels.each do |d|
|
730
|
+
puts "#{index} text=#{d.invoke('innerText')} class=#{d.invoke("className")} for=#{d.invoke("htmlFor")}"
|
731
|
+
index += 1
|
732
|
+
end
|
733
|
+
end
|
734
|
+
|
735
|
+
# Gives focus to the frame
|
736
|
+
def focus
|
737
|
+
active_element = document.activeElement
|
738
|
+
active_element.blur unless active_element.tagName == "BODY"
|
739
|
+
document.focus
|
740
|
+
end
|
741
|
+
|
742
|
+
def attach_command
|
743
|
+
"Watir::IE.attach(:hwnd, #{hwnd})"
|
744
|
+
end
|
745
|
+
|
746
|
+
private
|
747
|
+
|
748
|
+
def create_browser_window
|
749
|
+
@ie = WIN32OLE.new('InternetExplorer.Application')
|
750
|
+
end
|
751
|
+
|
752
|
+
def attach_browser_window how, what
|
753
|
+
log "Seeking Window with #{how}: #{what}"
|
754
|
+
ieTemp = nil
|
755
|
+
begin
|
756
|
+
Watir::until_with_timeout do
|
757
|
+
ieTemp = IE._find how, what
|
758
|
+
end
|
759
|
+
rescue Watir::Wait::TimeoutError
|
760
|
+
raise NoMatchingWindowFoundException,
|
761
|
+
"Unable to locate a window with #{how} of #{what}"
|
762
|
+
end
|
763
|
+
@ie = ieTemp
|
764
|
+
end
|
765
|
+
|
766
|
+
end # class IE
|
767
|
+
end
|