Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
seleniumhq
GitHub Repository: seleniumhq/selenium
Path: blob/trunk/javascript/selenium-webdriver/ie.js
2884 views
1
// Licensed to the Software Freedom Conservancy (SFC) under one
2
// or more contributor license agreements. See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership. The SFC licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License. You may obtain a copy of the License at
8
//
9
// http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied. See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
/**
19
* @fileoverview Defines a {@linkplain Driver WebDriver} client for Microsoft's
20
* Internet Explorer. Before using the IEDriver, you must download the latest
21
* [IEDriverServer](https://www.selenium.dev/downloads/)
22
* and place it on your
23
* [PATH](http://en.wikipedia.org/wiki/PATH_%28variable%29). You must also apply
24
* the system configuration outlined on the Selenium project
25
* [wiki](https://github.com/SeleniumHQ/selenium/wiki/InternetExplorerDriver)
26
*
27
* @module selenium-webdriver/ie
28
*/
29
30
'use strict'
31
32
const http = require('./http')
33
const portprober = require('./net/portprober')
34
const remote = require('./remote')
35
const webdriver = require('./lib/webdriver')
36
const { Browser, Capabilities } = require('./lib/capabilities')
37
const error = require('./lib/error')
38
const { getBinaryPaths } = require('./common/driverFinder')
39
40
const OPTIONS_CAPABILITY_KEY = 'se:ieOptions'
41
const SCROLL_BEHAVIOUR = {
42
BOTTOM: 1,
43
TOP: 0,
44
}
45
46
/**
47
* IEDriverServer logging levels.
48
* @enum {string}
49
*/
50
const Level = {
51
FATAL: 'FATAL',
52
ERROR: 'ERROR',
53
WARN: 'WARN',
54
INFO: 'INFO',
55
DEBUG: 'DEBUG',
56
TRACE: 'TRACE',
57
}
58
59
/**
60
* Option keys:
61
* https://github.com/SeleniumHQ/selenium/wiki/DesiredCapabilities#ie-specific
62
* @enum {string}
63
*/
64
const Key = {
65
IGNORE_PROTECTED_MODE_SETTINGS: 'ignoreProtectedModeSettings',
66
IGNORE_ZOOM_SETTING: 'ignoreZoomSetting',
67
INITIAL_BROWSER_URL: 'initialBrowserUrl',
68
ENABLE_PERSISTENT_HOVER: 'enablePersistentHover',
69
ENABLE_ELEMENT_CACHE_CLEANUP: 'enableElementCacheCleanup',
70
ELEMENT_SCROLL_BEHAVIOR: 'elementScrollBehavior',
71
REQUIRE_WINDOW_FOCUS: 'requireWindowFocus',
72
BROWSER_ATTACH_TIMEOUT: 'browserAttachTimeout',
73
FORCE_CREATE_PROCESS: 'ie.forceCreateProcessApi',
74
BROWSER_COMMAND_LINE_SWITCHES: 'ie.browserCommandLineSwitches',
75
USE_PER_PROCESS_PROXY: 'ie.usePerProcessProxy',
76
ENSURE_CLEAN_SESSION: 'ie.ensureCleanSession',
77
LOG_FILE: 'logFile',
78
LOG_LEVEL: 'logLevel',
79
HOST: 'host',
80
EXTRACT_PATH: 'extractPath',
81
SILENT: 'silent',
82
FILE_UPLOAD_DIALOG_TIMEOUT: 'ie.fileUploadDialogTimeout',
83
ATTACH_TO_EDGE_CHROMIUM: 'ie.edgechromium',
84
EDGE_EXECUTABLE_PATH: 'ie.edgepath',
85
IGNORE_PROCESS_MATCH: 'ie.ignoreprocessmatch',
86
}
87
88
/**
89
* Class for managing IEDriver specific options.
90
*/
91
class Options extends Capabilities {
92
/**
93
* @param {(Capabilities|Map<string, ?>|Object)=} other Another set of
94
* capabilities to initialize this instance from.
95
*/
96
constructor(other = undefined) {
97
super(other)
98
99
/** @private {!Object} */
100
this.options_ = this.get(OPTIONS_CAPABILITY_KEY) || {}
101
102
this.set(OPTIONS_CAPABILITY_KEY, this.options_)
103
this.setBrowserName(Browser.INTERNET_EXPLORER)
104
}
105
106
/**
107
* Whether to disable the protected mode settings check when the session is
108
* created. Disabling this setting may lead to significant instability as the
109
* browser may become unresponsive/hang. Only "best effort" support is provided
110
* when using this capability.
111
*
112
* For more information, refer to the IEDriver's
113
* [required system configuration](http://goo.gl/eH0Yi3).
114
*
115
* @param {boolean} ignoreSettings Whether to ignore protected mode settings.
116
* @return {!Options} A self reference.
117
*/
118
introduceFlakinessByIgnoringProtectedModeSettings(ignoreSettings) {
119
this.options_[Key.IGNORE_PROTECTED_MODE_SETTINGS] = !!ignoreSettings
120
return this
121
}
122
123
/**
124
* Indicates whether to skip the check that the browser's zoom level is set to
125
* 100%.
126
*
127
* @param {boolean} ignore Whether to ignore the browser's zoom level settings.
128
* @return {!Options} A self reference.
129
*/
130
ignoreZoomSetting(ignore) {
131
this.options_[Key.IGNORE_ZOOM_SETTING] = !!ignore
132
return this
133
}
134
135
/**
136
* Sets the initial URL loaded when IE starts. This is intended to be used with
137
* {@link #introduceFlakinessByIgnoringProtectedModeSettings} to allow the user to initialize IE in
138
* the proper Protected Mode zone. Setting this option may cause browser
139
* instability or flaky and unresponsive code. Only "best effort" support is
140
* provided when using this option.
141
*
142
* @param {string} url The initial browser URL.
143
* @return {!Options} A self reference.
144
*/
145
initialBrowserUrl(url) {
146
this.options_[Key.INITIAL_BROWSER_URL] = url
147
return this
148
}
149
150
/**
151
* Configures whether to enable persistent mouse hovering (true by default).
152
* Persistent hovering is achieved by continuously firing mouse over events at
153
* the last location the mouse cursor has been moved to.
154
*
155
* @param {boolean} enable Whether to enable persistent hovering.
156
* @return {!Options} A self reference.
157
*/
158
enablePersistentHover(enable) {
159
this.options_[Key.ENABLE_PERSISTENT_HOVER] = !!enable
160
return this
161
}
162
163
/**
164
* Configures whether the driver should attempt to remove obsolete
165
* {@linkplain webdriver.WebElement WebElements} from its internal cache on
166
* page navigation (true by default). Disabling this option will cause the
167
* driver to run with a larger memory footprint.
168
*
169
* @param {boolean} enable Whether to enable element reference cleanup.
170
* @return {!Options} A self reference.
171
*/
172
enableElementCacheCleanup(enable) {
173
this.options_[Key.ENABLE_ELEMENT_CACHE_CLEANUP] = !!enable
174
return this
175
}
176
177
/**
178
* Configures whether to require the IE window to have input focus before
179
* performing any user interactions (i.e. mouse or keyboard events). This
180
* option is disabled by default, but delivers much more accurate interaction
181
* events when enabled.
182
*
183
* @param {boolean} require Whether to require window focus.
184
* @return {!Options} A self reference.
185
*/
186
requireWindowFocus(require) {
187
this.options_[Key.REQUIRE_WINDOW_FOCUS] = !!require
188
return this
189
}
190
191
/**
192
* Configures the timeout, in milliseconds, that the driver will attempt to
193
* located and attach to a newly opened instance of Internet Explorer. The
194
* default is zero, which indicates waiting indefinitely.
195
*
196
* @param {number} timeout How long to wait for IE.
197
* @return {!Options} A self reference.
198
*/
199
browserAttachTimeout(timeout) {
200
this.options_[Key.BROWSER_ATTACH_TIMEOUT] = Math.max(timeout, 0)
201
return this
202
}
203
204
/**
205
* Configures whether to launch Internet Explorer using the CreateProcess API.
206
* If this option is not specified, IE is launched using IELaunchURL, if
207
* available. For IE 8 and above, this option requires the TabProcGrowth
208
* registry value to be set to 0.
209
*
210
* @param {boolean} force Whether to use the CreateProcess API.
211
* @return {!Options} A self reference.
212
*/
213
forceCreateProcessApi(force) {
214
this.options_[Key.FORCE_CREATE_PROCESS] = !!force
215
return this
216
}
217
218
/**
219
* Specifies command-line switches to use when launching Internet Explorer.
220
* This is only valid when used with {@link #forceCreateProcessApi}.
221
*
222
* @param {...(string|!Array.<string>)} args The arguments to add.
223
* @return {!Options} A self reference.
224
*/
225
226
addBrowserCommandSwitches(...args) {
227
let current = this.options_[Key.BROWSER_COMMAND_LINE_SWITCHES] || []
228
if (typeof current == 'string') {
229
current = current.split(' ')
230
}
231
this.options_[Key.BROWSER_COMMAND_LINE_SWITCHES] = current.concat(args).join(' ')
232
return this
233
}
234
235
/**
236
* Specifies command-line switches to use when launching Internet Explorer.
237
* This is only valid when used with {@link #forceCreateProcessApi}.
238
*
239
* @param {...(string|!Array.<string>)} args The arguments to add.
240
* @deprecated Use {@link #addBrowserCommandSwitches} instead.
241
* @return {!Options} A self reference.
242
*/
243
244
addArguments(...args) {
245
let current = this.options_[Key.BROWSER_COMMAND_LINE_SWITCHES] || []
246
if (typeof current == 'string') {
247
current = current.split(' ')
248
}
249
this.options_[Key.BROWSER_COMMAND_LINE_SWITCHES] = current.concat(args).join(' ')
250
return this
251
}
252
253
/**
254
* Configures whether proxies should be configured on a per-process basis. If
255
* not set, setting a {@linkplain #setProxy proxy} will configure the system
256
* proxy. The default behavior is to use the system proxy.
257
*
258
* @param {boolean} enable Whether to enable per-process proxy settings.
259
* @return {!Options} A self reference.
260
*/
261
usePerProcessProxy(enable) {
262
this.options_[Key.USE_PER_PROCESS_PROXY] = !!enable
263
return this
264
}
265
266
/**
267
* Configures whether to clear the cache, cookies, history, and saved form data
268
* before starting the browser. _Using this capability will clear session data
269
* for all running instances of Internet Explorer, including those started
270
* manually._
271
*
272
* @param {boolean} cleanSession Whether to clear all session data on startup.
273
* @return {!Options} A self reference.
274
*/
275
ensureCleanSession(cleanSession) {
276
this.options_[Key.ENSURE_CLEAN_SESSION] = !!cleanSession
277
return this
278
}
279
280
/**
281
* Sets the path to the log file the driver should log to.
282
* @param {string} file The log file path.
283
* @return {!Options} A self reference.
284
*/
285
setLogFile(file) {
286
this.options_[Key.LOG_FILE] = file
287
return this
288
}
289
290
/**
291
* Sets the IEDriverServer's logging {@linkplain Level level}.
292
* @param {Level} level The logging level.
293
* @return {!Options} A self reference.
294
*/
295
setLogLevel(level) {
296
this.options_[Key.LOG_LEVEL] = level
297
return this
298
}
299
300
/**
301
* Sets the IP address of the driver's host adapter.
302
* @param {string} host The IP address to use.
303
* @return {!Options} A self reference.
304
*/
305
setHost(host) {
306
this.options_[Key.HOST] = host
307
return this
308
}
309
310
/**
311
* Sets the path of the temporary data directory to use.
312
* @param {string} path The log file path.
313
* @return {!Options} A self reference.
314
*/
315
setExtractPath(path) {
316
this.options_[Key.EXTRACT_PATH] = path
317
return this
318
}
319
320
/**
321
* Sets whether the driver should start in silent mode.
322
* @param {boolean} silent Whether to run in silent mode.
323
* @return {!Options} A self reference.
324
*/
325
silent(silent) {
326
this.options_[Key.SILENT] = silent
327
return this
328
}
329
330
/**
331
* The options File Upload Dialog Timeout in milliseconds
332
*
333
* @param {number} timeout How long to wait for IE.
334
* @return {!Options} A self reference.
335
*/
336
fileUploadDialogTimeout(timeout) {
337
this.options_[Key.FILE_UPLOAD_DIALOG_TIMEOUT] = Math.max(timeout, 0)
338
return this
339
}
340
341
/**
342
* Sets the path of the EdgeChromium driver.
343
* @param {string} path The EdgeChromium driver path.
344
* @return {!Options} A self reference.
345
*/
346
setEdgePath(path) {
347
this.options_[Key.EDGE_EXECUTABLE_PATH] = path
348
return this
349
}
350
351
/**
352
* Sets the IEDriver to drive Chromium-based Edge in Internet Explorer mode.
353
*
354
* @param {boolean} attachEdgeChromium Whether to run in Chromium-based-Edge in IE mode
355
* @return {!Options} A self reference.
356
*/
357
setEdgeChromium(attachEdgeChromium) {
358
this.options_[Key.ATTACH_TO_EDGE_CHROMIUM] = !!attachEdgeChromium
359
return this
360
}
361
362
/**
363
* Sets how elements should be scrolled into view for interaction.
364
* @param {number} behavior The desired scroll behavior: either 0 to align with
365
* the top of the viewport or 1 to align with the bottom.
366
* @return {!Options} A self reference.
367
*/
368
setScrollBehavior(behavior) {
369
if (behavior && behavior !== SCROLL_BEHAVIOUR.TOP && behavior !== SCROLL_BEHAVIOUR.BOTTOM) {
370
throw new error.InvalidArgumentError(`Element Scroll Behavior out of range.
371
It should be either ${SCROLL_BEHAVIOUR.TOP} or ${SCROLL_BEHAVIOUR.BOTTOM}`)
372
}
373
this.options_[Key.ELEMENT_SCROLL_BEHAVIOR] = behavior
374
return this
375
}
376
}
377
378
function createServiceFromCapabilities(capabilities) {
379
if (process.platform !== 'win32') {
380
throw Error(
381
'The IEDriver may only be used on Windows, but you appear to be on ' +
382
process.platform +
383
'. Did you mean to run against a remote ' +
384
'WebDriver server?',
385
)
386
}
387
388
let exe = null // Let Selenium Manager find it
389
var args = []
390
if (capabilities.has(Key.HOST)) {
391
args.push('--host=' + capabilities.get(Key.HOST))
392
}
393
if (capabilities.has(Key.LOG_FILE)) {
394
args.push('--log-file=' + capabilities.get(Key.LOG_FILE))
395
}
396
if (capabilities.has(Key.LOG_LEVEL)) {
397
args.push('--log-level=' + capabilities.get(Key.LOG_LEVEL))
398
}
399
if (capabilities.has(Key.EXTRACT_PATH)) {
400
args.push('--extract-path=' + capabilities.get(Key.EXTRACT_PATH))
401
}
402
if (capabilities.get(Key.SILENT)) {
403
args.push('--silent')
404
}
405
406
var port = portprober.findFreePort()
407
return new remote.DriverService(exe, {
408
loopback: true,
409
port: port,
410
args: port.then(function (port) {
411
return args.concat('--port=' + port)
412
}),
413
stdio: 'ignore',
414
})
415
}
416
417
/**
418
* Creates {@link selenium-webdriver/remote.DriverService} instances that manage
419
* an [IEDriverServer](https://github.com/SeleniumHQ/selenium/wiki/InternetExplorerDriver)
420
* server in a child process.
421
*/
422
class ServiceBuilder extends remote.DriverService.Builder {
423
/**
424
* @param {string=} opt_exe Path to the server executable to use. If omitted,
425
* the builder will attempt to locate the IEDriverServer on the system PATH.
426
*/
427
constructor(opt_exe) {
428
super(opt_exe)
429
this.setLoopback(true) // Required.
430
}
431
}
432
433
/**
434
* A WebDriver client for Microsoft's Internet Explorer.
435
*/
436
class Driver extends webdriver.WebDriver {
437
/**
438
* Creates a new session for Microsoft's Internet Explorer.
439
*
440
* @param {(Capabilities|Options)=} options The configuration options.
441
* @param {(remote.DriverService)=} opt_service The `DriverService` to use
442
* to start the IEDriverServer in a child process, optionally.
443
* @return {!Driver} A new driver instance.
444
*/
445
static createSession(options, opt_service) {
446
options = options || new Options()
447
448
let service
449
450
if (opt_service instanceof remote.DriverService) {
451
service = opt_service
452
} else {
453
service = createServiceFromCapabilities(options)
454
}
455
if (!service.getExecutable()) {
456
service.setExecutable(getBinaryPaths(options).driverPath)
457
}
458
459
let client = service.start().then((url) => new http.HttpClient(url))
460
let executor = new http.Executor(client)
461
462
return /** @type {!Driver} */ (super.createSession(executor, options, () => service.kill()))
463
}
464
465
/**
466
* This function is a no-op as file detectors are not supported by this
467
* implementation.
468
* @override
469
*/
470
setFileDetector() {}
471
}
472
473
// PUBLIC API
474
475
exports.Driver = Driver
476
exports.Options = Options
477
exports.Level = Level
478
exports.ServiceBuilder = ServiceBuilder
479
exports.Key = Key
480
exports.VENDOR_COMMAND_PREFIX = OPTIONS_CAPABILITY_KEY
481
exports.Behavior = SCROLL_BEHAVIOUR
482
483