@appium/base-driver 9.5.1 → 9.5.3
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/build/lib/basedriver/capabilities.d.ts +27 -98
- package/build/lib/basedriver/capabilities.d.ts.map +1 -1
- package/build/lib/basedriver/capabilities.js +41 -131
- package/build/lib/basedriver/capabilities.js.map +1 -1
- package/build/lib/basedriver/commands/bidi.js.map +1 -1
- package/build/lib/basedriver/commands/event.js.map +1 -1
- package/build/lib/basedriver/commands/execute.js.map +1 -1
- package/build/lib/basedriver/commands/find.js.map +1 -1
- package/build/lib/basedriver/commands/log.js.map +1 -1
- package/build/lib/basedriver/commands/timeout.js.map +1 -1
- package/build/lib/basedriver/core.js.map +1 -1
- package/build/lib/basedriver/desired-caps.js.map +1 -1
- package/build/lib/basedriver/device-settings.js.map +1 -1
- package/build/lib/basedriver/driver.js.map +1 -1
- package/build/lib/basedriver/helpers.js +1 -1
- package/build/lib/basedriver/helpers.js.map +1 -1
- package/build/lib/express/express-logging.js.map +1 -1
- package/build/lib/express/idempotency.js.map +1 -1
- package/build/lib/express/middleware.js.map +1 -1
- package/build/lib/express/server.d.ts.map +1 -1
- package/build/lib/express/server.js.map +1 -1
- package/build/lib/express/static.js.map +1 -1
- package/build/lib/express/websocket.js.map +1 -1
- package/build/lib/helpers/capabilities.js.map +1 -1
- package/build/lib/index.js.map +1 -1
- package/build/lib/jsonwp-proxy/protocol-converter.d.ts +1 -1
- package/build/lib/jsonwp-proxy/protocol-converter.d.ts.map +1 -1
- package/build/lib/jsonwp-proxy/protocol-converter.js.map +1 -1
- package/build/lib/jsonwp-proxy/proxy.d.ts +1 -1
- package/build/lib/jsonwp-proxy/proxy.d.ts.map +1 -1
- package/build/lib/jsonwp-proxy/proxy.js.map +1 -1
- package/build/lib/jsonwp-status/status.js.map +1 -1
- package/build/lib/protocol/errors.d.ts +8 -5
- package/build/lib/protocol/errors.d.ts.map +1 -1
- package/build/lib/protocol/errors.js +30 -4
- package/build/lib/protocol/errors.js.map +1 -1
- package/build/lib/protocol/helpers.js.map +1 -1
- package/build/lib/protocol/protocol.js.map +1 -1
- package/build/lib/protocol/routes.js +2 -2
- package/build/lib/protocol/routes.js.map +1 -1
- package/build/lib/protocol/validators.js.map +1 -1
- package/lib/basedriver/{capabilities.js → capabilities.ts} +98 -169
- package/lib/protocol/errors.js +31 -4
- package/package.json +8 -9
|
@@ -1,34 +1,54 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import type {
|
|
2
|
+
Constraints,
|
|
3
|
+
NSCapabilities,
|
|
4
|
+
Capabilities,
|
|
5
|
+
W3CCapabilities,
|
|
6
|
+
StandardCapabilities,
|
|
7
|
+
} from '@appium/types';
|
|
8
|
+
import type {
|
|
9
|
+
StringKeyOf,
|
|
10
|
+
MergeExclusive,
|
|
11
|
+
} from 'type-fest';
|
|
3
12
|
import _ from 'lodash';
|
|
4
13
|
import {validator} from './desired-caps';
|
|
5
14
|
import {util} from '@appium/support';
|
|
6
15
|
import log from './logger';
|
|
7
16
|
import {errors} from '../protocol/errors';
|
|
8
17
|
|
|
9
|
-
const APPIUM_VENDOR_PREFIX = 'appium:';
|
|
10
|
-
const PREFIXED_APPIUM_OPTS_CAP = `${APPIUM_VENDOR_PREFIX}options`;
|
|
18
|
+
export const APPIUM_VENDOR_PREFIX = 'appium:';
|
|
19
|
+
export const PREFIXED_APPIUM_OPTS_CAP = `${APPIUM_VENDOR_PREFIX}options`;
|
|
20
|
+
|
|
21
|
+
export type ParsedCaps<C extends Constraints> = {
|
|
22
|
+
allFirstMatchCaps: NSCapabilities<C>[];
|
|
23
|
+
validatedFirstMatchCaps: Capabilities<C>[];
|
|
24
|
+
requiredCaps: NSCapabilities<C>;
|
|
25
|
+
matchedCaps: Capabilities<C> | null;
|
|
26
|
+
validationErrors: string[];
|
|
27
|
+
};
|
|
28
|
+
export type ValidateCapsOpts = {
|
|
29
|
+
/** if true, skip the presence constraint */
|
|
30
|
+
skipPresenceConstraint?: boolean | undefined;
|
|
31
|
+
}
|
|
11
32
|
|
|
12
33
|
/**
|
|
13
34
|
* Takes primary caps object and merges it into a secondary caps object.
|
|
14
|
-
*
|
|
15
|
-
* @template {Constraints} U
|
|
16
|
-
* @template {Capabilities<T>} Primary
|
|
17
|
-
* @template {Capabilities<U>} Secondary
|
|
18
|
-
* @param {Primary} [primary]
|
|
19
|
-
* @param {Secondary} [secondary]
|
|
20
|
-
* @returns {MergeExclusive<Primary, Secondary>}
|
|
35
|
+
*
|
|
21
36
|
* @see https://www.w3.org/TR/webdriver/#dfn-merging-capabilities)
|
|
22
37
|
*/
|
|
23
|
-
function mergeCaps
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
38
|
+
export function mergeCaps<
|
|
39
|
+
T extends Constraints,
|
|
40
|
+
U extends Constraints,
|
|
41
|
+
Primary extends Capabilities<T>,
|
|
42
|
+
Secondary extends Capabilities<U>
|
|
43
|
+
>(
|
|
44
|
+
primary: Primary | undefined = {} as Primary,
|
|
45
|
+
secondary: Secondary | undefined = {} as Secondary
|
|
46
|
+
): MergeExclusive<Primary, Secondary> {
|
|
47
|
+
const result = ({
|
|
28
48
|
...primary,
|
|
29
|
-
})
|
|
49
|
+
}) as MergeExclusive<Primary, Secondary>;
|
|
30
50
|
|
|
31
|
-
for (
|
|
51
|
+
for (const [name, value] of Object.entries(secondary)) {
|
|
32
52
|
// Overwriting is not allowed. Primary and secondary must have different properties (w3c rule 4.4)
|
|
33
53
|
if (!_.isUndefined(primary[name])) {
|
|
34
54
|
throw new errors.InvalidArgumentError(
|
|
@@ -37,7 +57,7 @@ function mergeCaps(
|
|
|
37
57
|
)}) and secondary (${JSON.stringify(secondary)}) object`
|
|
38
58
|
);
|
|
39
59
|
}
|
|
40
|
-
result[
|
|
60
|
+
result[name as keyof typeof result] = value;
|
|
41
61
|
}
|
|
42
62
|
|
|
43
63
|
return result;
|
|
@@ -45,21 +65,20 @@ function mergeCaps(
|
|
|
45
65
|
|
|
46
66
|
/**
|
|
47
67
|
* Validates caps against a set of constraints
|
|
48
|
-
* @template {Constraints} C
|
|
49
|
-
* @param {Capabilities<C>} caps
|
|
50
|
-
* @param {C} [constraints]
|
|
51
|
-
* @param {ValidateCapsOpts} [opts]
|
|
52
|
-
* @returns {Capabilities<C>}
|
|
53
68
|
*/
|
|
54
|
-
function validateCaps
|
|
55
|
-
|
|
69
|
+
export function validateCaps<C extends Constraints>(
|
|
70
|
+
caps: Capabilities<C>,
|
|
71
|
+
constraints: C | undefined = {} as C,
|
|
72
|
+
opts: ValidateCapsOpts | undefined = {}
|
|
73
|
+
): Capabilities<C> {
|
|
74
|
+
const {skipPresenceConstraint} = opts;
|
|
56
75
|
|
|
57
76
|
if (!_.isPlainObject(caps)) {
|
|
58
77
|
throw new errors.InvalidArgumentError(`must be a JSON object`);
|
|
59
78
|
}
|
|
60
79
|
|
|
61
80
|
// Remove the 'presence' constraint if we're not checking for it
|
|
62
|
-
constraints =
|
|
81
|
+
constraints = (
|
|
63
82
|
_.mapValues(
|
|
64
83
|
constraints,
|
|
65
84
|
skipPresenceConstraint
|
|
@@ -73,16 +92,16 @@ function validateCaps(caps, constraints = /** @type {C} */ ({}), opts = {}) {
|
|
|
73
92
|
return constraint;
|
|
74
93
|
}
|
|
75
94
|
)
|
|
76
|
-
);
|
|
95
|
+
) as C;
|
|
77
96
|
|
|
78
97
|
const validationErrors = validator.validate(_.pickBy(caps, util.hasValue), constraints, {
|
|
79
98
|
fullMessages: false,
|
|
80
99
|
});
|
|
81
100
|
|
|
82
101
|
if (validationErrors) {
|
|
83
|
-
|
|
84
|
-
for (
|
|
85
|
-
for (
|
|
102
|
+
const message: string[] = [];
|
|
103
|
+
for (const [attribute, reasons] of _.toPairs(validationErrors)) {
|
|
104
|
+
for (const reason of (reasons as string[])) {
|
|
86
105
|
message.push(`'${attribute}' ${reason}`);
|
|
87
106
|
}
|
|
88
107
|
}
|
|
@@ -99,7 +118,7 @@ function validateCaps(caps, constraints = /** @type {C} */ ({}), opts = {}) {
|
|
|
99
118
|
*/
|
|
100
119
|
export const STANDARD_CAPS = Object.freeze(
|
|
101
120
|
new Set(
|
|
102
|
-
|
|
121
|
+
([
|
|
103
122
|
'browserName',
|
|
104
123
|
'browserVersion',
|
|
105
124
|
'platformName',
|
|
@@ -110,29 +129,22 @@ export const STANDARD_CAPS = Object.freeze(
|
|
|
110
129
|
'timeouts',
|
|
111
130
|
'unhandledPromptBehavior',
|
|
112
131
|
'webSocketUrl',
|
|
113
|
-
])
|
|
132
|
+
]) as StringKeyOf<StandardCapabilities>[]
|
|
114
133
|
)
|
|
115
134
|
);
|
|
116
135
|
|
|
117
136
|
const STANDARD_CAPS_LOWER = new Set([...STANDARD_CAPS].map((cap) => cap.toLowerCase()));
|
|
118
137
|
|
|
119
|
-
|
|
120
|
-
* @param {string} cap
|
|
121
|
-
* @returns {boolean}
|
|
122
|
-
*/
|
|
123
|
-
function isStandardCap(cap) {
|
|
138
|
+
export function isStandardCap(cap: string): boolean {
|
|
124
139
|
return STANDARD_CAPS_LOWER.has(cap.toLowerCase());
|
|
125
140
|
}
|
|
126
141
|
|
|
127
142
|
/**
|
|
128
143
|
* If the 'appium:' prefix was provided and it's a valid capability, strip out the prefix
|
|
129
|
-
* @template {Constraints} C
|
|
130
|
-
* @param {NSCapabilities<C>} caps
|
|
131
144
|
* @see https://www.w3.org/TR/webdriver/#dfn-extension-capabilities
|
|
132
145
|
* @internal
|
|
133
|
-
* @returns {Capabilities<C>}
|
|
134
146
|
*/
|
|
135
|
-
function stripAppiumPrefixes(caps) {
|
|
147
|
+
export function stripAppiumPrefixes<C extends Constraints>(caps: NSCapabilities<C>): Capabilities<C> {
|
|
136
148
|
// split into prefixed and non-prefixed.
|
|
137
149
|
// non-prefixed should be standard caps at this point
|
|
138
150
|
const [prefixedCaps, nonPrefixedCaps] = _.partition(_.keys(caps), (cap) =>
|
|
@@ -140,14 +152,12 @@ function stripAppiumPrefixes(caps) {
|
|
|
140
152
|
);
|
|
141
153
|
|
|
142
154
|
// initialize this with the k/v pairs of the non-prefixed caps
|
|
143
|
-
|
|
144
|
-
const badPrefixedCaps = [];
|
|
155
|
+
const strippedCaps = (_.pick(caps, nonPrefixedCaps)) as Capabilities<C>;
|
|
156
|
+
const badPrefixedCaps: string[] = [];
|
|
145
157
|
|
|
146
158
|
// Strip out the 'appium:' prefix
|
|
147
|
-
for (
|
|
148
|
-
const strippedCapName =
|
|
149
|
-
prefixedCap.substring(APPIUM_VENDOR_PREFIX.length)
|
|
150
|
-
);
|
|
159
|
+
for (const prefixedCap of prefixedCaps) {
|
|
160
|
+
const strippedCapName = prefixedCap.substring(APPIUM_VENDOR_PREFIX.length) as StringKeyOf<Capabilities<C>>;
|
|
151
161
|
|
|
152
162
|
// If it's standard capability that was prefixed, add it to an array of incorrectly prefixed capabilities
|
|
153
163
|
if (isStandardCap(strippedCapName)) {
|
|
@@ -178,10 +188,13 @@ function stripAppiumPrefixes(caps) {
|
|
|
178
188
|
|
|
179
189
|
/**
|
|
180
190
|
* Get an array of all the unprefixed caps that are being used in 'alwaysMatch' and all of the 'firstMatch' object
|
|
181
|
-
* @template {Constraints} C
|
|
182
|
-
* @param {W3CCapabilities<C>} caps A capabilities object
|
|
183
191
|
*/
|
|
184
|
-
function findNonPrefixedCaps
|
|
192
|
+
export function findNonPrefixedCaps<C extends Constraints>(
|
|
193
|
+
{
|
|
194
|
+
alwaysMatch = {},
|
|
195
|
+
firstMatch = []
|
|
196
|
+
}: W3CCapabilities<C>
|
|
197
|
+
): string[] {
|
|
185
198
|
return _.chain([alwaysMatch, ...firstMatch])
|
|
186
199
|
.reduce(
|
|
187
200
|
(unprefixedCaps, caps) => [
|
|
@@ -194,27 +207,15 @@ function findNonPrefixedCaps({alwaysMatch = {}, firstMatch = []}) {
|
|
|
194
207
|
.value();
|
|
195
208
|
}
|
|
196
209
|
|
|
197
|
-
/**
|
|
198
|
-
* Returned by {@linkcode parseCaps}
|
|
199
|
-
* @template {Constraints} C
|
|
200
|
-
* @typedef ParsedCaps
|
|
201
|
-
* @property {NSCapabilities<C>[]} allFirstMatchCaps
|
|
202
|
-
* @property {Capabilities<C>[]} validatedFirstMatchCaps
|
|
203
|
-
* @property {NSCapabilities<C>} requiredCaps
|
|
204
|
-
* @property {Capabilities<C>|null} matchedCaps
|
|
205
|
-
* @property {string[]} validationErrors
|
|
206
|
-
*/
|
|
207
|
-
|
|
208
210
|
/**
|
|
209
211
|
* Parse capabilities
|
|
210
|
-
* @template {Constraints} C
|
|
211
|
-
* @param {W3CCapabilities<C>} caps
|
|
212
|
-
* @param {C} [constraints]
|
|
213
|
-
* @param {boolean} [shouldValidateCaps]
|
|
214
212
|
* @see https://www.w3.org/TR/webdriver/#processing-capabilities
|
|
215
|
-
* @returns {ParsedCaps<C>}
|
|
216
213
|
*/
|
|
217
|
-
function parseCaps
|
|
214
|
+
export function parseCaps<C extends Constraints>(
|
|
215
|
+
caps: W3CCapabilities<C>,
|
|
216
|
+
constraints: C | undefined = {} as C,
|
|
217
|
+
shouldValidateCaps: boolean | undefined = true
|
|
218
|
+
): ParsedCaps<C> {
|
|
218
219
|
// If capabilities request is not an object, return error (#1.1)
|
|
219
220
|
if (!_.isPlainObject(caps)) {
|
|
220
221
|
throw new errors.InvalidArgumentError(
|
|
@@ -224,9 +225,9 @@ function parseCaps(caps, constraints = /** @type {C} */ ({}), shouldValidateCaps
|
|
|
224
225
|
|
|
225
226
|
// Let 'requiredCaps' be property named 'alwaysMatch' from capabilities request (#2)
|
|
226
227
|
// and 'allFirstMatchCaps' be property named 'firstMatch' from capabilities request (#3)
|
|
227
|
-
|
|
228
|
-
alwaysMatch: requiredCaps =
|
|
229
|
-
firstMatch: allFirstMatchCaps =
|
|
228
|
+
const {
|
|
229
|
+
alwaysMatch: requiredCaps = {} as NSCapabilities<C>, // If 'requiredCaps' is undefined, set it to an empty JSON object (#2.1)
|
|
230
|
+
firstMatch: allFirstMatchCaps = [{}] as NSCapabilities<C>[], // If 'firstMatch' is undefined set it to a singleton list with one empty object (#3.1)
|
|
230
231
|
} = caps;
|
|
231
232
|
|
|
232
233
|
// Reject 'firstMatch' argument if it's not an array (#3.2)
|
|
@@ -247,7 +248,7 @@ function parseCaps(caps, constraints = /** @type {C} */ ({}), shouldValidateCaps
|
|
|
247
248
|
}
|
|
248
249
|
|
|
249
250
|
// Check for non-prefixed, non-standard capabilities and log warnings if they are found
|
|
250
|
-
|
|
251
|
+
const nonPrefixedCaps = findNonPrefixedCaps(caps);
|
|
251
252
|
if (!_.isEmpty(nonPrefixedCaps)) {
|
|
252
253
|
throw new errors.InvalidArgumentError(
|
|
253
254
|
`All non-standard capabilities should have a vendor prefix. The following capabilities did not have one: ${nonPrefixedCaps}`
|
|
@@ -256,8 +257,7 @@ function parseCaps(caps, constraints = /** @type {C} */ ({}), shouldValidateCaps
|
|
|
256
257
|
|
|
257
258
|
// Strip out the 'appium:' prefix from all
|
|
258
259
|
let strippedRequiredCaps = stripAppiumPrefixes(requiredCaps);
|
|
259
|
-
|
|
260
|
-
let strippedAllFirstMatchCaps = allFirstMatchCaps.map(stripAppiumPrefixes);
|
|
260
|
+
const strippedAllFirstMatchCaps: Capabilities<C>[] = allFirstMatchCaps.map(stripAppiumPrefixes);
|
|
261
261
|
|
|
262
262
|
// Validate the requiredCaps. But don't validate 'presence' because if that constraint fails on 'alwaysMatch' it could still pass on one of the 'firstMatch' keys
|
|
263
263
|
if (shouldValidateCaps) {
|
|
@@ -267,14 +267,11 @@ function parseCaps(caps, constraints = /** @type {C} */ ({}), shouldValidateCaps
|
|
|
267
267
|
}
|
|
268
268
|
// Remove the 'presence' constraint for any keys that are already present in 'requiredCaps'
|
|
269
269
|
// since we know that this constraint has already passed
|
|
270
|
-
const filteredConstraints =
|
|
271
|
-
_.omitBy(constraints, (_, key) => key in strippedRequiredCaps)
|
|
272
|
-
);
|
|
270
|
+
const filteredConstraints = _.omitBy(constraints, (_, key) => key in strippedRequiredCaps) as C;
|
|
273
271
|
|
|
274
272
|
// Validate all of the first match capabilities and return an array with only the valid caps (see spec #5)
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
let validatedFirstMatchCaps = _.compact(
|
|
273
|
+
const validationErrors: string[] = [];
|
|
274
|
+
const validatedFirstMatchCaps = _.compact(
|
|
278
275
|
strippedAllFirstMatchCaps.map((firstMatchCaps) => {
|
|
279
276
|
try {
|
|
280
277
|
// Validate firstMatch caps
|
|
@@ -285,17 +282,16 @@ function parseCaps(caps, constraints = /** @type {C} */ ({}), shouldValidateCaps
|
|
|
285
282
|
validationErrors.push(e.message);
|
|
286
283
|
}
|
|
287
284
|
})
|
|
288
|
-
);
|
|
285
|
+
) as Capabilities<C>[];
|
|
289
286
|
|
|
290
287
|
/**
|
|
291
288
|
* Try to merge requiredCaps with first match capabilities, break once it finds its first match
|
|
292
289
|
* (see spec #6)
|
|
293
|
-
* @type {ParsedCaps<C>['matchedCaps']}
|
|
294
290
|
*/
|
|
295
|
-
let matchedCaps = null;
|
|
296
|
-
for (
|
|
291
|
+
let matchedCaps: ParsedCaps<C>['matchedCaps'] = null;
|
|
292
|
+
for (const firstMatchCaps of validatedFirstMatchCaps) {
|
|
297
293
|
try {
|
|
298
|
-
matchedCaps = mergeCaps(strippedRequiredCaps, firstMatchCaps);
|
|
294
|
+
matchedCaps = mergeCaps(strippedRequiredCaps, firstMatchCaps) as ParsedCaps<C>['matchedCaps'];
|
|
299
295
|
if (matchedCaps) {
|
|
300
296
|
break;
|
|
301
297
|
}
|
|
@@ -317,18 +313,15 @@ function parseCaps(caps, constraints = /** @type {C} */ ({}), shouldValidateCaps
|
|
|
317
313
|
|
|
318
314
|
/**
|
|
319
315
|
* Calls parseCaps and just returns the matchedCaps variable
|
|
320
|
-
* @template {Constraints} C
|
|
321
|
-
* @template {W3CCapabilities<C>} W3CCaps
|
|
322
|
-
* @param {W3CCaps} w3cCaps
|
|
323
|
-
* @param {C} [constraints]
|
|
324
|
-
* @param {boolean} [shouldValidateCaps]
|
|
325
|
-
* @returns {Capabilities<C>}
|
|
326
316
|
*/
|
|
327
|
-
function processCapabilities
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
317
|
+
export function processCapabilities<
|
|
318
|
+
C extends Constraints,
|
|
319
|
+
W3CCaps extends W3CCapabilities<C>
|
|
320
|
+
>(
|
|
321
|
+
w3cCaps: W3CCaps,
|
|
322
|
+
constraints: C | undefined = {} as C,
|
|
323
|
+
shouldValidateCaps: boolean | undefined = true
|
|
324
|
+
): Capabilities<C> {
|
|
332
325
|
const {matchedCaps, validationErrors} = parseCaps(w3cCaps, constraints, shouldValidateCaps);
|
|
333
326
|
|
|
334
327
|
// If we found an error throw an exception
|
|
@@ -346,18 +339,14 @@ function processCapabilities(
|
|
|
346
339
|
}
|
|
347
340
|
}
|
|
348
341
|
|
|
349
|
-
return
|
|
342
|
+
return (matchedCaps ?? {}) as Capabilities<C>;
|
|
350
343
|
}
|
|
351
344
|
|
|
352
345
|
/**
|
|
353
346
|
* Return a copy of a "bare" (single-level, non-W3C) capabilities object which has taken everything
|
|
354
347
|
* within the 'appium:options' capability and promoted it to the top level.
|
|
355
|
-
*
|
|
356
|
-
* @template {Constraints} C
|
|
357
|
-
* @param {NSCapabilities<C>} obj
|
|
358
|
-
* @return {NSCapabilities<C>} the capabilities with 'options' promoted if necessary
|
|
359
348
|
*/
|
|
360
|
-
function promoteAppiumOptionsForObject(obj) {
|
|
349
|
+
export function promoteAppiumOptionsForObject<C extends Constraints>(obj: NSCapabilities<C>): NSCapabilities<C> {
|
|
361
350
|
const appiumOptions = obj[PREFIXED_APPIUM_OPTS_CAP];
|
|
362
351
|
if (!appiumOptions) {
|
|
363
352
|
return obj;
|
|
@@ -379,8 +368,8 @@ function promoteAppiumOptionsForObject(obj) {
|
|
|
379
368
|
/**
|
|
380
369
|
* @param {string} capName
|
|
381
370
|
*/
|
|
382
|
-
const shouldAddVendorPrefix = (capName) => !capName.startsWith(APPIUM_VENDOR_PREFIX);
|
|
383
|
-
const verifyIfAcceptable = (
|
|
371
|
+
const shouldAddVendorPrefix = (capName: string) => !capName.startsWith(APPIUM_VENDOR_PREFIX);
|
|
372
|
+
const verifyIfAcceptable = (capName: string) => {
|
|
384
373
|
if (!_.isString(capName)) {
|
|
385
374
|
throw new errors.SessionNotCreatedError(
|
|
386
375
|
`Capability names in ${PREFIXED_APPIUM_OPTS_CAP} must be strings. '${capName}' is unexpected`
|
|
@@ -394,8 +383,8 @@ function promoteAppiumOptionsForObject(obj) {
|
|
|
394
383
|
return capName;
|
|
395
384
|
};
|
|
396
385
|
const preprocessedOptions = _(appiumOptions)
|
|
397
|
-
.mapKeys((value,
|
|
398
|
-
.mapKeys((value, key) => (shouldAddVendorPrefix(key) ? `${APPIUM_VENDOR_PREFIX}${key}` : key))
|
|
386
|
+
.mapKeys((value, key: string) => verifyIfAcceptable(key))
|
|
387
|
+
.mapKeys((value, key: string) => (shouldAddVendorPrefix(key) ? `${APPIUM_VENDOR_PREFIX}${key}` : key))
|
|
399
388
|
.value();
|
|
400
389
|
// warn if we are going to overwrite any keys on the base caps object
|
|
401
390
|
const overwrittenKeys = _.intersection(Object.keys(obj), Object.keys(preprocessedOptions));
|
|
@@ -406,7 +395,7 @@ function promoteAppiumOptionsForObject(obj) {
|
|
|
406
395
|
);
|
|
407
396
|
}
|
|
408
397
|
return _.cloneDeep({
|
|
409
|
-
|
|
398
|
+
..._.omit(obj, PREFIXED_APPIUM_OPTS_CAP) as NSCapabilities<C>,
|
|
410
399
|
...preprocessedOptions,
|
|
411
400
|
});
|
|
412
401
|
}
|
|
@@ -414,13 +403,9 @@ function promoteAppiumOptionsForObject(obj) {
|
|
|
414
403
|
/**
|
|
415
404
|
* Return a copy of a capabilities object which has taken everything within the 'options'
|
|
416
405
|
* capability and promoted it to the top level.
|
|
417
|
-
*
|
|
418
|
-
* @template {Constraints} C
|
|
419
|
-
* @param {W3CCapabilities<C>} originalCaps
|
|
420
|
-
* @return {W3CCapabilities<C>} the capabilities with 'options' promoted if necessary
|
|
421
406
|
*/
|
|
422
|
-
function promoteAppiumOptions(originalCaps) {
|
|
423
|
-
const result = {}
|
|
407
|
+
export function promoteAppiumOptions<C extends Constraints>(originalCaps: W3CCapabilities<C>): W3CCapabilities<C> {
|
|
408
|
+
const result = {} as W3CCapabilities<C>;
|
|
424
409
|
const {alwaysMatch, firstMatch} = originalCaps;
|
|
425
410
|
if (_.isPlainObject(alwaysMatch)) {
|
|
426
411
|
result.alwaysMatch = promoteAppiumOptionsForObject(alwaysMatch);
|
|
@@ -434,59 +419,3 @@ function promoteAppiumOptions(originalCaps) {
|
|
|
434
419
|
}
|
|
435
420
|
return result;
|
|
436
421
|
}
|
|
437
|
-
|
|
438
|
-
export {
|
|
439
|
-
parseCaps,
|
|
440
|
-
processCapabilities,
|
|
441
|
-
validateCaps,
|
|
442
|
-
mergeCaps,
|
|
443
|
-
APPIUM_VENDOR_PREFIX,
|
|
444
|
-
findNonPrefixedCaps,
|
|
445
|
-
isStandardCap,
|
|
446
|
-
stripAppiumPrefixes,
|
|
447
|
-
promoteAppiumOptions,
|
|
448
|
-
promoteAppiumOptionsForObject,
|
|
449
|
-
PREFIXED_APPIUM_OPTS_CAP,
|
|
450
|
-
};
|
|
451
|
-
|
|
452
|
-
/**
|
|
453
|
-
* @typedef {import('@appium/types').Constraints} Constraints
|
|
454
|
-
* @typedef {import('@appium/types').Constraint} Constraint
|
|
455
|
-
* @typedef {import('@appium/types').StringRecord} StringRecord
|
|
456
|
-
* @typedef {import('@appium/types').BaseDriverCapConstraints} BaseDriverCapConstraints
|
|
457
|
-
*/
|
|
458
|
-
|
|
459
|
-
/**
|
|
460
|
-
* @template {Constraints} C
|
|
461
|
-
* @typedef {import('@appium/types').ConstraintsToCaps<C>} ConstraintsToCaps
|
|
462
|
-
*/
|
|
463
|
-
|
|
464
|
-
/**
|
|
465
|
-
* @typedef ValidateCapsOpts
|
|
466
|
-
* @property {boolean} [skipPresenceConstraint] - if true, skip the presence constraint
|
|
467
|
-
*/
|
|
468
|
-
|
|
469
|
-
/**
|
|
470
|
-
* @template {Constraints} C
|
|
471
|
-
* @typedef {import('@appium/types').NSCapabilities<C>} NSCapabilities
|
|
472
|
-
*/
|
|
473
|
-
|
|
474
|
-
/**
|
|
475
|
-
* @template {Constraints} C
|
|
476
|
-
* @typedef {import('@appium/types').Capabilities<C>} Capabilities
|
|
477
|
-
*/
|
|
478
|
-
|
|
479
|
-
/**
|
|
480
|
-
* @template {Constraints} C
|
|
481
|
-
* @typedef {import('@appium/types').W3CCapabilities<C>} W3CCapabilities
|
|
482
|
-
*/
|
|
483
|
-
|
|
484
|
-
/**
|
|
485
|
-
* @template T
|
|
486
|
-
* @typedef {import('type-fest').StringKeyOf<T>} StringKeyOf
|
|
487
|
-
*/
|
|
488
|
-
|
|
489
|
-
/**
|
|
490
|
-
* @template T,U
|
|
491
|
-
* @typedef {import('type-fest').MergeExclusive<T, U>} MergeExclusive<T,U>
|
|
492
|
-
*/
|
package/lib/protocol/errors.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import ES6Error from 'es6-error';
|
|
2
1
|
import _ from 'lodash';
|
|
3
2
|
import {util, logger} from '@appium/support';
|
|
4
3
|
import {StatusCodes as HTTPStatusCodes} from 'http-status-codes';
|
|
@@ -8,8 +7,36 @@ const w3cLog = logger.getLogger('W3C');
|
|
|
8
7
|
|
|
9
8
|
const W3C_UNKNOWN_ERROR = 'unknown error';
|
|
10
9
|
|
|
10
|
+
class BaseError extends Error {
|
|
11
|
+
constructor(message = '') {
|
|
12
|
+
super(message);
|
|
13
|
+
/** @type {[string, () => any][]} */
|
|
14
|
+
const propsMap = [
|
|
15
|
+
['message', () => message],
|
|
16
|
+
['name', () => this.constructor.name],
|
|
17
|
+
['stack', () => (new Error(message)).stack],
|
|
18
|
+
];
|
|
19
|
+
// eslint-disable-next-line no-prototype-builtins
|
|
20
|
+
const shouldSkipStack = Error.hasOwnProperty('captureStackTrace');
|
|
21
|
+
for (const [propName, valueGetter] of propsMap) {
|
|
22
|
+
if (propName === 'stack' && shouldSkipStack) {
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
Object.defineProperty(this, propName, {
|
|
26
|
+
configurable: true,
|
|
27
|
+
enumerable: false,
|
|
28
|
+
value: valueGetter(),
|
|
29
|
+
writable: true,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
if (shouldSkipStack) {
|
|
33
|
+
Error.captureStackTrace(this, this.constructor);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
11
38
|
// base error class for all of our errors
|
|
12
|
-
export class ProtocolError extends
|
|
39
|
+
export class ProtocolError extends BaseError {
|
|
13
40
|
constructor(msg, jsonwpCode, w3cStatus, error) {
|
|
14
41
|
super(msg);
|
|
15
42
|
this.jsonwpCode = jsonwpCode;
|
|
@@ -896,7 +923,7 @@ function generateBadParametersMessage(requiredParams, actualParams) {
|
|
|
896
923
|
}
|
|
897
924
|
|
|
898
925
|
// Equivalent to W3C InvalidArgumentError
|
|
899
|
-
export class BadParametersError extends
|
|
926
|
+
export class BadParametersError extends BaseError {
|
|
900
927
|
static error() {
|
|
901
928
|
return 'invalid argument';
|
|
902
929
|
}
|
|
@@ -916,7 +943,7 @@ export class BadParametersError extends ES6Error {
|
|
|
916
943
|
* In case of ProxyRequestError should fetch the actual error by calling `getActualError()`
|
|
917
944
|
* for proxy failure to generate the client response.
|
|
918
945
|
*/
|
|
919
|
-
export class ProxyRequestError extends
|
|
946
|
+
export class ProxyRequestError extends BaseError {
|
|
920
947
|
constructor(err, responseError, httpStatus) {
|
|
921
948
|
let responseErrorObj = util.safeJsonParse(responseError);
|
|
922
949
|
if (!_.isPlainObject(responseErrorObj)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@appium/base-driver",
|
|
3
|
-
"version": "9.5.
|
|
3
|
+
"version": "9.5.3",
|
|
4
4
|
"description": "Base driver class for Appium drivers",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"automation",
|
|
@@ -44,28 +44,27 @@
|
|
|
44
44
|
"test:types": "tsd"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@appium/support": "^4.2.
|
|
48
|
-
"@appium/types": "^0.16.
|
|
47
|
+
"@appium/support": "^4.2.3",
|
|
48
|
+
"@appium/types": "^0.16.2",
|
|
49
49
|
"@colors/colors": "1.6.0",
|
|
50
50
|
"@types/async-lock": "1.4.2",
|
|
51
51
|
"@types/bluebird": "3.5.42",
|
|
52
52
|
"@types/express": "4.17.21",
|
|
53
|
-
"@types/lodash": "4.
|
|
53
|
+
"@types/lodash": "4.17.0",
|
|
54
54
|
"@types/method-override": "0.0.35",
|
|
55
55
|
"@types/serve-favicon": "2.5.7",
|
|
56
56
|
"async-lock": "1.4.1",
|
|
57
57
|
"asyncbox": "3.0.0",
|
|
58
|
-
"axios": "1.6.
|
|
58
|
+
"axios": "1.6.8",
|
|
59
59
|
"bluebird": "3.7.2",
|
|
60
60
|
"body-parser": "1.20.2",
|
|
61
|
-
"
|
|
62
|
-
"express": "4.18.2",
|
|
61
|
+
"express": "4.19.2",
|
|
63
62
|
"http-status-codes": "2.3.0",
|
|
64
63
|
"lodash": "4.17.21",
|
|
65
64
|
"lru-cache": "10.2.0",
|
|
66
65
|
"method-override": "3.0.0",
|
|
67
66
|
"morgan": "1.10.0",
|
|
68
|
-
"path-to-regexp": "6.2.
|
|
67
|
+
"path-to-regexp": "6.2.2",
|
|
69
68
|
"serve-favicon": "2.5.0",
|
|
70
69
|
"source-map-support": "0.5.21",
|
|
71
70
|
"type-fest": "4.10.1",
|
|
@@ -81,7 +80,7 @@
|
|
|
81
80
|
"publishConfig": {
|
|
82
81
|
"access": "public"
|
|
83
82
|
},
|
|
84
|
-
"gitHead": "
|
|
83
|
+
"gitHead": "d44e66977c4fd7eb4587d9064594e2be5d311034",
|
|
85
84
|
"tsd": {
|
|
86
85
|
"directory": "test/types"
|
|
87
86
|
}
|