watir-classic 3.7.0 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/CHANGES +6 -0
- data/Rakefile +2 -0
- data/VERSION +1 -1
- data/lib/watir-classic.rb +36 -3
- data/lib/watir-classic/browser.rb +613 -115
- data/lib/watir-classic/{ie-process.rb → browser_process.rb} +4 -4
- data/lib/watir-classic/cookies.rb +1 -1
- data/lib/watir-classic/element.rb +2 -2
- data/lib/watir-classic/frame.rb +1 -1
- data/lib/watir-classic/ie_deprecated.rb +5 -0
- data/lib/watir-classic/modal_dialog.rb +1 -1
- data/lib/watir-classic/process.rb +1 -1
- data/lib/watir-classic/screenshot.rb +1 -1
- data/lib/watir-classic/window.rb +3 -3
- data/lib/watir-classic/xpath_locator.rb +2 -2
- data/spec/implementation.rb +1 -1
- data/watir-classic.gemspec +1 -1
- metadata +19 -24
- data/Gemfile.lock +0 -79
- data/lib/watir-classic/browsers.rb +0 -7
- data/lib/watir-classic/core.rb +0 -40
- data/lib/watir-classic/ie-class.rb +0 -664
- data/lib/watir-classic/ie.rb +0 -5
- data/lib/watir-classic/options.rb +0 -51
@@ -1,13 +1,13 @@
|
|
1
1
|
require 'win32/process'
|
2
2
|
|
3
3
|
module Watir
|
4
|
-
class
|
4
|
+
class Browser
|
5
5
|
class Process
|
6
6
|
def self.start
|
7
7
|
program_files = ENV['ProgramFiles'] || "c:\\Program Files"
|
8
8
|
startup_command = "#{program_files}\\Internet Explorer\\iexplore.exe"
|
9
|
-
startup_command << " -nomerge" if
|
10
|
-
startup_command << " -noframemerging" if
|
9
|
+
startup_command << " -nomerge" if Browser.version_parts.first.to_i == 8
|
10
|
+
startup_command << " -noframemerging" if Browser.version_parts.first.to_i >= 9
|
11
11
|
process_info = ::Process.create('app_name' => "#{startup_command} about:blank")
|
12
12
|
process_id = process_info.process_id
|
13
13
|
new process_id
|
@@ -22,7 +22,7 @@ module Watir
|
|
22
22
|
def window
|
23
23
|
Wait.until do
|
24
24
|
found_window = nil
|
25
|
-
|
25
|
+
Browser.each do | ie |
|
26
26
|
window = ie.ie
|
27
27
|
hwnd = ie.hwnd
|
28
28
|
process_id = Process.process_id_from_hwnd hwnd
|
@@ -361,7 +361,7 @@ module Watir
|
|
361
361
|
|
362
362
|
# @private
|
363
363
|
def dispatch_event(event)
|
364
|
-
if
|
364
|
+
if Browser.version_parts.first.to_i >= 9 && container.page_container.document.documentMode.to_i >= 9
|
365
365
|
ole_object.dispatchEvent(create_event(event))
|
366
366
|
else
|
367
367
|
ole_object.fireEvent(event)
|
@@ -454,7 +454,7 @@ module Watir
|
|
454
454
|
element = "#{self.class}.new(#{@page_container.attach_command}, :tag_name => Array.new << '#{tag_name}', :unique_number => #{unique_number})"
|
455
455
|
method = build_method(method_name, *args)
|
456
456
|
ruby_code = "$:.unshift(#{$LOAD_PATH.map {|p| "'#{p}'" }.join(").unshift(")});" <<
|
457
|
-
"require '#{File.expand_path(File.dirname(__FILE__))}
|
457
|
+
"require '#{File.expand_path(File.dirname(__FILE__))}/../watir-classic';#{element}.#{method};"
|
458
458
|
ruby_code
|
459
459
|
end
|
460
460
|
|
data/lib/watir-classic/frame.rb
CHANGED
@@ -22,7 +22,7 @@ module Watir
|
|
22
22
|
if @document
|
23
23
|
@document
|
24
24
|
else
|
25
|
-
raise FrameAccessDeniedException, "IE will not allow access to this frame for security reasons. You can work around this with
|
25
|
+
raise FrameAccessDeniedException, "IE will not allow access to this frame for security reasons. You can work around this with browser.goto(frame.src)"
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
data/lib/watir-classic/window.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module Watir
|
2
|
-
# Returned by {
|
2
|
+
# Returned by {Browser#window}.
|
3
3
|
class Window
|
4
4
|
include ElementExtensions
|
5
5
|
|
@@ -43,7 +43,7 @@ module Watir
|
|
43
43
|
# @return [Browser] browser of the window.
|
44
44
|
def browser
|
45
45
|
@browser ||= begin
|
46
|
-
|
46
|
+
Browser.find(@locators.keys.first, @locators.values.first)
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
@@ -68,7 +68,7 @@ module Watir
|
|
68
68
|
ensure
|
69
69
|
@main_browser.ie = self.class.__main_ie
|
70
70
|
# try to find some existing IE when needed
|
71
|
-
@main_browser.ie =
|
71
|
+
@main_browser.ie = Browser._find(:index, 0) unless @main_browser.exists?
|
72
72
|
end
|
73
73
|
end
|
74
74
|
self
|
@@ -29,7 +29,7 @@ module Watir
|
|
29
29
|
# execute xpath selector and return an array of elements
|
30
30
|
def elements_by_xpath(xpath)
|
31
31
|
doc = xmlparser_document_object
|
32
|
-
current_tag = @container.is_a?(
|
32
|
+
current_tag = @container.is_a?(Browser) ? "body" : @container.tag_name
|
33
33
|
|
34
34
|
doc.xpath(xpath).reduce([]) do |elements, element|
|
35
35
|
absolute_xpath_parts = element.path.split("/")
|
@@ -45,7 +45,7 @@ module Watir
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def direct_children container, elements
|
48
|
-
return elements if container.is_a?(
|
48
|
+
return elements if container.is_a?(Browser)
|
49
49
|
elements.select {|el| el.parent == container}
|
50
50
|
end
|
51
51
|
|
data/spec/implementation.rb
CHANGED
@@ -5,7 +5,7 @@ WatirSpec.implementation do |imp|
|
|
5
5
|
imp.name = :watir_classic
|
6
6
|
|
7
7
|
WatirSpec.persistent_browser = true
|
8
|
-
imp.browser_class = Watir::
|
8
|
+
imp.browser_class = Watir::Browser
|
9
9
|
browser = :internet_explorer
|
10
10
|
browser_version = "#{browser}#{imp.browser_class.version.to_i}".to_sym
|
11
11
|
|
data/watir-classic.gemspec
CHANGED
@@ -28,7 +28,6 @@ Gem::Specification.new do |s|
|
|
28
28
|
s.add_dependency 'nokogiri', ">= 1.5.7.rc3"
|
29
29
|
s.add_dependency 'ffi', '~>1.0'
|
30
30
|
s.add_dependency 'rautomation', '~>0.7'
|
31
|
-
s.add_dependency 'user-choices'
|
32
31
|
s.add_dependency 'multi_json'
|
33
32
|
s.add_dependency 'win32screenshot'
|
34
33
|
|
@@ -37,4 +36,5 @@ Gem::Specification.new do |s|
|
|
37
36
|
s.add_development_dependency("yard")
|
38
37
|
s.add_development_dependency("sinatra")
|
39
38
|
s.add_development_dependency("childprocess")
|
39
|
+
s.add_development_dependency('rake')
|
40
40
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: watir-classic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 4.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bret Pettichord
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-05
|
11
|
+
date: 2013-10-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: win32-process
|
@@ -80,20 +80,6 @@ dependencies:
|
|
80
80
|
- - ~>
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0.7'
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
name: user-choices
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - '>='
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: '0'
|
90
|
-
type: :runtime
|
91
|
-
prerelease: false
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - '>='
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: '0'
|
97
83
|
- !ruby/object:Gem::Dependency
|
98
84
|
name: multi_json
|
99
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -192,6 +178,20 @@ dependencies:
|
|
192
178
|
- - '>='
|
193
179
|
- !ruby/object:Gem::Version
|
194
180
|
version: '0'
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: rake
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - '>='
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '0'
|
188
|
+
type: :development
|
189
|
+
prerelease: false
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - '>='
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0'
|
195
195
|
description: |2
|
196
196
|
WATIR is "Web Application Testing in Ruby". Watir (pronounced water) is a free,
|
197
197
|
open-source functional testing tool for automating browser-based tests of web applications.
|
@@ -214,7 +214,6 @@ files:
|
|
214
214
|
- CHANGES
|
215
215
|
- CONTRIBUTORS.txt
|
216
216
|
- Gemfile
|
217
|
-
- Gemfile.lock
|
218
217
|
- LICENSE
|
219
218
|
- README.rdoc
|
220
219
|
- Rakefile
|
@@ -228,10 +227,9 @@ files:
|
|
228
227
|
- lib/watir-classic/IEDialog/stdafx.cpp
|
229
228
|
- lib/watir-classic/IEDialog/stdafx.h
|
230
229
|
- lib/watir-classic/browser.rb
|
231
|
-
- lib/watir-classic/
|
230
|
+
- lib/watir-classic/browser_process.rb
|
232
231
|
- lib/watir-classic/container.rb
|
233
232
|
- lib/watir-classic/cookies.rb
|
234
|
-
- lib/watir-classic/core.rb
|
235
233
|
- lib/watir-classic/dialogs/alert.rb
|
236
234
|
- lib/watir-classic/dialogs/file_field.rb
|
237
235
|
- lib/watir-classic/drag_and_drop_helper.rb
|
@@ -242,9 +240,7 @@ files:
|
|
242
240
|
- lib/watir-classic/ext/json2.js
|
243
241
|
- lib/watir-classic/form.rb
|
244
242
|
- lib/watir-classic/frame.rb
|
245
|
-
- lib/watir-classic/
|
246
|
-
- lib/watir-classic/ie-process.rb
|
247
|
-
- lib/watir-classic/ie.rb
|
243
|
+
- lib/watir-classic/ie_deprecated.rb
|
248
244
|
- lib/watir-classic/image.rb
|
249
245
|
- lib/watir-classic/input_elements.rb
|
250
246
|
- lib/watir-classic/link.rb
|
@@ -253,7 +249,6 @@ files:
|
|
253
249
|
- lib/watir-classic/modal_dialog.rb
|
254
250
|
- lib/watir-classic/module.rb
|
255
251
|
- lib/watir-classic/non_control_elements.rb
|
256
|
-
- lib/watir-classic/options.rb
|
257
252
|
- lib/watir-classic/page-container.rb
|
258
253
|
- lib/watir-classic/process.rb
|
259
254
|
- lib/watir-classic/screenshot.rb
|
@@ -304,7 +299,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
304
299
|
requirements:
|
305
300
|
- Microsoft Windows running Internet Explorer 5.5 or later.
|
306
301
|
rubyforge_project:
|
307
|
-
rubygems_version: 2.0.
|
302
|
+
rubygems_version: 2.0.7
|
308
303
|
signing_key:
|
309
304
|
specification_version: 4
|
310
305
|
summary: Automated testing tool for web applications.
|
data/Gemfile.lock
DELETED
@@ -1,79 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
watir-classic (3.7.0)
|
5
|
-
ffi (~> 1.0)
|
6
|
-
multi_json
|
7
|
-
nokogiri (>= 1.5.7.rc3)
|
8
|
-
rautomation (~> 0.7)
|
9
|
-
user-choices
|
10
|
-
win32-process (>= 0.5.5)
|
11
|
-
win32screenshot
|
12
|
-
windows-pr (>= 0.6.6)
|
13
|
-
|
14
|
-
GEM
|
15
|
-
remote: https://rubygems.org/
|
16
|
-
specs:
|
17
|
-
builder (3.2.0)
|
18
|
-
childprocess (0.3.9)
|
19
|
-
ffi (~> 1.0, >= 1.0.11)
|
20
|
-
diff-lcs (1.2.1)
|
21
|
-
ffi (1.8.1-x86-mingw32)
|
22
|
-
hoe (3.5.1)
|
23
|
-
rake (>= 0.8, < 11.0)
|
24
|
-
mini_magick (3.5.0)
|
25
|
-
subexec (~> 0.2.1)
|
26
|
-
multi_json (1.7.2)
|
27
|
-
nokogiri (1.5.7.rc3-x86-mingw32)
|
28
|
-
rack (1.5.2)
|
29
|
-
rack-protection (1.4.0)
|
30
|
-
rack
|
31
|
-
rake (10.0.4)
|
32
|
-
rautomation (0.8.0)
|
33
|
-
ffi
|
34
|
-
rspec (2.13.0)
|
35
|
-
rspec-core (~> 2.13.0)
|
36
|
-
rspec-expectations (~> 2.13.0)
|
37
|
-
rspec-mocks (~> 2.13.0)
|
38
|
-
rspec-core (2.13.0)
|
39
|
-
rspec-expectations (2.13.0)
|
40
|
-
diff-lcs (>= 1.1.3, < 2.0)
|
41
|
-
rspec-mocks (2.13.0)
|
42
|
-
s4t-utils (1.0.4)
|
43
|
-
hoe (>= 1.3.0)
|
44
|
-
sinatra (1.3.5)
|
45
|
-
rack (~> 1.4)
|
46
|
-
rack-protection (~> 1.3)
|
47
|
-
tilt (~> 1.3, >= 1.3.3)
|
48
|
-
subexec (0.2.2)
|
49
|
-
syntax (1.0.0)
|
50
|
-
tilt (1.3.4)
|
51
|
-
user-choices (1.1.6.1)
|
52
|
-
builder (>= 2.1.2)
|
53
|
-
s4t-utils (>= 1.0.3)
|
54
|
-
xml-simple (>= 1.0.11)
|
55
|
-
win32-api (1.4.8-x86-mingw32)
|
56
|
-
win32-process (0.7.1)
|
57
|
-
ffi (>= 1.0.0)
|
58
|
-
win32screenshot (1.0.8)
|
59
|
-
ffi (~> 1.0)
|
60
|
-
mini_magick (~> 3.2)
|
61
|
-
rautomation (~> 0.7)
|
62
|
-
windows-api (0.4.2)
|
63
|
-
win32-api (>= 1.4.5)
|
64
|
-
windows-pr (1.2.2)
|
65
|
-
win32-api (>= 1.4.5)
|
66
|
-
windows-api (>= 0.3.0)
|
67
|
-
xml-simple (1.1.2)
|
68
|
-
yard (0.8.5.2)
|
69
|
-
|
70
|
-
PLATFORMS
|
71
|
-
x86-mingw32
|
72
|
-
|
73
|
-
DEPENDENCIES
|
74
|
-
childprocess
|
75
|
-
rspec (~> 2.3)
|
76
|
-
sinatra
|
77
|
-
syntax
|
78
|
-
watir-classic!
|
79
|
-
yard
|
data/lib/watir-classic/core.rb
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
# these require statements are needed for Watir
|
2
|
-
# to work with minimum functionality
|
3
|
-
require 'timeout'
|
4
|
-
require 'watir-classic/win32ole'
|
5
|
-
|
6
|
-
require 'watir-classic/util'
|
7
|
-
require 'watir-classic/exceptions'
|
8
|
-
require 'watir-classic/matches'
|
9
|
-
require 'watir-classic/wait'
|
10
|
-
require 'watir-classic/wait_helper'
|
11
|
-
require 'watir-classic/element_extensions'
|
12
|
-
|
13
|
-
require 'watir-classic/container'
|
14
|
-
require 'watir-classic/xpath_locator'
|
15
|
-
require 'watir-classic/locator'
|
16
|
-
require 'watir-classic/page-container'
|
17
|
-
require 'watir-classic/ie-class'
|
18
|
-
require 'watir-classic/drag_and_drop_helper'
|
19
|
-
require 'watir-classic/element'
|
20
|
-
require 'watir-classic/element_collection'
|
21
|
-
require 'watir-classic/form'
|
22
|
-
require 'watir-classic/frame'
|
23
|
-
require 'watir-classic/input_elements'
|
24
|
-
require 'watir-classic/non_control_elements'
|
25
|
-
require 'watir-classic/table'
|
26
|
-
require 'watir-classic/image'
|
27
|
-
require 'watir-classic/link'
|
28
|
-
require 'watir-classic/window'
|
29
|
-
require 'watir-classic/cookies'
|
30
|
-
|
31
|
-
require 'watir-classic/win32'
|
32
|
-
require 'watir-classic/modal_dialog'
|
33
|
-
|
34
|
-
require 'watir-classic/module'
|
35
|
-
|
36
|
-
require 'rautomation'
|
37
|
-
require 'watir-classic/dialogs/file_field'
|
38
|
-
require 'watir-classic/dialogs/alert'
|
39
|
-
|
40
|
-
require 'watir-classic/supported_elements'
|
@@ -1,664 +0,0 @@
|
|
1
|
-
module Watir
|
2
|
-
# Main browser class.
|
3
|
-
class IE
|
4
|
-
include WaitHelper
|
5
|
-
include Exception
|
6
|
-
include Container
|
7
|
-
include PageContainer
|
8
|
-
|
9
|
-
class << self
|
10
|
-
# Maximum number of seconds to wait when attaching to a window
|
11
|
-
attr_writer :attach_timeout
|
12
|
-
|
13
|
-
def attach_timeout
|
14
|
-
@attach_timeout ||= 2
|
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 options
|
20
|
-
{:speed => self.speed, :visible => self.visible, :attach_timeout => self.attach_timeout}
|
21
|
-
end
|
22
|
-
|
23
|
-
# set values for options used when creating new instances of IE.
|
24
|
-
def set_options options
|
25
|
-
options.each do |name, value|
|
26
|
-
send "#{name}=", value
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
# The speed in which browser will type keys etc. Possible values are
|
31
|
-
# :slow (default), :fast and :zippy.
|
32
|
-
attr_writer :speed
|
33
|
-
|
34
|
-
def speed
|
35
|
-
@speed ||= :slow
|
36
|
-
end
|
37
|
-
|
38
|
-
# Set browser window to visible or hidden. Defaults to true.
|
39
|
-
attr_writer :visible
|
40
|
-
|
41
|
-
def visible
|
42
|
-
@visible ||= true
|
43
|
-
end
|
44
|
-
|
45
|
-
# Create a new IE window.
|
46
|
-
def new_window
|
47
|
-
ie = new true
|
48
|
-
ie._new_window_init
|
49
|
-
ie
|
50
|
-
end
|
51
|
-
|
52
|
-
# Create a new IE, starting at the specified url.
|
53
|
-
# @param [String] url url to navigate to.
|
54
|
-
def start(url=nil)
|
55
|
-
start_window url
|
56
|
-
end
|
57
|
-
|
58
|
-
# Create a new IE window, starting at the specified url.
|
59
|
-
# @param [String] url url to navigate to.
|
60
|
-
def start_window(url=nil)
|
61
|
-
ie = new_window
|
62
|
-
ie.goto url if url
|
63
|
-
ie
|
64
|
-
end
|
65
|
-
|
66
|
-
# Create a new IE window in a new process.
|
67
|
-
# @note This method will not work when
|
68
|
-
# Watir/Ruby is run under a service (instead of a user).
|
69
|
-
def new_process
|
70
|
-
ie = new true
|
71
|
-
ie._new_process_init
|
72
|
-
ie
|
73
|
-
end
|
74
|
-
|
75
|
-
# Create a new IE window in a new process, starting at the specified URL.
|
76
|
-
# @param [String] url url to navigate to.
|
77
|
-
def start_process(url=nil)
|
78
|
-
ie = new_process
|
79
|
-
ie.goto url if url
|
80
|
-
ie
|
81
|
-
end
|
82
|
-
|
83
|
-
# Attach to an existing IE {Browser}.
|
84
|
-
#
|
85
|
-
# @example Attach with full title:
|
86
|
-
# Watir::Browser.attach(:title, "Full title of IE")
|
87
|
-
#
|
88
|
-
# @example Attach with part of the title using {Regexp}:
|
89
|
-
# Watir::Browser.attach(:title, /part of the title of IE/)
|
90
|
-
#
|
91
|
-
# @example Attach with part of the url:
|
92
|
-
# Watir::Browser.attach(:url, /google/)
|
93
|
-
#
|
94
|
-
# @example Attach with window handle:
|
95
|
-
# Watir::Browser.attach(:hwnd, 123456)
|
96
|
-
#
|
97
|
-
# @param [Symbol] how type of the locator. Can be :title, :url or :hwnd.
|
98
|
-
# @param [Symbol] what value of the locator. Can be {String}, {Regexp} or {Fixnum}
|
99
|
-
# depending of the type parameter.
|
100
|
-
#
|
101
|
-
# @note This method will not work when
|
102
|
-
# Watir/Ruby is run under a service (instead of a user).
|
103
|
-
def attach(how, what)
|
104
|
-
ie = new true # don't create window
|
105
|
-
ie._attach_init(how, what)
|
106
|
-
ie
|
107
|
-
end
|
108
|
-
|
109
|
-
# Yields successively to each IE window on the current desktop. Takes a block.
|
110
|
-
# @note This method will not work when
|
111
|
-
# Watir/Ruby is run under a service (instead of a user).
|
112
|
-
# @yieldparam [IE] ie instances of IE found.
|
113
|
-
def each
|
114
|
-
shell = WIN32OLE.new('Shell.Application')
|
115
|
-
ie_browsers = []
|
116
|
-
shell.Windows.each do |window|
|
117
|
-
next unless (window.path =~ /Internet Explorer/ rescue false)
|
118
|
-
next unless (hwnd = window.hwnd rescue false)
|
119
|
-
ie = bind(window)
|
120
|
-
ie.hwnd = hwnd
|
121
|
-
ie_browsers << ie
|
122
|
-
end
|
123
|
-
ie_browsers.each do |ie|
|
124
|
-
yield ie
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
# @return [String] the IE browser version number as a string.
|
129
|
-
def version
|
130
|
-
@ie_version ||= begin
|
131
|
-
require 'win32/registry'
|
132
|
-
::Win32::Registry::HKEY_LOCAL_MACHINE.open("SOFTWARE\\Microsoft\\Internet Explorer") do |ie_key|
|
133
|
-
begin
|
134
|
-
ie_key['svcVersion']
|
135
|
-
rescue ::Win32::Registry::Error
|
136
|
-
ie_key['Version']
|
137
|
-
end
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
# @return [Array<String>] the IE browser version numbers split by "." in an Array.
|
143
|
-
def version_parts
|
144
|
-
version.split('.')
|
145
|
-
end
|
146
|
-
|
147
|
-
# Find existing IE window with locators.
|
148
|
-
# @see .attach
|
149
|
-
def find(how, what)
|
150
|
-
ie_ole = _find(how, what)
|
151
|
-
bind ie_ole if ie_ole
|
152
|
-
end
|
153
|
-
|
154
|
-
# Return an IE object that wraps the given window, typically obtained from
|
155
|
-
# Shell.Application.windows.
|
156
|
-
# @private
|
157
|
-
def bind(window)
|
158
|
-
ie = new true
|
159
|
-
ie.ie = window
|
160
|
-
ie.initialize_options
|
161
|
-
ie
|
162
|
-
end
|
163
|
-
|
164
|
-
# @private
|
165
|
-
def _find(how, what)
|
166
|
-
_find_all(how, what).first
|
167
|
-
end
|
168
|
-
|
169
|
-
# @private
|
170
|
-
def _find_all(how, what)
|
171
|
-
ies = []
|
172
|
-
count = -1
|
173
|
-
each do |ie|
|
174
|
-
window = ie.ie
|
175
|
-
|
176
|
-
case how
|
177
|
-
when :url
|
178
|
-
ies << window if (what.matches(window.locationURL))
|
179
|
-
when :title
|
180
|
-
# normal windows explorer shells do not have document
|
181
|
-
# note window.document will fail for "new" browsers
|
182
|
-
begin
|
183
|
-
title = window.locationname
|
184
|
-
title = window.document.title
|
185
|
-
rescue WIN32OLERuntimeError
|
186
|
-
end
|
187
|
-
ies << window if what.matches(title)
|
188
|
-
when :hwnd
|
189
|
-
begin
|
190
|
-
ies << window if what == window.HWND
|
191
|
-
rescue WIN32OLERuntimeError
|
192
|
-
end
|
193
|
-
when :index
|
194
|
-
count += 1
|
195
|
-
if count == what
|
196
|
-
ies << window
|
197
|
-
break
|
198
|
-
end
|
199
|
-
when nil
|
200
|
-
ies << window
|
201
|
-
else
|
202
|
-
raise ArgumentError
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
|
-
ies
|
207
|
-
end
|
208
|
-
|
209
|
-
end
|
210
|
-
|
211
|
-
# Used internally to determine when IE has finished loading a page.
|
212
|
-
# @private
|
213
|
-
READYSTATES = {:complete => 4}
|
214
|
-
|
215
|
-
# The default color for highlighting objects as they are accessed.
|
216
|
-
# @private
|
217
|
-
HIGHLIGHT_COLOR = 'yellow'
|
218
|
-
|
219
|
-
# The time, in seconds, it took for the new page to load after executing
|
220
|
-
# the last command.
|
221
|
-
attr_reader :down_load_time
|
222
|
-
|
223
|
-
# The OLE Internet Explorer object.
|
224
|
-
attr_accessor :ie
|
225
|
-
|
226
|
-
# The list of unique urls that have been visited.
|
227
|
-
attr_reader :url_list
|
228
|
-
|
229
|
-
# @private
|
230
|
-
attr_writer :hwnd
|
231
|
-
|
232
|
-
# Create an IE browser instance.
|
233
|
-
# @param [Boolean] suppress_new_window set to true for not creating a IE
|
234
|
-
# window.
|
235
|
-
def initialize(suppress_new_window=nil)
|
236
|
-
_new_window_init unless suppress_new_window
|
237
|
-
end
|
238
|
-
|
239
|
-
# Specifies the speed that commands will be executed at.
|
240
|
-
# Possible choices are:
|
241
|
-
# * :slow (default)
|
242
|
-
# * :fast
|
243
|
-
# * :zippy
|
244
|
-
#
|
245
|
-
# With :zippy, text fields will be entered at once, instead of
|
246
|
-
# character by character.
|
247
|
-
#
|
248
|
-
# @note :zippy speed does not trigger JavaScript events like onChange etc.
|
249
|
-
#
|
250
|
-
# @param [Symbol] how_fast possible choices are :slow (default), :fast and
|
251
|
-
# :zippy
|
252
|
-
# @raise [ArgumentError] when invalid speed is specified.
|
253
|
-
def speed=(how_fast)
|
254
|
-
case how_fast
|
255
|
-
when :zippy
|
256
|
-
@typingspeed = 0
|
257
|
-
@pause_after_wait = 0.01
|
258
|
-
@type_keys = false
|
259
|
-
@speed = :fast
|
260
|
-
when :fast
|
261
|
-
@typingspeed = 0
|
262
|
-
@pause_after_wait = 0.01
|
263
|
-
@type_keys = true
|
264
|
-
@speed = :fast
|
265
|
-
when :slow
|
266
|
-
@typingspeed = 0.08
|
267
|
-
@pause_after_wait = 0.1
|
268
|
-
@type_keys = true
|
269
|
-
@speed = :slow
|
270
|
-
else
|
271
|
-
raise ArgumentError, "Invalid speed: #{how_fast}. Possible choices are :slow, :fast and :zippy."
|
272
|
-
end
|
273
|
-
end
|
274
|
-
|
275
|
-
# @return [Symbol] current speed setting. May be :slow, :fast or :zippy.
|
276
|
-
def speed
|
277
|
-
return @speed if @speed == :slow
|
278
|
-
return @type_keys ? :fast : :zippy
|
279
|
-
end
|
280
|
-
|
281
|
-
# @deprecated Use {#speed=} with :fast argument instead.
|
282
|
-
def set_fast_speed
|
283
|
-
Kernel.warn "Deprecated(IE.set_fast_speed) - use Browser#speed = :fast instead."
|
284
|
-
self.speed = :fast
|
285
|
-
end
|
286
|
-
|
287
|
-
# @deprecated Use {#speed=} with :slow argument instead.
|
288
|
-
def set_slow_speed
|
289
|
-
Kernel.warn "Deprecated(IE.set_slow_speed) - use Browser#speed = :slow instead."
|
290
|
-
self.speed = :slow
|
291
|
-
end
|
292
|
-
|
293
|
-
# @return [Boolean] true when window is visible, false otherwise.
|
294
|
-
def visible
|
295
|
-
@ie.visible
|
296
|
-
end
|
297
|
-
|
298
|
-
# Set the visibility of IE window.
|
299
|
-
# @param [Boolean] boolean set to true if IE window should be visible, false
|
300
|
-
# otherwise.
|
301
|
-
def visible=(boolean)
|
302
|
-
@ie.visible = boolean if boolean != @ie.visible
|
303
|
-
end
|
304
|
-
|
305
|
-
# @return [Fixnum] current IE window handle.
|
306
|
-
# @raise [RuntimeError] when not attached to a browser.
|
307
|
-
def hwnd
|
308
|
-
raise "Not attached to a browser" if @ie.nil?
|
309
|
-
@hwnd ||= @ie.hwnd
|
310
|
-
end
|
311
|
-
|
312
|
-
# @return [Symbol] the name of the browser. Is always :internet_explorer.
|
313
|
-
def name
|
314
|
-
:internet_explorer
|
315
|
-
end
|
316
|
-
|
317
|
-
# @return [Boolean] true when IE is window exists, false otherwise.
|
318
|
-
def exists?
|
319
|
-
!!(@ie.name =~ /Internet Explorer/)
|
320
|
-
rescue WIN32OLERuntimeError, NoMethodError
|
321
|
-
false
|
322
|
-
end
|
323
|
-
|
324
|
-
alias :exist? :exists?
|
325
|
-
|
326
|
-
# @return [String] the title of the document.
|
327
|
-
def title
|
328
|
-
@ie.document.title
|
329
|
-
end
|
330
|
-
|
331
|
-
# @return [String] the status text of the window, typically from the status bar at the bottom.
|
332
|
-
# Will be empty if there's no status or when there are problems accessing status text.
|
333
|
-
def status
|
334
|
-
@ie.statusText
|
335
|
-
rescue WIN32OLERuntimeError
|
336
|
-
""
|
337
|
-
end
|
338
|
-
|
339
|
-
#
|
340
|
-
# Navigation
|
341
|
-
#
|
342
|
-
|
343
|
-
# Navigate to the specified URL.
|
344
|
-
# @param [String] url url to navigate to.
|
345
|
-
# @return [Fixnum] time in seconds the page took to load.
|
346
|
-
def goto(url)
|
347
|
-
url = "http://" + url unless url =~ %r{://} || url == "about:blank"
|
348
|
-
@ie.navigate(url)
|
349
|
-
wait
|
350
|
-
return @down_load_time
|
351
|
-
end
|
352
|
-
|
353
|
-
# Go to the previous page - the same as clicking the browsers back button.
|
354
|
-
# @raise [WIN32OLERuntimeError] when the browser can't go back.
|
355
|
-
def back
|
356
|
-
@ie.GoBack
|
357
|
-
wait
|
358
|
-
end
|
359
|
-
|
360
|
-
# Go to the next page - the same as clicking the browsers forward button.
|
361
|
-
# @raise [WIN32OLERuntimeError] when the browser can't go forward.
|
362
|
-
def forward
|
363
|
-
@ie.GoForward
|
364
|
-
wait
|
365
|
-
end
|
366
|
-
|
367
|
-
# Refresh the current page - the same as clicking the browsers refresh button.
|
368
|
-
# @raise [WIN32OLERuntimeError] when the browser can't refresh.
|
369
|
-
def refresh
|
370
|
-
@ie.refresh2(3)
|
371
|
-
wait
|
372
|
-
end
|
373
|
-
|
374
|
-
def inspect
|
375
|
-
'#<%s:0x%x url=%s title=%s>' % [self.class, hash*2, url.inspect, title.inspect]
|
376
|
-
end
|
377
|
-
|
378
|
-
# Clear the list of urls that have been visited.
|
379
|
-
def clear_url_list
|
380
|
-
@url_list.clear
|
381
|
-
end
|
382
|
-
|
383
|
-
# Close the {Browser}.
|
384
|
-
def close
|
385
|
-
return unless exists?
|
386
|
-
@ie.stop
|
387
|
-
wait rescue nil
|
388
|
-
chwnd = @ie.hwnd.to_i
|
389
|
-
@ie.quit
|
390
|
-
t = ::Time.now
|
391
|
-
while exists?
|
392
|
-
# just in case to avoid possible endless loop if failing to close some
|
393
|
-
# window or tab
|
394
|
-
break if ::Time.now - t > 10
|
395
|
-
sleep 0.3
|
396
|
-
end
|
397
|
-
end
|
398
|
-
|
399
|
-
# Maximize the window (expands to fill the screen).
|
400
|
-
def maximize
|
401
|
-
rautomation.maximize
|
402
|
-
end
|
403
|
-
|
404
|
-
# Minimize the window (appears as icon on taskbar).
|
405
|
-
def minimize
|
406
|
-
rautomation.minimize
|
407
|
-
end
|
408
|
-
|
409
|
-
# @return [Boolean] true when window is minimized, false otherwise.
|
410
|
-
def minimized?
|
411
|
-
rautomation.minimized?
|
412
|
-
end
|
413
|
-
|
414
|
-
# Restore the window (after minimizing or maximizing).
|
415
|
-
def restore
|
416
|
-
rautomation.restore
|
417
|
-
end
|
418
|
-
|
419
|
-
# Make the window come to the front.
|
420
|
-
def activate
|
421
|
-
rautomation.activate
|
422
|
-
end
|
423
|
-
|
424
|
-
alias :bring_to_front :activate
|
425
|
-
|
426
|
-
# @return [Boolean] true when window is in front e.g. in focus, false otherwise.
|
427
|
-
def active?
|
428
|
-
rautomation.active?
|
429
|
-
end
|
430
|
-
|
431
|
-
alias :front? :active?
|
432
|
-
|
433
|
-
# @return [RAutomation::Window] the RAutomation instance for this IE window.
|
434
|
-
# @see https://github.com/jarmo/rautomation
|
435
|
-
def rautomation
|
436
|
-
@rautomation ||= ::RAutomation::Window.new(:hwnd => hwnd)
|
437
|
-
end
|
438
|
-
|
439
|
-
# @deprecated use {#rautomation} instead.
|
440
|
-
def autoit
|
441
|
-
Kernel.warn "Deprecated(IE#autoit) - use IE#rautomation instead. Refer to https://github.com/jarmo/RAutomation for updating your scripts."
|
442
|
-
@autoit ||= ::RAutomation::Window.new(:hwnd => hwnd, :adapter => :autoit)
|
443
|
-
end
|
444
|
-
|
445
|
-
# Activates the window and sends keys to it.
|
446
|
-
#
|
447
|
-
# @example
|
448
|
-
# browser.send_keys("Hello World", :enter)
|
449
|
-
#
|
450
|
-
# @see https://github.com/jarmo/RAutomation/blob/master/lib/rautomation/adapter/win_32/window.rb RAutomation::Window#send_keys documentation.
|
451
|
-
def send_keys(*keys)
|
452
|
-
rautomation.send_keys *keys
|
453
|
-
end
|
454
|
-
|
455
|
-
#
|
456
|
-
# Document and Document Data
|
457
|
-
#
|
458
|
-
|
459
|
-
# @return [WIN32OLE] current IE document.
|
460
|
-
def document
|
461
|
-
@ie.document
|
462
|
-
end
|
463
|
-
|
464
|
-
# @return [String] current url, as displayed in the address bar of the browser.
|
465
|
-
def url
|
466
|
-
@ie.LocationURL
|
467
|
-
end
|
468
|
-
|
469
|
-
# Create a {Screenshot} instance.
|
470
|
-
def screenshot
|
471
|
-
Screenshot.new(hwnd)
|
472
|
-
end
|
473
|
-
|
474
|
-
# Retrieve a {Window} instance.
|
475
|
-
#
|
476
|
-
# @example Retrieve a different window without block.
|
477
|
-
# browser.window(:title => /other window title/).use
|
478
|
-
# browser.title # => "other window title"
|
479
|
-
#
|
480
|
-
# @example Use different window with block.
|
481
|
-
# browser.window(:title => /other window title/) do
|
482
|
-
# browser.title # => "other window title"
|
483
|
-
# end
|
484
|
-
# browser.title # => "current window title"
|
485
|
-
#
|
486
|
-
# @param [Hash] specifiers options for finding window.
|
487
|
-
# @option specifiers [String,Regexp] :title Title of the window.
|
488
|
-
# @option specifiers [String,Regexp] :url Url of the window.
|
489
|
-
# @option specifiers [Fixnum] :index The index of the window.
|
490
|
-
# @yield yield optionally to the found window.
|
491
|
-
# @return [Window] found window instance.
|
492
|
-
def window(specifiers={}, &blk)
|
493
|
-
win = Window.new(self, specifiers, &blk)
|
494
|
-
win.use &blk if blk
|
495
|
-
win
|
496
|
-
end
|
497
|
-
|
498
|
-
# @see #window
|
499
|
-
# @return [Array<Window>] array of found windows.
|
500
|
-
def windows(specifiers={})
|
501
|
-
self.class._find_all(specifiers.keys.first, specifiers.values.first).map {|ie| Window.new(self, specifiers, IE.bind(ie))}
|
502
|
-
end
|
503
|
-
|
504
|
-
# Retrieve {Cookies} instance.
|
505
|
-
def cookies
|
506
|
-
Cookies.new(self)
|
507
|
-
end
|
508
|
-
|
509
|
-
# Add an error checker that gets executed after every page load, click etc.
|
510
|
-
#
|
511
|
-
# @example
|
512
|
-
# browser.add_checker lambda { |browser| raise "Error!" if browser.text.include? "Error" }
|
513
|
-
#
|
514
|
-
# @param [Proc] checker Proc object which gets yielded with {IE} instance.
|
515
|
-
def add_checker(checker)
|
516
|
-
@error_checkers << checker
|
517
|
-
end
|
518
|
-
|
519
|
-
# Disable an error checker added via {#add_checker}.
|
520
|
-
#
|
521
|
-
# @param [Proc] checker Proc object to be removed from error checkers.
|
522
|
-
def disable_checker(checker)
|
523
|
-
@error_checkers.delete(checker)
|
524
|
-
end
|
525
|
-
|
526
|
-
# Gives focus to the window frame.
|
527
|
-
def focus
|
528
|
-
active_element = document.activeElement
|
529
|
-
active_element.blur if active_element && active_element.tagName != "BODY"
|
530
|
-
document.focus
|
531
|
-
end
|
532
|
-
|
533
|
-
# @private
|
534
|
-
def attach_command
|
535
|
-
"Watir::IE.attach(:hwnd, #{hwnd})"
|
536
|
-
end
|
537
|
-
|
538
|
-
# @private
|
539
|
-
def _new_window_init
|
540
|
-
create_browser_window
|
541
|
-
initialize_options
|
542
|
-
goto 'about:blank' # this avoids numerous problems caused by lack of a document
|
543
|
-
end
|
544
|
-
|
545
|
-
# @private
|
546
|
-
def _new_process_init
|
547
|
-
iep = Process.start
|
548
|
-
@ie = iep.window
|
549
|
-
@process_id = iep.process_id
|
550
|
-
initialize_options
|
551
|
-
goto 'about:blank'
|
552
|
-
end
|
553
|
-
|
554
|
-
# this method is used internally to attach to an existing window
|
555
|
-
# @private
|
556
|
-
def _attach_init how, what
|
557
|
-
attach_browser_window how, what
|
558
|
-
initialize_options
|
559
|
-
wait
|
560
|
-
end
|
561
|
-
|
562
|
-
# @private
|
563
|
-
def initialize_options
|
564
|
-
self.visible = IE.visible
|
565
|
-
self.speed = IE.speed
|
566
|
-
|
567
|
-
@ole_object = nil
|
568
|
-
@page_container = self
|
569
|
-
@error_checkers = []
|
570
|
-
@active_object_highlight_color = HIGHLIGHT_COLOR
|
571
|
-
@url_list = []
|
572
|
-
end
|
573
|
-
|
574
|
-
#
|
575
|
-
# Synchronization
|
576
|
-
#
|
577
|
-
|
578
|
-
# Block execution until the page has loaded.
|
579
|
-
#
|
580
|
-
# Will raise Timeout::Error if page hasn't been loaded within 5 minutes.
|
581
|
-
# Note: This code needs to be prepared for the ie object to be closed at
|
582
|
-
# any moment!
|
583
|
-
#
|
584
|
-
# @private
|
585
|
-
def wait(no_sleep=false)
|
586
|
-
@xml_parser_doc = nil
|
587
|
-
@down_load_time = 0.0
|
588
|
-
interval = 0.05
|
589
|
-
start_load_time = ::Time.now
|
590
|
-
|
591
|
-
Timeout::timeout(5*60) do
|
592
|
-
begin
|
593
|
-
while @ie.busy
|
594
|
-
sleep interval
|
595
|
-
end
|
596
|
-
|
597
|
-
until READYSTATES.has_value?(@ie.readyState)
|
598
|
-
sleep interval
|
599
|
-
end
|
600
|
-
|
601
|
-
until @ie.document
|
602
|
-
sleep interval
|
603
|
-
end
|
604
|
-
|
605
|
-
documents_to_wait_for = [@ie.document]
|
606
|
-
rescue WIN32OLERuntimeError # IE window must have been closed
|
607
|
-
@down_load_time = ::Time.now - start_load_time
|
608
|
-
return @down_load_time
|
609
|
-
end
|
610
|
-
|
611
|
-
while doc = documents_to_wait_for.shift
|
612
|
-
begin
|
613
|
-
until READYSTATES.has_key?(doc.readyState.to_sym)
|
614
|
-
sleep interval
|
615
|
-
end
|
616
|
-
@url_list << doc.location.href unless @url_list.include?(doc.location.href)
|
617
|
-
doc.frames.length.times do |n|
|
618
|
-
begin
|
619
|
-
documents_to_wait_for << doc.frames[n.to_s].document
|
620
|
-
rescue WIN32OLERuntimeError, NoMethodError
|
621
|
-
end
|
622
|
-
end
|
623
|
-
rescue WIN32OLERuntimeError
|
624
|
-
end
|
625
|
-
end
|
626
|
-
end
|
627
|
-
|
628
|
-
@down_load_time = ::Time.now - start_load_time
|
629
|
-
run_error_checks
|
630
|
-
sleep @pause_after_wait unless no_sleep
|
631
|
-
@down_load_time
|
632
|
-
end
|
633
|
-
|
634
|
-
# Error checkers
|
635
|
-
|
636
|
-
# Run the predefined error checks.
|
637
|
-
#
|
638
|
-
# @private
|
639
|
-
def run_error_checks
|
640
|
-
@error_checkers.each { |e| e.call(self) }
|
641
|
-
end
|
642
|
-
|
643
|
-
private
|
644
|
-
|
645
|
-
def create_browser_window
|
646
|
-
@ie = WIN32OLE.new('InternetExplorer.Application')
|
647
|
-
end
|
648
|
-
|
649
|
-
def attach_browser_window how, what
|
650
|
-
ieTemp = nil
|
651
|
-
begin
|
652
|
-
Wait.until(IE.attach_timeout) do
|
653
|
-
ieTemp = IE._find how, what
|
654
|
-
end
|
655
|
-
rescue Wait::TimeoutError
|
656
|
-
raise NoMatchingWindowFoundException,
|
657
|
-
"Unable to locate a window with #{how} of #{what}"
|
658
|
-
end
|
659
|
-
@ie = ieTemp
|
660
|
-
end
|
661
|
-
|
662
|
-
|
663
|
-
end # class IE
|
664
|
-
end
|