@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.
- package/build/lib/basedriver/capabilities.d.ts.map +1 -1
- package/build/lib/basedriver/capabilities.js +1 -1
- package/build/lib/basedriver/commands/event.js +1 -1
- package/build/lib/basedriver/commands/find.d.ts.map +1 -1
- package/build/lib/basedriver/commands/find.js +1 -1
- package/build/lib/basedriver/commands/index.js +1 -1
- package/build/lib/basedriver/commands/log.d.ts.map +1 -1
- package/build/lib/basedriver/commands/log.js +1 -1
- package/build/lib/basedriver/commands/session.js +1 -1
- package/build/lib/basedriver/commands/settings.d.ts.map +1 -1
- package/build/lib/basedriver/commands/settings.js +1 -1
- package/build/lib/basedriver/commands/timeout.d.ts.map +1 -1
- package/build/lib/basedriver/commands/timeout.js +1 -1
- package/build/lib/basedriver/core.d.ts +120 -139
- package/build/lib/basedriver/core.d.ts.map +1 -1
- package/build/lib/basedriver/core.js +1 -49
- package/build/lib/basedriver/desired-caps.d.ts +5 -2
- package/build/lib/basedriver/desired-caps.d.ts.map +1 -1
- package/build/lib/basedriver/desired-caps.js +14 -18
- package/build/lib/basedriver/device-settings.d.ts +9 -9
- package/build/lib/basedriver/device-settings.d.ts.map +1 -1
- package/build/lib/basedriver/device-settings.js +4 -4
- package/build/lib/basedriver/driver.d.ts +43 -38
- package/build/lib/basedriver/driver.d.ts.map +1 -1
- package/build/lib/basedriver/driver.js +58 -11
- package/build/lib/basedriver/helpers.d.ts +8 -3
- package/build/lib/basedriver/helpers.d.ts.map +1 -1
- package/build/lib/basedriver/helpers.js +4 -6
- package/build/lib/basedriver/logger.d.ts +1 -1
- package/build/lib/basedriver/logger.d.ts.map +1 -1
- package/build/lib/basedriver/logger.js +1 -1
- package/build/lib/constants.js +1 -1
- package/build/lib/express/crash.d.ts.map +1 -1
- package/build/lib/express/crash.js +1 -1
- package/build/lib/express/express-logging.d.ts.map +1 -1
- package/build/lib/express/express-logging.js +1 -1
- package/build/lib/express/idempotency.js +1 -1
- package/build/lib/express/logger.d.ts +1 -1
- package/build/lib/express/logger.d.ts.map +1 -1
- package/build/lib/express/logger.js +1 -1
- package/build/lib/express/middleware.d.ts.map +1 -1
- package/build/lib/express/middleware.js +1 -1
- package/build/lib/express/server.d.ts +21 -0
- package/build/lib/express/server.d.ts.map +1 -1
- package/build/lib/express/server.js +4 -9
- package/build/lib/express/static.d.ts.map +1 -1
- package/build/lib/express/static.js +2 -2
- package/build/lib/express/websocket.d.ts +14 -11
- package/build/lib/express/websocket.d.ts.map +1 -1
- package/build/lib/express/websocket.js +2 -2
- package/build/lib/helpers/capabilities.d.ts.map +1 -1
- package/build/lib/helpers/capabilities.js +1 -1
- package/build/lib/index.d.ts +2 -1
- package/build/lib/index.js +7 -1
- package/build/lib/jsonwp-proxy/protocol-converter.d.ts.map +1 -1
- package/build/lib/jsonwp-proxy/protocol-converter.js +2 -2
- package/build/lib/jsonwp-proxy/proxy.d.ts +30 -5
- package/build/lib/jsonwp-proxy/proxy.d.ts.map +1 -1
- package/build/lib/jsonwp-proxy/proxy.js +20 -4
- package/build/lib/jsonwp-status/status.d.ts.map +1 -1
- package/build/lib/jsonwp-status/status.js +2 -2
- package/build/lib/protocol/errors.d.ts +17 -8
- package/build/lib/protocol/errors.d.ts.map +1 -1
- package/build/lib/protocol/errors.js +9 -5
- package/build/lib/protocol/helpers.js +1 -1
- package/build/lib/protocol/index.js +1 -1
- package/build/lib/protocol/protocol.d.ts.map +1 -1
- package/build/lib/protocol/protocol.js +1 -1
- package/build/lib/protocol/routes.d.ts +17 -3
- package/build/lib/protocol/routes.d.ts.map +1 -1
- package/build/lib/protocol/routes.js +1 -1
- package/build/lib/protocol/validators.js +1 -1
- package/build/test/basedriver/driver-e2e-tests.js +1 -1
- package/build/test/basedriver/driver-tests.js +1 -1
- package/build/test/basedriver/index.js +1 -1
- package/build/test/e2e/basedriver/driver.e2e.spec.js +1 -1
- package/build/test/e2e/basedriver/helpers.e2e.spec.js +1 -1
- package/build/test/e2e/basedriver/websockets.e2e.spec.js +1 -1
- package/build/test/e2e/express/server.e2e.spec.js +1 -1
- package/build/test/e2e/jsonwp-proxy/proxy.e2e.spec.js +1 -1
- package/build/test/e2e/protocol/fake-driver.js +1 -1
- package/build/test/e2e/protocol/helpers.js +1 -1
- package/build/test/e2e/protocol/protocol.e2e.spec.js +13 -13
- package/build/test/helpers.js +1 -1
- package/build/test/unit/basedriver/capabilities.spec.js +12 -12
- package/build/test/unit/basedriver/capability.spec.js +15 -15
- package/build/test/unit/basedriver/commands/event.spec.js +1 -1
- package/build/test/unit/basedriver/commands/log.spec.js +1 -1
- package/build/test/unit/basedriver/device-settings.spec.js +1 -1
- package/build/test/unit/basedriver/driver.spec.js +1 -1
- package/build/test/unit/basedriver/helpers.spec.js +33 -33
- package/build/test/unit/basedriver/timeout.spec.js +1 -1
- package/build/test/unit/express/server.spec.js +1 -1
- package/build/test/unit/express/static.spec.js +2 -2
- package/build/test/unit/jsonwp-proxy/mock-request.js +1 -1
- package/build/test/unit/jsonwp-proxy/protocol-converter.spec.js +1 -1
- package/build/test/unit/jsonwp-proxy/proxy.spec.js +2 -2
- package/build/test/unit/jsonwp-proxy/url.spec.js +1 -1
- package/build/test/unit/jsonwp-status/status.spec.js +1 -1
- package/build/test/unit/protocol/errors.spec.js +1 -1
- package/build/test/unit/protocol/routes.spec.js +1 -1
- package/build/test/unit/protocol/validator.spec.js +1 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/lib/basedriver/capabilities.js +95 -47
- package/lib/basedriver/commands/event.js +4 -4
- package/lib/basedriver/commands/find.js +12 -26
- package/lib/basedriver/commands/index.js +7 -7
- package/lib/basedriver/commands/log.js +5 -7
- package/lib/basedriver/commands/session.js +3 -3
- package/lib/basedriver/commands/settings.js +3 -5
- package/lib/basedriver/commands/timeout.js +18 -23
- package/lib/basedriver/core.js +150 -229
- package/lib/basedriver/desired-caps.js +30 -29
- package/lib/basedriver/device-settings.js +21 -20
- package/lib/basedriver/driver.js +131 -96
- package/lib/basedriver/helpers.js +124 -81
- package/lib/basedriver/logger.js +1 -1
- package/lib/constants.js +2 -6
- package/lib/express/crash.js +4 -6
- package/lib/express/express-logging.js +26 -24
- package/lib/express/idempotency.js +16 -16
- package/lib/express/logger.js +1 -1
- package/lib/express/middleware.js +49 -33
- package/lib/express/server.js +68 -44
- package/lib/express/static.js +11 -12
- package/lib/express/websocket.js +26 -16
- package/lib/helpers/capabilities.js +11 -16
- package/lib/index.js +50 -33
- package/lib/jsonwp-proxy/protocol-converter.js +85 -69
- package/lib/jsonwp-proxy/proxy.js +116 -53
- package/lib/jsonwp-status/status.js +36 -29
- package/lib/protocol/errors.js +469 -292
- package/lib/protocol/helpers.js +5 -8
- package/lib/protocol/index.js +22 -15
- package/lib/protocol/protocol.js +103 -55
- package/lib/protocol/routes.js +430 -273
- package/lib/protocol/validators.js +5 -5
- package/package.json +9 -11
- package/test/basedriver/driver-e2e-tests.js +92 -66
- package/test/basedriver/driver-tests.js +90 -33
- package/test/basedriver/index.js +1 -1
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import log from './logger';
|
|
2
|
-
import
|
|
2
|
+
import _validator from 'validate.js';
|
|
3
3
|
import B from 'bluebird';
|
|
4
4
|
|
|
5
|
+
const validator =
|
|
6
|
+
/** @type {import('validate.js').ValidateJS & {promise: typeof import('bluebird')}} */ (
|
|
7
|
+
_validator
|
|
8
|
+
);
|
|
9
|
+
|
|
5
10
|
/** @type {import('@appium/types').Constraints} */
|
|
6
11
|
let desiredCapabilityConstraints = {
|
|
7
12
|
platformName: {
|
|
@@ -9,53 +14,50 @@ let desiredCapabilityConstraints = {
|
|
|
9
14
|
isString: true,
|
|
10
15
|
},
|
|
11
16
|
deviceName: {
|
|
12
|
-
isString: true
|
|
17
|
+
isString: true,
|
|
13
18
|
},
|
|
14
19
|
platformVersion: {
|
|
15
|
-
isString: true
|
|
20
|
+
isString: true,
|
|
16
21
|
},
|
|
17
22
|
newCommandTimeout: {
|
|
18
|
-
isNumber: true
|
|
23
|
+
isNumber: true,
|
|
19
24
|
},
|
|
20
25
|
automationName: {
|
|
21
|
-
isString: true
|
|
26
|
+
isString: true,
|
|
22
27
|
},
|
|
23
28
|
autoLaunch: {
|
|
24
|
-
isBoolean: true
|
|
29
|
+
isBoolean: true,
|
|
25
30
|
},
|
|
26
31
|
udid: {
|
|
27
|
-
isString: true
|
|
32
|
+
isString: true,
|
|
28
33
|
},
|
|
29
34
|
orientation: {
|
|
30
|
-
inclusion: [
|
|
31
|
-
'LANDSCAPE',
|
|
32
|
-
'PORTRAIT'
|
|
33
|
-
]
|
|
35
|
+
inclusion: ['LANDSCAPE', 'PORTRAIT'],
|
|
34
36
|
},
|
|
35
37
|
autoWebview: {
|
|
36
|
-
isBoolean: true
|
|
38
|
+
isBoolean: true,
|
|
37
39
|
},
|
|
38
40
|
noReset: {
|
|
39
|
-
isBoolean: true
|
|
41
|
+
isBoolean: true,
|
|
40
42
|
},
|
|
41
43
|
fullReset: {
|
|
42
|
-
isBoolean: true
|
|
44
|
+
isBoolean: true,
|
|
43
45
|
},
|
|
44
46
|
language: {
|
|
45
|
-
isString: true
|
|
47
|
+
isString: true,
|
|
46
48
|
},
|
|
47
49
|
locale: {
|
|
48
|
-
isString: true
|
|
50
|
+
isString: true,
|
|
49
51
|
},
|
|
50
52
|
eventTimings: {
|
|
51
|
-
isBoolean: true
|
|
53
|
+
isBoolean: true,
|
|
52
54
|
},
|
|
53
55
|
printPageSourceOnFindFailure: {
|
|
54
|
-
isBoolean: true
|
|
56
|
+
isBoolean: true,
|
|
55
57
|
},
|
|
56
58
|
};
|
|
57
59
|
|
|
58
|
-
validator.validators.isString = function isString
|
|
60
|
+
validator.validators.isString = function isString(value) {
|
|
59
61
|
if (typeof value === 'string') {
|
|
60
62
|
return null;
|
|
61
63
|
}
|
|
@@ -66,7 +68,7 @@ validator.validators.isString = function isString (value) {
|
|
|
66
68
|
|
|
67
69
|
return 'must be of type string';
|
|
68
70
|
};
|
|
69
|
-
validator.validators.isNumber = function isNumber
|
|
71
|
+
validator.validators.isNumber = function isNumber(value) {
|
|
70
72
|
if (typeof value === 'number') {
|
|
71
73
|
return null;
|
|
72
74
|
}
|
|
@@ -76,14 +78,14 @@ validator.validators.isNumber = function isNumber (value) {
|
|
|
76
78
|
}
|
|
77
79
|
|
|
78
80
|
// allow a string value
|
|
79
|
-
if (typeof value === 'string' && !isNaN(value)) {
|
|
81
|
+
if (typeof value === 'string' && !isNaN(Number(value))) {
|
|
80
82
|
log.warn('Number capability passed in as string. Functionality may be compromised.');
|
|
81
83
|
return null;
|
|
82
84
|
}
|
|
83
85
|
|
|
84
86
|
return 'must be of type number';
|
|
85
87
|
};
|
|
86
|
-
validator.validators.isBoolean = function isBoolean
|
|
88
|
+
validator.validators.isBoolean = function isBoolean(value) {
|
|
87
89
|
if (typeof value === 'boolean') {
|
|
88
90
|
return null;
|
|
89
91
|
}
|
|
@@ -99,7 +101,7 @@ validator.validators.isBoolean = function isBoolean (value) {
|
|
|
99
101
|
|
|
100
102
|
return 'must be of type boolean';
|
|
101
103
|
};
|
|
102
|
-
validator.validators.isObject = function isObject
|
|
104
|
+
validator.validators.isObject = function isObject(value) {
|
|
103
105
|
if (typeof value === 'object') {
|
|
104
106
|
return null;
|
|
105
107
|
}
|
|
@@ -110,7 +112,7 @@ validator.validators.isObject = function isObject (value) {
|
|
|
110
112
|
|
|
111
113
|
return 'must be of type object';
|
|
112
114
|
};
|
|
113
|
-
validator.validators.isArray = function isArray
|
|
115
|
+
validator.validators.isArray = function isArray(value) {
|
|
114
116
|
if (Array.isArray(value)) {
|
|
115
117
|
return null;
|
|
116
118
|
}
|
|
@@ -121,13 +123,13 @@ validator.validators.isArray = function isArray (value) {
|
|
|
121
123
|
|
|
122
124
|
return 'must be of type array';
|
|
123
125
|
};
|
|
124
|
-
validator.validators.deprecated = function deprecated
|
|
126
|
+
validator.validators.deprecated = function deprecated(value, options, key) {
|
|
125
127
|
if (options) {
|
|
126
128
|
log.warn(`${key} is a deprecated capability`);
|
|
127
129
|
}
|
|
128
130
|
return null;
|
|
129
131
|
};
|
|
130
|
-
validator.validators.inclusionCaseInsensitive = function inclusionCaseInsensitive
|
|
132
|
+
validator.validators.inclusionCaseInsensitive = function inclusionCaseInsensitive(value, options) {
|
|
131
133
|
if (typeof value === 'undefined') {
|
|
132
134
|
return null;
|
|
133
135
|
} else if (typeof value !== 'string') {
|
|
@@ -142,9 +144,8 @@ validator.validators.inclusionCaseInsensitive = function inclusionCaseInsensitiv
|
|
|
142
144
|
};
|
|
143
145
|
|
|
144
146
|
validator.promise = B;
|
|
145
|
-
validator.prettify = function prettify
|
|
147
|
+
validator.prettify = function prettify(val) {
|
|
146
148
|
return val;
|
|
147
149
|
};
|
|
148
150
|
|
|
149
|
-
|
|
150
|
-
export { desiredCapabilityConstraints, validator };
|
|
151
|
+
export {desiredCapabilityConstraints, validator};
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
1
|
import _ from 'lodash';
|
|
4
2
|
import log from './logger';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
3
|
+
import {node, util} from '@appium/support';
|
|
4
|
+
import {errors} from '../protocol/errors';
|
|
7
5
|
|
|
8
6
|
/**
|
|
9
7
|
* Maximum size (in bytes) of a given driver's settings object (which is internal to {@linkcode DriverSettings}).
|
|
@@ -11,14 +9,13 @@ import { errors } from '../protocol/errors';
|
|
|
11
9
|
export const MAX_SETTINGS_SIZE = 20 * 1024 * 1024; // 20 MB
|
|
12
10
|
|
|
13
11
|
/**
|
|
14
|
-
* @template
|
|
12
|
+
* @template T
|
|
15
13
|
* @implements {IDeviceSettings<T>}
|
|
16
14
|
*/
|
|
17
15
|
class DeviceSettings {
|
|
18
|
-
|
|
19
16
|
/**
|
|
20
17
|
* @protected
|
|
21
|
-
* @type {T}
|
|
18
|
+
* @type {Record<string,T>}
|
|
22
19
|
*/
|
|
23
20
|
_settings;
|
|
24
21
|
|
|
@@ -30,30 +27,34 @@ class DeviceSettings {
|
|
|
30
27
|
|
|
31
28
|
/**
|
|
32
29
|
* Creates a _shallow copy_ of the `defaultSettings` parameter!
|
|
33
|
-
* @param {T} [defaultSettings]
|
|
30
|
+
* @param {Record<string,T>} [defaultSettings]
|
|
34
31
|
* @param {import('@appium/types').SettingsUpdateListener<T>} [onSettingsUpdate]
|
|
35
32
|
*/
|
|
36
|
-
constructor
|
|
37
|
-
this._settings =
|
|
38
|
-
this._onSettingsUpdate = onSettingsUpdate
|
|
33
|
+
constructor(defaultSettings = {}, onSettingsUpdate = async () => {}) {
|
|
34
|
+
this._settings = {...defaultSettings};
|
|
35
|
+
this._onSettingsUpdate = onSettingsUpdate;
|
|
39
36
|
}
|
|
40
37
|
|
|
41
38
|
/**
|
|
42
39
|
* calls updateSettings from implementing driver every time a setting is changed.
|
|
43
|
-
* @param {T} newSettings
|
|
40
|
+
* @param {Record<string,T>} newSettings
|
|
44
41
|
*/
|
|
45
|
-
async update
|
|
42
|
+
async update(newSettings) {
|
|
46
43
|
if (!_.isPlainObject(newSettings)) {
|
|
47
|
-
throw new errors.InvalidArgumentError(
|
|
48
|
-
|
|
44
|
+
throw new errors.InvalidArgumentError(
|
|
45
|
+
`Settings update should be called with valid JSON. Got ` +
|
|
46
|
+
`${JSON.stringify(newSettings)} instead`
|
|
47
|
+
);
|
|
49
48
|
}
|
|
50
49
|
|
|
51
50
|
if (node.getObjectSize({...this._settings, ...newSettings}) >= MAX_SETTINGS_SIZE) {
|
|
52
|
-
throw new errors.InvalidArgumentError(
|
|
53
|
-
`
|
|
51
|
+
throw new errors.InvalidArgumentError(
|
|
52
|
+
`New settings cannot be applied, because the overall ` +
|
|
53
|
+
`object size exceeds the allowed limit of ${util.toReadableSizeString(MAX_SETTINGS_SIZE)}`
|
|
54
|
+
);
|
|
54
55
|
}
|
|
55
56
|
|
|
56
|
-
const props = /** @type {(keyof T & string)[]} */(_.keys(newSettings));
|
|
57
|
+
const props = /** @type {(keyof T & string)[]} */ (_.keys(newSettings));
|
|
57
58
|
for (const prop of props) {
|
|
58
59
|
if (!_.isUndefined(this._settings[prop])) {
|
|
59
60
|
if (this._settings[prop] === newSettings[prop]) {
|
|
@@ -66,13 +67,13 @@ class DeviceSettings {
|
|
|
66
67
|
}
|
|
67
68
|
}
|
|
68
69
|
|
|
69
|
-
getSettings
|
|
70
|
+
getSettings() {
|
|
70
71
|
return this._settings;
|
|
71
72
|
}
|
|
72
73
|
}
|
|
73
74
|
|
|
74
75
|
export default DeviceSettings;
|
|
75
|
-
export {
|
|
76
|
+
export {DeviceSettings};
|
|
76
77
|
|
|
77
78
|
/**
|
|
78
79
|
* @template T
|
package/lib/basedriver/driver.js
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
1
|
-
// @ts-check
|
|
2
1
|
/* eslint-disable require-await */
|
|
3
2
|
/* eslint-disable no-unused-vars */
|
|
4
3
|
|
|
5
|
-
import { DriverCore } from './core';
|
|
6
|
-
import { util } from '@appium/support';
|
|
7
|
-
import B from 'bluebird';
|
|
8
|
-
import _ from 'lodash';
|
|
9
|
-
import { fixCaps, isW3cCaps } from '../helpers/capabilities';
|
|
10
|
-
import { DELETE_SESSION_COMMAND, determineProtocol, errors } from '../protocol';
|
|
11
4
|
import {
|
|
5
|
+
validateCaps,
|
|
12
6
|
APPIUM_OPTS_CAP,
|
|
13
7
|
PREFIXED_APPIUM_OPTS_CAP,
|
|
14
8
|
processCapabilities,
|
|
15
|
-
promoteAppiumOptions
|
|
9
|
+
promoteAppiumOptions,
|
|
16
10
|
} from './capabilities';
|
|
17
|
-
import {
|
|
11
|
+
import {DriverCore} from './core';
|
|
12
|
+
import {util} from '@appium/support';
|
|
13
|
+
import B from 'bluebird';
|
|
14
|
+
import _ from 'lodash';
|
|
15
|
+
import {fixCaps, isW3cCaps} from '../helpers/capabilities';
|
|
16
|
+
import {DELETE_SESSION_COMMAND, determineProtocol, errors} from '../protocol';
|
|
17
|
+
import {createBaseDriverClass} from './commands';
|
|
18
18
|
import helpers from './helpers';
|
|
19
|
+
import {desiredCapabilityConstraints} from './desired-caps';
|
|
19
20
|
|
|
20
21
|
const EVENT_SESSION_INIT = 'newSessionRequested';
|
|
21
22
|
const EVENT_SESSION_START = 'newSessionStarted';
|
|
@@ -23,11 +24,11 @@ const EVENT_SESSION_QUIT_START = 'quitSessionRequested';
|
|
|
23
24
|
const EVENT_SESSION_QUIT_DONE = 'quitSessionFinished';
|
|
24
25
|
const ON_UNEXPECTED_SHUTDOWN_EVENT = 'onUnexpectedShutdown';
|
|
25
26
|
|
|
26
|
-
|
|
27
27
|
/**
|
|
28
28
|
* @implements {SessionHandler}
|
|
29
29
|
*/
|
|
30
30
|
export class BaseDriverCore extends DriverCore {
|
|
31
|
+
_constraints = _.cloneDeep(desiredCapabilityConstraints);
|
|
31
32
|
|
|
32
33
|
/** @type {Record<string,any>|undefined} */
|
|
33
34
|
cliArgs;
|
|
@@ -37,11 +38,11 @@ export class BaseDriverCore extends DriverCore {
|
|
|
37
38
|
// and ensuring that we execute commands one at a time. This method is called
|
|
38
39
|
// by MJSONWP's express router.
|
|
39
40
|
/**
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
async executeCommand
|
|
41
|
+
* @param {string} cmd
|
|
42
|
+
* @param {...any} args
|
|
43
|
+
* @returns {Promise<any>}
|
|
44
|
+
*/
|
|
45
|
+
async executeCommand(cmd, ...args) {
|
|
45
46
|
// get start time for this command, and log in special cases
|
|
46
47
|
let startTime = Date.now();
|
|
47
48
|
|
|
@@ -58,9 +59,7 @@ export class BaseDriverCore extends DriverCore {
|
|
|
58
59
|
await this.clearNewCommandTimeout();
|
|
59
60
|
|
|
60
61
|
if (this.shutdownUnexpectedly) {
|
|
61
|
-
throw new errors.NoSuchDriverError(
|
|
62
|
-
'The driver was unexpectedly shut down!',
|
|
63
|
-
);
|
|
62
|
+
throw new errors.NoSuchDriverError('The driver was unexpectedly shut down!');
|
|
64
63
|
}
|
|
65
64
|
|
|
66
65
|
// If we don't have this command, it must not be implemented
|
|
@@ -74,17 +73,14 @@ export class BaseDriverCore extends DriverCore {
|
|
|
74
73
|
this[cmd](...args),
|
|
75
74
|
new B((resolve, reject) => {
|
|
76
75
|
unexpectedShutdownListener = reject;
|
|
77
|
-
this.eventEmitter.on(
|
|
78
|
-
ON_UNEXPECTED_SHUTDOWN_EVENT,
|
|
79
|
-
unexpectedShutdownListener,
|
|
80
|
-
);
|
|
76
|
+
this.eventEmitter.on(ON_UNEXPECTED_SHUTDOWN_EVENT, unexpectedShutdownListener);
|
|
81
77
|
}),
|
|
82
78
|
]).finally(() => {
|
|
83
79
|
if (unexpectedShutdownListener) {
|
|
84
80
|
// This is needed to prevent memory leaks
|
|
85
81
|
this.eventEmitter.removeListener(
|
|
86
|
-
|
|
87
|
-
|
|
82
|
+
ON_UNEXPECTED_SHUTDOWN_EVENT,
|
|
83
|
+
unexpectedShutdownListener
|
|
88
84
|
);
|
|
89
85
|
unexpectedShutdownListener = null;
|
|
90
86
|
}
|
|
@@ -117,13 +113,11 @@ export class BaseDriverCore extends DriverCore {
|
|
|
117
113
|
}
|
|
118
114
|
|
|
119
115
|
/**
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
async startUnexpectedShutdown
|
|
124
|
-
err = new errors.NoSuchDriverError(
|
|
125
|
-
'The driver was unexpectedly shut down!',
|
|
126
|
-
),
|
|
116
|
+
*
|
|
117
|
+
* @param {Error} err
|
|
118
|
+
*/
|
|
119
|
+
async startUnexpectedShutdown(
|
|
120
|
+
err = new errors.NoSuchDriverError('The driver was unexpectedly shut down!')
|
|
127
121
|
) {
|
|
128
122
|
this.eventEmitter.emit(ON_UNEXPECTED_SHUTDOWN_EVENT, err); // allow others to listen for this
|
|
129
123
|
this.shutdownUnexpectedly = true;
|
|
@@ -136,7 +130,7 @@ export class BaseDriverCore extends DriverCore {
|
|
|
136
130
|
}
|
|
137
131
|
}
|
|
138
132
|
|
|
139
|
-
async startNewCommandTimeout
|
|
133
|
+
async startNewCommandTimeout() {
|
|
140
134
|
// make sure there are no rogue timeouts
|
|
141
135
|
await this.clearNewCommandTimeout();
|
|
142
136
|
|
|
@@ -146,7 +140,7 @@ export class BaseDriverCore extends DriverCore {
|
|
|
146
140
|
this.noCommandTimer = setTimeout(async () => {
|
|
147
141
|
this.log.warn(
|
|
148
142
|
`Shutting down because we waited ` +
|
|
149
|
-
`${this.newCommandTimeoutMs / 1000.0} seconds for a command
|
|
143
|
+
`${this.newCommandTimeoutMs / 1000.0} seconds for a command`
|
|
150
144
|
);
|
|
151
145
|
const errorMessage =
|
|
152
146
|
`New Command Timeout of ` +
|
|
@@ -164,7 +158,7 @@ export class BaseDriverCore extends DriverCore {
|
|
|
164
158
|
* @param {number} port
|
|
165
159
|
* @param {string} path
|
|
166
160
|
*/
|
|
167
|
-
assignServer
|
|
161
|
+
assignServer(server, host, port, path) {
|
|
168
162
|
this.server = server;
|
|
169
163
|
this.serverHost = host;
|
|
170
164
|
this.serverPort = port;
|
|
@@ -172,10 +166,10 @@ export class BaseDriverCore extends DriverCore {
|
|
|
172
166
|
}
|
|
173
167
|
|
|
174
168
|
/*
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
async reset
|
|
169
|
+
* Restart the session with the original caps,
|
|
170
|
+
* preserving the timeout config.
|
|
171
|
+
*/
|
|
172
|
+
async reset() {
|
|
179
173
|
this.log.debug('Resetting app mid-session');
|
|
180
174
|
this.log.debug('Running generic full reset');
|
|
181
175
|
|
|
@@ -209,40 +203,33 @@ export class BaseDriverCore extends DriverCore {
|
|
|
209
203
|
}
|
|
210
204
|
|
|
211
205
|
/**
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
async createSession
|
|
224
|
-
w3cCapabilities1,
|
|
225
|
-
w3cCapabilities2,
|
|
226
|
-
w3cCapabilities,
|
|
227
|
-
driverData,
|
|
228
|
-
) {
|
|
206
|
+
*
|
|
207
|
+
* Historically the first two arguments were reserved for JSONWP capabilities.
|
|
208
|
+
* Appium 2 has dropped the support of these, so now we only accept capability
|
|
209
|
+
* objects in W3C format and thus allow any of the three arguments to represent
|
|
210
|
+
* the latter.
|
|
211
|
+
* @param {W3CCapabilities} w3cCapabilities1
|
|
212
|
+
* @param {W3CCapabilities} [w3cCapabilities2]
|
|
213
|
+
* @param {W3CCapabilities} [w3cCapabilities]
|
|
214
|
+
* @param {DriverData[]} [driverData]
|
|
215
|
+
* @returns {Promise<[string,object]>}
|
|
216
|
+
*/
|
|
217
|
+
async createSession(w3cCapabilities1, w3cCapabilities2, w3cCapabilities, driverData) {
|
|
229
218
|
if (this.sessionId !== null) {
|
|
230
219
|
throw new errors.SessionNotCreatedError(
|
|
231
|
-
|
|
220
|
+
'Cannot create a new session while one is in progress'
|
|
232
221
|
);
|
|
233
222
|
}
|
|
234
223
|
|
|
235
224
|
this.log.debug();
|
|
236
225
|
|
|
237
|
-
const originalCaps = _.cloneDeep(
|
|
238
|
-
w3cCapabilities,
|
|
239
|
-
|
|
240
|
-
w3cCapabilities2,
|
|
241
|
-
].find(isW3cCaps));
|
|
226
|
+
const originalCaps = _.cloneDeep(
|
|
227
|
+
[w3cCapabilities, w3cCapabilities1, w3cCapabilities2].find(isW3cCaps)
|
|
228
|
+
);
|
|
242
229
|
if (!originalCaps) {
|
|
243
230
|
throw new errors.SessionNotCreatedError(
|
|
244
|
-
|
|
245
|
-
|
|
231
|
+
'Appium only supports W3C-style capability objects. ' +
|
|
232
|
+
'Your client is sending an older capabilities format. Please update your client library.'
|
|
246
233
|
);
|
|
247
234
|
}
|
|
248
235
|
|
|
@@ -250,23 +237,15 @@ export class BaseDriverCore extends DriverCore {
|
|
|
250
237
|
|
|
251
238
|
this.originalCaps = _.cloneDeep(originalCaps);
|
|
252
239
|
this.log.debug(
|
|
253
|
-
`Creating session with W3C capabilities: ${JSON.stringify(
|
|
254
|
-
originalCaps,
|
|
255
|
-
null,
|
|
256
|
-
2,
|
|
257
|
-
)}`,
|
|
240
|
+
`Creating session with W3C capabilities: ${JSON.stringify(originalCaps, null, 2)}`
|
|
258
241
|
);
|
|
259
242
|
|
|
260
243
|
let caps;
|
|
261
244
|
try {
|
|
262
|
-
caps = processCapabilities(
|
|
263
|
-
originalCaps,
|
|
264
|
-
this.desiredCapConstraints,
|
|
265
|
-
this.shouldValidateCaps,
|
|
266
|
-
);
|
|
245
|
+
caps = processCapabilities(originalCaps, this.desiredCapConstraints, this.shouldValidateCaps);
|
|
267
246
|
if (caps[APPIUM_OPTS_CAP]) {
|
|
268
247
|
this.log.debug(
|
|
269
|
-
|
|
248
|
+
`Found ${PREFIXED_APPIUM_OPTS_CAP} capability present; will promote items inside to caps`
|
|
270
249
|
);
|
|
271
250
|
caps = promoteAppiumOptions(caps);
|
|
272
251
|
}
|
|
@@ -289,9 +268,9 @@ export class BaseDriverCore extends DriverCore {
|
|
|
289
268
|
// both to true, but this is misguided and strange, so error here instead
|
|
290
269
|
if (this.opts.noReset && this.opts.fullReset) {
|
|
291
270
|
throw new Error(
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
271
|
+
"The 'noReset' and 'fullReset' capabilities are mutually " +
|
|
272
|
+
'exclusive and should not both be set to true. You ' +
|
|
273
|
+
"probably meant to just use 'fullReset' on its own"
|
|
295
274
|
);
|
|
296
275
|
}
|
|
297
276
|
if (this.opts.noReset === true) {
|
|
@@ -320,12 +299,12 @@ export class BaseDriverCore extends DriverCore {
|
|
|
320
299
|
}
|
|
321
300
|
|
|
322
301
|
/**
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
async deleteSession
|
|
302
|
+
*
|
|
303
|
+
* @param {string} [sessionId]
|
|
304
|
+
* @param {DriverData[]} [driverData]
|
|
305
|
+
* @returns {Promise<void>}
|
|
306
|
+
*/
|
|
307
|
+
async deleteSession(sessionId, driverData) {
|
|
329
308
|
await this.clearNewCommandTimeout();
|
|
330
309
|
if (this.isCommandsQueueEnabled && this.commandsQueueGuard.isBusy()) {
|
|
331
310
|
// simple hack to release pending commands if they exist
|
|
@@ -338,14 +317,80 @@ export class BaseDriverCore extends DriverCore {
|
|
|
338
317
|
this.sessionId = null;
|
|
339
318
|
this._log.prefix = helpers.generateDriverLogPrefix(this);
|
|
340
319
|
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
*
|
|
323
|
+
* @param {Capabilities} caps
|
|
324
|
+
*/
|
|
325
|
+
logExtraCaps(caps) {
|
|
326
|
+
let extraCaps = _.difference(_.keys(caps), _.keys(this._constraints));
|
|
327
|
+
if (extraCaps.length) {
|
|
328
|
+
this.log.warn(
|
|
329
|
+
`The following capabilities were provided, but are not ` + `recognized by Appium:`
|
|
330
|
+
);
|
|
331
|
+
for (const cap of extraCaps) {
|
|
332
|
+
this.log.warn(` ${cap}`);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
*
|
|
339
|
+
* @param {Capabilities} caps
|
|
340
|
+
* @returns {boolean}
|
|
341
|
+
*/
|
|
342
|
+
validateDesiredCaps(caps) {
|
|
343
|
+
if (!this.shouldValidateCaps) {
|
|
344
|
+
return true;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
try {
|
|
348
|
+
validateCaps(caps, this._constraints);
|
|
349
|
+
} catch (e) {
|
|
350
|
+
this.log.errorAndThrow(
|
|
351
|
+
new errors.SessionNotCreatedError(
|
|
352
|
+
`The desiredCapabilities object was not valid for the ` +
|
|
353
|
+
`following reason(s): ${e.message}`
|
|
354
|
+
)
|
|
355
|
+
);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
this.logExtraCaps(caps);
|
|
359
|
+
|
|
360
|
+
return true;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// we only want subclasses to ever extend the contraints
|
|
364
|
+
set desiredCapConstraints(constraints) {
|
|
365
|
+
this._constraints = Object.assign(this._constraints, constraints);
|
|
366
|
+
// 'presence' means different things in different versions of the validator,
|
|
367
|
+
// when we say 'true' we mean that it should not be able to be empty
|
|
368
|
+
for (const [, value] of _.toPairs(this._constraints)) {
|
|
369
|
+
if (value && value.presence === true) {
|
|
370
|
+
value.presence = {
|
|
371
|
+
allowEmpty: false,
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
get desiredCapConstraints() {
|
|
378
|
+
return this._constraints;
|
|
379
|
+
}
|
|
341
380
|
}
|
|
342
381
|
|
|
343
382
|
/**
|
|
344
383
|
* This ensures that all of the mixins correctly implement the interface described in {@linkcode Driver}.
|
|
345
384
|
* @implements {Driver}
|
|
346
385
|
*/
|
|
347
|
-
class
|
|
348
|
-
|
|
386
|
+
class _BaseDriver extends createBaseDriverClass(BaseDriverCore) {}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* @type {import('@appium/types').DriverClass<Driver>}
|
|
390
|
+
*/
|
|
391
|
+
const BaseDriver = _BaseDriver;
|
|
392
|
+
|
|
393
|
+
export {BaseDriver};
|
|
349
394
|
export default BaseDriver;
|
|
350
395
|
|
|
351
396
|
/**
|
|
@@ -357,7 +402,6 @@ export default BaseDriver;
|
|
|
357
402
|
* @typedef {import('@appium/types').DriverData} DriverData
|
|
358
403
|
*/
|
|
359
404
|
|
|
360
|
-
|
|
361
405
|
/**
|
|
362
406
|
* @callback UpdateServerCallback
|
|
363
407
|
* @param {import('express').Express} app - Express app
|
|
@@ -369,16 +413,7 @@ export default BaseDriver;
|
|
|
369
413
|
* This is used to extend {@linkcode BaseDriverCore} by the mixins and also external drivers.
|
|
370
414
|
* @template [Proto={}]
|
|
371
415
|
* @template [Static={}]
|
|
372
|
-
* @typedef {import('@appium/types').Class<BaseDriverCore & Proto,
|
|
373
|
-
*/
|
|
374
|
-
|
|
375
|
-
/**
|
|
376
|
-
* Static properties of `BaseDriver` and optional properties for subclasses.
|
|
377
|
-
* @template {ExternalDriver} [T=ExternalDriver]
|
|
378
|
-
* @typedef BaseDriverStatic
|
|
379
|
-
* @property {string} baseVersion
|
|
380
|
-
* @property {UpdateServerCallback} [updateServer]
|
|
381
|
-
* @property {import('@appium/types').MethodMap<T>} [newMethodMap]
|
|
416
|
+
* @typedef {import('@appium/types').Class<BaseDriverCore & Proto,import('@appium/types').DriverStatic & Static>} BaseDriverBase
|
|
382
417
|
*/
|
|
383
418
|
|
|
384
419
|
/**
|