@appium/base-driver 8.3.0 → 8.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (202) hide show
  1. package/build/lib/basedriver/capabilities.d.ts +80 -0
  2. package/build/lib/basedriver/capabilities.d.ts.map +1 -0
  3. package/build/lib/basedriver/capabilities.js +12 -13
  4. package/build/lib/basedriver/commands/event.d.ts +9 -0
  5. package/build/lib/basedriver/commands/event.d.ts.map +1 -0
  6. package/build/lib/basedriver/commands/event.js +21 -23
  7. package/build/lib/basedriver/commands/find.d.ts +11 -0
  8. package/build/lib/basedriver/commands/find.d.ts.map +1 -0
  9. package/build/lib/basedriver/commands/find.js +42 -37
  10. package/build/lib/basedriver/commands/index.d.ts +8 -0
  11. package/build/lib/basedriver/commands/index.d.ts.map +1 -0
  12. package/build/lib/basedriver/commands/index.js +17 -16
  13. package/build/lib/basedriver/commands/log.d.ts +12 -0
  14. package/build/lib/basedriver/commands/log.d.ts.map +1 -0
  15. package/build/lib/basedriver/commands/log.js +23 -27
  16. package/build/lib/basedriver/commands/session.d.ts +11 -0
  17. package/build/lib/basedriver/commands/session.d.ts.map +1 -0
  18. package/build/lib/basedriver/commands/session.js +21 -149
  19. package/build/lib/basedriver/commands/settings.d.ts +10 -0
  20. package/build/lib/basedriver/commands/settings.d.ts.map +1 -0
  21. package/build/lib/basedriver/commands/settings.js +19 -19
  22. package/build/lib/basedriver/commands/timeout.d.ts +8 -0
  23. package/build/lib/basedriver/commands/timeout.d.ts.map +1 -0
  24. package/build/lib/basedriver/commands/timeout.js +118 -139
  25. package/build/lib/basedriver/core.d.ts +235 -0
  26. package/build/lib/basedriver/core.d.ts.map +1 -0
  27. package/build/lib/basedriver/core.js +283 -0
  28. package/build/lib/basedriver/desired-caps.d.ts +5 -0
  29. package/build/lib/basedriver/desired-caps.d.ts.map +1 -0
  30. package/build/lib/basedriver/desired-caps.js +2 -4
  31. package/build/lib/basedriver/device-settings.d.ts +32 -0
  32. package/build/lib/basedriver/device-settings.d.ts.map +1 -0
  33. package/build/lib/basedriver/device-settings.js +20 -14
  34. package/build/lib/basedriver/driver.d.ts +83 -0
  35. package/build/lib/basedriver/driver.d.ts.map +1 -0
  36. package/build/lib/basedriver/driver.js +101 -256
  37. package/build/lib/basedriver/helpers.d.ts +132 -0
  38. package/build/lib/basedriver/helpers.d.ts.map +1 -0
  39. package/build/lib/basedriver/helpers.js +16 -2
  40. package/build/lib/basedriver/logger.d.ts +3 -0
  41. package/build/lib/basedriver/logger.d.ts.map +1 -0
  42. package/build/lib/basedriver/logger.js +2 -4
  43. package/build/lib/constants.d.ts +9 -0
  44. package/build/lib/constants.d.ts.map +1 -0
  45. package/build/lib/constants.js +2 -4
  46. package/build/lib/express/crash.d.ts +3 -0
  47. package/build/lib/express/crash.d.ts.map +1 -0
  48. package/build/lib/express/crash.js +2 -4
  49. package/build/lib/express/express-logging.d.ts +3 -0
  50. package/build/lib/express/express-logging.d.ts.map +1 -0
  51. package/build/lib/express/express-logging.js +2 -4
  52. package/build/lib/express/idempotency.d.ts +2 -0
  53. package/build/lib/express/idempotency.d.ts.map +1 -0
  54. package/build/lib/express/idempotency.js +2 -4
  55. package/build/lib/express/logger.d.ts +3 -0
  56. package/build/lib/express/logger.d.ts.map +1 -0
  57. package/build/lib/express/logger.js +2 -4
  58. package/build/lib/express/middleware.d.ts +9 -0
  59. package/build/lib/express/middleware.d.ts.map +1 -0
  60. package/build/lib/express/middleware.js +2 -4
  61. package/build/lib/express/server.d.ts +10 -0
  62. package/build/lib/express/server.d.ts.map +1 -0
  63. package/build/lib/express/server.js +2 -4
  64. package/build/lib/express/static.d.ts +6 -0
  65. package/build/lib/express/static.d.ts.map +1 -0
  66. package/build/lib/express/static.js +2 -4
  67. package/build/lib/express/websocket.d.ts +64 -0
  68. package/build/lib/express/websocket.d.ts.map +1 -0
  69. package/build/lib/express/websocket.js +40 -41
  70. package/build/lib/helpers/capabilities.d.ts +13 -0
  71. package/build/lib/helpers/capabilities.d.ts.map +1 -0
  72. package/build/lib/helpers/capabilities.js +40 -2
  73. package/build/lib/index.d.ts +183 -0
  74. package/build/lib/index.d.ts.map +1 -0
  75. package/build/lib/index.js +41 -23
  76. package/build/lib/jsonwp-proxy/protocol-converter.d.ts +48 -0
  77. package/build/lib/jsonwp-proxy/protocol-converter.d.ts.map +1 -0
  78. package/build/lib/jsonwp-proxy/protocol-converter.js +2 -4
  79. package/build/lib/jsonwp-proxy/proxy.d.ts +41 -0
  80. package/build/lib/jsonwp-proxy/proxy.d.ts.map +1 -0
  81. package/build/lib/jsonwp-proxy/proxy.js +25 -9
  82. package/build/lib/jsonwp-status/status.d.ts +159 -0
  83. package/build/lib/jsonwp-status/status.d.ts.map +1 -0
  84. package/build/lib/jsonwp-status/status.js +2 -4
  85. package/build/lib/protocol/errors.d.ts +310 -0
  86. package/build/lib/protocol/errors.d.ts.map +1 -0
  87. package/build/lib/protocol/errors.js +82 -5
  88. package/build/lib/protocol/helpers.d.ts +22 -0
  89. package/build/lib/protocol/helpers.d.ts.map +1 -0
  90. package/build/lib/protocol/helpers.js +2 -4
  91. package/build/lib/protocol/index.d.ts +16 -0
  92. package/build/lib/protocol/index.d.ts.map +1 -0
  93. package/build/lib/protocol/index.js +8 -10
  94. package/build/lib/protocol/protocol.d.ts +11 -0
  95. package/build/lib/protocol/protocol.d.ts.map +1 -0
  96. package/build/lib/protocol/protocol.js +3 -9
  97. package/build/lib/protocol/routes.d.ts +6 -0
  98. package/build/lib/protocol/routes.d.ts.map +1 -0
  99. package/build/lib/protocol/routes.js +18 -4
  100. package/build/lib/protocol/validators.d.ts +8 -0
  101. package/build/lib/protocol/validators.d.ts.map +1 -0
  102. package/build/lib/protocol/validators.js +2 -4
  103. package/build/test/basedriver/README.md +5 -0
  104. package/build/test/basedriver/driver-e2e-tests.js +2 -4
  105. package/build/test/basedriver/driver-tests.js +31 -6
  106. package/build/test/basedriver/index.js +2 -4
  107. package/build/test/e2e/basedriver/driver.e2e.spec.js +15 -0
  108. package/build/test/e2e/basedriver/helpers.e2e.spec.js +192 -0
  109. package/build/test/e2e/basedriver/websockets.e2e.spec.js +87 -0
  110. package/build/test/e2e/express/server.e2e.spec.js +159 -0
  111. package/build/test/e2e/jsonwp-proxy/proxy.e2e.spec.js +59 -0
  112. package/build/test/e2e/protocol/fake-driver.js +163 -0
  113. package/build/test/e2e/protocol/helpers.js +25 -0
  114. package/build/test/e2e/protocol/protocol.e2e.spec.js +1186 -0
  115. package/build/test/helpers.js +2 -4
  116. package/build/test/unit/basedriver/capabilities.spec.js +672 -0
  117. package/build/test/unit/basedriver/capability.spec.js +353 -0
  118. package/build/test/unit/basedriver/commands/event.spec.js +110 -0
  119. package/build/test/unit/basedriver/commands/log.spec.js +92 -0
  120. package/build/test/unit/basedriver/driver.spec.js +15 -0
  121. package/build/test/unit/basedriver/helpers.spec.js +151 -0
  122. package/build/test/unit/basedriver/timeout.spec.js +135 -0
  123. package/build/test/unit/express/server.spec.js +155 -0
  124. package/build/test/unit/express/static.spec.js +26 -0
  125. package/build/test/unit/jsonwp-proxy/mock-request.js +91 -0
  126. package/build/test/unit/jsonwp-proxy/protocol-converter.spec.js +171 -0
  127. package/build/test/unit/jsonwp-proxy/proxy.spec.js +292 -0
  128. package/build/test/unit/jsonwp-proxy/url.spec.js +165 -0
  129. package/build/test/unit/jsonwp-status/status.spec.js +34 -0
  130. package/build/test/unit/protocol/errors.spec.js +390 -0
  131. package/build/test/unit/protocol/routes.spec.js +80 -0
  132. package/build/test/unit/protocol/validator.spec.js +149 -0
  133. package/build/tsconfig.tsbuildinfo +1 -0
  134. package/lib/basedriver/capabilities.js +49 -10
  135. package/lib/basedriver/commands/event.js +49 -31
  136. package/lib/basedriver/commands/find.js +108 -43
  137. package/lib/basedriver/commands/index.js +25 -19
  138. package/lib/basedriver/commands/log.js +60 -33
  139. package/lib/basedriver/commands/session.js +39 -141
  140. package/lib/basedriver/commands/settings.js +33 -13
  141. package/lib/basedriver/commands/timeout.js +153 -153
  142. package/lib/basedriver/core.js +497 -0
  143. package/lib/basedriver/desired-caps.js +1 -1
  144. package/lib/basedriver/device-settings.js +47 -12
  145. package/lib/basedriver/driver.js +272 -383
  146. package/lib/basedriver/helpers.js +18 -2
  147. package/lib/express/websocket.js +35 -32
  148. package/lib/helpers/capabilities.js +60 -1
  149. package/lib/index.js +16 -12
  150. package/lib/jsonwp-proxy/proxy.js +26 -6
  151. package/lib/protocol/errors.js +42 -42
  152. package/lib/protocol/index.js +4 -4
  153. package/lib/protocol/protocol.js +1 -3
  154. package/lib/protocol/routes.js +9 -0
  155. package/package.json +22 -14
  156. package/test/basedriver/README.md +5 -0
  157. package/test/basedriver/driver-e2e-tests.js +1 -1
  158. package/test/basedriver/driver-tests.js +31 -2
  159. package/build/test/basedriver/capabilities-specs.js +0 -674
  160. package/build/test/basedriver/capability-specs.js +0 -355
  161. package/build/test/basedriver/commands/event-specs.js +0 -112
  162. package/build/test/basedriver/commands/log-specs.js +0 -87
  163. package/build/test/basedriver/driver-e2e-specs.js +0 -17
  164. package/build/test/basedriver/driver-specs.js +0 -17
  165. package/build/test/basedriver/helpers-e2e-specs.js +0 -194
  166. package/build/test/basedriver/helpers-specs.js +0 -153
  167. package/build/test/basedriver/timeout-specs.js +0 -137
  168. package/build/test/basedriver/websockets-e2e-specs.js +0 -84
  169. package/build/test/express/server-e2e-specs.js +0 -161
  170. package/build/test/express/server-specs.js +0 -157
  171. package/build/test/express/static-specs.js +0 -28
  172. package/build/test/jsonwp-proxy/mock-request.js +0 -93
  173. package/build/test/jsonwp-proxy/protocol-converter-specs.js +0 -173
  174. package/build/test/jsonwp-proxy/proxy-e2e-specs.js +0 -61
  175. package/build/test/jsonwp-proxy/proxy-specs.js +0 -294
  176. package/build/test/jsonwp-proxy/url-specs.js +0 -167
  177. package/build/test/jsonwp-status/status-specs.js +0 -36
  178. package/build/test/protocol/errors-specs.js +0 -388
  179. package/build/test/protocol/fake-driver.js +0 -165
  180. package/build/test/protocol/helpers.js +0 -27
  181. package/build/test/protocol/protocol-e2e-specs.js +0 -1188
  182. package/build/test/protocol/routes-specs.js +0 -82
  183. package/build/test/protocol/validator-specs.js +0 -151
  184. package/index.d.ts +0 -386
  185. package/test/basedriver/capabilities-specs.js +0 -537
  186. package/test/basedriver/capability-specs.js +0 -383
  187. package/test/basedriver/commands/event-specs.js +0 -74
  188. package/test/basedriver/commands/log-specs.js +0 -79
  189. package/test/basedriver/driver-e2e-specs.js +0 -8
  190. package/test/basedriver/driver-specs.js +0 -8
  191. package/test/basedriver/fixtures/BadZippedApp.zip +0 -1
  192. package/test/basedriver/fixtures/FakeAndroidApp.apk +0 -1
  193. package/test/basedriver/fixtures/FakeAndroidApp.asd +0 -0
  194. package/test/basedriver/fixtures/FakeIOSApp.app +0 -1
  195. package/test/basedriver/fixtures/FakeIOSApp.app.zip +0 -0
  196. package/test/basedriver/fixtures/FakeIOSApp.ipa +0 -0
  197. package/test/basedriver/fixtures/custom-element-finder-bad.js +0 -5
  198. package/test/basedriver/fixtures/custom-element-finder.js +0 -29
  199. package/test/basedriver/helpers-e2e-specs.js +0 -187
  200. package/test/basedriver/helpers-specs.js +0 -137
  201. package/test/basedriver/timeout-specs.js +0 -128
  202. package/test/basedriver/websockets-e2e-specs.js +0 -75
