appium 3.2.2 → 3.3.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/build/lib/appium.d.ts +147 -205
- package/build/lib/appium.d.ts.map +1 -1
- package/build/lib/appium.js +169 -282
- package/build/lib/appium.js.map +1 -1
- package/build/lib/bidi-commands.d.ts.map +1 -1
- package/build/lib/bidi-commands.js +11 -11
- package/build/lib/bidi-commands.js.map +1 -1
- package/build/lib/bootstrap/appium-initializer.d.ts +21 -0
- package/build/lib/bootstrap/appium-initializer.d.ts.map +1 -0
- package/build/lib/bootstrap/appium-initializer.js +146 -0
- package/build/lib/bootstrap/appium-initializer.js.map +1 -0
- package/build/lib/bootstrap/appium-main-runner.d.ts +22 -0
- package/build/lib/bootstrap/appium-main-runner.d.ts.map +1 -0
- package/build/lib/bootstrap/appium-main-runner.js +109 -0
- package/build/lib/bootstrap/appium-main-runner.js.map +1 -0
- package/build/lib/bootstrap/config-file.d.ts +37 -0
- package/build/lib/bootstrap/config-file.d.ts.map +1 -0
- package/build/lib/{config-file.js → bootstrap/config-file.js} +62 -138
- package/build/lib/bootstrap/config-file.js.map +1 -0
- package/build/lib/bootstrap/grid-v3-register.d.ts +20 -0
- package/build/lib/bootstrap/grid-v3-register.d.ts.map +1 -0
- package/build/lib/bootstrap/grid-v3-register.js +185 -0
- package/build/lib/bootstrap/grid-v3-register.js.map +1 -0
- package/build/lib/bootstrap/init-types.d.ts +16 -0
- package/build/lib/bootstrap/init-types.d.ts.map +1 -0
- package/build/lib/bootstrap/init-types.js +3 -0
- package/build/lib/bootstrap/init-types.js.map +1 -0
- package/build/lib/bootstrap/main-helpers.d.ts +55 -0
- package/build/lib/bootstrap/main-helpers.d.ts.map +1 -0
- package/build/lib/bootstrap/main-helpers.js +187 -0
- package/build/lib/bootstrap/main-helpers.js.map +1 -0
- package/build/lib/bootstrap/node-helpers.d.ts +32 -0
- package/build/lib/bootstrap/node-helpers.d.ts.map +1 -0
- package/build/lib/bootstrap/node-helpers.js +201 -0
- package/build/lib/bootstrap/node-helpers.js.map +1 -0
- package/build/lib/bootstrap/startup-config.d.ts +22 -0
- package/build/lib/bootstrap/startup-config.d.ts.map +1 -0
- package/build/lib/bootstrap/startup-config.js +111 -0
- package/build/lib/bootstrap/startup-config.js.map +1 -0
- package/build/lib/cli/args.d.ts +16 -12
- package/build/lib/cli/args.d.ts.map +1 -1
- package/build/lib/cli/args.js +20 -40
- package/build/lib/cli/args.js.map +1 -1
- package/build/lib/cli/driver-command.d.ts +51 -93
- package/build/lib/cli/driver-command.d.ts.map +1 -1
- package/build/lib/cli/driver-command.js +11 -66
- package/build/lib/cli/driver-command.js.map +1 -1
- package/build/lib/cli/extension-command.d.ts +173 -377
- package/build/lib/cli/extension-command.d.ts.map +1 -1
- package/build/lib/cli/extension-command.js +387 -656
- package/build/lib/cli/extension-command.js.map +1 -1
- package/build/lib/cli/extension.d.ts +10 -15
- package/build/lib/cli/extension.d.ts.map +1 -1
- package/build/lib/cli/extension.js +15 -33
- package/build/lib/cli/extension.js.map +1 -1
- package/build/lib/cli/parser.d.ts +37 -66
- package/build/lib/cli/parser.d.ts.map +1 -1
- package/build/lib/cli/parser.js +69 -104
- package/build/lib/cli/parser.js.map +1 -1
- package/build/lib/cli/plugin-command.d.ts +50 -90
- package/build/lib/cli/plugin-command.d.ts.map +1 -1
- package/build/lib/cli/plugin-command.js +11 -63
- package/build/lib/cli/plugin-command.js.map +1 -1
- package/build/lib/cli/setup-command.d.ts +21 -26
- package/build/lib/cli/setup-command.d.ts.map +1 -1
- package/build/lib/cli/setup-command.js +19 -61
- package/build/lib/cli/setup-command.js.map +1 -1
- package/build/lib/cli/utils.d.ts +33 -35
- package/build/lib/cli/utils.d.ts.map +1 -1
- package/build/lib/cli/utils.js +48 -50
- package/build/lib/cli/utils.js.map +1 -1
- package/build/lib/constants.d.ts +23 -23
- package/build/lib/constants.d.ts.map +1 -1
- package/build/lib/constants.js +10 -15
- package/build/lib/constants.js.map +1 -1
- package/build/lib/doctor/doctor.d.ts +40 -57
- package/build/lib/doctor/doctor.d.ts.map +1 -1
- package/build/lib/doctor/doctor.js +31 -62
- package/build/lib/doctor/doctor.js.map +1 -1
- package/build/lib/extension/driver-config.d.ts +18 -77
- package/build/lib/extension/driver-config.d.ts.map +1 -1
- package/build/lib/extension/driver-config.js +37 -125
- package/build/lib/extension/driver-config.js.map +1 -1
- package/build/lib/extension/extension-config.d.ts +103 -210
- package/build/lib/extension/extension-config.d.ts.map +1 -1
- package/build/lib/extension/extension-config.js +180 -342
- package/build/lib/extension/extension-config.js.map +1 -1
- package/build/lib/extension/index.d.ts +12 -29
- package/build/lib/extension/index.d.ts.map +1 -1
- package/build/lib/extension/index.js +33 -75
- package/build/lib/extension/index.js.map +1 -1
- package/build/lib/extension/manifest-migrations.d.ts +3 -20
- package/build/lib/extension/manifest-migrations.d.ts.map +1 -1
- package/build/lib/extension/manifest-migrations.js +20 -101
- package/build/lib/extension/manifest-migrations.js.map +1 -1
- package/build/lib/extension/manifest.d.ts +61 -107
- package/build/lib/extension/manifest.d.ts.map +1 -1
- package/build/lib/extension/manifest.js +181 -356
- package/build/lib/extension/manifest.js.map +1 -1
- package/build/lib/extension/package-changed.d.ts +1 -3
- package/build/lib/extension/package-changed.d.ts.map +1 -1
- package/build/lib/extension/package-changed.js +8 -15
- package/build/lib/extension/package-changed.js.map +1 -1
- package/build/lib/extension/plugin-config.d.ts +10 -52
- package/build/lib/extension/plugin-config.d.ts.map +1 -1
- package/build/lib/extension/plugin-config.js +11 -63
- package/build/lib/extension/plugin-config.js.map +1 -1
- package/build/lib/helpers/build.d.ts +22 -0
- package/build/lib/helpers/build.d.ts.map +1 -0
- package/build/lib/helpers/build.js +109 -0
- package/build/lib/helpers/build.js.map +1 -0
- package/build/lib/helpers/capability.d.ts +38 -0
- package/build/lib/helpers/capability.d.ts.map +1 -0
- package/build/lib/helpers/capability.js +128 -0
- package/build/lib/helpers/capability.js.map +1 -0
- package/build/lib/helpers/network.d.ts +14 -0
- package/build/lib/helpers/network.d.ts.map +1 -0
- package/build/lib/helpers/network.js +35 -0
- package/build/lib/helpers/network.js.map +1 -0
- package/build/lib/insecure-features.js +6 -6
- package/build/lib/insecure-features.js.map +1 -1
- package/build/lib/inspector-commands.d.ts +6 -0
- package/build/lib/inspector-commands.d.ts.map +1 -1
- package/build/lib/inspector-commands.js +6 -0
- package/build/lib/inspector-commands.js.map +1 -1
- package/build/lib/logger.d.ts +2 -3
- package/build/lib/logger.d.ts.map +1 -1
- package/build/lib/logger.js +2 -3
- package/build/lib/logger.js.map +1 -1
- package/build/lib/logsink.d.ts +13 -22
- package/build/lib/logsink.d.ts.map +1 -1
- package/build/lib/logsink.js +48 -103
- package/build/lib/logsink.js.map +1 -1
- package/build/lib/main.d.ts +15 -58
- package/build/lib/main.d.ts.map +1 -1
- package/build/lib/main.js +25 -425
- package/build/lib/main.js.map +1 -1
- package/build/lib/schema/arg-spec.d.ts +32 -107
- package/build/lib/schema/arg-spec.d.ts.map +1 -1
- package/build/lib/schema/arg-spec.js +11 -107
- package/build/lib/schema/arg-spec.js.map +1 -1
- package/build/lib/schema/cli-args-guards.d.ts +34 -0
- package/build/lib/schema/cli-args-guards.d.ts.map +1 -0
- package/build/lib/schema/cli-args-guards.js +49 -0
- package/build/lib/schema/cli-args-guards.js.map +1 -0
- package/build/lib/schema/cli-args.d.ts +3 -15
- package/build/lib/schema/cli-args.d.ts.map +1 -1
- package/build/lib/schema/cli-args.js +17 -107
- package/build/lib/schema/cli-args.js.map +1 -1
- package/build/lib/schema/cli-transformers.d.ts +15 -12
- package/build/lib/schema/cli-transformers.d.ts.map +1 -1
- package/build/lib/schema/cli-transformers.js +15 -45
- package/build/lib/schema/cli-transformers.js.map +1 -1
- package/build/lib/schema/format-errors.d.ts +28 -0
- package/build/lib/schema/format-errors.d.ts.map +1 -0
- package/build/lib/schema/format-errors.js +29 -0
- package/build/lib/schema/format-errors.js.map +1 -0
- package/build/lib/schema/index.d.ts +4 -2
- package/build/lib/schema/index.d.ts.map +1 -1
- package/build/lib/schema/index.js +2 -0
- package/build/lib/schema/index.js.map +1 -1
- package/build/lib/schema/keywords.d.ts +12 -20
- package/build/lib/schema/keywords.d.ts.map +1 -1
- package/build/lib/schema/keywords.js +6 -51
- package/build/lib/schema/keywords.js.map +1 -1
- package/build/lib/schema/schema.d.ts +106 -231
- package/build/lib/schema/schema.d.ts.map +1 -1
- package/build/lib/schema/schema.js +88 -358
- package/build/lib/schema/schema.js.map +1 -1
- package/build/lib/utils.d.ts +7 -267
- package/build/lib/utils.d.ts.map +1 -1
- package/build/lib/utils.js +10 -409
- package/build/lib/utils.js.map +1 -1
- package/lib/{appium.js → appium.ts} +297 -341
- package/lib/bidi-commands.ts +10 -14
- package/lib/bootstrap/appium-initializer.ts +212 -0
- package/lib/bootstrap/appium-main-runner.ts +172 -0
- package/lib/bootstrap/config-file.ts +178 -0
- package/lib/bootstrap/grid-v3-register.ts +250 -0
- package/lib/bootstrap/init-types.ts +31 -0
- package/lib/bootstrap/main-helpers.ts +223 -0
- package/lib/bootstrap/node-helpers.ts +180 -0
- package/lib/bootstrap/startup-config.ts +143 -0
- package/lib/cli/{args.js → args.ts} +45 -56
- package/lib/cli/driver-command.ts +122 -0
- package/lib/cli/{extension-command.js → extension-command.ts} +827 -906
- package/lib/cli/extension.ts +65 -0
- package/lib/cli/{parser.js → parser.ts} +93 -116
- package/lib/cli/plugin-command.ts +117 -0
- package/lib/cli/{setup-command.js → setup-command.ts} +59 -74
- package/lib/cli/utils.ts +97 -0
- package/lib/{constants.js → constants.ts} +30 -41
- package/lib/doctor/{doctor.js → doctor.ts} +82 -92
- package/lib/extension/driver-config.ts +165 -0
- package/lib/extension/{extension-config.js → extension-config.ts} +291 -405
- package/lib/extension/index.ts +143 -0
- package/lib/extension/manifest-migrations.ts +57 -0
- package/lib/extension/manifest.ts +369 -0
- package/lib/extension/{package-changed.js → package-changed.ts} +9 -18
- package/lib/extension/plugin-config.ts +62 -0
- package/lib/helpers/build.ts +111 -0
- package/lib/helpers/capability.ts +171 -0
- package/lib/helpers/network.ts +30 -0
- package/lib/insecure-features.ts +1 -1
- package/lib/inspector-commands.ts +6 -1
- package/lib/{logger.js → logger.ts} +1 -2
- package/lib/{logsink.js → logsink.ts} +91 -137
- package/lib/main.ts +60 -0
- package/lib/schema/arg-spec.ts +131 -0
- package/lib/schema/cli-args-guards.ts +67 -0
- package/lib/schema/cli-args.ts +171 -0
- package/lib/schema/cli-transformers.ts +83 -0
- package/lib/schema/format-errors.ts +43 -0
- package/lib/schema/index.ts +4 -0
- package/lib/schema/keywords.ts +96 -0
- package/lib/schema/schema.ts +448 -0
- package/lib/utils.ts +73 -0
- package/package.json +17 -18
- package/scripts/autoinstall-extensions.js +3 -0
- package/build/lib/config-file.d.ts +0 -100
- package/build/lib/config-file.d.ts.map +0 -1
- package/build/lib/config-file.js.map +0 -1
- package/build/lib/config.d.ts +0 -70
- package/build/lib/config.d.ts.map +0 -1
- package/build/lib/config.js +0 -390
- package/build/lib/config.js.map +0 -1
- package/build/lib/grid-register.d.ts +0 -10
- package/build/lib/grid-register.d.ts.map +0 -1
- package/build/lib/grid-register.js +0 -134
- package/build/lib/grid-register.js.map +0 -1
- package/lib/cli/driver-command.js +0 -174
- package/lib/cli/extension.js +0 -74
- package/lib/cli/plugin-command.js +0 -164
- package/lib/cli/utils.js +0 -91
- package/lib/config-file.js +0 -228
- package/lib/config.js +0 -389
- package/lib/extension/driver-config.js +0 -245
- package/lib/extension/index.js +0 -169
- package/lib/extension/manifest-migrations.js +0 -136
- package/lib/extension/manifest.js +0 -550
- package/lib/extension/plugin-config.js +0 -112
- package/lib/grid-register.js +0 -146
- package/lib/main.js +0 -545
- package/lib/schema/arg-spec.js +0 -229
- package/lib/schema/cli-args.js +0 -254
- package/lib/schema/cli-transformers.js +0 -113
- package/lib/schema/index.js +0 -2
- package/lib/schema/keywords.js +0 -136
- package/lib/schema/schema.js +0 -725
- package/lib/utils.js +0 -512
package/build/lib/appium.js
CHANGED
|
@@ -36,19 +36,18 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
36
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.
|
|
39
|
+
exports.NoDriverProxyCommandError = exports.AppiumDriver = void 0;
|
|
40
40
|
const lodash_1 = __importDefault(require("lodash"));
|
|
41
|
-
const config_1 = require("./config");
|
|
42
41
|
const base_driver_1 = require("@appium/base-driver");
|
|
43
|
-
const
|
|
44
|
-
const
|
|
42
|
+
const build_1 = require("./helpers/build");
|
|
43
|
+
const capability_1 = require("./helpers/capability");
|
|
45
44
|
const support_1 = require("@appium/support");
|
|
46
45
|
const schema_1 = require("./schema");
|
|
47
46
|
const constants_1 = require("./constants");
|
|
48
47
|
const bidiCommands = __importStar(require("./bidi-commands"));
|
|
49
48
|
const insecureFeatures = __importStar(require("./insecure-features"));
|
|
50
49
|
const inspectorCommands = __importStar(require("./inspector-commands"));
|
|
51
|
-
const desiredCapabilityConstraints =
|
|
50
|
+
const desiredCapabilityConstraints = {
|
|
52
51
|
automationName: {
|
|
53
52
|
presence: true,
|
|
54
53
|
isString: true,
|
|
@@ -57,65 +56,41 @@ const desiredCapabilityConstraints = /** @type {const} */ ({
|
|
|
57
56
|
presence: true,
|
|
58
57
|
isString: true,
|
|
59
58
|
},
|
|
60
|
-
}
|
|
61
|
-
const sessionsListGuard = new async_lock_1.default();
|
|
62
|
-
const pendingDriversGuard = new async_lock_1.default();
|
|
59
|
+
};
|
|
63
60
|
/**
|
|
64
|
-
*
|
|
61
|
+
* Umbrella driver: owns the session table, loads platform drivers and plugins, and routes
|
|
62
|
+
* commands to the right session driver or plugin chain.
|
|
65
63
|
*/
|
|
66
64
|
class AppiumDriver extends base_driver_1.DriverCore {
|
|
65
|
+
sessions = {};
|
|
66
|
+
pendingDrivers = {};
|
|
67
67
|
/**
|
|
68
|
-
*
|
|
69
|
-
* it might be changed by other async calls at any time
|
|
70
|
-
* It is not recommended to access this property directly from the outside
|
|
71
|
-
* @type {Record<string,ExternalDriver>}
|
|
72
|
-
*/
|
|
73
|
-
sessions;
|
|
74
|
-
/**
|
|
75
|
-
* Access to pending drivers list must be guarded with a Semaphore, because
|
|
76
|
-
* it might be changed by other async calls at any time
|
|
77
|
-
* It is not recommended to access this property directly from the outside
|
|
78
|
-
* @type {Record<string,ExternalDriver[]>}
|
|
79
|
-
*/
|
|
80
|
-
pendingDrivers;
|
|
81
|
-
/**
|
|
82
|
-
* Note that {@linkcode AppiumDriver} has no `newCommandTimeout` method.
|
|
83
|
-
* `AppiumDriver` does not set and observe its own timeouts; individual
|
|
84
|
-
* sessions (managed drivers) do instead.
|
|
68
|
+
* The umbrella driver does not observe its own command timeout; inner session drivers do.
|
|
85
69
|
*/
|
|
86
|
-
newCommandTimeoutMs;
|
|
87
|
-
/**
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* map of sessions to actual plugin instances per session
|
|
94
|
-
* @type {Record<string,InstanceType<PluginClass>[]>}
|
|
95
|
-
*/
|
|
96
|
-
sessionPlugins;
|
|
97
|
-
/**
|
|
98
|
-
* some commands are sessionless, so we need a set of plugins for them
|
|
99
|
-
* @type {InstanceType<PluginClass>[]}
|
|
100
|
-
*/
|
|
101
|
-
sessionlessPlugins;
|
|
102
|
-
/** @type {DriverConfig} */
|
|
70
|
+
newCommandTimeoutMs = 0;
|
|
71
|
+
/** Filled during server bootstrap; keep this map instance (do not reassign). */
|
|
72
|
+
pluginClasses = new Map();
|
|
73
|
+
sessionPlugins = {};
|
|
74
|
+
sessionlessPlugins = [];
|
|
75
|
+
/** Set during server init before listen; tests may assign a mock after construction. */
|
|
103
76
|
driverConfig;
|
|
104
|
-
/**
|
|
77
|
+
/** Set when the HTTP server is created in server bootstrap. */
|
|
105
78
|
server;
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
bidiProxyClients;
|
|
110
|
-
/**
|
|
111
|
-
* @type {AppiumDriverConstraints}
|
|
112
|
-
* @readonly
|
|
113
|
-
*/
|
|
114
|
-
desiredCapConstraints;
|
|
115
|
-
/** @type {import('@appium/types').DriverOpts<AppiumDriverConstraints>} */
|
|
79
|
+
bidiSockets = {};
|
|
80
|
+
bidiProxyClients = {};
|
|
81
|
+
desiredCapConstraints = desiredCapabilityConstraints;
|
|
116
82
|
args;
|
|
83
|
+
onBidiConnection = bidiCommands.onBidiConnection;
|
|
84
|
+
onBidiMessage = bidiCommands.onBidiMessage;
|
|
85
|
+
onBidiServerError = bidiCommands.onBidiServerError;
|
|
86
|
+
cleanupBidiSockets = bidiCommands.cleanupBidiSockets;
|
|
87
|
+
configureGlobalFeatures = insecureFeatures.configureGlobalFeatures;
|
|
88
|
+
configureDriverFeatures = insecureFeatures.configureDriverFeatures;
|
|
89
|
+
listCommands = inspectorCommands.listCommands;
|
|
90
|
+
listExtensions = inspectorCommands.listExtensions;
|
|
91
|
+
_isShuttingDown = false;
|
|
117
92
|
/**
|
|
118
|
-
* @param
|
|
93
|
+
* @param opts - CLI/server options (address, port, security, default capabilities, etc.)
|
|
119
94
|
*/
|
|
120
95
|
constructor(opts) {
|
|
121
96
|
// It is necessary to set `--tmp` here since it should be set to
|
|
@@ -127,42 +102,36 @@ class AppiumDriver extends base_driver_1.DriverCore {
|
|
|
127
102
|
}
|
|
128
103
|
super(opts);
|
|
129
104
|
this.args = { ...opts };
|
|
130
|
-
this.sessions = {};
|
|
131
|
-
this.pendingDrivers = {};
|
|
132
|
-
this.newCommandTimeoutMs = 0;
|
|
133
|
-
this.pluginClasses = new Map();
|
|
134
|
-
this.sessionPlugins = {};
|
|
135
|
-
this.sessionlessPlugins = [];
|
|
136
|
-
this.bidiSockets = {};
|
|
137
|
-
this.bidiProxyClients = {};
|
|
138
|
-
this.desiredCapConstraints = desiredCapabilityConstraints;
|
|
139
|
-
this._isShuttingDown = false;
|
|
140
105
|
// allow this to happen in the background, so no `await`
|
|
141
|
-
(async () => {
|
|
106
|
+
void (async () => {
|
|
142
107
|
try {
|
|
143
|
-
await (0,
|
|
108
|
+
await (0, build_1.updateBuildInfo)();
|
|
144
109
|
}
|
|
145
110
|
catch (e) {
|
|
146
111
|
// make sure we catch any possible errors to avoid unhandled rejections
|
|
147
|
-
|
|
112
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
113
|
+
this.log.debug(`Cannot fetch Appium build info: ${msg}`);
|
|
148
114
|
}
|
|
149
115
|
})();
|
|
150
116
|
}
|
|
151
|
-
/**
|
|
152
|
-
* Cancel commands queueing for the umbrella Appium driver
|
|
153
|
-
*/
|
|
117
|
+
/** The umbrella driver does not queue commands; inner session drivers may. */
|
|
154
118
|
get isCommandsQueueEnabled() {
|
|
155
119
|
return false;
|
|
156
120
|
}
|
|
121
|
+
/** Whether a non-null session id is registered on this server. */
|
|
157
122
|
sessionExists(sessionId) {
|
|
158
123
|
const dstSession = this.sessions[sessionId];
|
|
159
|
-
return dstSession && dstSession.sessionId !== null;
|
|
124
|
+
return Boolean(dstSession && dstSession.sessionId !== null);
|
|
160
125
|
}
|
|
126
|
+
/** Active automation driver for the session, or `null` if unknown. */
|
|
161
127
|
driverForSession(sessionId) {
|
|
162
|
-
return this.sessions[sessionId];
|
|
128
|
+
return this.sessions[sessionId] ?? null;
|
|
163
129
|
}
|
|
130
|
+
/**
|
|
131
|
+
* WebDriver status payload (readiness message and build metadata).
|
|
132
|
+
* @see https://www.w3.org/TR/webdriver/#dfn-status
|
|
133
|
+
*/
|
|
164
134
|
async getStatus() {
|
|
165
|
-
// https://www.w3.org/TR/webdriver/#dfn-status
|
|
166
135
|
const statusObj = this._isShuttingDown
|
|
167
136
|
? {
|
|
168
137
|
ready: false,
|
|
@@ -174,36 +143,34 @@ class AppiumDriver extends base_driver_1.DriverCore {
|
|
|
174
143
|
};
|
|
175
144
|
return {
|
|
176
145
|
...statusObj,
|
|
177
|
-
build: lodash_1.default.clone((0,
|
|
146
|
+
build: lodash_1.default.clone((0, build_1.getBuildInfo)()),
|
|
178
147
|
};
|
|
179
148
|
}
|
|
180
|
-
/**
|
|
181
|
-
* @param {string|null} reason An optional shutdown reason
|
|
182
|
-
*/
|
|
149
|
+
/** Marks the server as shutting down and ends all sessions (forced unexpected shutdown). */
|
|
183
150
|
async shutdown(reason = null) {
|
|
184
151
|
this._isShuttingDown = true;
|
|
185
152
|
await this.deleteAllSessions({
|
|
186
153
|
force: true,
|
|
187
|
-
reason,
|
|
154
|
+
reason: reason ?? undefined,
|
|
188
155
|
});
|
|
189
156
|
}
|
|
190
157
|
/**
|
|
191
158
|
* Retrieve information about all active sessions.
|
|
192
159
|
* Results are returned only if the `session_discovery` insecure feature is enabled.
|
|
193
|
-
* @returns {Promise<import('@appium/types').TimestampedMultiSessionData[]>}
|
|
194
160
|
*/
|
|
195
161
|
async getAppiumSessions() {
|
|
196
162
|
this.assertFeatureEnabled(constants_1.SESSION_DISCOVERY_FEATURE);
|
|
197
163
|
return lodash_1.default.toPairs(this.sessions).map(([id, driver]) => ({
|
|
198
164
|
id,
|
|
199
165
|
created: driver.sessionCreationTimestampMs,
|
|
200
|
-
capabilities:
|
|
166
|
+
capabilities: driver.caps,
|
|
201
167
|
}));
|
|
202
168
|
}
|
|
169
|
+
/** Logs BaseDriver version lines when starting a new inner-driver session. */
|
|
203
170
|
printNewSessionAnnouncement(driverName, driverVersion, driverBaseVersion) {
|
|
204
171
|
this.log.info(driverVersion
|
|
205
|
-
? `Appium v${
|
|
206
|
-
: `Appium v${
|
|
172
|
+
? `Appium v${build_1.APPIUM_VER} creating new ${driverName} (v${driverVersion}) session`
|
|
173
|
+
: `Appium v${build_1.APPIUM_VER} creating new ${driverName} session`);
|
|
207
174
|
this.log.info(`Checking BaseDriver versions for Appium and ${driverName}`);
|
|
208
175
|
this.log.info(AppiumDriver.baseVersion
|
|
209
176
|
? `Appium's BaseDriver version is ${AppiumDriver.baseVersion}`
|
|
@@ -213,82 +180,64 @@ class AppiumDriver extends base_driver_1.DriverCore {
|
|
|
213
180
|
: `Could not determine ${driverName}'s BaseDriver version`);
|
|
214
181
|
}
|
|
215
182
|
/**
|
|
216
|
-
*
|
|
217
|
-
* @param {string} extName - Plugin name
|
|
218
|
-
* @returns {StringRecord} Arguments object. If none, an empty object.
|
|
183
|
+
* CLI arguments object for a plugin (from server config). Empty object if none were passed.
|
|
219
184
|
*/
|
|
220
185
|
getCliArgsForPlugin(extName) {
|
|
221
|
-
return
|
|
186
|
+
return (this.args.plugin?.[extName] ?? {});
|
|
222
187
|
}
|
|
223
188
|
/**
|
|
224
|
-
*
|
|
225
|
-
*
|
|
226
|
-
*
|
|
227
|
-
*
|
|
228
|
-
* _Note that this behavior currently (May 18 2022) differs from how plugins are handled_ (see {@linkcode AppiumDriver.getCliArgsForPlugin}).
|
|
229
|
-
* @param {string} extName - Driver name
|
|
230
|
-
* @returns {StringRecord|undefined} Arguments object. If none, `undefined`
|
|
189
|
+
* CLI arguments for a driver, omitting keys that match schema defaults (unlike
|
|
190
|
+
* {@link AppiumDriver.getCliArgsForPlugin}, which returns defaults explicitly). `undefined` if
|
|
191
|
+
* there is nothing to pass after omitting defaults.
|
|
231
192
|
*/
|
|
232
193
|
getCliArgsForDriver(extName) {
|
|
233
|
-
const allCliArgsForExt =
|
|
234
|
-
if (
|
|
235
|
-
|
|
236
|
-
const cliArgs = lodash_1.default.isEmpty(defaults)
|
|
237
|
-
? allCliArgsForExt
|
|
238
|
-
: lodash_1.default.omitBy(allCliArgsForExt, (value, key) => lodash_1.default.isEqual(defaults[key], value));
|
|
239
|
-
if (!lodash_1.default.isEmpty(cliArgs)) {
|
|
240
|
-
return cliArgs;
|
|
241
|
-
}
|
|
194
|
+
const allCliArgsForExt = this.args.driver?.[extName];
|
|
195
|
+
if (lodash_1.default.isEmpty(allCliArgsForExt)) {
|
|
196
|
+
return undefined;
|
|
242
197
|
}
|
|
198
|
+
const defaults = (0, schema_1.getDefaultsForExtension)(constants_1.DRIVER_TYPE, extName);
|
|
199
|
+
const cliArgs = lodash_1.default.isEmpty(defaults)
|
|
200
|
+
? allCliArgsForExt
|
|
201
|
+
: lodash_1.default.omitBy(allCliArgsForExt, (value, key) => lodash_1.default.isEqual(defaults[key], value));
|
|
202
|
+
return lodash_1.default.isEmpty(cliArgs) ? undefined : cliArgs;
|
|
243
203
|
}
|
|
244
204
|
/**
|
|
245
|
-
*
|
|
246
|
-
*
|
|
247
|
-
*
|
|
248
|
-
* @param {W3CAppiumDriverCaps} [w3cCapabilities2] W3C capabilities (legacy)
|
|
249
|
-
* @param {W3CAppiumDriverCaps} [w3cCapabilities3] W3C capabilities (legacy)
|
|
250
|
-
* @returns {Promise<SessionHandlerCreateResult>}
|
|
205
|
+
* Creates a session: picks an inner driver from caps, runs plugin hooks, and returns a protocol
|
|
206
|
+
* envelope with either `[sessionId, caps, protocol]` or an error. Legacy call sites may pass the
|
|
207
|
+
* same W3C caps in up to three positions; the first W3C-shaped value wins.
|
|
251
208
|
*/
|
|
252
209
|
async createSession(w3cCapabilities1, w3cCapabilities2, w3cCapabilities3) {
|
|
253
210
|
const defaultCapabilities = lodash_1.default.cloneDeep(this.args.defaultCapabilities);
|
|
254
|
-
const defaultSettings = (0,
|
|
211
|
+
const defaultSettings = (0, capability_1.pullSettings)((defaultCapabilities ?? {}));
|
|
255
212
|
const w3cCapabilities = lodash_1.default.cloneDeep([w3cCapabilities3, w3cCapabilities2, w3cCapabilities1].find(base_driver_1.isW3cCaps));
|
|
256
213
|
if (!w3cCapabilities) {
|
|
257
|
-
throw (0,
|
|
214
|
+
throw (0, capability_1.makeNonW3cCapsError)();
|
|
258
215
|
}
|
|
259
216
|
const w3cSettings = {
|
|
260
217
|
...defaultSettings,
|
|
261
|
-
...(0,
|
|
218
|
+
...(0, capability_1.pullSettings)(w3cCapabilities.alwaysMatch ?? {}),
|
|
262
219
|
};
|
|
263
220
|
for (const firstMatchEntry of w3cCapabilities.firstMatch ?? []) {
|
|
264
|
-
Object.assign(w3cSettings, (0,
|
|
221
|
+
Object.assign(w3cSettings, (0, capability_1.pullSettings)(firstMatchEntry));
|
|
265
222
|
}
|
|
266
223
|
const protocol = base_driver_1.PROTOCOLS.W3C;
|
|
267
|
-
let innerSessionId
|
|
224
|
+
let innerSessionId;
|
|
225
|
+
let dCaps;
|
|
268
226
|
try {
|
|
269
227
|
// Parse the caps into a format that the InnerDriver will accept
|
|
270
|
-
const parsedCaps = (0,
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
const error = /** @type {import('./utils').InvalidCaps<AppiumDriverConstraints>} */ (parsedCaps).error;
|
|
274
|
-
// If the parsing of the caps produced an error, throw it in here
|
|
275
|
-
if (error) {
|
|
276
|
-
throw error;
|
|
228
|
+
const parsedCaps = (0, capability_1.parseCapsForInnerDriver)((0, base_driver_1.promoteAppiumOptions)(w3cCapabilities), this.desiredCapConstraints, defaultCapabilities ? (0, base_driver_1.promoteAppiumOptionsForObject)(defaultCapabilities) : undefined);
|
|
229
|
+
if ('error' in parsedCaps && parsedCaps.error) {
|
|
230
|
+
throw parsedCaps.error;
|
|
277
231
|
}
|
|
232
|
+
const { desiredCaps, processedW3CCapabilities } = parsedCaps;
|
|
278
233
|
const { driver: InnerDriver, version: driverVersion, driverName, } = await this.driverConfig.findMatchingDriver(desiredCaps);
|
|
279
234
|
this.printNewSessionAnnouncement(InnerDriver.name, driverVersion, InnerDriver.baseVersion);
|
|
280
235
|
if (this.args.sessionOverride) {
|
|
281
236
|
await this.deleteAllSessions();
|
|
282
237
|
}
|
|
283
|
-
/**
|
|
284
|
-
* @type {DriverData[]}
|
|
285
|
-
*/
|
|
286
238
|
let runningDriversData = [];
|
|
287
|
-
/**
|
|
288
|
-
* @type {DriverData[]}
|
|
289
|
-
*/
|
|
290
239
|
let otherPendingDriversData = [];
|
|
291
|
-
const driverInstance =
|
|
240
|
+
const driverInstance = new InnerDriver(this.args, true);
|
|
292
241
|
this.configureDriverFeatures(driverInstance, driverName);
|
|
293
242
|
// We also want to assign any new Bidi Commands that the driver has specified, including all
|
|
294
243
|
// the standard bidi commands. But add a method existence guard since some old driver class
|
|
@@ -313,22 +262,18 @@ class AppiumDriver extends base_driver_1.DriverCore {
|
|
|
313
262
|
runningDriversData = (await this.curSessionDataForDriver(InnerDriver)) ?? [];
|
|
314
263
|
}
|
|
315
264
|
catch (e) {
|
|
316
|
-
|
|
265
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
266
|
+
throw new base_driver_1.errors.SessionNotCreatedError(msg);
|
|
317
267
|
}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
this.pendingDrivers[InnerDriver.name].push(driverInstance);
|
|
322
|
-
});
|
|
268
|
+
this.pendingDrivers[InnerDriver.name] = this.pendingDrivers[InnerDriver.name] || [];
|
|
269
|
+
otherPendingDriversData = lodash_1.default.compact(this.pendingDrivers[InnerDriver.name].map((drv) => drv.driverData));
|
|
270
|
+
this.pendingDrivers[InnerDriver.name].push(driverInstance);
|
|
323
271
|
try {
|
|
324
|
-
[innerSessionId, dCaps] = await driverInstance.createSession(
|
|
325
|
-
/** @type {any} */ (processedW3CCapabilities), processedW3CCapabilities, processedW3CCapabilities, [...runningDriversData, ...otherPendingDriversData]);
|
|
272
|
+
[innerSessionId, dCaps] = (await driverInstance.createSession(processedW3CCapabilities, processedW3CCapabilities, processedW3CCapabilities, [...runningDriversData, ...otherPendingDriversData]));
|
|
326
273
|
this.sessions[innerSessionId] = driverInstance;
|
|
327
274
|
}
|
|
328
275
|
finally {
|
|
329
|
-
|
|
330
|
-
lodash_1.default.pull(this.pendingDrivers[InnerDriver.name], driverInstance);
|
|
331
|
-
});
|
|
276
|
+
lodash_1.default.pull(this.pendingDrivers[InnerDriver.name], driverInstance);
|
|
332
277
|
}
|
|
333
278
|
this.attachUnexpectedShutdownHandler(driverInstance, innerSessionId);
|
|
334
279
|
this.log.info(`New ${InnerDriver.name} session created successfully, session ` +
|
|
@@ -360,7 +305,7 @@ class AppiumDriver extends base_driver_1.DriverCore {
|
|
|
360
305
|
catch (error) {
|
|
361
306
|
return {
|
|
362
307
|
protocol,
|
|
363
|
-
error,
|
|
308
|
+
error: error instanceof Error ? error : new Error(String(error)),
|
|
364
309
|
};
|
|
365
310
|
}
|
|
366
311
|
return {
|
|
@@ -369,19 +314,18 @@ class AppiumDriver extends base_driver_1.DriverCore {
|
|
|
369
314
|
};
|
|
370
315
|
}
|
|
371
316
|
/**
|
|
372
|
-
*
|
|
373
|
-
*
|
|
374
|
-
* @param {string} innerSessionId
|
|
317
|
+
* Subscribes to the inner driver’s unexpected-shutdown hook so Appium can drop the session and
|
|
318
|
+
* notify plugins.
|
|
375
319
|
*/
|
|
376
320
|
attachUnexpectedShutdownHandler(driver, innerSessionId) {
|
|
377
|
-
const onShutdown = (cause = new Error('Unknown error')) => {
|
|
321
|
+
const onShutdown = async (cause = new Error('Unknown error')) => {
|
|
378
322
|
this.log.warn(`Ending session, cause was '${cause.message}'`);
|
|
379
323
|
if (this.sessionPlugins[innerSessionId]) {
|
|
380
324
|
for (const plugin of this.sessionPlugins[innerSessionId]) {
|
|
381
325
|
if (lodash_1.default.isFunction(plugin.onUnexpectedShutdown)) {
|
|
382
326
|
this.log.debug(`Plugin ${plugin.name} defines an unexpected shutdown handler; calling it now`);
|
|
383
327
|
try {
|
|
384
|
-
plugin.onUnexpectedShutdown(driver, cause);
|
|
328
|
+
await plugin.onUnexpectedShutdown(driver, cause);
|
|
385
329
|
}
|
|
386
330
|
catch (e) {
|
|
387
331
|
this.log.warn(`Got an error when running plugin ${plugin.name} shutdown handler: ${e}`);
|
|
@@ -405,11 +349,9 @@ class AppiumDriver extends base_driver_1.DriverCore {
|
|
|
405
349
|
}
|
|
406
350
|
}
|
|
407
351
|
/**
|
|
408
|
-
*
|
|
409
|
-
*
|
|
410
|
-
* @
|
|
411
|
-
* @privateRemarks The _intent_ is that `InnerDriver` is the class of a driver, but it only really
|
|
412
|
-
* needs to be a function or constructor.
|
|
352
|
+
* Collects `driverData` for every active session whose driver class matches `InnerDriver.name`
|
|
353
|
+
* (used when creating another session of the same driver type).
|
|
354
|
+
* @remarks `InnerDriver` is expected to be the driver class; only `.name` is read.
|
|
413
355
|
*/
|
|
414
356
|
async curSessionDataForDriver(InnerDriver) {
|
|
415
357
|
const data = lodash_1.default.compact(lodash_1.default.values(this.sessions)
|
|
@@ -424,21 +366,20 @@ class AppiumDriver extends base_driver_1.DriverCore {
|
|
|
424
366
|
return data;
|
|
425
367
|
}
|
|
426
368
|
/**
|
|
427
|
-
*
|
|
369
|
+
* Ends one session: removes it from the master list immediately, then delegates to the inner
|
|
370
|
+
* driver’s `deleteSession` with sibling-session metadata.
|
|
428
371
|
*/
|
|
429
372
|
async deleteSession(sessionId) {
|
|
430
373
|
let protocol;
|
|
431
374
|
try {
|
|
432
375
|
let otherSessionsData;
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
return;
|
|
436
|
-
}
|
|
376
|
+
let dstSession;
|
|
377
|
+
if (this.sessions[sessionId]) {
|
|
437
378
|
const curConstructorName = this.sessions[sessionId].constructor.name;
|
|
438
379
|
otherSessionsData = lodash_1.default.toPairs(this.sessions)
|
|
439
380
|
.filter(([key, value]) => value.constructor.name === curConstructorName && key !== sessionId)
|
|
440
381
|
.map(([, value]) => value.driverData);
|
|
441
|
-
|
|
382
|
+
dstSession = this.sessions[sessionId];
|
|
442
383
|
protocol = dstSession.protocol;
|
|
443
384
|
this.log.info(`Removing session ${sessionId} from our master session list`);
|
|
444
385
|
// regardless of whether the deleteSession completes successfully or not
|
|
@@ -447,8 +388,7 @@ class AppiumDriver extends base_driver_1.DriverCore {
|
|
|
447
388
|
delete this.sessions[sessionId];
|
|
448
389
|
delete this.sessionPlugins[sessionId];
|
|
449
390
|
this.cleanupBidiSockets(sessionId);
|
|
450
|
-
|
|
451
|
-
});
|
|
391
|
+
}
|
|
452
392
|
// this may not be correct, but if `dstSession` was falsy, the call to `deleteSession()` would
|
|
453
393
|
// throw anyway.
|
|
454
394
|
if (!dstSession) {
|
|
@@ -460,13 +400,18 @@ class AppiumDriver extends base_driver_1.DriverCore {
|
|
|
460
400
|
};
|
|
461
401
|
}
|
|
462
402
|
catch (e) {
|
|
463
|
-
|
|
403
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
404
|
+
this.log.error(`Had trouble ending session ${sessionId}: ${msg}`);
|
|
464
405
|
return {
|
|
465
406
|
protocol,
|
|
466
|
-
error: e,
|
|
407
|
+
error: e instanceof Error ? e : new Error(msg),
|
|
467
408
|
};
|
|
468
409
|
}
|
|
469
410
|
}
|
|
411
|
+
/**
|
|
412
|
+
* Ends every active session, either by normal `deleteSession` or by `startUnexpectedShutdown`
|
|
413
|
+
* when `force` is true.
|
|
414
|
+
*/
|
|
470
415
|
async deleteAllSessions(opts = {}) {
|
|
471
416
|
const sessionsCount = lodash_1.default.size(this.sessions);
|
|
472
417
|
if (0 === sessionsCount) {
|
|
@@ -476,7 +421,7 @@ class AppiumDriver extends base_driver_1.DriverCore {
|
|
|
476
421
|
const { force = false, reason } = opts;
|
|
477
422
|
this.log.debug(`Cleaning up ${support_1.util.pluralize('active session', sessionsCount, true)}`);
|
|
478
423
|
const cleanupPromises = force
|
|
479
|
-
? lodash_1.default.values(this.sessions).map((drv) => drv.startUnexpectedShutdown(reason
|
|
424
|
+
? lodash_1.default.values(this.sessions).map((drv) => drv.startUnexpectedShutdown(reason ? new Error(reason) : undefined))
|
|
480
425
|
: lodash_1.default.keys(this.sessions).map((id) => this.deleteSession(id));
|
|
481
426
|
for (const cleanupPromise of cleanupPromises) {
|
|
482
427
|
try {
|
|
@@ -488,16 +433,20 @@ class AppiumDriver extends base_driver_1.DriverCore {
|
|
|
488
433
|
}
|
|
489
434
|
}
|
|
490
435
|
/**
|
|
491
|
-
*
|
|
492
|
-
*
|
|
493
|
-
* @param {string|null} [sessionId=null] - the sessionId (or null) to use to find plugins
|
|
494
|
-
* @returns {Array<import('@appium/types').Plugin>} - array of plugin instances
|
|
436
|
+
* Plugin instances for a session id, or the shared sessionless list when `sessionId` is null.
|
|
437
|
+
* Lazily builds sessionless instances on first use.
|
|
495
438
|
*/
|
|
496
439
|
pluginsForSession(sessionId = null) {
|
|
497
440
|
if (sessionId) {
|
|
441
|
+
const existingPlugins = this.sessionPlugins[sessionId];
|
|
442
|
+
if (existingPlugins) {
|
|
443
|
+
return existingPlugins;
|
|
444
|
+
}
|
|
498
445
|
const driver = this.sessions[sessionId];
|
|
499
|
-
|
|
500
|
-
|
|
446
|
+
if (!driver) {
|
|
447
|
+
return [];
|
|
448
|
+
}
|
|
449
|
+
return (this.sessionPlugins[sessionId] = this.createPluginInstances((0, base_driver_1.generateDriverLogPrefix)(driver)));
|
|
501
450
|
}
|
|
502
451
|
if (lodash_1.default.isEmpty(this.sessionlessPlugins)) {
|
|
503
452
|
this.sessionlessPlugins = this.createPluginInstances();
|
|
@@ -505,14 +454,8 @@ class AppiumDriver extends base_driver_1.DriverCore {
|
|
|
505
454
|
return this.sessionlessPlugins;
|
|
506
455
|
}
|
|
507
456
|
/**
|
|
508
|
-
*
|
|
509
|
-
*
|
|
510
|
-
* plugin instances reserved for sessionless commands (and we lazily create plugin instances on
|
|
511
|
-
* first use)
|
|
512
|
-
*
|
|
513
|
-
* @param {string} cmd - the name of the command to find a plugin to handle
|
|
514
|
-
* @param {?string} sessionId - the particular session for which to find a plugin, or null if
|
|
515
|
-
* sessionless
|
|
457
|
+
* Plugins that declare a method named `cmd` or a generic `handle` method, scoped to the given
|
|
458
|
+
* session (or sessionless when `sessionId` is null).
|
|
516
459
|
*/
|
|
517
460
|
pluginsToHandleCmd(cmd, sessionId = null) {
|
|
518
461
|
// to handle a given command, a plugin should either implement that command as a plugin
|
|
@@ -520,29 +463,25 @@ class AppiumDriver extends base_driver_1.DriverCore {
|
|
|
520
463
|
return this.pluginsForSession(sessionId).filter((p) => lodash_1.default.isFunction(p[cmd]) || lodash_1.default.isFunction(p.handle));
|
|
521
464
|
}
|
|
522
465
|
/**
|
|
523
|
-
*
|
|
524
|
-
*
|
|
525
|
-
* @returns {Plugin[]}
|
|
466
|
+
* One instance per registered plugin class. `driverId` becomes the plugin log prefix segment
|
|
467
|
+
* when tied to a session driver; use `null` for sessionless plugins.
|
|
526
468
|
*/
|
|
527
469
|
createPluginInstances(driverId = null) {
|
|
528
|
-
/** @type {Plugin[]} */
|
|
529
470
|
const pluginInstances = [];
|
|
530
471
|
for (const [PluginClass, name] of this.pluginClasses.entries()) {
|
|
531
472
|
const cliArgs = this.getCliArgsForPlugin(name);
|
|
532
473
|
const plugin = new PluginClass(name, cliArgs, driverId);
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
474
|
+
const extPlugin = plugin;
|
|
475
|
+
if (lodash_1.default.isFunction(extPlugin.updateBidiCommands)) {
|
|
476
|
+
extPlugin.updateBidiCommands(PluginClass.newBidiCommands ?? {});
|
|
536
477
|
}
|
|
537
478
|
pluginInstances.push(plugin);
|
|
538
479
|
}
|
|
539
480
|
return pluginInstances;
|
|
540
481
|
}
|
|
541
482
|
/**
|
|
542
|
-
*
|
|
543
|
-
*
|
|
544
|
-
* @param {...any} args
|
|
545
|
-
* @returns {Promise<{value: any, error?: Error, protocol: string} | import('type-fest').AsyncReturnType<ExternalDriver['executeCommand']>>}
|
|
483
|
+
* Dispatches a WebDriver/Appium command: may run on this driver, a session’s inner driver, or
|
|
484
|
+
* through a plugin chain, and normalizes the return value into a protocol-shaped result.
|
|
546
485
|
*/
|
|
547
486
|
async executeCommand(cmd, ...args) {
|
|
548
487
|
// We have basically three cases for how to handle commands:
|
|
@@ -568,12 +507,11 @@ class AppiumDriver extends base_driver_1.DriverCore {
|
|
|
568
507
|
let sessionId = null;
|
|
569
508
|
let dstSession = null;
|
|
570
509
|
let protocol = null;
|
|
571
|
-
/** @type {this | ExternalDriver} */
|
|
572
510
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
573
511
|
let driver = this;
|
|
574
512
|
if (isSessionCmd) {
|
|
575
513
|
sessionId = lodash_1.default.last(args);
|
|
576
|
-
dstSession = this.sessions[sessionId];
|
|
514
|
+
dstSession = this.sessions[sessionId] ?? null;
|
|
577
515
|
if (!dstSession) {
|
|
578
516
|
throw new Error(`The session with id '${sessionId}' does not exist`);
|
|
579
517
|
}
|
|
@@ -630,8 +568,10 @@ class AppiumDriver extends base_driver_1.DriverCore {
|
|
|
630
568
|
// not the platform driver
|
|
631
569
|
return await base_driver_1.BaseDriver.prototype.executeCommand.call(this, cmd, ...args);
|
|
632
570
|
}
|
|
633
|
-
|
|
634
|
-
|
|
571
|
+
if (!dstSession) {
|
|
572
|
+
throw new Error('Internal error: session command without a session driver');
|
|
573
|
+
}
|
|
574
|
+
return await dstSession.executeCommand(cmd, ...args);
|
|
635
575
|
};
|
|
636
576
|
// now take our default behavior, wrap it with any number of plugin behaviors, and run it
|
|
637
577
|
const wrappedCmd = this.wrapCommandWithPlugins({
|
|
@@ -661,21 +601,22 @@ class AppiumDriver extends base_driver_1.DriverCore {
|
|
|
661
601
|
// previously sessionless to use the new sessionId, so that plugins can share state between
|
|
662
602
|
// their createSession method and other instance methods
|
|
663
603
|
if (cmd === base_driver_1.CREATE_SESSION_COMMAND && this.sessionlessPlugins.length && !res.error) {
|
|
664
|
-
const
|
|
604
|
+
const newSessionId = lodash_1.default.first(res.value);
|
|
665
605
|
this.log.info(`Promoting ${this.sessionlessPlugins.length} sessionless plugins to be attached ` +
|
|
666
|
-
`to session ID ${
|
|
667
|
-
this.sessionPlugins[
|
|
668
|
-
|
|
606
|
+
`to session ID ${newSessionId}`);
|
|
607
|
+
this.sessionPlugins[newSessionId] = this.sessionlessPlugins;
|
|
608
|
+
const promoted = this.sessionPlugins[newSessionId];
|
|
609
|
+
for (const p of promoted) {
|
|
669
610
|
if (lodash_1.default.isFunction(p.updateLogPrefix)) {
|
|
670
|
-
|
|
671
|
-
p.updateLogPrefix(`${(0, base_driver_1.generateDriverLogPrefix)(p)} <${(0, base_driver_1.generateDriverLogPrefix)(this.sessions[sessionId])}>`);
|
|
611
|
+
p.updateLogPrefix(`${(0, base_driver_1.generateDriverLogPrefix)(p)} <${(0, base_driver_1.generateDriverLogPrefix)(this.sessions[newSessionId])}>`);
|
|
672
612
|
}
|
|
673
613
|
}
|
|
674
614
|
this.sessionlessPlugins = [];
|
|
675
615
|
}
|
|
676
616
|
return res;
|
|
677
617
|
}
|
|
678
|
-
|
|
618
|
+
/** Builds an async chain: each plugin wraps `next` until the default driver behavior runs. */
|
|
619
|
+
wrapCommandWithPlugins({ driver, cmd, args, next, cmdHandledBy, plugins, }) {
|
|
679
620
|
if (plugins.length) {
|
|
680
621
|
this.log.info(`Plugins which can handle cmd '${cmd}': ${plugins.map((p) => p.name)}`);
|
|
681
622
|
}
|
|
@@ -690,15 +631,20 @@ class AppiumDriver extends base_driver_1.DriverCore {
|
|
|
690
631
|
this.log.info(`Plugin ${plugin.name} is now handling cmd '${cmd}'`);
|
|
691
632
|
cmdHandledBy[plugin.name] = true; // if we make it here, this plugin has attempted to handle cmd
|
|
692
633
|
// first attempt to handle the command via a command-specific handler on the plugin
|
|
693
|
-
|
|
694
|
-
|
|
634
|
+
const cmdHandler = plugin[cmd];
|
|
635
|
+
if (lodash_1.default.isFunction(cmdHandler)) {
|
|
636
|
+
// Command methods must run with plugin as `this` (detached property access drops binding).
|
|
637
|
+
return await cmdHandler.call(plugin, _next, driver, ...args);
|
|
638
|
+
}
|
|
639
|
+
if (!lodash_1.default.isFunction(plugin.handle)) {
|
|
640
|
+
throw new Error(`Plugin ${plugin.name} cannot handle command '${cmd}'`);
|
|
695
641
|
}
|
|
696
|
-
// otherwise, call the generic 'handle' method
|
|
697
642
|
return await plugin.handle(_next, driver, cmd, ...args);
|
|
698
643
|
})(next);
|
|
699
644
|
}
|
|
700
645
|
return next;
|
|
701
646
|
}
|
|
647
|
+
/** After a command with plugins, logs which handlers ran vs. were skipped (debugging aid). */
|
|
702
648
|
logPluginHandlerReport(plugins, { cmd, cmdHandledBy }) {
|
|
703
649
|
if (!plugins.length) {
|
|
704
650
|
return;
|
|
@@ -717,8 +663,11 @@ class AppiumDriver extends base_driver_1.DriverCore {
|
|
|
717
663
|
`command *was* handled by these: ${JSON.stringify(didHandle)}.`);
|
|
718
664
|
}
|
|
719
665
|
}
|
|
720
|
-
|
|
721
|
-
|
|
666
|
+
/** Runs the wrapped plugin chain and merges the result into a `SessionHandlerResult` shape. */
|
|
667
|
+
async executeWrappedCommand({ wrappedCmd, protocol, }) {
|
|
668
|
+
let cmdRes;
|
|
669
|
+
let cmdErr;
|
|
670
|
+
const res = {};
|
|
722
671
|
try {
|
|
723
672
|
// At this point, `wrappedCmd` defines a whole sequence of plugin handlers, culminating in
|
|
724
673
|
// our default handler. Whatever it returns is what we're going to want to send back to the
|
|
@@ -732,64 +681,37 @@ class AppiumDriver extends base_driver_1.DriverCore {
|
|
|
732
681
|
// object, or a protocol-aware object with protocol and error/value keys. So we need to sniff
|
|
733
682
|
// it and make sure we don't double-wrap it if it's the latter kind.
|
|
734
683
|
if (lodash_1.default.isPlainObject(cmdRes) && lodash_1.default.has(cmdRes, 'protocol')) {
|
|
735
|
-
res
|
|
684
|
+
Object.assign(res, cmdRes);
|
|
736
685
|
}
|
|
737
686
|
else {
|
|
738
687
|
res.value = cmdRes;
|
|
739
|
-
res.error = cmdErr;
|
|
740
|
-
res.protocol = protocol;
|
|
688
|
+
res.error = cmdErr instanceof Error ? cmdErr : undefined;
|
|
689
|
+
res.protocol = protocol ?? undefined;
|
|
741
690
|
}
|
|
742
691
|
return res;
|
|
743
692
|
}
|
|
693
|
+
/** Whether the inner session driver is actively proxying for this session id. */
|
|
744
694
|
proxyActive(sessionId) {
|
|
745
695
|
const dstSession = this.sessions[sessionId];
|
|
746
|
-
return
|
|
696
|
+
return lodash_1.default.isFunction(dstSession?.proxyActive) && dstSession.proxyActive(sessionId);
|
|
747
697
|
}
|
|
748
|
-
/**
|
|
749
|
-
*
|
|
750
|
-
* @param {string} sessionId
|
|
751
|
-
* @returns {import('@appium/types').RouteMatcher[]}
|
|
752
|
-
*/
|
|
698
|
+
/** URL patterns the session driver does not want proxied; empty if no session or no list. */
|
|
753
699
|
getProxyAvoidList(sessionId) {
|
|
754
700
|
const dstSession = this.sessions[sessionId];
|
|
755
|
-
return dstSession ? dstSession.getProxyAvoidList() : [];
|
|
701
|
+
return lodash_1.default.isFunction(dstSession?.getProxyAvoidList) ? dstSession.getProxyAvoidList() : [];
|
|
756
702
|
}
|
|
703
|
+
/** Whether the session driver supports proxying for this session. */
|
|
757
704
|
canProxy(sessionId) {
|
|
758
705
|
const dstSession = this.sessions[sessionId];
|
|
759
|
-
return dstSession && dstSession.canProxy(sessionId);
|
|
706
|
+
return lodash_1.default.isFunction(dstSession?.canProxy) && dstSession.canProxy(sessionId);
|
|
760
707
|
}
|
|
761
|
-
onBidiConnection = bidiCommands.onBidiConnection;
|
|
762
|
-
onBidiMessage = bidiCommands.onBidiMessage;
|
|
763
|
-
onBidiServerError = bidiCommands.onBidiServerError;
|
|
764
|
-
cleanupBidiSockets = bidiCommands.cleanupBidiSockets;
|
|
765
|
-
configureGlobalFeatures = insecureFeatures.configureGlobalFeatures;
|
|
766
|
-
configureDriverFeatures = insecureFeatures.configureDriverFeatures;
|
|
767
|
-
listCommands = inspectorCommands.listCommands;
|
|
768
|
-
listExtensions = inspectorCommands.listExtensions;
|
|
769
708
|
}
|
|
770
709
|
exports.AppiumDriver = AppiumDriver;
|
|
771
|
-
/**
|
|
772
|
-
* Help decide which commands should be proxied to sub-drivers and which
|
|
773
|
-
* should be handled by this, our umbrella driver
|
|
774
|
-
* @param {string} cmd
|
|
775
|
-
* @returns {boolean}
|
|
776
|
-
*/
|
|
777
|
-
function isAppiumDriverCommand(cmd) {
|
|
778
|
-
return !(0, base_driver_1.isSessionCommand)(cmd)
|
|
779
|
-
|| lodash_1.default.includes([
|
|
780
|
-
base_driver_1.DELETE_SESSION_COMMAND,
|
|
781
|
-
base_driver_1.LIST_DRIVER_COMMANDS_COMMAND,
|
|
782
|
-
base_driver_1.LIST_DRIVER_EXTENSIONS_COMMAND,
|
|
783
|
-
], cmd);
|
|
784
|
-
}
|
|
785
710
|
/**
|
|
786
711
|
* Thrown when Appium tried to proxy a command using a driver's `proxyCommand` method but the
|
|
787
712
|
* method did not exist
|
|
788
713
|
*/
|
|
789
714
|
class NoDriverProxyCommandError extends Error {
|
|
790
|
-
/**
|
|
791
|
-
* @type {Readonly<string>}
|
|
792
|
-
*/
|
|
793
715
|
code = 'APPIUMERR_NO_DRIVER_PROXYCOMMAND';
|
|
794
716
|
constructor() {
|
|
795
717
|
super(`The default behavior for this command was to proxy, but the driver ` +
|
|
@@ -799,48 +721,13 @@ class NoDriverProxyCommandError extends Error {
|
|
|
799
721
|
}
|
|
800
722
|
}
|
|
801
723
|
exports.NoDriverProxyCommandError = NoDriverProxyCommandError;
|
|
802
|
-
/**
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
* @typedef {import('@appium/types').StringRecord} StringRecord
|
|
812
|
-
* @typedef {import('@appium/types').ExternalDriver} ExternalDriver
|
|
813
|
-
* @typedef {import('@appium/types').PluginClass} PluginClass
|
|
814
|
-
* @typedef {import('@appium/types').Plugin} Plugin
|
|
815
|
-
* @typedef {import('@appium/base-driver').ExtensionCore} ExtensionCore
|
|
816
|
-
* @typedef {import('@appium/types').DriverClass<import('@appium/types').Driver>} DriverClass
|
|
817
|
-
*/
|
|
818
|
-
/**
|
|
819
|
-
* @typedef {import('@appium/types').ISessionHandler<AppiumDriverConstraints,
|
|
820
|
-
* SessionHandlerCreateResult, SessionHandlerDeleteResult>} AppiumSessionHandler
|
|
821
|
-
*/
|
|
822
|
-
/**
|
|
823
|
-
* @typedef {SessionHandlerResult<[innerSessionId: string, caps:
|
|
824
|
-
* import('@appium/types').DriverCaps<Constraints>, protocol: string|undefined]>} SessionHandlerCreateResult
|
|
825
|
-
*/
|
|
826
|
-
/**
|
|
827
|
-
* @template {Constraints} C
|
|
828
|
-
* @typedef {import('@appium/types').Core<C>} Core
|
|
829
|
-
*/
|
|
830
|
-
/**
|
|
831
|
-
* @typedef {SessionHandlerResult<void>} SessionHandlerDeleteResult
|
|
832
|
-
*/
|
|
833
|
-
/**
|
|
834
|
-
* Used by {@linkcode AppiumDriver.createSession} and {@linkcode AppiumDriver.deleteSession} to describe
|
|
835
|
-
* result.
|
|
836
|
-
* @template V
|
|
837
|
-
* @typedef SessionHandlerResult
|
|
838
|
-
* @property {V} [value]
|
|
839
|
-
* @property {Error} [error]
|
|
840
|
-
* @property {string} [protocol]
|
|
841
|
-
*/
|
|
842
|
-
/**
|
|
843
|
-
* @typedef {typeof desiredCapabilityConstraints} AppiumDriverConstraints
|
|
844
|
-
* @typedef {import('@appium/types').W3CDriverCaps<AppiumDriverConstraints>} W3CAppiumDriverCaps
|
|
845
|
-
*/
|
|
724
|
+
/** True if `cmd` should run on the umbrella driver instead of only on the session’s inner driver. */
|
|
725
|
+
function isAppiumDriverCommand(cmd) {
|
|
726
|
+
return !(0, base_driver_1.isSessionCommand)(cmd)
|
|
727
|
+
|| lodash_1.default.includes([
|
|
728
|
+
base_driver_1.DELETE_SESSION_COMMAND,
|
|
729
|
+
base_driver_1.LIST_DRIVER_COMMANDS_COMMAND,
|
|
730
|
+
base_driver_1.LIST_DRIVER_EXTENSIONS_COMMAND,
|
|
731
|
+
], cmd);
|
|
732
|
+
}
|
|
846
733
|
//# sourceMappingURL=appium.js.map
|