UNPKG

15 kBJavaScriptView Raw
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'use strict'
19
20/**
21 * @fileoverview Defines types related to describing the capabilities of a
22 * WebDriver session.
23 */
24
25const Symbols = require('./symbols')
26
27/**
28 * Recognized browser names.
29 * @enum {string}
30 */
31const Browser = {
32 CHROME: 'chrome',
33 EDGE: 'MicrosoftEdge',
34 FIREFOX: 'firefox',
35 INTERNET_EXPLORER: 'internet explorer',
36 SAFARI: 'safari',
37 OPERA: 'opera',
38}
39
40/**
41 * Strategies for waiting for [document readiness] after a navigation
42 * event.
43 *
44 * [document readiness]: https://html.spec.whatwg.org/#current-document-readiness
45 *
46 * @enum {string}
47 */
48const PageLoadStrategy = {
49 /**
50 * Indicates WebDriver should not wait on the document readiness state after a
51 * navigation event.
52 */
53 NONE: 'none',
54
55 /**
56 * Indicates WebDriver should wait for the document readiness state to
57 * become "interactive" after navigation.
58 */
59 EAGER: 'eager',
60
61 /**
62 * Indicates WebDriver should wait for the document readiness state to
63 * be "complete" after navigation. This is the default page loading strategy.
64 */
65 NORMAL: 'normal',
66}
67
68/**
69 * Common platform names. These platforms are not explicitly defined by the
70 * WebDriver spec, however, their use is encouraged for interoperability.
71 *
72 * @enum {string}
73 * @see <https://w3c.github.io/webdriver/webdriver-spec.html>
74 */
75const Platform = {
76 LINUX: 'linux',
77 MAC: 'mac',
78 WINDOWS: 'windows',
79}
80
81/**
82 * Record object defining the timeouts that apply to certain WebDriver actions.
83 *
84 * @record
85 */
86function Timeouts() { }
87
88/**
89 * Defines when, in milliseconds, to interrupt a script that is being
90 * {@linkplain ./webdriver.IWebDriver#executeScript evaluated}.
91 * @type {number}
92 */
93Timeouts.prototype.script
94
95/**
96 * The timeout, in milliseconds, to apply to navigation events along with the
97 * {@link PageLoadStrategy}.
98 * @type {number}
99 */
100Timeouts.prototype.pageLoad
101
102/**
103 * The maximum amount of time, in milliseconds, to spend attempting to
104 * {@linkplain ./webdriver.IWebDriver#findElement locate} an element on the
105 * current page.
106 * @type {number}
107 */
108Timeouts.prototype.implicit
109
110/**
111 * The possible default actions a WebDriver session can take to respond to
112 * unhandled user prompts (`window.alert()`, `window.confirm()`, and
113 * `window.prompt()`).
114 *
115 * @enum {string}
116 */
117const UserPromptHandler = {
118 /** All prompts should be silently accepted. */
119 ACCEPT: 'accept',
120 /** All prompts should be silently dismissed. */
121 DISMISS: 'dismiss',
122 /**
123 * All prompts should be automatically accepted, but an error should be
124 * returned to the next (or currently executing) WebDriver command.
125 */
126 ACCEPT_AND_NOTIFY: 'accept and notify',
127 /**
128 * All prompts should be automatically dismissed, but an error should be
129 * returned to the next (or currently executing) WebDriver command.
130 */
131 DISMISS_AND_NOTIFY: 'dismiss and notify',
132 /** All prompts should be left unhandled. */
133 IGNORE: 'ignore',
134}
135
136/**
137 * The standard WebDriver capability keys.
138 *
139 * @enum {string}
140 * @see <https://w3c.github.io/webdriver/webdriver-spec.html#capabilities>
141 */
142const Capability = {
143 /**
144 * Indicates whether a WebDriver session implicitly trusts otherwise untrusted
145 * and self-signed TLS certificates during navigation.
146 */
147 ACCEPT_INSECURE_TLS_CERTS: 'acceptInsecureCerts',
148
149 /**
150 * The browser name. Common browser names are defined in the
151 * {@link ./capabilities.Browser Browser} enum.
152 */
153 BROWSER_NAME: 'browserName',
154
155 /** Identifies the browser version. */
156 BROWSER_VERSION: 'browserVersion',
157
158 /**
159 * Key for the logging driver logging preferences.
160 * The browser name. Common browser names are defined in the
161 * {@link ./capabilities.Browser Browser} enum.
162 */
163 LOGGING_PREFS: 'goog:loggingPrefs',
164
165 /**
166 * Defines the session's
167 * {@linkplain ./capabilities.PageLoadStrategy page loading strategy}.
168 */
169 PAGE_LOAD_STRATEGY: 'pageLoadStrategy',
170
171 /**
172 * Identifies the operating system of the endpoint node. Common values
173 * recognized by the most WebDriver server implementations are predefined in
174 * the {@link ./capabilities.Platform Platform} enum.
175 */
176 PLATFORM_NAME: 'platformName',
177
178 /**
179 * Describes the proxy configuration to use for a new WebDriver session.
180 */
181 PROXY: 'proxy',
182
183 /**
184 * Indicates whether the remote end supports all of the window resizing and
185 * positioning commands:
186 *
187 * - {@linkplain ./webdriver.Window#getRect Window.getRect()}
188 * - {@linkplain ./webdriver.Window#setRect Window.setRect()}
189 * - {@linkplain ./webdriver.Window#maximize Window.maximize()}
190 * - {@linkplain ./webdriver.Window#minimize Window.minimize()}
191 * - {@linkplain ./webdriver.Window#fullscreen Window.fullscreen()}
192 */
193 SET_WINDOW_RECT: 'setWindowRect',
194
195 /**
196 * Describes the {@linkplain ./capabilities.Timeouts timeouts} imposed on
197 * certain session operations.
198 */
199 TIMEOUTS: 'timeouts',
200
201 /**
202 * Defines how a WebDriver session should
203 * {@linkplain ./capabilities.UserPromptHandler respond} to unhandled user
204 * prompts.
205 */
206 UNHANDLED_PROMPT_BEHAVIOR: 'unhandledPromptBehavior',
207
208 /**
209 * Defines the current session’s strict file interactability.
210 * Used to upload a file when strict file interactability is on
211 */
212 STRICT_FILE_INTERACTABILITY: 'strictFileInteractability',
213}
214
215/**
216 * Converts a generic hash object to a map.
217 * @param {!Object<string, ?>} hash The hash object.
218 * @return {!Map<string, ?>} The converted map.
219 */
220function toMap(hash) {
221 let m = new Map()
222 for (let key in hash) {
223 if (Object.prototype.hasOwnProperty.call(hash, key)) {
224 m.set(key, hash[key])
225 }
226 }
227 return m
228}
229
230/**
231 * Describes a set of capabilities for a WebDriver session.
232 */
233class Capabilities {
234 /**
235 * @param {(Capabilities|Map<string, ?>|Object)=} other Another set of
236 * capabilities to initialize this instance from.
237 */
238 constructor(other = undefined) {
239 if (other instanceof Capabilities) {
240 other = other.map_
241 } else if (other && !(other instanceof Map)) {
242 other = toMap(other)
243 }
244 /** @private @const {!Map<string, ?>} */
245 this.map_ = new Map(other)
246 }
247
248 /**
249 * @return {!Capabilities} A basic set of capabilities for Chrome.
250 */
251 static chrome() {
252 return new Capabilities().setBrowserName(Browser.CHROME)
253 }
254
255 /**
256 * @return {!Capabilities} A basic set of capabilities for Microsoft Edge.
257 */
258 static edge() {
259 return new Capabilities().setBrowserName(Browser.EDGE)
260 }
261
262 /**
263 * @return {!Capabilities} A basic set of capabilities for Firefox.
264 */
265 static firefox() {
266 return new Capabilities()
267 .setBrowserName(Browser.FIREFOX)
268 .set('moz:debuggerAddress', true)
269 }
270
271 /**
272 * @return {!Capabilities} A basic set of capabilities for Internet Explorer.
273 */
274 static ie() {
275 return new Capabilities().setBrowserName(Browser.INTERNET_EXPLORER)
276 }
277
278 /**
279 * @return {!Capabilities} A basic set of capabilities for Safari.
280 */
281 static safari() {
282 return new Capabilities().setBrowserName(Browser.SAFARI)
283 }
284
285 /**
286 * @return {!Capabilities} A basic set of capabilities for Opera
287 */
288 static opera() {
289 return new Capabilities().setBrowserName(Browser.OPERA)
290 }
291
292 /**
293 * @return {!Object<string, ?>} The JSON representation of this instance.
294 * Note, the returned object may contain nested promised values.
295 * @suppress {checkTypes} Suppress [] access on a struct (state inherited from
296 * Map).
297 */
298 [Symbols.serialize]() {
299 return serialize(this)
300 }
301
302 /**
303 * @param {string} key the parameter key to get.
304 * @return {T} the stored parameter value.
305 * @template T
306 */
307 get(key) {
308 return this.map_.get(key)
309 }
310
311 /**
312 * @param {string} key the key to test.
313 * @return {boolean} whether this capability set has the specified key.
314 */
315 has(key) {
316 return this.map_.has(key)
317 }
318
319 /**
320 * @return {!Iterator<string>} an iterator of the keys set.
321 */
322 keys() {
323 return this.map_.keys()
324 }
325
326 /** @return {number} The number of capabilities set. */
327 get size() {
328 return this.map_.size
329 }
330
331 /**
332 * Merges another set of capabilities into this instance.
333 * @param {!(Capabilities|Map<String, ?>|Object<string, ?>)} other The other
334 * set of capabilities to merge.
335 * @return {!Capabilities} A self reference.
336 */
337 merge(other) {
338 if (other) {
339 let otherMap
340 if (other instanceof Capabilities) {
341 otherMap = other.map_
342 } else if (other instanceof Map) {
343 otherMap = other
344 } else {
345 otherMap = toMap(other)
346 }
347 otherMap.forEach((value, key) => {
348 this.set(key, value)
349 })
350 return this
351 } else {
352 throw new TypeError('no capabilities provided for merge')
353 }
354 }
355
356 /**
357 * Deletes an entry from this set of capabilities.
358 *
359 * @param {string} key the capability key to delete.
360 */
361 delete(key) {
362 this.map_.delete(key)
363 }
364
365 /**
366 * @param {string} key The capability key.
367 * @param {*} value The capability value.
368 * @return {!Capabilities} A self reference.
369 * @throws {TypeError} If the `key` is not a string.
370 */
371 set(key, value) {
372 if (typeof key !== 'string') {
373 throw new TypeError('Capability keys must be strings: ' + typeof key)
374 }
375 this.map_.set(key, value)
376 return this
377 }
378
379 /**
380 * Sets whether a WebDriver session should implicitly accept self-signed, or
381 * other untrusted TLS certificates on navigation.
382 *
383 * @param {boolean} accept whether to accept insecure certs.
384 * @return {!Capabilities} a self reference.
385 */
386 setAcceptInsecureCerts(accept) {
387 return this.set(Capability.ACCEPT_INSECURE_TLS_CERTS, accept)
388 }
389
390 /**
391 * @return {boolean} whether the session is configured to accept insecure
392 * TLS certificates.
393 */
394 getAcceptInsecureCerts() {
395 return this.get(Capability.ACCEPT_INSECURE_TLS_CERTS)
396 }
397
398 /**
399 * Sets the name of the target browser.
400 *
401 * @param {(Browser|string)} name the browser name.
402 * @return {!Capabilities} a self reference.
403 */
404 setBrowserName(name) {
405 return this.set(Capability.BROWSER_NAME, name)
406 }
407
408 /**
409 * @return {(string|undefined)} the configured browser name, or undefined if
410 * not set.
411 */
412 getBrowserName() {
413 return this.get(Capability.BROWSER_NAME)
414 }
415
416 /**
417 * Sets the desired version of the target browser.
418 *
419 * @param {string} version the desired version.
420 * @return {!Capabilities} a self reference.
421 */
422 setBrowserVersion(version) {
423 return this.set(Capability.BROWSER_VERSION, version)
424 }
425
426 /**
427 * @return {(string|undefined)} the configured browser version, or undefined
428 * if not set.
429 */
430 getBrowserVersion() {
431 return this.get(Capability.BROWSER_VERSION)
432 }
433
434 /**
435 * Sets the desired page loading strategy for a new WebDriver session.
436 *
437 * @param {PageLoadStrategy} strategy the desired strategy.
438 * @return {!Capabilities} a self reference.
439 */
440 setPageLoadStrategy(strategy) {
441 return this.set(Capability.PAGE_LOAD_STRATEGY, strategy)
442 }
443
444 /**
445 * Returns the configured page load strategy.
446 *
447 * @return {(string|undefined)} the page load strategy.
448 */
449 getPageLoadStrategy() {
450 return this.get(Capability.PAGE_LOAD_STRATEGY)
451 }
452
453 /**
454 * Sets the target platform.
455 *
456 * @param {(Platform|string)} platform the target platform.
457 * @return {!Capabilities} a self reference.
458 */
459 setPlatform(platform) {
460 return this.set(Capability.PLATFORM_NAME, platform)
461 }
462
463 /**
464 * @return {(string|undefined)} the configured platform or undefined if not
465 * set.
466 */
467 getPlatform() {
468 return this.get(Capability.PLATFORM_NAME)
469 }
470
471 /**
472 * Sets the logging preferences. Preferences may be specified as a
473 * {@link ./logging.Preferences} instance, or as a map of log-type to
474 * log-level.
475 * @param {!(./logging.Preferences|Object<string>)} prefs The logging
476 * preferences.
477 * @return {!Capabilities} A self reference.
478 */
479 setLoggingPrefs(prefs) {
480 return this.set(Capability.LOGGING_PREFS, prefs)
481 }
482
483 /**
484 * Sets the proxy configuration for this instance.
485 * @param {proxy.Config} proxy The desired proxy configuration.
486 * @return {!Capabilities} A self reference.
487 */
488 setProxy(proxy) {
489 return this.set(Capability.PROXY, proxy)
490 }
491
492 /**
493 * @return {(proxy.Config|undefined)} the configured proxy settings, or
494 * undefined if not set.
495 */
496 getProxy() {
497 return this.get(Capability.PROXY)
498 }
499
500 /**
501 * Sets the default action to take with an unexpected alert before returning
502 * an error. If unspecified, WebDriver will default to
503 * {@link UserPromptHandler.DISMISS_AND_NOTIFY}.
504 *
505 * @param {?UserPromptHandler} behavior The way WebDriver should respond to
506 * unhandled user prompts.
507 * @return {!Capabilities} A self reference.
508 */
509 setAlertBehavior(behavior) {
510 return this.set(Capability.UNHANDLED_PROMPT_BEHAVIOR, behavior)
511 }
512
513 /**
514 * @return {(UserPromptHandler|undefined)} the behavior pattern for responding
515 * to unhandled user prompts, or undefined if not set.
516 */
517 getAlertBehavior() {
518 return this.get(Capability.UNHANDLED_PROMPT_BEHAVIOR)
519 }
520
521 /**
522 * Sets the boolean flag configuration for this instance.
523 */
524 setStrictFileInteractability(strictFileInteractability) {
525 return this.set(
526 Capability.STRICT_FILE_INTERACTABILITY,
527 strictFileInteractability
528 )
529 }
530}
531
532/**
533 * Serializes a capabilities object. This is defined as a standalone function
534 * so it may be type checked (where Capabilities[Symbols.serialize] has type
535 * checking disabled since it is defined with [] access on a struct).
536 *
537 * @param {!Capabilities} caps The capabilities to serialize.
538 * @return {!Object<string, ?>} The JSON representation of this instance.
539 * Note, the returned object may contain nested promised values.
540 */
541function serialize(caps) {
542 let ret = {}
543 for (let key of caps.keys()) {
544 let cap = caps.get(key)
545 if (cap !== undefined && cap !== null) {
546 ret[key] = cap
547 }
548 }
549 return ret
550}
551
552// PUBLIC API
553
554module.exports = {
555 Browser,
556 Capabilities,
557 Capability,
558 PageLoadStrategy,
559 Platform,
560 Timeouts,
561 UserPromptHandler,
562}