@@ -2,7 +2,7 @@ import _ from 'lodash';
2
2
  import path from 'path';
3
3
  import url from 'url';
4
4
  import logger from './logger';
5
- import { tempDir, fs, util, zip, net, timing } from '@appium/support';
5
+ import { tempDir, fs, util, zip, net, timing, node } from '@appium/support';
6
6
  import LRU from 'lru-cache';
7
7
  import AsyncLock from 'async-lock';
8
8
  import axios from 'axios';
@@ -546,6 +546,22 @@ function parseCapsArray (cap) {
546
546
  throw new Error(`must provide a string or JSON Array; received ${cap}`);
547
547
  }
548
548
 
549
+ /**
550
+ * Generate a string that uniquely describes driver instance
551
+ *
552
+ * @param {import('@appium/types').Core} obj driver instance
553
+ * @param {string?} sessionId session identifier (if exists)
554
+ * @returns {string}
555
+ */
556
+ function generateDriverLogPrefix (obj, sessionId = null) {
557
+ const instanceName = `${obj.constructor.name}@${node.getObjectId(obj).substring(0, 4)}`;
558
+ return sessionId ? `${instanceName} (${sessionId.substring(0, 8)})` : instanceName;
559
+ }
560
+
561
+ /** @type {import('@appium/types').DriverHelpers} */
562
+ export default {
563
+ configureApp, isPackageOrBundle, duplicateKeys, parseCapsArray, generateDriverLogPrefix
564
+ };
549
565
  export {
550
- configureApp, isPackageOrBundle, duplicateKeys, parseCapsArray
566
+ configureApp, isPackageOrBundle, duplicateKeys, parseCapsArray, generateDriverLogPrefix
551
567
  };
