@appium/base-driver 10.2.0 → 10.2.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.
- package/LICENSE +201 -0
- package/build/lib/basedriver/capabilities.js +7 -7
- package/build/lib/basedriver/capabilities.js.map +1 -1
- package/build/lib/basedriver/commands/event.d.ts +1 -1
- package/build/lib/basedriver/commands/event.d.ts.map +1 -1
- package/build/lib/basedriver/commands/execute.d.ts +1 -1
- package/build/lib/basedriver/commands/execute.d.ts.map +1 -1
- package/build/lib/basedriver/commands/find.d.ts +1 -1
- package/build/lib/basedriver/commands/find.d.ts.map +1 -1
- package/build/lib/basedriver/commands/mixin.d.ts +1 -1
- package/build/lib/basedriver/commands/mixin.d.ts.map +1 -1
- package/build/lib/basedriver/commands/timeout.d.ts +1 -1
- package/build/lib/basedriver/commands/timeout.d.ts.map +1 -1
- package/build/lib/basedriver/device-settings.d.ts +14 -23
- package/build/lib/basedriver/device-settings.d.ts.map +1 -1
- package/build/lib/basedriver/device-settings.js +11 -26
- package/build/lib/basedriver/device-settings.js.map +1 -1
- package/build/lib/basedriver/helpers.d.ts +36 -57
- package/build/lib/basedriver/helpers.d.ts.map +1 -1
- package/build/lib/basedriver/helpers.js +148 -239
- package/build/lib/basedriver/helpers.js.map +1 -1
- package/build/lib/basedriver/logger.d.ts +1 -2
- package/build/lib/basedriver/logger.d.ts.map +1 -1
- package/build/lib/basedriver/logger.js +2 -2
- package/build/lib/basedriver/logger.js.map +1 -1
- package/build/lib/basedriver/validation.d.ts.map +1 -1
- package/build/lib/basedriver/validation.js +3 -3
- package/build/lib/basedriver/validation.js.map +1 -1
- package/build/lib/constants.d.ts +1 -1
- package/build/lib/constants.d.ts.map +1 -1
- package/build/lib/express/crash.d.ts +8 -2
- package/build/lib/express/crash.d.ts.map +1 -1
- package/build/lib/express/crash.js +6 -0
- package/build/lib/express/crash.js.map +1 -1
- package/build/lib/express/express-logging.d.ts +12 -2
- package/build/lib/express/express-logging.d.ts.map +1 -1
- package/build/lib/express/express-logging.js +34 -26
- package/build/lib/express/express-logging.js.map +1 -1
- package/build/lib/express/idempotency.d.ts +4 -10
- package/build/lib/express/idempotency.d.ts.map +1 -1
- package/build/lib/express/idempotency.js +69 -73
- package/build/lib/express/idempotency.js.map +1 -1
- package/build/lib/express/logger.d.ts +1 -2
- package/build/lib/express/logger.d.ts.map +1 -1
- package/build/lib/express/logger.js +2 -2
- package/build/lib/express/logger.js.map +1 -1
- package/build/lib/express/middleware.d.ts +37 -41
- package/build/lib/express/middleware.d.ts.map +1 -1
- package/build/lib/express/middleware.js +48 -60
- package/build/lib/express/middleware.js.map +1 -1
- package/build/lib/express/server.d.ts +57 -101
- package/build/lib/express/server.d.ts.map +1 -1
- package/build/lib/express/server.js +51 -128
- package/build/lib/express/server.js.map +1 -1
- package/build/lib/express/static.d.ts +10 -5
- package/build/lib/express/static.d.ts.map +1 -1
- package/build/lib/express/static.js +32 -42
- package/build/lib/express/static.js.map +1 -1
- package/build/lib/express/websocket.d.ts +22 -6
- package/build/lib/express/websocket.d.ts.map +1 -1
- package/build/lib/express/websocket.js +10 -15
- package/build/lib/express/websocket.js.map +1 -1
- package/build/lib/helpers/capabilities.d.ts +4 -16
- package/build/lib/helpers/capabilities.d.ts.map +1 -1
- package/build/lib/helpers/capabilities.js +36 -48
- package/build/lib/helpers/capabilities.js.map +1 -1
- package/build/lib/jsonwp-status/status.d.ts +113 -158
- package/build/lib/jsonwp-status/status.d.ts.map +1 -1
- package/build/lib/jsonwp-status/status.js +10 -14
- package/build/lib/jsonwp-status/status.js.map +1 -1
- package/build/lib/protocol/bidi-commands.d.ts +31 -36
- package/build/lib/protocol/bidi-commands.d.ts.map +1 -1
- package/build/lib/protocol/bidi-commands.js +5 -5
- package/build/lib/protocol/bidi-commands.js.map +1 -1
- package/build/lib/protocol/errors.d.ts.map +1 -1
- package/build/lib/protocol/helpers.d.ts +7 -11
- package/build/lib/protocol/helpers.d.ts.map +1 -1
- package/build/lib/protocol/helpers.js +5 -9
- package/build/lib/protocol/helpers.js.map +1 -1
- package/build/lib/protocol/index.d.ts +4 -21
- package/build/lib/protocol/index.d.ts.map +1 -1
- package/build/lib/protocol/index.js.map +1 -1
- package/build/lib/protocol/protocol.d.ts +15 -1
- package/build/lib/protocol/protocol.d.ts.map +1 -1
- package/build/lib/protocol/protocol.js +50 -20
- package/build/lib/protocol/protocol.js.map +1 -1
- package/build/lib/protocol/routes.d.ts +8 -15
- package/build/lib/protocol/routes.d.ts.map +1 -1
- package/build/lib/protocol/routes.js +18 -33
- package/build/lib/protocol/routes.js.map +1 -1
- package/lib/basedriver/capabilities.ts +1 -1
- package/lib/basedriver/commands/event.ts +2 -2
- package/lib/basedriver/commands/execute.ts +2 -2
- package/lib/basedriver/commands/find.ts +2 -2
- package/lib/basedriver/commands/mixin.ts +1 -1
- package/lib/basedriver/commands/timeout.ts +2 -2
- package/lib/basedriver/{device-settings.js → device-settings.ts} +24 -35
- package/lib/basedriver/{helpers.js → helpers.ts} +208 -266
- package/lib/basedriver/logger.ts +3 -0
- package/lib/basedriver/validation.ts +2 -2
- package/lib/constants.ts +1 -1
- package/lib/express/crash.ts +15 -0
- package/lib/express/express-logging.ts +84 -0
- package/lib/express/{idempotency.js → idempotency.ts} +105 -89
- package/lib/express/logger.ts +3 -0
- package/lib/express/middleware.ts +187 -0
- package/lib/express/{server.js → server.ts} +175 -167
- package/lib/express/static.ts +77 -0
- package/lib/express/websocket.ts +81 -0
- package/lib/helpers/capabilities.ts +83 -0
- package/lib/jsonwp-status/{status.js → status.ts} +12 -15
- package/lib/protocol/{bidi-commands.js → bidi-commands.ts} +7 -5
- package/lib/protocol/errors.ts +1 -1
- package/lib/protocol/{helpers.js → helpers.ts} +8 -11
- package/lib/protocol/protocol.ts +57 -26
- package/lib/protocol/{routes.js → routes.ts} +29 -40
- package/package.json +11 -11
- package/tsconfig.json +3 -1
- package/lib/basedriver/logger.js +0 -4
- package/lib/express/crash.js +0 -11
- package/lib/express/express-logging.js +0 -60
- package/lib/express/logger.js +0 -4
- package/lib/express/middleware.js +0 -171
- package/lib/express/static.js +0 -76
- package/lib/express/websocket.js +0 -79
- package/lib/helpers/capabilities.js +0 -93
- /package/lib/protocol/{index.js → index.ts} +0 -0
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import _ from 'lodash';
|
|
2
|
-
import '@colors/colors';
|
|
3
|
-
import morgan from 'morgan';
|
|
4
|
-
import log from './logger';
|
|
5
|
-
import {MAX_LOG_BODY_LENGTH} from '../constants';
|
|
6
|
-
import {logger} from '@appium/support';
|
|
7
|
-
|
|
8
|
-
// Copied the morgan compile function over so that cooler formats
|
|
9
|
-
// may be configured
|
|
10
|
-
function compile(fmt) {
|
|
11
|
-
// escape quotes
|
|
12
|
-
fmt = fmt.replace(/"/g, '\\"');
|
|
13
|
-
fmt = fmt.replace(/:([-\w]{2,})(?:\[([^\]]+)\])?/g, function replace(_, name, arg) {
|
|
14
|
-
return `"\n + (tokens["${name}"](req, res, "${arg}") || "-") + "`;
|
|
15
|
-
});
|
|
16
|
-
let js = ` return "${fmt}";`;
|
|
17
|
-
return new Function('tokens, req, res', js);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function requestEndLoggingFormat(tokens, req, res) {
|
|
21
|
-
let status = res.statusCode;
|
|
22
|
-
let statusStr = ':status';
|
|
23
|
-
if (status >= 500) {
|
|
24
|
-
statusStr = statusStr.red;
|
|
25
|
-
} else if (status >= 400) {
|
|
26
|
-
statusStr = statusStr.yellow;
|
|
27
|
-
} else if (status >= 300) {
|
|
28
|
-
statusStr = statusStr.cyan;
|
|
29
|
-
} else {
|
|
30
|
-
statusStr = statusStr.green;
|
|
31
|
-
}
|
|
32
|
-
let fn = compile(
|
|
33
|
-
`${'<-- :method :url '.white}${statusStr} ${':response-time ms - :res[content-length]'.grey}`
|
|
34
|
-
);
|
|
35
|
-
return fn(tokens, req, res);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const endLogFormatter = morgan((tokens, req, res) => {
|
|
39
|
-
log.info(requestEndLoggingFormat(tokens, req, res), (res.jsonResp || '').grey);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
const requestStartLoggingFormat = compile(`${'-->'.white} ${':method'.white} ${':url'.white}`);
|
|
43
|
-
|
|
44
|
-
const startLogFormatter = morgan(
|
|
45
|
-
(tokens, req, res) => {
|
|
46
|
-
// morgan output is redirected straight to winston
|
|
47
|
-
let reqBody = '';
|
|
48
|
-
if (req.body) {
|
|
49
|
-
try {
|
|
50
|
-
reqBody = _.truncate(_.isString(req.body) ? req.body : JSON.stringify(req.body), {
|
|
51
|
-
length: MAX_LOG_BODY_LENGTH,
|
|
52
|
-
});
|
|
53
|
-
} catch {}
|
|
54
|
-
}
|
|
55
|
-
log.info(requestStartLoggingFormat(tokens, req, res), logger.markSensitive(reqBody.grey));
|
|
56
|
-
},
|
|
57
|
-
{immediate: true}
|
|
58
|
-
);
|
|
59
|
-
|
|
60
|
-
export {endLogFormatter, startLogFormatter};
|
package/lib/express/logger.js
DELETED
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
import _ from 'lodash';
|
|
2
|
-
import log from './logger';
|
|
3
|
-
import {errors} from '../protocol';
|
|
4
|
-
export {handleIdempotency} from './idempotency';
|
|
5
|
-
import {match} from 'path-to-regexp';
|
|
6
|
-
import {util} from '@appium/support';
|
|
7
|
-
import {calcSignature} from '../helpers/session';
|
|
8
|
-
import {getResponseForW3CError} from '../protocol/errors';
|
|
9
|
-
|
|
10
|
-
const SESSION_ID_PATTERN = /\/session\/([^/]+)/;
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
*
|
|
14
|
-
* @param {import('express').Request} req
|
|
15
|
-
* @param {import('express').Response} res
|
|
16
|
-
* @param {import('express').NextFunction} next
|
|
17
|
-
* @returns {any}
|
|
18
|
-
*/
|
|
19
|
-
export function allowCrossDomain(req, res, next) {
|
|
20
|
-
res.header('Access-Control-Allow-Origin', '*');
|
|
21
|
-
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, OPTIONS, DELETE');
|
|
22
|
-
res.header(
|
|
23
|
-
'Access-Control-Allow-Headers',
|
|
24
|
-
'Cache-Control, Pragma, Origin, X-Requested-With, Content-Type, Accept, User-Agent'
|
|
25
|
-
);
|
|
26
|
-
|
|
27
|
-
// need to respond 200 to OPTIONS
|
|
28
|
-
if ('OPTIONS' === req.method) {
|
|
29
|
-
return res.sendStatus(200);
|
|
30
|
-
}
|
|
31
|
-
next();
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* @param {string} basePath
|
|
36
|
-
* @returns {import('express').RequestHandler}
|
|
37
|
-
*/
|
|
38
|
-
export function allowCrossDomainAsyncExecute(basePath) {
|
|
39
|
-
return (req, res, next) => {
|
|
40
|
-
// there are two paths for async responses, so cover both
|
|
41
|
-
// https://regex101.com/r/txYiEz/1
|
|
42
|
-
const receiveAsyncResponseRegExp = new RegExp(
|
|
43
|
-
`${_.escapeRegExp(basePath)}/session/[a-f0-9-]+/(appium/)?receive_async_response`
|
|
44
|
-
);
|
|
45
|
-
if (!receiveAsyncResponseRegExp.test(req.url)) {
|
|
46
|
-
return next();
|
|
47
|
-
}
|
|
48
|
-
allowCrossDomain(req, res, next);
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
*
|
|
54
|
-
* @param {import('express').Request} req
|
|
55
|
-
* @param {import('express').Response} res
|
|
56
|
-
* @param {import('express').NextFunction} next
|
|
57
|
-
* @returns {any}
|
|
58
|
-
*/
|
|
59
|
-
export function handleLogContext(req, res, next) {
|
|
60
|
-
const requestId = fetchHeaderValue(req, 'x-request-id') || util.uuidV4();
|
|
61
|
-
|
|
62
|
-
const sessionId = SESSION_ID_PATTERN.exec(req.url)?.[1];
|
|
63
|
-
const sessionInfo = sessionId ? {sessionId, sessionSignature: calcSignature(sessionId)} : {};
|
|
64
|
-
const isSensitiveHeaderValue = fetchHeaderValue(req, 'x-appium-is-sensitive');
|
|
65
|
-
|
|
66
|
-
log.updateAsyncContext({
|
|
67
|
-
requestId,
|
|
68
|
-
...sessionInfo,
|
|
69
|
-
isSensitive: ['true', '1', 'yes'].includes(_.toLower(isSensitiveHeaderValue)),
|
|
70
|
-
}, true);
|
|
71
|
-
|
|
72
|
-
return next();
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
*
|
|
77
|
-
* @param {import('express').Request} req
|
|
78
|
-
* @param {import('express').Response} res
|
|
79
|
-
* @param {import('express').NextFunction} next
|
|
80
|
-
* @returns {any}
|
|
81
|
-
*/
|
|
82
|
-
export function defaultToJSONContentType(req, res, next) {
|
|
83
|
-
if (!req.headers['content-type']) {
|
|
84
|
-
req.headers['content-type'] = 'application/json; charset=utf-8';
|
|
85
|
-
}
|
|
86
|
-
next();
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Core function to handle WebSocket upgrade requests by matching the request path
|
|
91
|
-
* against registered WebSocket handlers in the webSocketsMapping.
|
|
92
|
-
*
|
|
93
|
-
* @param {import('http').IncomingMessage} req - The HTTP request
|
|
94
|
-
* @param {import('stream').Duplex} socket - The network socket
|
|
95
|
-
* @param {Buffer} head - The first packet of the upgraded stream
|
|
96
|
-
* @param {import('@appium/types').StringRecord<import('@appium/types').WSServer>} webSocketsMapping - Mapping of paths to WebSocket servers
|
|
97
|
-
* @returns {boolean} - Returns true if the upgrade was handled, false otherwise
|
|
98
|
-
*/
|
|
99
|
-
export function tryHandleWebSocketUpgrade(req, socket, head, webSocketsMapping) {
|
|
100
|
-
if (_.toLower(req.headers?.upgrade) !== 'websocket') {
|
|
101
|
-
return false;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
let currentPathname;
|
|
105
|
-
try {
|
|
106
|
-
currentPathname = new URL(req.url ?? '', 'http://localhost').pathname;
|
|
107
|
-
} catch {
|
|
108
|
-
currentPathname = req.url ?? '';
|
|
109
|
-
}
|
|
110
|
-
for (const [pathname, wsServer] of _.toPairs(webSocketsMapping)) {
|
|
111
|
-
if (match(pathname)(currentPathname)) {
|
|
112
|
-
wsServer.handleUpgrade(req, socket, head, (ws) => {
|
|
113
|
-
wsServer.emit('connection', ws, req);
|
|
114
|
-
});
|
|
115
|
-
return true;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
log.info(`Did not match the websocket upgrade request at ${currentPathname} to any known route`);
|
|
119
|
-
return false;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
*
|
|
124
|
-
* @param {import('@appium/types').StringRecord<import('@appium/types').WSServer>} webSocketsMapping
|
|
125
|
-
* @returns {import('express').RequestHandler}
|
|
126
|
-
*/
|
|
127
|
-
export function handleUpgrade(webSocketsMapping) {
|
|
128
|
-
return (req, res, next) => {
|
|
129
|
-
if (tryHandleWebSocketUpgrade(req, req.socket, Buffer.from(''), webSocketsMapping)) {
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
132
|
-
next();
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* @param {Error} err
|
|
138
|
-
* @param {import('express').Request} req
|
|
139
|
-
* @param {import('express').Response} res
|
|
140
|
-
* @param {import('express').NextFunction} next
|
|
141
|
-
*/
|
|
142
|
-
export function catchAllHandler(err, req, res, next) {
|
|
143
|
-
if (res.headersSent) {
|
|
144
|
-
return next(err);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
log.error(`Uncaught error: ${err.message}`);
|
|
148
|
-
const [status, body] = getResponseForW3CError(err);
|
|
149
|
-
res.status(status).json(body);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* @param {import('express').Request} req
|
|
154
|
-
* @param {import('express').Response} res
|
|
155
|
-
*/
|
|
156
|
-
export function catch404Handler(req, res) {
|
|
157
|
-
log.debug(`No route found for ${req.url}`);
|
|
158
|
-
const [status, body] = getResponseForW3CError(new errors.UnknownCommandError());
|
|
159
|
-
res.status(status).json(body);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* @param {import('express').Request} req
|
|
164
|
-
* @param {string} name
|
|
165
|
-
* @returns {string | undefined}
|
|
166
|
-
*/
|
|
167
|
-
function fetchHeaderValue(req, name) {
|
|
168
|
-
return _.isArray(req.headers[name])
|
|
169
|
-
? req.headers[name][0]
|
|
170
|
-
: req.headers[name];
|
|
171
|
-
}
|
package/lib/express/static.js
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
|
-
import log from './logger';
|
|
3
|
-
import _ from 'lodash';
|
|
4
|
-
import {fs} from '@appium/support';
|
|
5
|
-
import B from 'bluebird';
|
|
6
|
-
|
|
7
|
-
let STATIC_DIR = path.resolve(__dirname, '..', '..', '..', 'static');
|
|
8
|
-
if (_.isNull(path.resolve(__dirname).match(/build[/\\]lib[/\\]express$/))) {
|
|
9
|
-
// in some contexts we are not in the build directory,
|
|
10
|
-
// so we don't want to go back the extra level
|
|
11
|
-
STATIC_DIR = path.resolve(__dirname, '..', '..', 'static');
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
async function guineaPigTemplate(req, res, page) {
|
|
15
|
-
const delay = parseInt(req.params.delay || req.query.delay || 0, 10);
|
|
16
|
-
const throwError = req.params.throwError || req.query.throwError || '';
|
|
17
|
-
let params = {
|
|
18
|
-
throwError,
|
|
19
|
-
serverTime: new Date(),
|
|
20
|
-
userAgent: req.headers['user-agent'],
|
|
21
|
-
comment: 'None',
|
|
22
|
-
};
|
|
23
|
-
if (req.method === 'POST') {
|
|
24
|
-
params.comment = req.body.comments || params.comment;
|
|
25
|
-
}
|
|
26
|
-
log.debug(`Sending guinea pig response with params: ${JSON.stringify(params)}`);
|
|
27
|
-
if (delay) {
|
|
28
|
-
log.debug(`Waiting ${delay}ms before responding`);
|
|
29
|
-
await B.delay(delay);
|
|
30
|
-
}
|
|
31
|
-
res.set('content-type', 'text/html');
|
|
32
|
-
res.cookie('guineacookie1', 'i am a cookie value', {path: '/'});
|
|
33
|
-
res.cookie('guineacookie2', 'cookié2', {path: '/'});
|
|
34
|
-
res.cookie('guineacookie3', 'cant access this', {
|
|
35
|
-
domain: '.blargimarg.com',
|
|
36
|
-
path: '/',
|
|
37
|
-
});
|
|
38
|
-
res.send((await getTemplate(page))(params));
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/*
|
|
42
|
-
* Dynamic page mapped to /test/guinea-pig
|
|
43
|
-
*/
|
|
44
|
-
async function guineaPig(req, res) {
|
|
45
|
-
return await guineaPigTemplate(req, res, 'guinea-pig.html');
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/*
|
|
49
|
-
* Dynamic page mapped to /test/guinea-pig-scrollable
|
|
50
|
-
*/
|
|
51
|
-
async function guineaPigScrollable(req, res) {
|
|
52
|
-
return await guineaPigTemplate(req, res, 'guinea-pig-scrollable.html');
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/*
|
|
56
|
-
* Dynamic page mapped to /test/guinea-pig-app-banner
|
|
57
|
-
*/
|
|
58
|
-
async function guineaPigAppBanner(req, res) {
|
|
59
|
-
return await guineaPigTemplate(req, res, 'guinea-pig-app-banner.html');
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/*
|
|
63
|
-
* Dynamic page mapped to /welcome
|
|
64
|
-
*/
|
|
65
|
-
async function welcome(req, res) {
|
|
66
|
-
let params = {message: "Let's browse!"};
|
|
67
|
-
log.debug(`Sending welcome response with params: ${JSON.stringify(params)}`);
|
|
68
|
-
res.send((await getTemplate('welcome.html'))(params));
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
async function getTemplate(templateName) {
|
|
72
|
-
let content = await fs.readFile(path.resolve(STATIC_DIR, 'test', templateName));
|
|
73
|
-
return _.template(content.toString());
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export {guineaPig, guineaPigScrollable, guineaPigAppBanner, welcome, STATIC_DIR};
|
package/lib/express/websocket.js
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import _ from 'lodash';
|
|
3
|
-
import B from 'bluebird';
|
|
4
|
-
|
|
5
|
-
const DEFAULT_WS_PATHNAME_PREFIX = '/ws';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* @this {AppiumServer}
|
|
9
|
-
* @type {AppiumServer['addWebSocketHandler']}
|
|
10
|
-
*/
|
|
11
|
-
async function addWebSocketHandler(handlerPathname, handlerServer) {
|
|
12
|
-
this.webSocketsMapping[handlerPathname] = handlerServer;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* @this {AppiumServer}
|
|
17
|
-
* @type {AppiumServer['getWebSocketHandlers']}
|
|
18
|
-
*/
|
|
19
|
-
async function getWebSocketHandlers(keysFilter = null) {
|
|
20
|
-
return _.toPairs(this.webSocketsMapping).reduce((acc, [pathname, wsServer]) => {
|
|
21
|
-
if (!_.isString(keysFilter) || pathname.includes(keysFilter)) {
|
|
22
|
-
acc[pathname] = wsServer;
|
|
23
|
-
}
|
|
24
|
-
return acc;
|
|
25
|
-
}, {});
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* @this {AppiumServer}
|
|
30
|
-
* @type {AppiumServer['removeWebSocketHandler']}
|
|
31
|
-
*/
|
|
32
|
-
async function removeWebSocketHandler(handlerPathname) {
|
|
33
|
-
const wsServer = this.webSocketsMapping?.[handlerPathname];
|
|
34
|
-
if (!wsServer) {
|
|
35
|
-
return false;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
try {
|
|
39
|
-
wsServer.close();
|
|
40
|
-
for (const client of wsServer.clients || []) {
|
|
41
|
-
client.terminate();
|
|
42
|
-
}
|
|
43
|
-
return true;
|
|
44
|
-
} catch {
|
|
45
|
-
// ignore
|
|
46
|
-
} finally {
|
|
47
|
-
delete this.webSocketsMapping[handlerPathname];
|
|
48
|
-
}
|
|
49
|
-
return false;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
*
|
|
54
|
-
* @this {AppiumServer}
|
|
55
|
-
* @type {AppiumServer['removeAllWebSocketHandlers']}
|
|
56
|
-
*/
|
|
57
|
-
async function removeAllWebSocketHandlers() {
|
|
58
|
-
if (_.isEmpty(this.webSocketsMapping)) {
|
|
59
|
-
return false;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
return _.some(
|
|
63
|
-
await B.all(
|
|
64
|
-
_.keys(this.webSocketsMapping).map((pathname) => this.removeWebSocketHandler(pathname))
|
|
65
|
-
)
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export {
|
|
70
|
-
addWebSocketHandler,
|
|
71
|
-
removeWebSocketHandler,
|
|
72
|
-
removeAllWebSocketHandlers,
|
|
73
|
-
getWebSocketHandlers,
|
|
74
|
-
DEFAULT_WS_PATHNAME_PREFIX,
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* @typedef {import('@appium/types').AppiumServer} AppiumServer
|
|
79
|
-
*/
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
import _ from 'lodash';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Determine whether the given argument is valid
|
|
7
|
-
* W3C capabilities instance.
|
|
8
|
-
*
|
|
9
|
-
* @param {any} caps
|
|
10
|
-
* @returns {caps is import('@appium/types').W3CCapabilities}
|
|
11
|
-
*/
|
|
12
|
-
export function isW3cCaps(caps) {
|
|
13
|
-
if (!_.isPlainObject(caps)) {
|
|
14
|
-
return false;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const isFirstMatchValid = () =>
|
|
18
|
-
_.isArray(caps.firstMatch) &&
|
|
19
|
-
!_.isEmpty(caps.firstMatch) &&
|
|
20
|
-
_.every(caps.firstMatch, _.isPlainObject);
|
|
21
|
-
const isAlwaysMatchValid = () => _.isPlainObject(caps.alwaysMatch);
|
|
22
|
-
if (_.has(caps, 'firstMatch') && _.has(caps, 'alwaysMatch')) {
|
|
23
|
-
return isFirstMatchValid() && isAlwaysMatchValid();
|
|
24
|
-
}
|
|
25
|
-
if (_.has(caps, 'firstMatch')) {
|
|
26
|
-
return isFirstMatchValid();
|
|
27
|
-
}
|
|
28
|
-
if (_.has(caps, 'alwaysMatch')) {
|
|
29
|
-
return isAlwaysMatchValid();
|
|
30
|
-
}
|
|
31
|
-
return false;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
*
|
|
36
|
-
* @template {Constraints} C
|
|
37
|
-
* @param {any} oldCaps
|
|
38
|
-
* @param {C} desiredCapConstraints
|
|
39
|
-
* @param {AppiumLogger} log
|
|
40
|
-
* @returns {Capabilities<C>}
|
|
41
|
-
*/
|
|
42
|
-
export function fixCaps(oldCaps, desiredCapConstraints, log) {
|
|
43
|
-
let caps = _.clone(oldCaps);
|
|
44
|
-
|
|
45
|
-
// boolean capabilities can be passed in as strings 'false' and 'true'
|
|
46
|
-
// which we want to translate into boolean values
|
|
47
|
-
let booleanCaps = _.keys(_.pickBy(desiredCapConstraints, (k) => k.isBoolean === true));
|
|
48
|
-
for (let cap of booleanCaps) {
|
|
49
|
-
let value = oldCaps[cap];
|
|
50
|
-
if (_.isString(value)) {
|
|
51
|
-
value = value.toLowerCase();
|
|
52
|
-
if (value === 'true' || value === 'false') {
|
|
53
|
-
log.warn(
|
|
54
|
-
`Capability '${cap}' changed from string to boolean. This may cause unexpected behavior`
|
|
55
|
-
);
|
|
56
|
-
caps[cap] = value === 'true';
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// int capabilities are often sent in as strings by frameworks
|
|
62
|
-
let intCaps = /** @type {import('type-fest').KeyAsString<typeof caps>[]} */ (
|
|
63
|
-
_.keys(_.pickBy(desiredCapConstraints, (k) => k.isNumber === true))
|
|
64
|
-
);
|
|
65
|
-
for (let cap of intCaps) {
|
|
66
|
-
let value = oldCaps[cap];
|
|
67
|
-
if (_.isString(value)) {
|
|
68
|
-
value = value.trim();
|
|
69
|
-
let newValue = parseInt(value, 10);
|
|
70
|
-
if (value !== `${newValue}`) {
|
|
71
|
-
newValue = parseFloat(value);
|
|
72
|
-
}
|
|
73
|
-
log.warn(
|
|
74
|
-
`Capability '${cap}' changed from string ('${value}') to integer (${newValue}). This may cause unexpected behavior`
|
|
75
|
-
);
|
|
76
|
-
caps[cap] = newValue;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
return caps;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* @typedef {import('@appium/types').Constraints} Constraints
|
|
85
|
-
* @typedef {import('@appium/types').AppiumLogger} AppiumLogger
|
|
86
|
-
* @typedef {import('@appium/types').StringRecord} StringRecord
|
|
87
|
-
* @typedef {import('@appium/types').BaseDriverCapConstraints} BaseDriverCapConstraints
|
|
88
|
-
*/
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* @template {Constraints} C
|
|
92
|
-
* @typedef {import('@appium/types').Capabilities<C>} Capabilities
|
|
93
|
-
*/
|
|
File without changes
|