capabilities.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  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. 'use strict';
  18. /**
  19. * @fileoverview Defines types related to describing the capabilities of a
  20. * WebDriver session.
  21. */
  22. const Symbols = require('./symbols');
  23. /**
  24. * Recognized browser names.
  25. * @enum {string}
  26. */
  27. const Browser = {
  28. ANDROID: 'android',
  29. CHROME: 'chrome',
  30. EDGE: 'MicrosoftEdge',
  31. FIREFOX: 'firefox',
  32. IE: 'internet explorer',
  33. INTERNET_EXPLORER: 'internet explorer',
  34. IPAD: 'iPad',
  35. IPHONE: 'iPhone',
  36. OPERA: 'opera',
  37. PHANTOM_JS: 'phantomjs',
  38. SAFARI: 'safari',
  39. HTMLUNIT: 'htmlunit'
  40. };
  41. /**
  42. * Common Capability keys.
  43. * @enum {string}
  44. */
  45. const Capability = {
  46. /**
  47. * Indicates whether a driver should accept all SSL certs by default. This
  48. * capability only applies when requesting a new session. To query whether
  49. * a driver can handle insecure SSL certs, see {@link #SECURE_SSL}.
  50. */
  51. ACCEPT_SSL_CERTS: 'acceptSslCerts',
  52. /**
  53. * The browser name. Common browser names are defined in the {@link Browser}
  54. * enum.
  55. */
  56. BROWSER_NAME: 'browserName',
  57. /**
  58. * Defines how elements should be scrolled into the viewport for interaction.
  59. * This capability will be set to zero (0) if elements are aligned with the
  60. * top of the viewport, or one (1) if aligned with the bottom. The default
  61. * behavior is to align with the top of the viewport.
  62. */
  63. ELEMENT_SCROLL_BEHAVIOR: 'elementScrollBehavior',
  64. /**
  65. * Whether the driver is capable of handling modal alerts (e.g. alert,
  66. * confirm, prompt). To define how a driver <i>should</i> handle alerts,
  67. * use {@link #UNEXPECTED_ALERT_BEHAVIOR}.
  68. */
  69. HANDLES_ALERTS: 'handlesAlerts',
  70. /**
  71. * Key for the logging driver logging preferences.
  72. */
  73. LOGGING_PREFS: 'loggingPrefs',
  74. /**
  75. * Whether this session generates native events when simulating user input.
  76. */
  77. NATIVE_EVENTS: 'nativeEvents',
  78. /**
  79. * Describes the platform the browser is running on. Will be one of
  80. * ANDROID, IOS, LINUX, MAC, UNIX, or WINDOWS. When <i>requesting</i> a
  81. * session, ANY may be used to indicate no platform preference (this is
  82. * semantically equivalent to omitting the platform capability).
  83. */
  84. PLATFORM: 'platform',
  85. /**
  86. * Describes the proxy configuration to use for a new WebDriver session.
  87. */
  88. PROXY: 'proxy',
  89. /** Whether the driver supports changing the browser's orientation. */
  90. ROTATABLE: 'rotatable',
  91. /**
  92. * Whether a driver is only capable of handling secure SSL certs. To request
  93. * that a driver accept insecure SSL certs by default, use
  94. * {@link #ACCEPT_SSL_CERTS}.
  95. */
  96. SECURE_SSL: 'secureSsl',
  97. /** Whether the driver supports manipulating the app cache. */
  98. SUPPORTS_APPLICATION_CACHE: 'applicationCacheEnabled',
  99. /** Whether the driver supports locating elements with CSS selectors. */
  100. SUPPORTS_CSS_SELECTORS: 'cssSelectorsEnabled',
  101. /** Whether the browser supports JavaScript. */
  102. SUPPORTS_JAVASCRIPT: 'javascriptEnabled',
  103. /** Whether the driver supports controlling the browser's location info. */
  104. SUPPORTS_LOCATION_CONTEXT: 'locationContextEnabled',
  105. /** Whether the driver supports taking screenshots. */
  106. TAKES_SCREENSHOT: 'takesScreenshot',
  107. /**
  108. * Defines how the driver should handle unexpected alerts. The value should
  109. * be one of "accept", "dismiss", or "ignore".
  110. */
  111. UNEXPECTED_ALERT_BEHAVIOR: 'unexpectedAlertBehaviour',
  112. /** Defines the browser version. */
  113. VERSION: 'version'
  114. };
  115. /**
  116. * Describes how a proxy should be configured for a WebDriver session.
  117. * @record
  118. */
  119. function ProxyConfig() {}
  120. /**
  121. * The proxy type. Must be one of {"manual", "pac", "system"}.
  122. * @type {string}
  123. */
  124. ProxyConfig.prototype.proxyType;
  125. /**
  126. * URL for the PAC file to use. Only used if {@link #proxyType} is "pac".
  127. * @type {(string|undefined)}
  128. */
  129. ProxyConfig.prototype.proxyAutoconfigUrl;
  130. /**
  131. * The proxy host for FTP requests. Only used if {@link #proxyType} is "manual".
  132. * @type {(string|undefined)}
  133. */
  134. ProxyConfig.prototype.ftpProxy;
  135. /**
  136. * The proxy host for HTTP requests. Only used if {@link #proxyType} is
  137. * "manual".
  138. * @type {(string|undefined)}
  139. */
  140. ProxyConfig.prototype.httpProxy;
  141. /**
  142. * The proxy host for HTTPS requests. Only used if {@link #proxyType} is
  143. * "manual".
  144. * @type {(string|undefined)}
  145. */
  146. ProxyConfig.prototype.sslProxy;
  147. /**
  148. * A comma delimited list of hosts which should bypass all proxies. Only used if
  149. * {@link #proxyType} is "manual".
  150. * @type {(string|undefined)}
  151. */
  152. ProxyConfig.prototype.noProxy;
  153. /**
  154. * Converts a generic hash object to a map.
  155. * @param {!Object<string, ?>} hash The hash object.
  156. * @return {!Map<string, ?>} The converted map.
  157. */
  158. function toMap(hash) {
  159. let m = new Map;
  160. for (let key in hash) {
  161. if (hash.hasOwnProperty(key)) {
  162. m.set(key, hash[key]);
  163. }
  164. }
  165. return m;
  166. }
  167. /**
  168. * Describes a set of capabilities for a WebDriver session.
  169. */
  170. class Capabilities {
  171. /**
  172. * @param {(Capabilities|Map<string, ?>|Object)=} other Another set of
  173. * capabilities to initialize this instance from.
  174. */
  175. constructor(other = undefined) {
  176. if (other instanceof Capabilities) {
  177. other = other.map_;
  178. } else if (other && !(other instanceof Map)) {
  179. other = toMap(other);
  180. }
  181. /** @private @const {!Map<string, ?>} */
  182. this.map_ = new Map(other);
  183. }
  184. /**
  185. * @return {!Capabilities} A basic set of capabilities for Android.
  186. */
  187. static android() {
  188. return new Capabilities()
  189. .set(Capability.BROWSER_NAME, Browser.ANDROID);
  190. }
  191. /**
  192. * @return {!Capabilities} A basic set of capabilities for Chrome.
  193. */
  194. static chrome() {
  195. return new Capabilities().set(Capability.BROWSER_NAME, Browser.CHROME);
  196. }
  197. /**
  198. * @return {!Capabilities} A basic set of capabilities for Microsoft Edge.
  199. */
  200. static edge() {
  201. return new Capabilities()
  202. .set(Capability.BROWSER_NAME, Browser.EDGE);
  203. }
  204. /**
  205. * @return {!Capabilities} A basic set of capabilities for Firefox.
  206. */
  207. static firefox() {
  208. return new Capabilities().set(Capability.BROWSER_NAME, Browser.FIREFOX);
  209. }
  210. /**
  211. * @return {!Capabilities} A basic set of capabilities for Internet Explorer.
  212. */
  213. static ie() {
  214. return new Capabilities().
  215. set(Capability.BROWSER_NAME, Browser.INTERNET_EXPLORER);
  216. }
  217. /**
  218. * @return {!Capabilities} A basic set of capabilities for iPad.
  219. */
  220. static ipad() {
  221. return new Capabilities().
  222. set(Capability.BROWSER_NAME, Browser.IPAD);
  223. }
  224. /**
  225. * @return {!Capabilities} A basic set of capabilities for iPhone.
  226. */
  227. static iphone() {
  228. return new Capabilities().
  229. set(Capability.BROWSER_NAME, Browser.IPHONE);
  230. }
  231. /**
  232. * @return {!Capabilities} A basic set of capabilities for Opera.
  233. */
  234. static opera() {
  235. return new Capabilities().
  236. set(Capability.BROWSER_NAME, Browser.OPERA);
  237. }
  238. /**
  239. * @return {!Capabilities} A basic set of capabilities for PhantomJS.
  240. */
  241. static phantomjs() {
  242. return new Capabilities().
  243. set(Capability.BROWSER_NAME, Browser.PHANTOM_JS);
  244. }
  245. /**
  246. * @return {!Capabilities} A basic set of capabilities for Safari.
  247. */
  248. static safari() {
  249. return new Capabilities().
  250. set(Capability.BROWSER_NAME, Browser.SAFARI);
  251. }
  252. /**
  253. * @return {!Capabilities} A basic set of capabilities for HTMLUnit.
  254. */
  255. static htmlunit() {
  256. return new Capabilities().
  257. set(Capability.BROWSER_NAME, Browser.HTMLUNIT);
  258. }
  259. /**
  260. * @return {!Capabilities} A basic set of capabilities for HTMLUnit
  261. * with enabled Javascript.
  262. */
  263. static htmlunitwithjs() {
  264. return new Capabilities().
  265. set(Capability.BROWSER_NAME, Browser.HTMLUNIT).
  266. set(Capability.SUPPORTS_JAVASCRIPT, true);
  267. }
  268. /**
  269. * @return {!Object<string, ?>} The JSON representation of this instance.
  270. * Note, the returned object may contain nested promised values.
  271. * @suppress {checkTypes} Suppress [] access on a struct (state inherited from
  272. * Map).
  273. */
  274. [Symbols.serialize]() {
  275. return serialize(this);
  276. }
  277. /**
  278. * @param {string} key the parameter key to get.
  279. * @return {T} the stored parameter value.
  280. * @template T
  281. */
  282. get(key) {
  283. return this.map_.get(key);
  284. }
  285. /**
  286. * @param {string} key the key to test.
  287. * @return {boolean} whether this capability set has the specified key.
  288. */
  289. has(key) {
  290. return this.map_.has(key);
  291. }
  292. /**
  293. * @return {!Iterator<string>} an iterator of the keys set.
  294. */
  295. keys() {
  296. return this.map_.keys();
  297. }
  298. /** @return {number} The number of capabilities set. */
  299. get size() {
  300. return this.map_.size;
  301. }
  302. /**
  303. * Merges another set of capabilities into this instance.
  304. * @param {!(Capabilities|Map<String, ?>|Object<string, ?>)} other The other
  305. * set of capabilities to merge.
  306. * @return {!Capabilities} A self reference.
  307. */
  308. merge(other) {
  309. if (!other) {
  310. throw new TypeError('no capabilities provided for merge');
  311. }
  312. let map;
  313. if (other instanceof Capabilities) {
  314. map = other.map_;
  315. } else if (other instanceof Map) {
  316. map = other;
  317. } else {
  318. other = toMap(other);
  319. }
  320. for (let key of other.keys()) {
  321. this.set(key, other.get(key));
  322. }
  323. return this;
  324. }
  325. /**
  326. * Deletes an entry from this set of capabilities.
  327. *
  328. * @param {string} key the capability key to delete.
  329. */
  330. delete(key) {
  331. this.map_.delete(key);
  332. }
  333. /**
  334. * @param {string} key The capability key.
  335. * @param {*} value The capability value.
  336. * @return {!Capabilities} A self reference.
  337. * @throws {TypeError} If the `key` is not a string.
  338. */
  339. set(key, value) {
  340. if (typeof key !== 'string') {
  341. throw new TypeError('Capability keys must be strings: ' + typeof key);
  342. }
  343. this.map_.set(key, value);
  344. return this;
  345. }
  346. /**
  347. * Sets the logging preferences. Preferences may be specified as a
  348. * {@link ./logging.Preferences} instance, or as a map of log-type to
  349. * log-level.
  350. * @param {!(./logging.Preferences|Object<string>)} prefs The logging
  351. * preferences.
  352. * @return {!Capabilities} A self reference.
  353. */
  354. setLoggingPrefs(prefs) {
  355. return this.set(Capability.LOGGING_PREFS, prefs);
  356. }
  357. /**
  358. * Sets the proxy configuration for this instance.
  359. * @param {ProxyConfig} proxy The desired proxy configuration.
  360. * @return {!Capabilities} A self reference.
  361. */
  362. setProxy(proxy) {
  363. return this.set(Capability.PROXY, proxy);
  364. }
  365. /**
  366. * Sets whether native events should be used.
  367. * @param {boolean} enabled Whether to enable native events.
  368. * @return {!Capabilities} A self reference.
  369. */
  370. setEnableNativeEvents(enabled) {
  371. return this.set(Capability.NATIVE_EVENTS, enabled);
  372. }
  373. /**
  374. * Sets how elements should be scrolled into view for interaction.
  375. * @param {number} behavior The desired scroll behavior: either 0 to align
  376. * with the top of the viewport or 1 to align with the bottom.
  377. * @return {!Capabilities} A self reference.
  378. */
  379. setScrollBehavior(behavior) {
  380. return this.set(Capability.ELEMENT_SCROLL_BEHAVIOR, behavior);
  381. }
  382. /**
  383. * Sets the default action to take with an unexpected alert before returning
  384. * an error.
  385. * @param {string} behavior The desired behavior should be "accept",
  386. * "dismiss", or "ignore". Defaults to "dismiss".
  387. * @return {!Capabilities} A self reference.
  388. */
  389. setAlertBehavior(behavior) {
  390. return this.set(Capability.UNEXPECTED_ALERT_BEHAVIOR, behavior);
  391. }
  392. }
  393. /**
  394. * Serializes a capabilities object. This is defined as a standalone function
  395. * so it may be type checked (where Capabilities[Symbols.serialize] has type
  396. * checking disabled since it is defined with [] access on a struct).
  397. *
  398. * @param {!Capabilities} caps The capabilities to serialize.
  399. * @return {!Object<string, ?>} The JSON representation of this instance.
  400. * Note, the returned object may contain nested promised values.
  401. */
  402. function serialize(caps) {
  403. let ret = {};
  404. for (let key of caps.keys()) {
  405. let cap = caps.get(key);
  406. if (cap !== undefined && cap !== null) {
  407. ret[key] = cap;
  408. }
  409. }
  410. return ret;
  411. }
  412. // PUBLIC API
  413. module.exports = {
  414. Browser: Browser,
  415. Capabilities: Capabilities,
  416. Capability: Capability,
  417. ProxyConfig: ProxyConfig
  418. };