@@ -1,5 +1,6 @@
1
1
  import _ from 'lodash';
2
- import url from 'url';
2
+ import { URL } from 'url';
3
+ import B from 'bluebird';
3
4
 
4
5
  const DEFAULT_WS_PATHNAME_PREFIX = '/ws';
5
6
 
@@ -18,29 +19,28 @@ const DEFAULT_WS_PATHNAME_PREFIX = '/ws';
18
19
  * on how to configure the handler properly.
19
20
  */
20
21
  async function addWebSocketHandler (handlerPathname, handlerServer) { // eslint-disable-line require-await
21
- let isUpgradeListenerAssigned = true;
22
22
  if (_.isUndefined(this.webSocketsMapping)) {
23
23
  this.webSocketsMapping = {};
24
- isUpgradeListenerAssigned = false;
24
+ // https://github.com/websockets/ws/pull/885
25
+ this.on('upgrade', (request, socket, head) => {
26
+ let currentPathname;
27
+ try {
28
+ currentPathname = (new URL(request.url)).pathname;
29
+ } catch (ign) {
30
+ currentPathname = request.url;
31
+ }
32
+ for (const [pathname, wsServer] of _.toPairs(this.webSocketsMapping)) {
33
+ if (currentPathname === pathname) {
34
+ wsServer.handleUpgrade(request, socket, head, (ws) => {
35
+ wsServer.emit('connection', ws, request);
36
+ });
37
+ return;
38
+ }
39
+ }
40
+ socket.destroy();
41
+ });
25
42
  }
26
43
  this.webSocketsMapping[handlerPathname] = handlerServer;
27
- if (isUpgradeListenerAssigned) {
28
- return;
29
- }
30
-
31
- // https://github.com/websockets/ws/pull/885
32
- this.on('upgrade', (request, socket, head) => {
33
- const currentPathname = url.parse(request.url).pathname;
34
- for (const [pathname, wsServer] of _.toPairs(this.webSocketsMapping)) {
35
- if (currentPathname === pathname) {
36
- wsServer.handleUpgrade(request, socket, head, (ws) => {
37
- wsServer.emit('connection', ws, request);
38
- });
39
- return;
40
- }
41
- }
42
- socket.destroy();
43
- });
44
44
  }
