@appium/base-driver 8.5.3 → 8.5.6

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 (141) hide show
  1. package/build/lib/basedriver/capabilities.d.ts.map +1 -1
  2. package/build/lib/basedriver/capabilities.js +1 -1
  3. package/build/lib/basedriver/commands/event.js +1 -1
  4. package/build/lib/basedriver/commands/find.d.ts.map +1 -1
  5. package/build/lib/basedriver/commands/find.js +1 -1
  6. package/build/lib/basedriver/commands/index.js +1 -1
  7. package/build/lib/basedriver/commands/log.d.ts.map +1 -1
  8. package/build/lib/basedriver/commands/log.js +1 -1
  9. package/build/lib/basedriver/commands/session.js +1 -1
  10. package/build/lib/basedriver/commands/settings.d.ts.map +1 -1
  11. package/build/lib/basedriver/commands/settings.js +1 -1
  12. package/build/lib/basedriver/commands/timeout.d.ts.map +1 -1
  13. package/build/lib/basedriver/commands/timeout.js +1 -1
  14. package/build/lib/basedriver/core.d.ts +120 -139
  15. package/build/lib/basedriver/core.d.ts.map +1 -1
  16. package/build/lib/basedriver/core.js +1 -49
  17. package/build/lib/basedriver/desired-caps.d.ts +5 -2
  18. package/build/lib/basedriver/desired-caps.d.ts.map +1 -1
  19. package/build/lib/basedriver/desired-caps.js +14 -18
  20. package/build/lib/basedriver/device-settings.d.ts +9 -9
  21. package/build/lib/basedriver/device-settings.d.ts.map +1 -1
  22. package/build/lib/basedriver/device-settings.js +4 -4
  23. package/build/lib/basedriver/driver.d.ts +43 -38
  24. package/build/lib/basedriver/driver.d.ts.map +1 -1
  25. package/build/lib/basedriver/driver.js +58 -11
  26. package/build/lib/basedriver/helpers.d.ts +8 -3
  27. package/build/lib/basedriver/helpers.d.ts.map +1 -1
  28. package/build/lib/basedriver/helpers.js +4 -6
  29. package/build/lib/basedriver/logger.d.ts +1 -1
  30. package/build/lib/basedriver/logger.d.ts.map +1 -1
  31. package/build/lib/basedriver/logger.js +1 -1
  32. package/build/lib/constants.js +1 -1
  33. package/build/lib/express/crash.d.ts.map +1 -1
  34. package/build/lib/express/crash.js +1 -1
  35. package/build/lib/express/express-logging.d.ts.map +1 -1
  36. package/build/lib/express/express-logging.js +1 -1
  37. package/build/lib/express/idempotency.js +1 -1
  38. package/build/lib/express/logger.d.ts +1 -1
  39. package/build/lib/express/logger.d.ts.map +1 -1
  40. package/build/lib/express/logger.js +1 -1
  41. package/build/lib/express/middleware.d.ts.map +1 -1
  42. package/build/lib/express/middleware.js +1 -1
  43. package/build/lib/express/server.d.ts +21 -0
  44. package/build/lib/express/server.d.ts.map +1 -1
  45. package/build/lib/express/server.js +4 -9
  46. package/build/lib/express/static.d.ts.map +1 -1
  47. package/build/lib/express/static.js +2 -2
  48. package/build/lib/express/websocket.d.ts +14 -11
  49. package/build/lib/express/websocket.d.ts.map +1 -1
  50. package/build/lib/express/websocket.js +2 -2
  51. package/build/lib/helpers/capabilities.d.ts.map +1 -1
  52. package/build/lib/helpers/capabilities.js +1 -1
  53. package/build/lib/index.d.ts +2 -1
  54. package/build/lib/index.js +7 -1
  55. package/build/lib/jsonwp-proxy/protocol-converter.d.ts.map +1 -1
  56. package/build/lib/jsonwp-proxy/protocol-converter.js +2 -2
  57. package/build/lib/jsonwp-proxy/proxy.d.ts +30 -5
  58. package/build/lib/jsonwp-proxy/proxy.d.ts.map +1 -1
  59. package/build/lib/jsonwp-proxy/proxy.js +23 -4
  60. package/build/lib/jsonwp-status/status.d.ts.map +1 -1
  61. package/build/lib/jsonwp-status/status.js +2 -2
  62. package/build/lib/protocol/errors.d.ts +17 -8
  63. package/build/lib/protocol/errors.d.ts.map +1 -1
  64. package/build/lib/protocol/errors.js +9 -5
  65. package/build/lib/protocol/helpers.js +1 -1
  66. package/build/lib/protocol/index.js +1 -1
  67. package/build/lib/protocol/protocol.d.ts.map +1 -1
  68. package/build/lib/protocol/protocol.js +1 -1
  69. package/build/lib/protocol/routes.d.ts +17 -3
  70. package/build/lib/protocol/routes.d.ts.map +1 -1
  71. package/build/lib/protocol/routes.js +1 -1
  72. package/build/lib/protocol/validators.js +1 -1
  73. package/build/test/basedriver/driver-e2e-tests.js +1 -1
  74. package/build/test/basedriver/driver-tests.js +1 -1
  75. package/build/test/basedriver/index.js +1 -1
  76. package/build/test/e2e/basedriver/driver.e2e.spec.js +1 -1
  77. package/build/test/e2e/basedriver/helpers.e2e.spec.js +1 -1
  78. package/build/test/e2e/basedriver/websockets.e2e.spec.js +1 -1
  79. package/build/test/e2e/express/server.e2e.spec.js +1 -1
  80. package/build/test/e2e/jsonwp-proxy/proxy.e2e.spec.js +1 -1
  81. package/build/test/e2e/protocol/fake-driver.js +1 -1
  82. package/build/test/e2e/protocol/helpers.js +1 -1
  83. package/build/test/e2e/protocol/protocol.e2e.spec.js +13 -13
  84. package/build/test/helpers.js +1 -1
  85. package/build/test/unit/basedriver/capabilities.spec.js +12 -12
  86. package/build/test/unit/basedriver/capability.spec.js +15 -15
  87. package/build/test/unit/basedriver/commands/event.spec.js +1 -1
  88. package/build/test/unit/basedriver/commands/log.spec.js +1 -1
  89. package/build/test/unit/basedriver/device-settings.spec.js +1 -1
  90. package/build/test/unit/basedriver/driver.spec.js +1 -1
  91. package/build/test/unit/basedriver/helpers.spec.js +33 -33
  92. package/build/test/unit/basedriver/timeout.spec.js +1 -1
  93. package/build/test/unit/express/server.spec.js +1 -1
  94. package/build/test/unit/express/static.spec.js +2 -2
  95. package/build/test/unit/jsonwp-proxy/mock-request.js +1 -1
  96. package/build/test/unit/jsonwp-proxy/protocol-converter.spec.js +1 -1
  97. package/build/test/unit/jsonwp-proxy/proxy.spec.js +2 -2
  98. package/build/test/unit/jsonwp-proxy/url.spec.js +1 -1
  99. package/build/test/unit/jsonwp-status/status.spec.js +1 -1
  100. package/build/test/unit/protocol/errors.spec.js +1 -1
  101. package/build/test/unit/protocol/routes.spec.js +1 -1
  102. package/build/test/unit/protocol/validator.spec.js +1 -1
  103. package/build/tsconfig.tsbuildinfo +1 -1
  104. package/lib/basedriver/capabilities.js +95 -47
  105. package/lib/basedriver/commands/event.js +4 -4
  106. package/lib/basedriver/commands/find.js +12 -26
  107. package/lib/basedriver/commands/index.js +7 -7
  108. package/lib/basedriver/commands/log.js +5 -7
  109. package/lib/basedriver/commands/session.js +3 -3
  110. package/lib/basedriver/commands/settings.js +3 -5
  111. package/lib/basedriver/commands/timeout.js +18 -23
  112. package/lib/basedriver/core.js +150 -229
  113. package/lib/basedriver/desired-caps.js +30 -29
  114. package/lib/basedriver/device-settings.js +21 -20
  115. package/lib/basedriver/driver.js +131 -96
  116. package/lib/basedriver/helpers.js +124 -81
  117. package/lib/basedriver/logger.js +1 -1
  118. package/lib/constants.js +2 -6
  119. package/lib/express/crash.js +4 -6
  120. package/lib/express/express-logging.js +26 -24
  121. package/lib/express/idempotency.js +16 -16
  122. package/lib/express/logger.js +1 -1
  123. package/lib/express/middleware.js +49 -33
  124. package/lib/express/server.js +68 -44
  125. package/lib/express/static.js +11 -12
  126. package/lib/express/websocket.js +26 -16
  127. package/lib/helpers/capabilities.js +11 -16
  128. package/lib/index.js +50 -33
  129. package/lib/jsonwp-proxy/protocol-converter.js +85 -69
  130. package/lib/jsonwp-proxy/proxy.js +132 -53
  131. package/lib/jsonwp-status/status.js +36 -29
  132. package/lib/protocol/errors.js +469 -292
  133. package/lib/protocol/helpers.js +5 -8
  134. package/lib/protocol/index.js +22 -15
  135. package/lib/protocol/protocol.js +103 -55
  136. package/lib/protocol/routes.js +430 -273
  137. package/lib/protocol/validators.js +5 -5
  138. package/package.json +7 -6
  139. package/test/basedriver/driver-e2e-tests.js +92 -66
  140. package/test/basedriver/driver-tests.js +90 -33
  141. package/test/basedriver/index.js +1 -1
