@appium/base-driver 8.5.2 → 8.5.5

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 +20 -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 +116 -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 +9 -11
  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,13 +1,16 @@
1
1
  import _ from 'lodash';
2
2
  import log from './logger';
3
- import { errors } from '../protocol';
4
- import { handleIdempotency } from './idempotency';
3
+ import {errors} from '../protocol';
4
+ import {handleIdempotency} from './idempotency';
5
5
 
6
- function allowCrossDomain (req, res, next) {
6
+ function allowCrossDomain(req, res, next) {
7
7
  try {
8
8
  res.header('Access-Control-Allow-Origin', '*');
9
9
  res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, OPTIONS, DELETE');
10
- res.header('Access-Control-Allow-Headers', 'Cache-Control, Pragma, Origin, X-Requested-With, Content-Type, Accept, User-Agent');
10
+ res.header(
11
+ 'Access-Control-Allow-Headers',
12
+ 'Cache-Control, Pragma, Origin, X-Requested-With, Content-Type, Accept, User-Agent'
13
+ );
11
14
 
12
15
  // need to respond 200 to OPTIONS
13
16
  if ('OPTIONS' === req.method) {
@@ -19,11 +22,13 @@ function allowCrossDomain (req, res, next) {
19
22
  next();
20
23
  }
21
24
 
22
- function allowCrossDomainAsyncExecute (basePath) {
25
+ function allowCrossDomainAsyncExecute(basePath) {
23
26
  return (req, res, next) => {
24
27
  // there are two paths for async responses, so cover both
25
28
  // https://regex101.com/r/txYiEz/1
26
- const receiveAsyncResponseRegExp = new RegExp(`${_.escapeRegExp(basePath)}/session/[a-f0-9-]+/(appium/)?receive_async_response`);
29
+ const receiveAsyncResponseRegExp = new RegExp(
30
+ `${_.escapeRegExp(basePath)}/session/[a-f0-9-]+/(appium/)?receive_async_response`
31
+ );
27
32
  if (!receiveAsyncResponseRegExp.test(req.url)) {
28
33
  return next();
29
34
  }
@@ -31,10 +36,13 @@ function allowCrossDomainAsyncExecute (basePath) {
31
36
  };
32
37
  }
33
38
 
34
- function fixPythonContentType (basePath) {
39
+ function fixPythonContentType(basePath) {
35
40
  return (req, res, next) => {
36
41
  // hack because python client library gives us wrong content-type
37
- if (new RegExp(`^${_.escapeRegExp(basePath)}`).test(req.path) && /^Python/.test(req.headers['user-agent'])) {
42
+ if (
43
+ new RegExp(`^${_.escapeRegExp(basePath)}`).test(req.path) &&
44
+ /^Python/.test(req.headers['user-agent'])
45
+ ) {
38
46
  if (req.headers['content-type'] === 'application/x-www-form-urlencoded') {
39
47
  req.headers['content-type'] = 'application/json; charset=utf-8';
40
48
  }
@@ -43,14 +51,14 @@ function fixPythonContentType (basePath) {
43
51
  };
44
52
  }
45
53
 
46
- function defaultToJSONContentType (req, res, next) {
54
+ function defaultToJSONContentType(req, res, next) {
47
55
  if (!req.headers['content-type']) {
48
56
  req.headers['content-type'] = 'application/json; charset=utf-8';
49
57
  }
50
58
  next();
51
59
  }
52
60
 
53
- function catchAllHandler (err, req, res, next) {
61
+ function catchAllHandler(err, req, res, next) {
54
62
  if (res.headersSent) {
55
63
  return next(err);
56
64
  }
@@ -58,36 +66,40 @@ function catchAllHandler (err, req, res, next) {
58
66
  log.error(`Uncaught error: ${err.message}`);
59
67
  log.error('Sending generic error response');
60
68
  const error = errors.UnknownError;
61
- res.status(error.w3cStatus()).json(patchWithSessionId(req, {
62
- status: error.code(),
63
- value: {
64
- error: error.error(),
65
- message: `An unknown server-side error occurred while processing the command: ${err.message}`,
66
- stacktrace: err.stack,
67
- }
68
- }));
69
+ res.status(error.w3cStatus()).json(
70
+ patchWithSessionId(req, {
71
+ status: error.code(),
72
+ value: {
73
+ error: error.error(),
74
+ message: `An unknown server-side error occurred while processing the command: ${err.message}`,
75
+ stacktrace: err.stack,
76
+ },
77
+ })
78
+ );
69
79
  log.error(err);
70
80
  }
71
81
 
72
- function catch404Handler (req, res) {
82
+ function catch404Handler(req, res) {
73
83
  log.debug(`No route found for ${req.url}`);
74
84
  const error = errors.UnknownCommandError;
75
- res.status(error.w3cStatus()).json(patchWithSessionId(req, {
76
- status: error.code(),
77
- value: {
78
- error: error.error(),
79
- message: 'The requested resource could not be found, or a request was ' +
80
- 'received using an HTTP method that is not supported by the mapped ' +
81
- 'resource',
82
- stacktrace: '',
83
- }
84
- }));
85
+ res.status(error.w3cStatus()).json(
86
+ patchWithSessionId(req, {
87
+ status: error.code(),
88
+ value: {
89
+ error: error.error(),
90
+ message:
91
+ 'The requested resource could not be found, or a request was ' +
92
+ 'received using an HTTP method that is not supported by the mapped ' +
93
+ 'resource',
94
+ stacktrace: '',
95
+ },
96
+ })
97
+ );
85
98
  }
86
99
 
87
-
88
100
  const SESSION_ID_PATTERN = /\/session\/([^/]+)/;
89
101
 
90
- function patchWithSessionId (req, body) {
102
+ function patchWithSessionId(req, body) {
91
103
  const match = SESSION_ID_PATTERN.exec(req.url);
92
104
  if (match) {
93
105
  body.sessionId = match[1];
@@ -96,7 +108,11 @@ function patchWithSessionId (req, body) {
96
108
  }
97
109
 
98
110
  export {
99
- allowCrossDomain, fixPythonContentType, defaultToJSONContentType,
100
- catchAllHandler, allowCrossDomainAsyncExecute, handleIdempotency,
111
+ allowCrossDomain,
112
+ fixPythonContentType,
113
+ defaultToJSONContentType,
114
+ catchAllHandler,
115
+ allowCrossDomainAsyncExecute,
116
+ handleIdempotency,
101
117
  catch404Handler,
102
118
  };
@@ -6,27 +6,31 @@ import favicon from 'serve-favicon';
6
6
  import bodyParser from 'body-parser';
7
7
  import methodOverride from 'method-override';
8
8
  import log from './logger';
9
- import { startLogFormatter, endLogFormatter } from './express-logging';
9
+ import {startLogFormatter, endLogFormatter} from './express-logging';
10
10
  import {
11
- allowCrossDomain, fixPythonContentType, defaultToJSONContentType,
12
- catchAllHandler, allowCrossDomainAsyncExecute, handleIdempotency,
11
+ allowCrossDomain,
12
+ fixPythonContentType,
13
+ defaultToJSONContentType,
14
+ catchAllHandler,
15
+ allowCrossDomainAsyncExecute,
16
+ handleIdempotency,
13
17
  catch404Handler,
14
18
  } from './middleware';
15
- import { guineaPig, guineaPigScrollable, guineaPigAppBanner, welcome, STATIC_DIR } from './static';
16
- import { produceError, produceCrash } from './crash';
19
+ import {guineaPig, guineaPigScrollable, guineaPigAppBanner, welcome, STATIC_DIR} from './static';
20
+ import {produceError, produceCrash} from './crash';
17
21
  import {
18
- addWebSocketHandler, removeWebSocketHandler, removeAllWebSocketHandlers,
19
- getWebSocketHandlers
22
+ addWebSocketHandler,
23
+ removeWebSocketHandler,
24
+ removeAllWebSocketHandlers,
25
+ getWebSocketHandlers,
20
26
  } from './websocket';
21
27
  import B from 'bluebird';
22
- import { DEFAULT_BASE_PATH } from '../constants';
23
- import { EventEmitter } from 'events';
24
-
28
+ import {DEFAULT_BASE_PATH} from '../constants';
29
+ import {EventEmitter} from 'events';
25
30
 
26
31
  const KEEP_ALIVE_TIMEOUT_MS = 10 * 60 * 1000; // 10 minutes
27
32
 
28
-
29
- async function server (opts = {}) {
33
+ async function server(opts = {}) {
30
34
  const {
31
35
  routeConfiguringFunction,
32
36
  port,
@@ -49,7 +53,13 @@ async function server (opts = {}) {
49
53
  // try/catch so any errors can be passed to reject.
50
54
  try {
51
55
  configureHttp({httpServer, reject, keepAliveTimeout});
52
- configureServer({app, addRoutes: routeConfiguringFunction, allowCors, basePath, extraMethodMap});
56
+ configureServer({
57
+ app,
58
+ addRoutes: routeConfiguringFunction,
59
+ allowCors,
60
+ basePath,
61
+ extraMethodMap,
62
+ });
53
63
  // allow extensions to update the app and http server objects
54
64
  for (const updater of serverUpdaters) {
55
65
  await updater(app, httpServer);
@@ -66,10 +76,9 @@ async function server (opts = {}) {
66
76
  reject(err);
67
77
  }
68
78
  });
69
-
70
79
  }
71
80
 
72
- function configureServer ({
81
+ function configureServer({
73
82
  app,
74
83
  addRoutes,
75
84
  allowCors = true,
@@ -116,7 +125,7 @@ function configureServer ({
116
125
  app.all('/test/guinea-pig-app-banner', guineaPigAppBanner);
117
126
  }
118
127
 
119
- function configureHttp ({httpServer, reject, keepAliveTimeout}) {
128
+ function configureHttp({httpServer, reject, keepAliveTimeout}) {
120
129
  const serverState = {
121
130
  notifier: new EventEmitter(),
122
131
  closed: false,
@@ -129,28 +138,32 @@ function configureHttp ({httpServer, reject, keepAliveTimeout}) {
129
138
  // http.Server.close() only stops new connections, but we need to wait until
130
139
  // all connections are closed and the `close` event is emitted
131
140
  const close = httpServer.close.bind(httpServer);
132
- httpServer.close = async () => await new B((resolve, reject) => {
133
- // https://github.com/nodejs/node-v0.x-archive/issues/9066#issuecomment-124210576
134
- serverState.closed = true;
135
- serverState.notifier.emit('shutdown');
136
- log.info('Waiting until the server is closed');
137
- httpServer.on('close', () => {
138
- log.info('Received server close event');
139
- resolve();
140
- });
141
- close((err) => {
142
- if (err) reject(err); // eslint-disable-line curly
141
+ httpServer.close = async () =>
142
+ await new B((resolve, reject) => {
143
+ // https://github.com/nodejs/node-v0.x-archive/issues/9066#issuecomment-124210576
144
+ serverState.closed = true;
145
+ serverState.notifier.emit('shutdown');
146
+ log.info('Waiting until the server is closed');
147
+ httpServer.on('close', () => {
148
+ log.info('Received server close event');
149
+ resolve();
150
+ });
151
+ close((err) => {
152
+ if (err) reject(err); // eslint-disable-line curly
153
+ });
143
154
  });
144
- });
145
155
 
146
156
  httpServer.on('error', (err) => {
147
157
  if (err.code === 'EADDRNOTAVAIL') {
148
- log.error('Could not start REST http interface listener. ' +
149
- 'Requested address is not available.');
158
+ log.error(
159
+ 'Could not start REST http interface listener. ' + 'Requested address is not available.'
160
+ );
150
161
  } else {
151
- log.error('Could not start REST http interface listener. The requested ' +
152
- 'port may already be in use. Please make sure there is no ' +
153
- 'other instance of this server running already.');
162
+ log.error(
163
+ 'Could not start REST http interface listener. The requested ' +
164
+ 'port may already be in use. Please make sure there is no ' +
165
+ 'other instance of this server running already.'
166
+ );
154
167
  }
155
168
  reject(err);
156
169
  });
@@ -159,7 +172,7 @@ function configureHttp ({httpServer, reject, keepAliveTimeout}) {
159
172
  socket.setTimeout(keepAliveTimeout);
160
173
  socket.on('error', reject);
161
174
 
162
- function destroy () {
175
+ function destroy() {
163
176
  socket.destroy();
164
177
  }
165
178
  socket._openReqCount = 0;
@@ -179,21 +192,23 @@ function configureHttp ({httpServer, reject, keepAliveTimeout}) {
179
192
  });
180
193
  }
181
194
 
182
- async function startServer ({httpServer, port, hostname, keepAliveTimeout}) {
183
- const serverArgs = [port];
184
- if (hostname) {
185
- // If the hostname is omitted, the server will accept
186
- // connections on any IP address
187
- serverArgs.push(hostname);
188
- }
189
- const startPromise = B.promisify(httpServer.listen, {context: httpServer})(...serverArgs);
195
+ /**
196
+ *
197
+ * @param {StartServerOpts} opts
198
+ */
199
+ async function startServer({httpServer, port, hostname, keepAliveTimeout}) {
200
+ // If the hostname is omitted, the server will accept
201
+ // connections on any IP address
202
+ /** @type {(port: number, hostname?: string) => B<http.Server>} */
203
+ const start = B.promisify(httpServer.listen, {context: httpServer});
204
+ const startPromise = start(port, hostname);
190
205
  httpServer.keepAliveTimeout = keepAliveTimeout;
191
206
  // headers timeout must be greater than keepAliveTimeout
192
207
  httpServer.headersTimeout = keepAliveTimeout + 5 * 1000;
193
208
  await startPromise;
194
209
  }
195
210
 
196
- function normalizeBasePath (basePath) {
211
+ function normalizeBasePath(basePath) {
197
212
  if (!_.isString(basePath)) {
198
213
  throw new Error(`Invalid path prefix ${basePath}`);
199
214
  }
@@ -211,4 +226,13 @@ function normalizeBasePath (basePath) {
211
226
  return basePath;
212
227
  }
213
228
 
214
- export { server, configureServer, normalizeBasePath };
229
+ export {server, configureServer, normalizeBasePath};
230
+
231
+ /**
232
+ * Options for {@linkcode startServer}.
233
+ * @typedef StartServerOpts
234
+ * @property {import('http').Server} httpServer - HTTP server instance
235
+ * @property {number} port - Port to run on
236
+ * @property {number} keepAliveTimeout - Keep-alive timeout in milliseconds
237
+ * @property {string} [hostname] - Optional hostname
238
+ */
@@ -1,10 +1,9 @@
1
1
  import path from 'path';
2
2
  import log from './logger';
3
3
  import _ from 'lodash';
4
- import { fs } from '@appium/support';
4
+ import {fs} from '@appium/support';
5
5
  import B from 'bluebird';
6
6
 
7
-
8
7
  let STATIC_DIR = path.resolve(__dirname, '..', '..', '..', 'static');
9
8
  if (_.isNull(path.resolve(__dirname).match(/build[/\\]lib[/\\]express$/))) {
10
9
  // in some contexts we are not in the build directory,
@@ -12,14 +11,14 @@ if (_.isNull(path.resolve(__dirname).match(/build[/\\]lib[/\\]express$/))) {
12
11
  STATIC_DIR = path.resolve(__dirname, '..', '..', 'static');
13
12
  }
14
13
 
15
- async function guineaPigTemplate (req, res, page) {
14
+ async function guineaPigTemplate(req, res, page) {
16
15
  const delay = parseInt(req.params.delay || req.query.delay || 0, 10);
17
16
  const throwError = req.params.throwError || req.query.throwError || '';
18
17
  let params = {
19
18
  throwError,
20
19
  serverTime: new Date(),
21
20
  userAgent: req.headers['user-agent'],
22
- comment: 'None'
21
+ comment: 'None',
23
22
  };
24
23
  if (req.method === 'POST') {
25
24
  params.comment = req.body.comments || params.comment;
@@ -34,7 +33,7 @@ async function guineaPigTemplate (req, res, page) {
34
33
  res.cookie('guineacookie2', 'cookié2', {path: '/'});
35
34
  res.cookie('guineacookie3', 'cant access this', {
36
35
  domain: '.blargimarg.com',
37
- path: '/'
36
+ path: '/',
38
37
  });
39
38
  res.send((await getTemplate(page))(params));
40
39
  }
@@ -42,36 +41,36 @@ async function guineaPigTemplate (req, res, page) {
42
41
  /*
43
42
  * Dynamic page mapped to /test/guinea-pig
44
43
  */
45
- async function guineaPig (req, res) {
44
+ async function guineaPig(req, res) {
46
45
  return await guineaPigTemplate(req, res, 'guinea-pig.html');
47
46
  }
48
47
 
49
48
  /*
50
49
  * Dynamic page mapped to /test/guinea-pig-scrollable
51
50
  */
52
- async function guineaPigScrollable (req, res) {
51
+ async function guineaPigScrollable(req, res) {
53
52
  return await guineaPigTemplate(req, res, 'guinea-pig-scrollable.html');
54
53
  }
55
54
 
56
55
  /*
57
56
  * Dynamic page mapped to /test/guinea-pig-app-banner
58
57
  */
59
- async function guineaPigAppBanner (req, res) {
58
+ async function guineaPigAppBanner(req, res) {
60
59
  return await guineaPigTemplate(req, res, 'guinea-pig-app-banner.html');
61
60
  }
62
61
 
63
62
  /*
64
63
  * Dynamic page mapped to /welcome
65
64
  */
66
- async function welcome (req, res) {
67
- let params = {message: 'Let\'s browse!'};
65
+ async function welcome(req, res) {
66
+ let params = {message: "Let's browse!"};
68
67
  log.debug(`Sending welcome response with params: ${JSON.stringify(params)}`);
69
68
  res.send((await getTemplate('welcome.html'))(params));
70
69
  }
71
70
 
72
- async function getTemplate (templateName) {
71
+ async function getTemplate(templateName) {
73
72
  let content = await fs.readFile(path.resolve(STATIC_DIR, 'test', templateName));
74
73
  return _.template(content.toString());
75
74
  }
76
75
 
77
- export { guineaPig, guineaPigScrollable, guineaPigAppBanner, welcome, STATIC_DIR };
76
+ export {guineaPig, guineaPigScrollable, guineaPigAppBanner, welcome, STATIC_DIR};
@@ -1,16 +1,15 @@
1
1
  import _ from 'lodash';
2
- import { URL } from 'url';
2
+ import {URL} from 'url';
3
3
  import B from 'bluebird';
4
4
 
5
5
  const DEFAULT_WS_PATHNAME_PREFIX = '/ws';
6
6
 
7
-
8
7
  /**
9
8
  * Adds websocket handler to express server instance.
10
9
  * It is expected this function is called in Express
11
10
  * server instance context.
12
11
  *
13
- * @param {Object} server - An instance of express HTTP server.
12
+ * @this {WebSocketServer} - An instance of express HTTP server.
14
13
  * @param {string} handlerPathname - Web socket endpoint path starting with
15
14
  * a single slash character. It is recommended to always add
16
15
  * DEFAULT_WS_PATHNAME_PREFIX to all web socket pathnames.
@@ -18,15 +17,17 @@ const DEFAULT_WS_PATHNAME_PREFIX = '/ws';
18
17
  * https://github.com/websockets/ws/pull/885 for more details
19
18
  * on how to configure the handler properly.
20
19
  */
21
- async function addWebSocketHandler (handlerPathname, handlerServer) { // eslint-disable-line require-await
20
+ // eslint-disable-next-line require-await
21
+ async function addWebSocketHandler(handlerPathname, handlerServer) {
22
22
  if (_.isUndefined(this.webSocketsMapping)) {
23
23
  this.webSocketsMapping = {};
24
24
  // https://github.com/websockets/ws/pull/885
25
25
  this.on('upgrade', (request, socket, head) => {
26
26
  let currentPathname;
27
27
  try {
28
- currentPathname = (new URL(request.url)).pathname;
29
- } catch (ign) {
28
+ // @ts-expect-error
29
+ currentPathname = new URL(request.url).pathname;
30
+ } catch {
30
31
  currentPathname = request.url;
31
32
  }
32
33
  for (const [pathname, wsServer] of _.toPairs(this.webSocketsMapping)) {
@@ -49,12 +50,13 @@ async function addWebSocketHandler (handlerPathname, handlerServer) { // eslint-
49
50
  * It is expected this function is called in Express
50
51
  * server instance context.
51
52
  *
52
- * @param {?string} keysFilter [null]- Only include pathnames with given
53
+ * @param {string?} [keysFilter] - Only include pathnames with given
53
54
  * `keysFilter` value if set. All pairs will be included by default.
54
- * @returns {Object} pathnames to websocket server isntances mapping
55
+ * @returns {Promise<Object>} pathnames to websocket server isntances mapping
55
56
  * matching the search criteria or an empty object otherwise.
56
57
  */
57
- async function getWebSocketHandlers (keysFilter = null) { // eslint-disable-line require-await
58
+ // eslint-disable-next-line require-await
59
+ async function getWebSocketHandlers(keysFilter = null) {
58
60
  if (_.isEmpty(this.webSocketsMapping)) {
59
61
  return {};
60
62
  }
@@ -75,9 +77,10 @@ async function getWebSocketHandlers (keysFilter = null) { // eslint-disable-line
75
77
  * server instance context.
76
78
  *
77
79
  * @param {string} handlerPathname - Websocket endpoint path.
78
- * @returns {boolean} true if the handlerPathname was found and deleted
80
+ * @returns {Promise<boolean>} true if the handlerPathname was found and deleted
79
81
  */
80
- async function removeWebSocketHandler (handlerPathname) { // eslint-disable-line require-await
82
+ // eslint-disable-next-line require-await
83
+ async function removeWebSocketHandler(handlerPathname) {
81
84
  const wsServer = this.webSocketsMapping?.[handlerPathname];
82
85
  if (!wsServer) {
83
86
  return false;
@@ -85,7 +88,7 @@ async function removeWebSocketHandler (handlerPathname) { // eslint-disable-line
85
88
 
86
89
  try {
87
90
  wsServer.close();
88
- for (const client of (wsServer.clients || [])) {
91
+ for (const client of wsServer.clients || []) {
89
92
  client.terminate();
90
93
  }
91
94
  return true;
@@ -102,9 +105,9 @@ async function removeWebSocketHandler (handlerPathname) { // eslint-disable-line
102
105
  * It is expected this function is called in Express
103
106
  * server instance context.
104
107
  *
105
- * @returns {boolean} true if at least one handler has been deleted
108
+ * @returns {Promise<boolean>} true if at least one handler has been deleted
106
109
  */
107
- async function removeAllWebSocketHandlers () {
110
+ async function removeAllWebSocketHandlers() {
108
111
  if (_.isEmpty(this.webSocketsMapping)) {
109
112
  return false;
110
113
  }
@@ -117,6 +120,13 @@ async function removeAllWebSocketHandlers () {
117
120
  }
118
121
 
119
122
  export {
120
- addWebSocketHandler, removeWebSocketHandler, removeAllWebSocketHandlers,
121
- getWebSocketHandlers, DEFAULT_WS_PATHNAME_PREFIX,
123
+ addWebSocketHandler,
124
+ removeWebSocketHandler,
125
+ removeAllWebSocketHandlers,
126
+ getWebSocketHandlers,
127
+ DEFAULT_WS_PATHNAME_PREFIX,
122
128
  };
129
+
130
+ /**
131
+ * @typedef {import('http').Server & {webSocketsMapping: Record<string,import('ws').Server>}} WebSocketServer
132
+ */
@@ -2,13 +2,15 @@
2
2
 
3
3
  import _ from 'lodash';
4
4
 
5
- function isW3cCaps (caps) {
5
+ function isW3cCaps(caps) {
6
6
  if (!_.isPlainObject(caps)) {
7
7
  return false;
8
8
  }
9
9
 
10
- const isFirstMatchValid = () => _.isArray(caps.firstMatch)
11
- && !_.isEmpty(caps.firstMatch) && _.every(caps.firstMatch, _.isPlainObject);
10
+ const isFirstMatchValid = () =>
11
+ _.isArray(caps.firstMatch) &&
12
+ !_.isEmpty(caps.firstMatch) &&
13
+ _.every(caps.firstMatch, _.isPlainObject);
12
14
  const isAlwaysMatchValid = () => _.isPlainObject(caps.alwaysMatch);
13
15
  if (_.has(caps, 'firstMatch') && _.has(caps, 'alwaysMatch')) {
14
16
  return isFirstMatchValid() && isAlwaysMatchValid();
@@ -29,21 +31,19 @@ function isW3cCaps (caps) {
29
31
  * @param {AppiumLogger} log
30
32
  * @returns {Capabilities}
31
33
  */
32
- function fixCaps (originalCaps, desiredCapConstraints, log) {
34
+ function fixCaps(originalCaps, desiredCapConstraints, log) {
33
35
  let caps = _.clone(originalCaps);
34
36
 
35
37
  // boolean capabilities can be passed in as strings 'false' and 'true'
36
38
  // which we want to translate into boolean values
37
- let booleanCaps = _.keys(
38
- _.pickBy(desiredCapConstraints, (k) => k.isBoolean === true),
39
- );
39
+ let booleanCaps = _.keys(_.pickBy(desiredCapConstraints, (k) => k.isBoolean === true));
40
40
  for (let cap of booleanCaps) {
41
41
  let value = originalCaps[cap];
42
42
  if (_.isString(value)) {
43
43
  value = value.toLowerCase();
44
44
  if (value === 'true' || value === 'false') {
45
45
  log.warn(
46
- `Capability '${cap}' changed from string to boolean. This may cause unexpected behavior`,
46
+ `Capability '${cap}' changed from string to boolean. This may cause unexpected behavior`
47
47
  );
48
48
  caps[cap] = value === 'true';
49
49
  }
@@ -51,9 +51,7 @@ function fixCaps (originalCaps, desiredCapConstraints, log) {
51
51
  }
52
52
 
53
53
  // int capabilities are often sent in as strings by frameworks
54
- let intCaps = _.keys(
55
- _.pickBy(desiredCapConstraints, (k) => k.isNumber === true),
56
- );
54
+ let intCaps = _.keys(_.pickBy(desiredCapConstraints, (k) => k.isNumber === true));
57
55
  for (let cap of intCaps) {
58
56
  let value = originalCaps[cap];
59
57
  if (_.isString(value)) {
@@ -63,7 +61,7 @@ function fixCaps (originalCaps, desiredCapConstraints, log) {
63
61
  newValue = parseFloat(value);
64
62
  }
65
63
  log.warn(
66
- `Capability '${cap}' changed from string ('${value}') to integer (${newValue}). This may cause unexpected behavior`,
64
+ `Capability '${cap}' changed from string ('${value}') to integer (${newValue}). This may cause unexpected behavior`
67
65
  );
68
66
  caps[cap] = newValue;
69
67
  }
@@ -72,10 +70,7 @@ function fixCaps (originalCaps, desiredCapConstraints, log) {
72
70
  return caps;
73
71
  }
74
72
 
75
- export {
76
- isW3cCaps,
77
- fixCaps
78
- };
73
+ export {isW3cCaps, fixCaps};
79
74
 
80
75
  /**
81
76
  * @typedef {import('@appium/types').Capabilities} Capabilities