45
45
 
46
46
  /**
@@ -59,13 +59,12 @@ async function getWebSocketHandlers (keysFilter = null) { // eslint-disable-line
59
59
  return {};
60
60
  }
61
61
 
62
- let result = {};
63
- for (const [pathname, wsServer] of _.toPairs(this.webSocketsMapping)) {
62
+ return _.toPairs(this.webSocketsMapping).reduce((acc, [pathname, wsServer]) => {
64
63
  if (!_.isString(keysFilter) || pathname.includes(keysFilter)) {
65
- result[pathname] = wsServer;
64
+ acc[pathname] = wsServer;
66
65
  }
67
- }
68
- return result;
66
+ return acc;
67
+ }, {});
69
68
  }
70
69
 
71
70
  /**
@@ -79,12 +78,16 @@ async function getWebSocketHandlers (keysFilter = null) { // eslint-disable-line
79
78
  * @returns {boolean} true if the handlerPathname was found and deleted
80
79
  */
81
80
  async function removeWebSocketHandler (handlerPathname) { // eslint-disable-line require-await
82
- if (!this.webSocketsMapping || !this.webSocketsMapping[handlerPathname]) {
81
+ const wsServer = this.webSocketsMapping?.[handlerPathname];
82
+ if (!wsServer) {
83
83
  return false;
84
84
  }
85
85
 
86
86
  try {
87
- this.webSocketsMapping[handlerPathname].close();
87
+ wsServer.close();
88
+ for (const client of (wsServer.clients || [])) {
89
+ client.terminate();
90
+ }
88
91
  return true;
89
92
  } catch (ign) {
90
93
  // ignore
@@ -106,11 +109,11 @@ async function removeAllWebSocketHandlers () {
106
109
  return false;
107
110
  }
108
111
 
109
- let result = false;
110
- for (const pathname of _.keys(this.webSocketsMapping)) {
111
- result = result || await this.removeWebSocketHandler(pathname);
112
- }
113
- return result;
112
+ return _.some(
113
+ await B.all(
114
+ _.keys(this.webSocketsMapping).map((pathname) => this.removeWebSocketHandler(pathname))
115
+ )
116
+ );
114
117
  }
115
118
 
116
119
  export {
@@ -1,3 +1,5 @@
1
+ // @ts-check
2
+
1
3
  import _ from 'lodash';
2
4
 
3
5
  function isW3cCaps (caps) {
@@ -20,6 +22,63 @@ function isW3cCaps (caps) {
20
22
  return false;
21
23
  }
22
24
 
25
+ /**
26
+ *
27
+ * @param {Capabilities} originalCaps
28
+ * @param {Constraints} desiredCapConstraints
29
+ * @param {AppiumLogger} log
30
+ * @returns {Capabilities}
31
+ */
32
+ function fixCaps (originalCaps, desiredCapConstraints, log) {
33
+ let caps = _.clone(originalCaps);
34
+
35
+ // boolean capabilities can be passed in as strings 'false' and 'true'
36
+ // which we want to translate into boolean values
37
+ let booleanCaps = _.keys(
38
+ _.pickBy(desiredCapConstraints, (k) => k.isBoolean === true),
39
+ );
40
+ for (let cap of booleanCaps) {
41
+ let value = originalCaps[cap];
42
+ if (_.isString(value)) {
43
+ value = value.toLowerCase();
44
+ if (value === 'true' || value === 'false') {
45
+ log.warn(
46
+ `Capability '${cap}' changed from string to boolean. This may cause unexpected behavior`,
47
+ );
48
+ caps[cap] = value === 'true';
49
+ }
50
+ }
51
+ }
52
+
53
+ // int capabilities are often sent in as strings by frameworks
54
+ let intCaps = _.keys(
55
+ _.pickBy(desiredCapConstraints, (k) => k.isNumber === true),
56
+ );
57
+ for (let cap of intCaps) {
58
+ let value = originalCaps[cap];
59
+ if (_.isString(value)) {
60
+ value = value.trim();
61
+ let newValue = parseInt(value, 10);
62
+ if (value !== `${newValue}`) {
63
+ newValue = parseFloat(value);
64
+ }
65
+ log.warn(
66
+ `Capability '${cap}' changed from string ('${value}') to integer (${newValue}). This may cause unexpected behavior`,
67
+ );
68
+ caps[cap] = newValue;
69
+ }
70
+ }
71
+
72
+ return caps;
73
+ }
74
+
23
75
  export {
24
76
  isW3cCaps,
25
- };
77
+ fixCaps
78
+ };
79
+
80
+ /**
81
+ * @typedef {import('@appium/types').Capabilities} Capabilities
82
+ * @typedef {import('@appium/types').Constraints} Constraints
83
+ * @typedef {import('@appium/types').AppiumLogger} AppiumLogger
84
+ */
package/lib/index.js CHANGED
@@ -1,11 +1,15 @@
1
- // transpile:main
1
+ // @ts-check
2
2
 
3
- // BaseDriver exports
4
- import * as driver from './basedriver/driver';
5
- import * as deviceSettings from './basedriver/device-settings';
3
+ import B from 'bluebird';
4
+
5
+ B.config({
6
+ cancellation: true,
7
+ });
6
8
 
7
- const { BaseDriver } = driver;
8
- const { DeviceSettings } = deviceSettings;
9
+ // BaseDriver exports
10
+ import { BaseDriver } from './basedriver/driver';
11
+ export { DriverCore } from './basedriver/core';
12
+ import { DeviceSettings } from './basedriver/device-settings';
9
13
 
10
14
  export { BaseDriver, DeviceSettings };
11
15
  export default BaseDriver;
@@ -18,19 +22,19 @@ import {
18
22
  } from './constants';
19
23
 
20
24
  const {
21
- Protocol, routeConfiguringFunction, errors, isErrorType,
25
+ routeConfiguringFunction, errors, isErrorType,
22
26
  errorFromMJSONWPStatusCode, errorFromW3CJsonCode, ALL_COMMANDS, METHOD_MAP,
23
27
  routeToCommandName, NO_SESSION_ID_COMMANDS, isSessionCommand,
24
- normalizeBasePath, determineProtocol, CREATE_SESSION_COMMAND,
28
+ determineProtocol, CREATE_SESSION_COMMAND,
25
29
  DELETE_SESSION_COMMAND, GET_STATUS_COMMAND,
26
30
  } = protocol;
27
31
 
28
32
  export {
29
- Protocol, routeConfiguringFunction, errors, isErrorType, PROTOCOLS,
33
+ routeConfiguringFunction, errors, isErrorType, PROTOCOLS,
30
34
  errorFromMJSONWPStatusCode, errorFromW3CJsonCode, determineProtocol,
31
35
  errorFromMJSONWPStatusCode as errorFromCode, ALL_COMMANDS, METHOD_MAP,
32
36
  routeToCommandName, NO_SESSION_ID_COMMANDS, isSessionCommand,
33
- DEFAULT_BASE_PATH, normalizeBasePath, CREATE_SESSION_COMMAND,
37
+ DEFAULT_BASE_PATH, CREATE_SESSION_COMMAND,
34
38
  DELETE_SESSION_COMMAND, GET_STATUS_COMMAND,
35
39
  };
36
40
 
@@ -40,8 +44,8 @@ const { STATIC_DIR } = staticIndex;
40
44
  export { STATIC_DIR };
41
45
 
42
46
  import * as serverIndex from './express/server';
43
- const { server } = serverIndex;
44
- export { server };
47
+ const { server, normalizeBasePath } = serverIndex;
48
+ export { server, normalizeBasePath };
45
49
 
46
50
  // jsonwp-proxy exports
47
51
  import * as proxyIndex from './jsonwp-proxy/proxy';
@@ -3,7 +3,8 @@ import { logger, util } from '@appium/support';
3
3
  import axios from 'axios';
4
4
  import { getSummaryByCode } from '../jsonwp-status/status';
5
5
  import {
6
- errors, isErrorType, errorFromMJSONWPStatusCode, errorFromW3CJsonCode
6
+ errors, isErrorType, errorFromMJSONWPStatusCode, errorFromW3CJsonCode,
7
+ getResponseForW3CError,
7
8
  } from '../protocol/errors';
8
9
  import { routeToCommandName } from '../protocol';
9
10
  import { MAX_LOG_BODY_LENGTH, DEFAULT_BASE_PATH, PROTOCOLS } from '../constants';
@@ -312,15 +313,34 @@ class JWProxy {
312
313
  }
313
314
 
314
315
  async proxyReqRes (req, res) {
315
- const [response, resBodyObj] = await this.proxyCommand(req.originalUrl, req.method, req.body);
316
+ // ! this method must not throw any exceptions
317
+ // ! make sure to call res.send before return
318
+ let statusCode;
319
+ let resBodyObj;
320
+ try {
321
+ let response;
322
+ [response, resBodyObj] = await this.proxyCommand(req.originalUrl, req.method, req.body);
323
+ res.headers = response.headers;
324
+ statusCode = response.statusCode;
325
+ } catch (err) {
326
+ [statusCode, resBodyObj] = getResponseForW3CError(
327
+ isErrorType(err, errors.ProxyRequestError) ? err.getActualError() : err
328
+ );
329
+ }
330
+ res.set('content-type', 'application/json; charset=utf-8');
331
+ if (!_.isPlainObject(resBodyObj)) {
332
+ const error = new errors.UnknownError(
333
+ `The downstream server response with the status code ${statusCode} is not a valid JSON object: ` +
334
+ _.truncate(`${resBodyObj}`, {length: 300})
335
+ );
336
+ [statusCode, resBodyObj] = getResponseForW3CError(error);
337
+ }
316
338
 
317
- res.headers = response.headers;
318
- res.set('content-type', response.headers['content-type']);
319
339
  // if the proxied response contains a sessionId that the downstream
320
340
  // driver has generated, we don't want to return that to the client.
321
341
  // Instead, return the id from the request or from current session
322
- const reqSessionId = this.getSessionIdFromUrl(req.originalUrl);
323
342
  if (_.has(resBodyObj, 'sessionId')) {
343
+ const reqSessionId = this.getSessionIdFromUrl(req.originalUrl);
324
344
  if (reqSessionId) {
325
345
  this.log.info(`Replacing sessionId ${resBodyObj.sessionId} with ${reqSessionId}`);
326
346
  resBodyObj.sessionId = reqSessionId;
@@ -330,7 +350,7 @@ class JWProxy {
330
350
  }
331
351
  }
332
352
  resBodyObj.value = formatResponseValue(resBodyObj.value);
333
- res.status(response.statusCode).send(JSON.stringify(formatStatus(resBodyObj)));
353
+ res.status(statusCode).send(JSON.stringify(formatStatus(resBodyObj)));
334
354
  }
335
355
  }
336
356
 
@@ -9,7 +9,7 @@ const w3cLog = logger.getLogger('W3C');
9
9
  const W3C_UNKNOWN_ERROR = 'unknown error';
10
10
 
11
11
  // base error class for all of our errors
12
- class ProtocolError extends ES6Error {
12
+ export class ProtocolError extends ES6Error {
13
13
  constructor (msg, jsonwpCode, w3cStatus, error) {
14
14
  super(msg);
15
15
  this.jsonwpCode = jsonwpCode;
@@ -34,7 +34,7 @@ class ProtocolError extends ES6Error {
34
34
  // https://github.com/SeleniumHQ/selenium/issues/5562#issuecomment-370379470
35
35
  // https://w3c.github.io/webdriver/webdriver-spec.html#dfn-error-code
36
36
 
37
- class NoSuchDriverError extends ProtocolError {
37
+ export class NoSuchDriverError extends ProtocolError {
38
38
  static code () {
39
39
  return 6;
40
40
  }
@@ -51,7 +51,7 @@ class NoSuchDriverError extends ProtocolError {
51
51
  }
52
52
  }
53
53
 
54
- class NoSuchElementError extends ProtocolError {
54
+ export class NoSuchElementError extends ProtocolError {
55
55
  static code () {
56
56
  return 7;
57
57
  }
@@ -68,7 +68,7 @@ class NoSuchElementError extends ProtocolError {
68
68
  }
69
69
  }
70
70
 
71
- class NoSuchFrameError extends ProtocolError {
71
+ export class NoSuchFrameError extends ProtocolError {
72
72
  static code () {
73
73
  return 8;
74
74
  }
@@ -85,7 +85,7 @@ class NoSuchFrameError extends ProtocolError {
85
85
  }
86
86
  }
87
87
 
88
- class UnknownCommandError extends ProtocolError {
88
+ export class UnknownCommandError extends ProtocolError {
89
89
  static code () {
90
90
  return 9;
91
91
  }
@@ -102,7 +102,7 @@ class UnknownCommandError extends ProtocolError {
102
102
  }
103
103
  }
104
104
 
105
- class StaleElementReferenceError extends ProtocolError {
105
+ export class StaleElementReferenceError extends ProtocolError {
106
106
  static code () {
107
107
  return 10;
108
108
  }
@@ -119,7 +119,7 @@ class StaleElementReferenceError extends ProtocolError {
119
119
  }
120
120
  }
121
121
 
122
- class ElementNotVisibleError extends ProtocolError {
122
+ export class ElementNotVisibleError extends ProtocolError {
123
123
  static code () {
124
124
  return 11;
125
125
  }
@@ -136,7 +136,7 @@ class ElementNotVisibleError extends ProtocolError {
136
136
  }
137
137
  }
138
138
 
139
- class InvalidElementStateError extends ProtocolError {
139
+ export class InvalidElementStateError extends ProtocolError {
140
140
  static code () {
141
141
  return 12;
142
142
  }
@@ -154,7 +154,7 @@ class InvalidElementStateError extends ProtocolError {
154
154
  }
155
155
  }
156
156
 
157
- class UnknownError extends ProtocolError {
157
+ export class UnknownError extends ProtocolError {
158
158
  static code () {
159
159
  return 13;
160
160
  }
@@ -174,7 +174,7 @@ class UnknownError extends ProtocolError {
174
174
  }
175
175
  }
176
176
 
177
- class UnknownMethodError extends ProtocolError {
177
+ export class UnknownMethodError extends ProtocolError {
178
178
  static code () {
179
179
  return 405;
180
180
  }
@@ -190,7 +190,7 @@ class UnknownMethodError extends ProtocolError {
190
190
  }
191
191
  }
192
192
 
193
- class UnsupportedOperationError extends ProtocolError {
193
+ export class UnsupportedOperationError extends ProtocolError {
194
194
  static code () {
195
195
  return 405;
196
196
  }
@@ -207,7 +207,7 @@ class UnsupportedOperationError extends ProtocolError {
207
207
  }
208
208
  }
209
209
 
210
- class ElementIsNotSelectableError extends ProtocolError {
210
+ export class ElementIsNotSelectableError extends ProtocolError {
211
211
  static code () {
212
212
  return 15;
213
213
  }
@@ -224,7 +224,7 @@ class ElementIsNotSelectableError extends ProtocolError {
224
224
  }
225
225
  }
226
226
 
227
- class ElementClickInterceptedError extends ProtocolError {
227
+ export class ElementClickInterceptedError extends ProtocolError {
228
228
  static code () {
229
229
  return 64;
230
230
  }
@@ -242,7 +242,7 @@ class ElementClickInterceptedError extends ProtocolError {
242
242
  }
243
243
  }
244
244
 
245
- class ElementNotInteractableError extends ProtocolError {
245
+ export class ElementNotInteractableError extends ProtocolError {
246
246
  static code () {
247
247
  return 60;
248
248
  }
@@ -259,7 +259,7 @@ class ElementNotInteractableError extends ProtocolError {
259
259
  }
260
260
  }
261
261
 
262
- class InsecureCertificateError extends ProtocolError {
262
+ export class InsecureCertificateError extends ProtocolError {
263
263
  static error () {
264
264
  return 'insecure certificate';
265
265
  }
@@ -269,7 +269,7 @@ class InsecureCertificateError extends ProtocolError {
269
269
  }
270
270
  }
271
271
 
272
- class JavaScriptError extends ProtocolError {
272
+ export class JavaScriptError extends ProtocolError {
273
273
  static code () {
274
274
  return 17;
275
275
  }
@@ -285,7 +285,7 @@ class JavaScriptError extends ProtocolError {
285
285
  }
286
286
  }
287
287
 
288
- class XPathLookupError extends ProtocolError {
288
+ export class XPathLookupError extends ProtocolError {
289
289
  static code () {
290
290
  return 19;
291
291
  }
@@ -301,7 +301,7 @@ class XPathLookupError extends ProtocolError {
301
301
  }
302
302
  }
303
303
 
304
- class TimeoutError extends ProtocolError {
304
+ export class TimeoutError extends ProtocolError {
305
305
  static code () {
306
306
  return 21;
307
307
  }
@@ -317,7 +317,7 @@ class TimeoutError extends ProtocolError {
317
317
  }
318
318
  }
319
319
 
320
- class NoSuchWindowError extends ProtocolError {
320
+ export class NoSuchWindowError extends ProtocolError {
321
321
  static code () {
322
322
  return 23;
323
323
  }
@@ -334,7 +334,7 @@ class NoSuchWindowError extends ProtocolError {
334
334
  }
335
335
  }
336
336
 
337
- class InvalidArgumentError extends ProtocolError {
337
+ export class InvalidArgumentError extends ProtocolError {
338
338
  static code () {
339
339
  return 61;
340
340
  }
@@ -351,7 +351,7 @@ class InvalidArgumentError extends ProtocolError {
351
351
  }
352
352
  }
353
353
 
354
- class InvalidCookieDomainError extends ProtocolError {
354
+ export class InvalidCookieDomainError extends ProtocolError {
355
355
  static code () {
356
356
  return 24;
357
357
  }
@@ -368,7 +368,7 @@ class InvalidCookieDomainError extends ProtocolError {
368
368
  }
369
369
  }
370
370
 
371
- class NoSuchCookieError extends ProtocolError {
371
+ export class NoSuchCookieError extends ProtocolError {
372
372
  static code () {
373
373
  return 62;
374
374
  }
@@ -384,7 +384,7 @@ class NoSuchCookieError extends ProtocolError {
384
384
  }
385
385
  }
386
386
 
387
- class UnableToSetCookieError extends ProtocolError {
387
+ export class UnableToSetCookieError extends ProtocolError {
388
388
  static code () {
389
389
  return 25;
390
390
  }
@@ -400,7 +400,7 @@ class UnableToSetCookieError extends ProtocolError {
400
400
  }
401
401
  }
402
402
 
403
- class UnexpectedAlertOpenError extends ProtocolError {
403
+ export class UnexpectedAlertOpenError extends ProtocolError {
404
404
  static code () {
405
405
  return 26;
406
406
  }
@@ -416,7 +416,7 @@ class UnexpectedAlertOpenError extends ProtocolError {
416
416
  }
417
417
  }
418
418
 
419
- class NoAlertOpenError extends ProtocolError {
419
+ export class NoAlertOpenError extends ProtocolError {
420
420
  static code () {
421
421
  return 27;
422
422
  }
@@ -432,9 +432,9 @@ class NoAlertOpenError extends ProtocolError {
432
432
  }
433
433
  }
434
434
 
435
- class NoSuchAlertError extends NoAlertOpenError {}
435
+ export class NoSuchAlertError extends NoAlertOpenError {}
436
436
 
437
- class ScriptTimeoutError extends ProtocolError {
437
+ export class ScriptTimeoutError extends ProtocolError {
438
438
  static code () {
439
439
  return 28;
440
440
  }
@@ -450,7 +450,7 @@ class ScriptTimeoutError extends ProtocolError {
450
450
  }
451
451
  }
452
452
 
453
- class InvalidElementCoordinatesError extends ProtocolError {
453
+ export class InvalidElementCoordinatesError extends ProtocolError {
454
454
  static code () {
455
455
  return 29;
456
456
  }
@@ -467,9 +467,9 @@ class InvalidElementCoordinatesError extends ProtocolError {
467
467
  }
468
468
  }
469
469
 
470
- class InvalidCoordinatesError extends InvalidElementCoordinatesError {}
470
+ export class InvalidCoordinatesError extends InvalidElementCoordinatesError {}
471
471
 
472
- class IMENotAvailableError extends ProtocolError {
472
+ export class IMENotAvailableError extends ProtocolError {
473
473
  static code () {
474
474
  return 30;
475
475
  }
@@ -485,7 +485,7 @@ class IMENotAvailableError extends ProtocolError {
485
485
  }
486
486
  }
487
487
 
488
- class IMEEngineActivationFailedError extends ProtocolError {
488
+ export class IMEEngineActivationFailedError extends ProtocolError {
489
489
  static code () {
490
490
  return 31;
491
491
  }
@@ -502,7 +502,7 @@ class IMEEngineActivationFailedError extends ProtocolError {
502
502
  }
503
503
  }
504
504
 
505
- class InvalidSelectorError extends ProtocolError {
505
+ export class InvalidSelectorError extends ProtocolError {
506
506
  static code () {
507
507
  return 32;
508
508
  }
@@ -519,7 +519,7 @@ class InvalidSelectorError extends ProtocolError {
519
519
  }
520
520
  }
521
521
 
522
- class SessionNotCreatedError extends ProtocolError {
522
+ export class SessionNotCreatedError extends ProtocolError {
523
523
  static code () {
524
524
  return 33;
525
525
  }
@@ -539,7 +539,7 @@ class SessionNotCreatedError extends ProtocolError {
539
539
  }
540
540
  }
541
541
 
542
- class MoveTargetOutOfBoundsError extends ProtocolError {
542
+ export class MoveTargetOutOfBoundsError extends ProtocolError {
543
543
  static code () {
544
544
  return 34;
545
545
  }
@@ -555,7 +555,7 @@ class MoveTargetOutOfBoundsError extends ProtocolError {
555
555
  }
556
556
  }
557
557
 
558
- class NoSuchContextError extends ProtocolError {
558
+ export class NoSuchContextError extends ProtocolError {
559
559
  static code () {
560
560
  return 35;
561
561
  }
@@ -564,7 +564,7 @@ class NoSuchContextError extends ProtocolError {
564
564
  }
565
565
  }
566
566
 
567
- class InvalidContextError extends ProtocolError {
567
+ export class InvalidContextError extends ProtocolError {
568
568
  static code () {
569
569
  return 36;
570
570
  }
@@ -575,18 +575,18 @@ class InvalidContextError extends ProtocolError {
575
575
  }
576
576
 
577
577
  // These are aliases for UnknownMethodError
578
- class NotYetImplementedError extends UnknownMethodError {
578
+ export class NotYetImplementedError extends UnknownMethodError {
579
579
  constructor (err) {
580
580
  super(err || 'Method has not yet been implemented');
581
581
  }
582
582
  }
583
- class NotImplementedError extends UnknownMethodError {
583
+ export class NotImplementedError extends UnknownMethodError {
584
584
  constructor (err) {
585
585
  super(err || 'Method is not implemented');
586
586
  }
587
587
  }
588
588
 
589
- class UnableToCaptureScreen extends ProtocolError {
589
+ export class UnableToCaptureScreen extends ProtocolError {
590
590
  static code () {
591
591
  return 63;
592
592
  }
@@ -604,7 +604,7 @@ class UnableToCaptureScreen extends ProtocolError {
604
604
 
605
605
 
606
606
  // Equivalent to W3C InvalidArgumentError
607
- class BadParametersError extends ES6Error {
607
+ export class BadParametersError extends ES6Error {
608
608
  static error () {
609
609
  return 'invalid argument';
610
610
  }
@@ -628,7 +628,7 @@ class BadParametersError extends ES6Error {
628
628
  * In case of ProxyRequestError should fetch the actual error by calling `getActualError()`
629
629
  * for proxy failure to generate the client response.
630
630
  */
631
- class ProxyRequestError extends ES6Error {
631
+ export class ProxyRequestError extends ES6Error {
632
632
  constructor (err, responseError, httpStatus) {
633
633
  let responseErrorObj = util.safeJsonParse(responseError);
634
634
  if (!_.isPlainObject(responseErrorObj)) {
@@ -864,7 +864,7 @@ function getResponseForJsonwpError (err) {
864
864
  }
865
865
 
866
866
  export {
867
- ProtocolError, errors, isErrorType, isUnknownError,
867
+ errors, isErrorType, isUnknownError,
868
868
  errorFromMJSONWPStatusCode, errorFromW3CJsonCode,
869
869
  getResponseForW3CError, getResponseForJsonwpError,
870
870
  };
@@ -1,8 +1,8 @@
1
1
  // transpile:main
2
2
 
3
3
  import {
4
- Protocol, isSessionCommand, routeConfiguringFunction, determineProtocol,
5
- CREATE_SESSION_COMMAND, DELETE_SESSION_COMMAND,
4
+ isSessionCommand, routeConfiguringFunction, determineProtocol,
5
+ CREATE_SESSION_COMMAND, DELETE_SESSION_COMMAND, GET_STATUS_COMMAND
6
6
  } from './protocol';
7
7
  import {
8
8
  NO_SESSION_ID_COMMANDS, ALL_COMMANDS, METHOD_MAP,
@@ -13,8 +13,8 @@ import {
13
13
  } from './errors';
14
14
 
15
15
  export {
16
- Protocol, routeConfiguringFunction, errors, isErrorType,
16
+ routeConfiguringFunction, errors, isErrorType,
17
17
  errorFromMJSONWPStatusCode, errorFromW3CJsonCode, ALL_COMMANDS, METHOD_MAP,
18
18
  routeToCommandName, NO_SESSION_ID_COMMANDS, isSessionCommand, determineProtocol,
19
- CREATE_SESSION_COMMAND, DELETE_SESSION_COMMAND,
19
+ CREATE_SESSION_COMMAND, DELETE_SESSION_COMMAND, GET_STATUS_COMMAND
20
20
  };