@@ -1,30 +1,61 @@
1
1
  import _ from 'lodash';
2
- import { logger, util } from '@appium/support';
2
+ import {logger, util} from '@appium/support';
3
3
  import axios from 'axios';
4
- import { getSummaryByCode } from '../jsonwp-status/status';
4
+ import {getSummaryByCode} from '../jsonwp-status/status';
5
5
  import {
6
- errors, isErrorType, errorFromMJSONWPStatusCode, errorFromW3CJsonCode,
6
+ errors,
7
+ isErrorType,
8
+ errorFromMJSONWPStatusCode,
9
+ errorFromW3CJsonCode,
7
10
  getResponseForW3CError,
8
11
  } from '../protocol/errors';
9
- import { routeToCommandName } from '../protocol';
10
- import { MAX_LOG_BODY_LENGTH, DEFAULT_BASE_PATH, PROTOCOLS } from '../constants';
12
+ import {routeToCommandName} from '../protocol';
13
+ import {MAX_LOG_BODY_LENGTH, DEFAULT_BASE_PATH, PROTOCOLS} from '../constants';
11
14
  import ProtocolConverter from './protocol-converter';
12
- import { formatResponseValue, formatStatus } from '../protocol/helpers';
15
+ import {formatResponseValue, formatStatus} from '../protocol/helpers';
13
16
  import http from 'http';
14
17
  import https from 'https';
15
18
 
16
19
  const DEFAULT_LOG = logger.getLogger('WD Proxy');
17
20
  const DEFAULT_REQUEST_TIMEOUT = 240000;
18
- const COMPACT_ERROR_PATTERNS = [
19
- /\bECONNREFUSED\b/,
20
- /socket hang up/,
21
- ];
21
+ const COMPACT_ERROR_PATTERNS = [/\bECONNREFUSED\b/, /socket hang up/];
22
22
 
23
23
  const {MJSONWP, W3C} = PROTOCOLS;
24
24
 
25
+ const ALLOWED_OPTS = [
26
+ 'scheme',
27
+ 'server',
28
+ 'port',
29
+ 'base',
30
+ 'reqBasePath',
31
+ 'sessionId',
32
+ 'timeout',
33
+ 'log',
34
+ 'keepAlive',
35
+ ];
36
+
25
37
  class JWProxy {
26
- constructor (opts = {}) {
27
- _.defaults(this, opts, {
38
+ /** @type {string} */
39
+ scheme;
40
+ /** @type {string} */
41
+ server;
42
+ /** @type {number} */
43
+ port;
44
+ /** @type {string} */
45
+ base;
46
+ /** @type {string} */
47
+ reqBasePath;
48
+ /** @type {string?} */
49
+ sessionId;
50
+ /** @type {number} */
51
+ timeout;
52
+
53
+ constructor(opts = {}) {
54
+ opts = _.pick(opts, ALLOWED_OPTS);
55
+
56
+ // omit 'log' in the defaults assignment here because 'log' is a getter and we are going to set
57
+ // it to this._log (which lies behind the getter) further down
58
+ const options = _.defaults(_.omit(opts, 'log'), {
28
59
  scheme: 'http',
29
60
  server: 'localhost',
30
61
  port: 4444,
@@ -33,7 +64,9 @@ class JWProxy {
33
64
  sessionId: null,
34
65
  timeout: DEFAULT_REQUEST_TIMEOUT,
35
66
  });
36
- this.scheme = this.scheme.toLowerCase();
67
+ options.scheme = options.scheme.toLowerCase();
68
+ Object.assign(this, options);
69
+
37
70
  this._activeRequests = [];
38
71
  this._downstreamProtocol = null;
39
72
  const agentOpts = {
@@ -47,7 +80,7 @@ class JWProxy {
47
80
  this._log = opts.log;
48
81
  }
49
82
 
50
- get log () {
83
+ get log() {
51
84
  return this._log ?? DEFAULT_LOG;
52
85
  }
53
86
 
@@ -57,10 +90,10 @@ class JWProxy {
57
90
  * @private - Do not call this method directly,
58
91
  * it uses client-specific arguments and responses!
59
92
  *
60
- * @param {AxiosRequestConfig} requestConfig
61
- * @returns {AxiosResponse}
93
+ * @param {import('axios').AxiosRequestConfig} requestConfig
94
+ * @returns {Promise<import('axios').AxiosResponse>}
62
95
  */
63
- async request (requestConfig) {
96
+ async request(requestConfig) {
64
97
  const reqPromise = axios(requestConfig);
65
98
  this._activeRequests.push(reqPromise);
66
99
  try {
@@ -70,28 +103,28 @@ class JWProxy {
70
103
  }
71
104
  }
72
105
 
73
- getActiveRequestsCount () {
106
+ getActiveRequestsCount() {
74
107
  return this._activeRequests.length;
75
108
  }
76
109
 
77
- cancelActiveRequests () {
110
+ cancelActiveRequests() {
78
111
  this._activeRequests = [];
79
112
  }
80
113
 
81
- endpointRequiresSessionId (endpoint) {
114
+ endpointRequiresSessionId(endpoint) {
82
115
  return !_.includes(['/session', '/sessions', '/status'], endpoint);
83
116
  }
84
117
 
85
- set downstreamProtocol (value) {
118
+ set downstreamProtocol(value) {
86
119
  this._downstreamProtocol = value;
87
120
  this.protocolConverter.downstreamProtocol = value;
88
121
  }
89
122
 
90
- get downstreamProtocol () {
123
+ get downstreamProtocol() {
91
124
  return this._downstreamProtocol;
92
125
  }
93
126
 
94
- getUrlForProxy (url) {
127
+ getUrlForProxy(url) {
95
128
  if (url === '') {
96
129
  url = '/';
97
130
  }
@@ -99,12 +132,12 @@ class JWProxy {
99
132
  const endpointRe = '(/(session|status))';
100
133
  let remainingUrl = '';
101
134
  if (/^http/.test(url)) {
102
- const first = (new RegExp(`(https?://.+)${endpointRe}`)).exec(url);
135
+ const first = new RegExp(`(https?://.+)${endpointRe}`).exec(url);
103
136
  if (!first) {
104
137
  throw new Error('Got a complete url but could not extract JWP endpoint');
105
138
  }
106
139
  remainingUrl = url.replace(first[1], '');
107
- } else if ((new RegExp('^/')).test(url)) {
140
+ } else if (new RegExp('^/').test(url)) {
108
141
  remainingUrl = url;
109
142
  } else {
110
143
  throw new Error(`Did not know what to do with url '${url}'`);
@@ -112,10 +145,10 @@ class JWProxy {
112
145
 
113
146
  const stripPrefixRe = new RegExp('^.*?(/(session|status).*)$');
114
147
  if (stripPrefixRe.test(remainingUrl)) {
115
- remainingUrl = stripPrefixRe.exec(remainingUrl)[1];
148
+ remainingUrl = /** @type {RegExpExecArray} */ (stripPrefixRe.exec(remainingUrl))[1];
116
149
  }
117
150
 
118
- if (!(new RegExp(endpointRe)).test(remainingUrl)) {
151
+ if (!new RegExp(endpointRe).test(remainingUrl)) {
119
152
  remainingUrl = `/session/${this.sessionId}${remainingUrl}`;
120
153
  }
121
154
 
@@ -127,10 +160,20 @@ class JWProxy {
127
160
 
128
161
  const sessionBaseRe = new RegExp('^/session/([^/]+)');
129
162
  if (sessionBaseRe.test(remainingUrl)) {
163
+ if (this.sessionId === null) {
164
+ throw new ReferenceError(
165
+ `Session ID is not set, but saw a URL path referencing a session (${remainingUrl}). This may be a bug in your client.`
166
+ );
167
+ }
130
168
  // we have something like /session/:id/foobar, so we need to replace
131
169
  // the session id
132
170
  const match = sessionBaseRe.exec(remainingUrl);
133
- remainingUrl = remainingUrl.replace(match[1], this.sessionId);
171
+ // TODO: if `requiresSessionId` is `false` and `sessionId` is `null`, this is a bug.
172
+ // are we sure `sessionId` is not `null`?
173
+ remainingUrl = remainingUrl.replace(
174
+ /** @type {RegExpExecArray} */ (match)[1],
175
+ /** @type {string} */ (this.sessionId)
176
+ );
134
177
  } else if (requiresSessionId) {
135
178
  throw new Error(`Could not find :session section for url: ${remainingUrl}`);
136
179
  }
@@ -139,12 +182,14 @@ class JWProxy {
139
182
  return proxyBase + remainingUrl;
140
183
  }
141
184
 
142
- async proxy (url, method, body = null) {
185
+ async proxy(url, method, body = null) {
143
186
  method = method.toUpperCase();
144
187
  const newUrl = this.getUrlForProxy(url);
145
- const truncateBody = (content) => _.truncate(
146
- _.isString(content) ? content : JSON.stringify(content),
147
- { length: MAX_LOG_BODY_LENGTH });
188
+ const truncateBody = (content) =>
189
+ _.truncate(_.isString(content) ? content : JSON.stringify(content), {
190
+ length: MAX_LOG_BODY_LENGTH,
191
+ });
192
+ /** @type {import('axios').AxiosRequestConfig} */
148
193
  const reqOpts = {
149
194
  url: newUrl,
150
195
  method,
@@ -171,14 +216,16 @@ class JWProxy {
171
216
  }
172
217
  }
173
218
 
174
- this.log.debug(`Proxying [${method} ${url || '/'}] to [${method} ${newUrl}] ` +
175
- (reqOpts.data ? `with body: ${truncateBody(reqOpts.data)}` : 'with no body'));
219
+ this.log.debug(
220
+ `Proxying [${method} ${url || '/'}] to [${method} ${newUrl}] ` +
221
+ (reqOpts.data ? `with body: ${truncateBody(reqOpts.data)}` : 'with no body')
222
+ );
176
223
 
177
224
  const throwProxyError = (error) => {
178
- const err = new Error(`The request to ${url} has failed`);
225
+ const err = /** @type {ProxyError} */ (new Error(`The request to ${url} has failed`));
179
226
  err.response = {
180
227
  data: error,
181
- status: 500
228
+ status: 500,
182
229
  };
183
230
  throw err;
184
231
  };
@@ -216,9 +263,11 @@ class JWProxy {
216
263
  if (util.hasValue(e.response)) {
217
264
  if (!isResponseLogged) {
218
265
  const error = truncateBody(e.response.data);
219
- this.log.info(util.hasValue(e.response.status)
220
- ? `Got response with status ${e.response.status}: ${error}`
221
- : `Got response with unknown status: ${error}`);
266
+ this.log.info(
267
+ util.hasValue(e.response.status)
268
+ ? `Got response with status ${e.response.status}: ${error}`
269
+ : `Got response with unknown status: ${error}`
270
+ );
222
271
  }
223
272
  } else {
224
273
  proxyErrorMsg = `Could not proxy command to the remote server. Original error: ${e.message}`;
@@ -232,7 +281,7 @@ class JWProxy {
232
281
  }
233
282
  }
234
283
 
235
- getProtocolFromResBody (resObj) {
284
+ getProtocolFromResBody(resObj) {
236
285
  if (_.isInteger(resObj.status)) {
237
286
  return MJSONWP;
238
287
  }
@@ -241,14 +290,29 @@ class JWProxy {
241
290
  }
242
291
  }
243
292
 
244
- requestToCommandName (url, method) {
293
+ /**
294
+ *
295
+ * @param {string} url
296
+ * @param {import('@appium/types').HTTPMethod} method
297
+ * @returns {string|undefined}
298
+ */
299
+ requestToCommandName(url, method) {
300
+ /**
301
+ *
302
+ * @param {RegExp} pattern
303
+ * @returns {string|undefined}
304
+ */
245
305
  const extractCommandName = (pattern) => {
246
306
  const pathMatch = pattern.exec(url);
247
- return pathMatch ? routeToCommandName(pathMatch[1], method, this.reqBasePath) : null;
307
+ if (pathMatch) {
308
+ return routeToCommandName(pathMatch[1], method, this.reqBasePath);
309
+ }
248
310
  };
249
311
  let commandName = routeToCommandName(url, method, this.reqBasePath);
250
312
  if (!commandName && _.includes(url, `${this.reqBasePath}/session/`)) {
251
- commandName = extractCommandName(new RegExp(`${_.escapeRegExp(this.reqBasePath)}/session/[^/]+(.+)`));
313
+ commandName = extractCommandName(
314
+ new RegExp(`${_.escapeRegExp(this.reqBasePath)}/session/[^/]+(.+)`)
315
+ );
252
316
  }
253
317
  if (!commandName && _.includes(url, this.reqBasePath)) {
254
318
  commandName = extractCommandName(new RegExp(`${_.escapeRegExp(this.reqBasePath)}(/.+)`));
@@ -256,7 +320,7 @@ class JWProxy {
256
320
  return commandName;
257
321
  }
258
322
 
259
- async proxyCommand (url, method, body = null) {
323
+ async proxyCommand(url, method, body = null) {
260
324
  const commandName = this.requestToCommandName(url, method);
261
325
  if (!commandName) {
262
326
  return await this.proxy(url, method, body);
@@ -266,7 +330,7 @@ class JWProxy {
266
330
  return await this.protocolConverter.convertAndProxy(commandName, url, method, body);
267
331
  }
268
332
 
269
- async command (url, method, body = null) {
333
+ async command(url, method, body = null) {
270
334
  let response;
271
335
  let resBodyObj;
272
336
  try {
@@ -289,7 +353,10 @@ class JWProxy {
289
353
  if (_.has(message, 'message')) {
290
354
  message = message.message;
291
355
  }
292
- throw errorFromMJSONWPStatusCode(status, _.isEmpty(message) ? getSummaryByCode(status) : message);
356
+ throw errorFromMJSONWPStatusCode(
357
+ status,
358
+ _.isEmpty(message) ? getSummaryByCode(status) : message
359
+ );
293
360
  }
294
361
  } else if (protocol === W3C) {
295
362
  // Got response in W3C format
@@ -297,22 +364,30 @@ class JWProxy {
297
364
  return resBodyObj.value;
298
365
  }
299
366
  if (_.isPlainObject(resBodyObj.value) && resBodyObj.value.error) {
300
- throw errorFromW3CJsonCode(resBodyObj.value.error, resBodyObj.value.message, resBodyObj.value.stacktrace);
367
+ throw errorFromW3CJsonCode(
368
+ resBodyObj.value.error,
369
+ resBodyObj.value.message,
370
+ resBodyObj.value.stacktrace
371
+ );
301
372
  }
302
373
  } else if (response.statusCode === 200) {
303
374
  // Unknown protocol. Keeping it because of the backward compatibility
304
375
  return resBodyObj;
305
376
  }
306
- throw new errors.UnknownError(`Did not know what to do with response code '${response.statusCode}' ` +
307
- `and response body '${_.truncate(JSON.stringify(resBodyObj), {length: 300})}'`);
377
+ throw new errors.UnknownError(
378
+ `Did not know what to do with response code '${response.statusCode}' ` +
379
+ `and response body '${_.truncate(JSON.stringify(resBodyObj), {
380
+ length: 300,
381
+ })}'`
382
+ );
308
383
  }
309
384
 
310
- getSessionIdFromUrl (url) {
385
+ getSessionIdFromUrl(url) {
311
386
  const match = url.match(/\/session\/([^/]+)/);
312
387
  return match ? match[1] : null;
313
388
  }
314
389
 
315
- async proxyReqRes (req, res) {
390
+ async proxyReqRes(req, res) {
316
391
  // ! this method must not throw any exceptions
317
392
  // ! make sure to call res.send before return
318
393
  let statusCode;
@@ -331,7 +406,7 @@ class JWProxy {
331
406
  if (!_.isPlainObject(resBodyObj)) {
332
407
  const error = new errors.UnknownError(
333
408
  `The downstream server response with the status code ${statusCode} is not a valid JSON object: ` +
334
- _.truncate(`${resBodyObj}`, {length: 300})
409
+ _.truncate(`${resBodyObj}`, {length: 300})
335
410
  );
336
411
  [statusCode, resBodyObj] = getResponseForW3CError(error);
337
412
  }
@@ -354,5 +429,9 @@ class JWProxy {
354
429
  }
355
430
  }
356
431
 
357
- export { JWProxy };
432
+ export {JWProxy};
358
433
  export default JWProxy;
434
+
435
+ /**
436
+ * @typedef {Error & {response: {data: import('type-fest').JsonObject, status: import('http-status-codes').StatusCodes}}} ProxyError
437
+ */
@@ -3,111 +3,118 @@ import _ from 'lodash';
3
3
  const codes = {
4
4
  Success: {
5
5
  code: 0,
6
- summary: 'The command executed successfully.'
6
+ summary: 'The command executed successfully.',
7
7
  },
8
8
  NoSuchDriver: {
9
9
  code: 6,
10
- summary: 'A session is either terminated or not started'
10
+ summary: 'A session is either terminated or not started',
11
11
  },
12
12
  NoSuchElement: {
13
13
  code: 7,
14
- summary: 'An element could not be located on the page using the given search parameters.'
14
+ summary: 'An element could not be located on the page using the given search parameters.',
15
15
  },
16
16
  NoSuchFrame: {
17
17
  code: 8,
18
- summary: 'A request to switch to a frame could not be satisfied because the frame could not be found.'
18
+ summary:
19
+ 'A request to switch to a frame could not be satisfied because the frame could not be found.',
19
20
  },
20
21
  UnknownCommand: {
21
22
  code: 9,
22
- summary: 'The requested resource could not be found, or a request was received using an HTTP method that is not supported by the mapped resource.'
23
+ summary:
24
+ 'The requested resource could not be found, or a request was received using an HTTP method that is not supported by the mapped resource.',
23
25
  },
24
26
  StaleElementReference: {
25
27
  code: 10,
26
- summary: 'An element command failed because the referenced element is no longer attached to the DOM.'
28
+ summary:
29
+ 'An element command failed because the referenced element is no longer attached to the DOM.',
27
30
  },
28
31
  ElementNotVisible: {
29
32
  code: 11,
30
- summary: 'An element command could not be completed because the element is not visible on the page.'
33
+ summary:
34
+ 'An element command could not be completed because the element is not visible on the page.',
31
35
  },
32
36
  InvalidElementState: {
33
37
  code: 12,
34
- summary: 'An element command could not be completed because the element is in an invalid state (e.g. attempting to click a disabled element).'
38
+ summary:
39
+ 'An element command could not be completed because the element is in an invalid state (e.g. attempting to click a disabled element).',
35
40
  },
36
41
  UnknownError: {
37
42
  code: 13,
38
- summary: 'An unknown server-side error occurred while processing the command.'
43
+ summary: 'An unknown server-side error occurred while processing the command.',
39
44
  },
40
45
  ElementIsNotSelectable: {
41
46
  code: 15,
42
- summary: 'An attempt was made to select an element that cannot be selected.'
47
+ summary: 'An attempt was made to select an element that cannot be selected.',
43
48
  },
44
49
  JavaScriptError: {
45
50
  code: 17,
46
- summary: 'An error occurred while executing user supplied JavaScript.'
51
+ summary: 'An error occurred while executing user supplied JavaScript.',
47
52
  },
48
53
  XPathLookupError: {
49
54
  code: 19,
50
- summary: 'An error occurred while searching for an element by XPath.'
55
+ summary: 'An error occurred while searching for an element by XPath.',
51
56
  },
52
57
  Timeout: {
53
58
  code: 21,
54
- summary: 'An operation did not complete before its timeout expired.'
59
+ summary: 'An operation did not complete before its timeout expired.',
55
60
  },
56
61
  NoSuchWindow: {
57
62
  code: 23,
58
- summary: 'A request to switch to a different window could not be satisfied because the window could not be found.'
63
+ summary:
64
+ 'A request to switch to a different window could not be satisfied because the window could not be found.',
59
65
  },
60
66
  InvalidCookieDomain: {
61
67
  code: 24,
62
- summary: 'An illegal attempt was made to set a cookie under a different domain than the current page.'
68
+ summary:
69
+ 'An illegal attempt was made to set a cookie under a different domain than the current page.',
63
70
  },
64
71
  UnableToSetCookie: {
65
72
  code: 25,
66
- summary: 'A request to set a cookie\'s value could not be satisfied.'
73
+ summary: "A request to set a cookie's value could not be satisfied.",
67
74
  },
68
75
  UnexpectedAlertOpen: {
69
76
  code: 26,
70
- summary: 'A modal dialog was open, blocking this operation'
77
+ summary: 'A modal dialog was open, blocking this operation',
71
78
  },
72
79
  NoAlertOpenError: {
73
80
  code: 27,
74
- summary: 'An attempt was made to operate on a modal dialog when one was not open.'
81
+ summary: 'An attempt was made to operate on a modal dialog when one was not open.',
75
82
  },
76
83
  ScriptTimeout: {
77
84
  code: 28,
78
- summary: 'A script did not complete before its timeout expired.'
85
+ summary: 'A script did not complete before its timeout expired.',
79
86
  },
80
87
  InvalidElementCoordinates: {
81
88
  code: 29,
82
- summary: 'The coordinates provided to an interactions operation are invalid.'
89
+ summary: 'The coordinates provided to an interactions operation are invalid.',
83
90
  },
84
91
  IMENotAvailable: {
85
92
  code: 30,
86
- summary: 'IME was not available.'
93
+ summary: 'IME was not available.',
87
94
  },
88
95
  IMEEngineActivationFailed: {
89
96
  code: 31,
90
- summary: 'An IME engine could not be started.'
97
+ summary: 'An IME engine could not be started.',
91
98
  },
92
99
  InvalidSelector: {
93
100
  code: 32,
94
- summary: 'Argument was an invalid selector (e.g. XPath/CSS).'
101
+ summary: 'Argument was an invalid selector (e.g. XPath/CSS).',
95
102
  },
96
103
  SessionNotCreatedException: {
97
104
  code: 33,
98
- summary: 'A new session could not be created.'
105
+ summary: 'A new session could not be created.',
99
106
  },
100
107
  MoveTargetOutOfBounds: {
101
108
  code: 34,
102
- summary: 'Target provided for a move action is out of bounds.'
109
+ summary: 'Target provided for a move action is out of bounds.',
103
110
  },
104
111
  NoSuchContext: {
105
112
  code: 35,
106
- summary: 'No such context found.'
107
- }
113
+ summary: 'No such context found.',
114
+ },
108
115
  };
109
116
 
110
- function getSummaryByCode (code) {
117
+ function getSummaryByCode(code) {
111
118
  code = parseInt(code, 10);
112
119
  for (let obj of _.values(codes)) {
113
120
  if (!_.isUndefined(obj.code) && obj.code === code) {
@@ -118,4 +125,4 @@ function getSummaryByCode (code) {
118
125
  }
119
126
 
120
127
  export default codes;
121
- export { codes, getSummaryByCode };
128
+ export {codes, getSummaryByCode};