appium-geckodriver 2.1.11 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +1 -0
  3. package/build/lib/commands/find.d.ts.map +1 -1
  4. package/build/lib/commands/find.js.map +1 -1
  5. package/build/lib/constants.d.ts +9 -0
  6. package/build/lib/constants.d.ts.map +1 -1
  7. package/build/lib/constants.js +10 -1
  8. package/build/lib/constants.js.map +1 -1
  9. package/build/lib/desired-caps.d.ts +3 -0
  10. package/build/lib/desired-caps.d.ts.map +1 -1
  11. package/build/lib/desired-caps.js +17 -14
  12. package/build/lib/desired-caps.js.map +1 -1
  13. package/build/lib/doctor/optional-checks.d.ts.map +1 -1
  14. package/build/lib/doctor/optional-checks.js.map +1 -1
  15. package/build/lib/driver.d.ts +1 -0
  16. package/build/lib/driver.d.ts.map +1 -1
  17. package/build/lib/driver.js +14 -0
  18. package/build/lib/driver.js.map +1 -1
  19. package/build/lib/gecko.d.ts.map +1 -1
  20. package/build/lib/gecko.js +28 -14
  21. package/build/lib/gecko.js.map +1 -1
  22. package/build/lib/index.d.ts.map +1 -1
  23. package/build/lib/index.js.map +1 -1
  24. package/build/lib/logger.js.map +1 -1
  25. package/build/lib/utils.d.ts.map +1 -1
  26. package/build/lib/utils.js +3 -4
  27. package/build/lib/utils.js.map +1 -1
  28. package/build/tsconfig.tsbuildinfo +1 -1
  29. package/lib/commands/find.ts +8 -4
  30. package/lib/constants.ts +10 -0
  31. package/lib/desired-caps.ts +19 -17
  32. package/lib/doctor/optional-checks.ts +6 -3
  33. package/lib/doctor/required-checks.ts +0 -1
  34. package/lib/doctor/utils.ts +0 -1
  35. package/lib/driver.ts +32 -13
  36. package/lib/gecko.ts +86 -56
  37. package/lib/index.ts +2 -2
  38. package/lib/logger.ts +1 -2
  39. package/lib/utils.ts +26 -14
  40. package/npm-shrinkwrap.json +307 -1862
  41. package/package.json +4 -2
@@ -1,9 +1,13 @@
1
- import { util } from 'appium/support';
2
- import type { GeckoDriver } from '../driver';
1
+ import {util} from 'appium/support';
2
+ import type {GeckoDriver} from '../driver';
3
3
 
4
4
  // This is needed to make lookup by image working
5
- export async function findElOrEls (
6
- this: GeckoDriver, strategy: string, selector: string, mult: boolean, context?: string
5
+ export async function findElOrEls(
6
+ this: GeckoDriver,
7
+ strategy: string,
8
+ selector: string,
9
+ mult: boolean,
10
+ context?: string,
7
11
  ): Promise<any> {
8
12
  const endpoint = `/element${context ? `/${util.unwrapElement(context)}/element` : ''}${mult ? 's' : ''}`;
9
13
  return await this.gecko.proxy.command(endpoint, 'POST', {
package/lib/constants.ts CHANGED
@@ -2,3 +2,13 @@ export const VERBOSITY = {
2
2
  DEBUG: 'debug',
3
3
  TRACE: 'trace',
4
4
  } as const;
5
+
6
+ /**
7
+ * Insecure feature flag name which must be enabled on the Appium server
8
+ * in order to use the `geckodriverExecutable` capability.
9
+ *
10
+ * Note: when starting the Appium server, this feature must be referenced
11
+ * with the automation name prefix (for example
12
+ * `--allow-insecure gecko:custom_geckodriver_executable`).
13
+ */
14
+ export const INSECURE_FEAT_CUSTOM_GECKODRIVER_EXECUTABLE = 'custom_geckodriver_executable' as const;
@@ -1,49 +1,51 @@
1
- import type { Constraints } from '@appium/types';
2
- import { VERBOSITY } from './constants';
1
+ import type {Constraints} from '@appium/types';
2
+ import {VERBOSITY} from './constants';
3
3
 
4
4
  const DESIRED_CAP_CONSTRAINTS = {
5
5
  browserName: {
6
- isString: true
6
+ isString: true,
7
7
  },
8
8
  browserVersion: {
9
- isString: true
9
+ isString: true,
10
10
  },
11
11
  acceptInsecureCerts: {
12
- isBoolean: true
12
+ isBoolean: true,
13
13
  },
14
14
  pageLoadStrategy: {
15
- isString: true
15
+ isString: true,
16
16
  },
17
17
  proxy: {
18
- isObject: true
18
+ isObject: true,
19
19
  },
20
20
  setWindowRect: {
21
- isBoolean: true
21
+ isBoolean: true,
22
22
  },
23
23
  timeouts: {
24
- isObject: true
24
+ isObject: true,
25
25
  },
26
26
  unhandledPromptBehavior: {
27
- isString: true
27
+ isString: true,
28
28
  },
29
29
  systemPort: {
30
- isNumber: true
30
+ isNumber: true,
31
31
  },
32
32
  marionettePort: {
33
- isNumber: true
33
+ isNumber: true,
34
+ },
35
+ geckodriverExecutable: {
36
+ isString: true,
34
37
  },
35
38
  verbosity: {
36
39
  isString: true,
37
- inclusionCaseInsensitive: Object.values(VERBOSITY) as [string, ...string[]]
40
+ inclusionCaseInsensitive: Object.values(VERBOSITY) as [string, ...string[]],
38
41
  },
39
42
  androidStorage: {
40
43
  isString: true,
41
- inclusionCaseInsensitive: ['auto', 'app', 'internal', 'sdcard']
44
+ inclusionCaseInsensitive: ['auto', 'app', 'internal', 'sdcard'],
42
45
  },
43
46
  'moz:firefoxOptions': {
44
- isObject: true
45
- }
47
+ isObject: true,
48
+ },
46
49
  } as const satisfies Constraints;
47
50
 
48
51
  export const desiredCapConstraints = DESIRED_CAP_CONSTRAINTS;
49
-
@@ -78,7 +78,9 @@ export class AndroidSdkCheck implements IDoctorCheck {
78
78
  const listOfTools = this.TOOL_NAMES.join(', ');
79
79
  const sdkRoot = getSdkRootFromEnv();
80
80
  if (!sdkRoot) {
81
- return doctor.nokOptional(`${listOfTools} could not be found because ANDROID_HOME is NOT set!`);
81
+ return doctor.nokOptional(
82
+ `${listOfTools} could not be found because ANDROID_HOME is NOT set!`,
83
+ );
82
84
  }
83
85
 
84
86
  this.log.info(` Checking ${listOfTools}`);
@@ -92,7 +94,9 @@ export class AndroidSdkCheck implements IDoctorCheck {
92
94
  }
93
95
 
94
96
  if (missingBinaries.length > 0) {
95
- return doctor.nokOptional(`${missingBinaries.join(', ')} could NOT be found in '${sdkRoot}'!`);
97
+ return doctor.nokOptional(
98
+ `${missingBinaries.join(', ')} could NOT be found in '${sdkRoot}'!`,
99
+ );
96
100
  }
97
101
 
98
102
  return doctor.okOptional(`${listOfTools} exist in '${sdkRoot}'`);
@@ -115,4 +119,3 @@ export class AndroidSdkCheck implements IDoctorCheck {
115
119
  }
116
120
  }
117
121
  export const androidSdkCheck = new AndroidSdkCheck();
118
-
@@ -33,4 +33,3 @@ export class GeckodriverCheck implements IDoctorCheck {
33
33
  }
34
34
  }
35
35
  export const geckodriverCheck = new GeckodriverCheck();
36
-
@@ -12,4 +12,3 @@ export async function resolveExecutablePath(cmd: string): Promise<string | null>
12
12
  } catch {}
13
13
  return null;
14
14
  }
15
-
package/lib/driver.ts CHANGED
@@ -7,11 +7,12 @@ import type {
7
7
  ExternalDriver,
8
8
  W3CDriverCaps,
9
9
  } from '@appium/types';
10
- import { BaseDriver } from 'appium/driver';
11
- import { GECKO_SERVER_HOST, GeckoDriverServer } from './gecko';
12
- import { desiredCapConstraints } from './desired-caps';
10
+ import {BaseDriver, errors} from 'appium/driver';
11
+ import {GECKO_SERVER_HOST, GeckoDriverServer} from './gecko';
12
+ import {desiredCapConstraints} from './desired-caps';
13
+ import {INSECURE_FEAT_CUSTOM_GECKODRIVER_EXECUTABLE} from './constants';
13
14
  import * as findCommands from './commands/find';
14
- import { formatCapsForServer } from './utils';
15
+ import {formatCapsForServer} from './utils';
15
16
 
16
17
  const NO_PROXY: RouteMatcher[] = [
17
18
  ['GET', new RegExp('^/session/[^/]+/appium')],
@@ -31,7 +32,7 @@ export class GeckoDriver
31
32
  private _bidiProxyUrl: string | null = null;
32
33
  public proxyReqRes: (...args: any) => any;
33
34
 
34
- constructor (opts: InitialOpts = {} as InitialOpts) {
35
+ constructor(opts: InitialOpts = {} as InitialOpts) {
35
36
  super(opts);
36
37
  this.desiredCapConstraints = _.cloneDeep(desiredCapConstraints);
37
38
  this.locatorStrategies = [
@@ -48,26 +49,45 @@ export class GeckoDriver
48
49
  }
49
50
 
50
51
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
51
- override proxyActive (sessionId?: string): boolean {
52
+ override proxyActive(sessionId?: string): boolean {
52
53
  return this.isProxyActive;
53
54
  }
54
55
 
55
- override getProxyAvoidList (): RouteMatcher[] {
56
+ override getProxyAvoidList(): RouteMatcher[] {
56
57
  return NO_PROXY;
57
58
  }
58
59
 
59
- override canProxy (): boolean {
60
+ override canProxy(): boolean {
60
61
  return true;
61
62
  }
62
63
 
63
- get gecko (): GeckoDriverServer {
64
+ get gecko(): GeckoDriverServer {
64
65
  if (!this._gecko) {
65
66
  throw new Error('Gecko driver is not initialized');
66
67
  }
67
68
  return this._gecko;
68
69
  }
69
70
 
70
- override async createSession (
71
+ override validateDesiredCaps(caps: any): caps is any {
72
+ const isValid = super.validateDesiredCaps(caps);
73
+ if (!isValid) {
74
+ return false;
75
+ }
76
+
77
+ if (
78
+ caps.geckodriverExecutable &&
79
+ !this.isFeatureEnabled(INSECURE_FEAT_CUSTOM_GECKODRIVER_EXECUTABLE)
80
+ ) {
81
+ throw new errors.SessionNotCreatedError(
82
+ `The 'geckodriverExecutable' capability requires the ` +
83
+ `'${INSECURE_FEAT_CUSTOM_GECKODRIVER_EXECUTABLE}' insecure feature to be enabled ` +
84
+ `on the Appium server.`,
85
+ );
86
+ }
87
+ return true;
88
+ }
89
+
90
+ override async createSession(
71
91
  w3cCaps1: W3CDriverCaps<GeckoConstraints>,
72
92
  w3cCaps2?: W3CDriverCaps<GeckoConstraints>,
73
93
  ...args: any[]
@@ -96,7 +116,7 @@ export class GeckoDriver
96
116
  return this._bidiProxyUrl;
97
117
  }
98
118
 
99
- override async deleteSession (): Promise<void> {
119
+ override async deleteSession(): Promise<void> {
100
120
  this.log.info('Ending Gecko Driver session');
101
121
  await this._gecko?.stop();
102
122
  this.resetState();
@@ -104,7 +124,7 @@ export class GeckoDriver
104
124
  await super.deleteSession();
105
125
  }
106
126
 
107
- private resetState (): void {
127
+ private resetState(): void {
108
128
  this._gecko = null;
109
129
  this.proxyReqRes = null as any;
110
130
  this.isProxyActive = false;
@@ -131,4 +151,3 @@ export class GeckoDriver
131
151
  }
132
152
 
133
153
  export default GeckoDriver;
134
-
package/lib/gecko.ts CHANGED
@@ -1,21 +1,21 @@
1
1
  import _ from 'lodash';
2
2
  import os from 'node:os';
3
3
  import path from 'node:path';
4
- import { JWProxy, errors } from 'appium/driver';
5
- import { fs, util, system } from 'appium/support';
6
- import { SubProcess } from 'teen_process';
7
- import { waitForCondition } from 'asyncbox';
8
- import { findAPortNotInUse } from 'portscanner';
9
- import { execSync } from 'node:child_process';
10
- import type { AppiumLogger, StringRecord, HTTPMethod, HTTPBody } from '@appium/types';
11
- import { VERBOSITY } from './constants';
4
+ import {JWProxy, errors} from 'appium/driver';
5
+ import {fs, util, system} from 'appium/support';
6
+ import {SubProcess} from 'teen_process';
7
+ import {waitForCondition} from 'asyncbox';
8
+ import {findAPortNotInUse} from 'portscanner';
9
+ import {execSync} from 'node:child_process';
10
+ import type {AppiumLogger, StringRecord, HTTPMethod, HTTPBody} from '@appium/types';
11
+ import {VERBOSITY} from './constants';
12
12
 
13
13
  const GD_BINARY = `geckodriver${system.isWindows() ? '.exe' : ''}`;
14
14
  const STARTUP_TIMEOUT_MS = 10000; // 10 seconds
15
15
  const GECKO_PORT_RANGE: [number, number] = [5200, 5300];
16
16
  const GECKO_SERVER_GUARD = util.getLockFileGuard(
17
17
  path.resolve(os.tmpdir(), 'gecko_server_guard.lock'),
18
- {timeout: 5, tryRecovery: true}
18
+ {timeout: 5, tryRecovery: true},
19
19
  );
20
20
  const DEFAULT_MARIONETTE_PORT = 2828;
21
21
  export const GECKO_SERVER_HOST = '127.0.0.1';
@@ -27,11 +27,12 @@ export interface SessionOptions {
27
27
  export class GeckoProxy extends JWProxy {
28
28
  didProcessExit?: boolean;
29
29
 
30
- override async proxyCommand (url: string, method: HTTPMethod, body: HTTPBody = null) {
30
+ override async proxyCommand(url: string, method: HTTPMethod, body: HTTPBody = null) {
31
31
  if (this.didProcessExit) {
32
32
  throw new errors.InvalidContextError(
33
33
  `'${method} ${url}' cannot be proxied to Gecko Driver server because ` +
34
- 'its process is not running (probably crashed). Check the Appium log for more details');
34
+ 'its process is not running (probably crashed). Check the Appium log for more details',
35
+ );
35
36
  }
36
37
  return await super.proxyCommand(url, method, body);
37
38
  }
@@ -42,32 +43,34 @@ class GeckoDriverProcess {
42
43
  private readonly verbosity?: string;
43
44
  private readonly androidStorage?: string;
44
45
  private readonly marionettePort?: number;
46
+ private readonly geckodriverExecutable?: string;
45
47
  private _port?: number;
46
48
  private readonly log: AppiumLogger;
47
49
  private _proc: SubProcess | null = null;
48
50
 
49
- constructor (log: AppiumLogger, opts: StringRecord = {}) {
51
+ constructor(log: AppiumLogger, opts: StringRecord = {}) {
50
52
  this.noReset = opts.noReset;
51
53
  this.verbosity = opts.verbosity;
52
54
  this.androidStorage = opts.androidStorage;
53
55
  this.marionettePort = opts.marionettePort;
56
+ this.geckodriverExecutable = opts.geckodriverExecutable;
54
57
  this._port = opts.systemPort;
55
58
  this.log = log;
56
59
  }
57
60
 
58
- get isRunning (): boolean {
59
- return !!(this._proc?.isRunning);
61
+ get isRunning(): boolean {
62
+ return !!this._proc?.isRunning;
60
63
  }
61
64
 
62
- get port (): number | undefined {
65
+ get port(): number | undefined {
63
66
  return this._port;
64
67
  }
65
68
 
66
- get proc (): SubProcess | null {
69
+ get proc(): SubProcess | null {
67
70
  return this._proc;
68
71
  }
69
72
 
70
- async init (): Promise<void> {
73
+ async init(): Promise<void> {
71
74
  if (this.isRunning) {
72
75
  return;
73
76
  }
@@ -80,19 +83,14 @@ class GeckoDriverProcess {
80
83
  } catch {
81
84
  throw new Error(
82
85
  `Cannot find any free port in range ${startPort}..${endPort}. ` +
83
- `Double check the processes that are locking ports within this range and terminate ` +
84
- `these which are not needed anymore or set any free port number to the 'systemPort' capability`);
86
+ `Double check the processes that are locking ports within this range and terminate ` +
87
+ `these which are not needed anymore or set any free port number to the 'systemPort' capability`,
88
+ );
85
89
  }
86
90
  });
87
91
  }
88
92
 
89
- let driverBin: string;
90
- try {
91
- driverBin = await fs.which(GD_BINARY);
92
- } catch {
93
- throw new Error(`${GD_BINARY} binary cannot be found in PATH. ` +
94
- `Please make sure it is present on your system`);
95
- }
93
+ const driverBin = await this.resolveGeckodriverBinary();
96
94
  const args: string[] = [];
97
95
  /* #region Options */
98
96
  switch (_.toLower(this.verbosity)) {
@@ -107,8 +105,12 @@ class GeckoDriverProcess {
107
105
  args.push('--connect-existing');
108
106
  // https://firefox-source-docs.mozilla.org/testing/geckodriver/Flags.html#code-connect-existing-code
109
107
  if (_.isNil(this.marionettePort)) {
110
- this.log.info(`'marionettePort' capability value is not provided while 'noReset' is enabled`);
111
- this.log.info(`Assigning 'marionettePort' to the default value (${DEFAULT_MARIONETTE_PORT})`);
108
+ this.log.info(
109
+ `'marionettePort' capability value is not provided while 'noReset' is enabled`,
110
+ );
111
+ this.log.info(
112
+ `Assigning 'marionettePort' to the default value (${DEFAULT_MARIONETTE_PORT})`,
113
+ );
112
114
  }
113
115
  args.push('--marionette-port', `${this.marionettePort ?? DEFAULT_MARIONETTE_PORT}`);
114
116
  } else if (!_.isNil(this.marionettePort)) {
@@ -134,19 +136,40 @@ class GeckoDriverProcess {
134
136
  await this._proc.start(0);
135
137
  }
136
138
 
137
- async stop (): Promise<void> {
139
+ async stop(): Promise<void> {
138
140
  if (this.isRunning) {
139
141
  await this._proc?.stop('SIGTERM');
140
142
  }
141
143
  }
142
144
 
143
- async kill (): Promise<void> {
145
+ async kill(): Promise<void> {
144
146
  if (this.isRunning) {
145
147
  try {
146
148
  await this._proc?.stop('SIGKILL');
147
149
  } catch {}
148
150
  }
149
151
  }
152
+
153
+ private async resolveGeckodriverBinary(): Promise<string> {
154
+ if (this.geckodriverExecutable) {
155
+ if (!(await fs.exists(this.geckodriverExecutable))) {
156
+ throw new Error(
157
+ `The custom geckodriver binary at '${this.geckodriverExecutable}' cannot be found. ` +
158
+ `Make sure the path is correct and accessible to the Appium server process`,
159
+ );
160
+ }
161
+ return this.geckodriverExecutable;
162
+ }
163
+
164
+ try {
165
+ return await fs.which(GD_BINARY);
166
+ } catch {
167
+ throw new Error(
168
+ `${GD_BINARY} binary cannot be found in PATH. ` +
169
+ `Please make sure it is present on your system`,
170
+ );
171
+ }
172
+ }
150
173
  }
151
174
 
152
175
  const RUNNING_PROCESS_IDS: (number | undefined)[] = [];
@@ -156,7 +179,10 @@ process.once('exit', () => {
156
179
  }
157
180
 
158
181
  const command = system.isWindows()
159
- ? ('taskkill.exe ' + RUNNING_PROCESS_IDS.filter((pid): pid is number => pid !== undefined).map((pid) => `/PID ${pid}`).join(' '))
182
+ ? 'taskkill.exe ' +
183
+ RUNNING_PROCESS_IDS.filter((pid): pid is number => pid !== undefined)
184
+ .map((pid) => `/PID ${pid}`)
185
+ .join(' ')
160
186
  : `kill ${RUNNING_PROCESS_IDS.filter((pid): pid is number => pid !== undefined).join(' ')}`;
161
187
  try {
162
188
  execSync(command);
@@ -168,24 +194,24 @@ export class GeckoDriverServer {
168
194
  private readonly _process: GeckoDriverProcess;
169
195
  private readonly log: AppiumLogger;
170
196
 
171
- constructor (log: AppiumLogger, caps: StringRecord) {
197
+ constructor(log: AppiumLogger, caps: StringRecord) {
172
198
  this._process = new GeckoDriverProcess(log, caps);
173
199
  this.log = log;
174
200
  this._proxy = null;
175
201
  }
176
202
 
177
- get proxy (): GeckoProxy {
203
+ get proxy(): GeckoProxy {
178
204
  if (!this._proxy) {
179
205
  throw new Error('Gecko proxy is not initialized');
180
206
  }
181
207
  return this._proxy;
182
208
  }
183
209
 
184
- get isRunning (): boolean {
185
- return !!(this._process?.isRunning);
210
+ get isRunning(): boolean {
211
+ return !!this._process?.isRunning;
186
212
  }
187
213
 
188
- async start (geckoCaps: StringRecord, opts: SessionOptions = {}): Promise<StringRecord> {
214
+ async start(geckoCaps: StringRecord, opts: SessionOptions = {}): Promise<StringRecord> {
189
215
  await this._process.init();
190
216
 
191
217
  const proxyOpts: any = {
@@ -207,28 +233,33 @@ export class GeckoDriverServer {
207
233
  });
208
234
 
209
235
  try {
210
- await waitForCondition(async () => {
211
- try {
212
- await this._proxy?.command('/status', 'GET');
213
- return true;
214
- } catch (err: any) {
215
- if (this._proxy?.didProcessExit) {
216
- throw new Error(err.message);
236
+ await waitForCondition(
237
+ async () => {
238
+ try {
239
+ await this._proxy?.command('/status', 'GET');
240
+ return true;
241
+ } catch (err: any) {
242
+ if (this._proxy?.didProcessExit) {
243
+ throw new Error(err.message);
244
+ }
245
+ return false;
217
246
  }
218
- return false;
219
- }
220
- }, {
221
- waitMs: STARTUP_TIMEOUT_MS,
222
- intervalMs: 1000,
223
- });
247
+ },
248
+ {
249
+ waitMs: STARTUP_TIMEOUT_MS,
250
+ intervalMs: 1000,
251
+ },
252
+ );
224
253
  } catch (e: any) {
225
254
  if (this._process.isRunning) {
226
255
  // avoid "frozen" processes,
227
256
  await this._process.kill();
228
257
  }
229
258
  if (/Condition unmet/.test(e.message)) {
230
- throw new Error(`Gecko Driver server is not listening within ${STARTUP_TIMEOUT_MS}ms timeout. ` +
231
- `Make sure it could be started manually from a terminal`);
259
+ throw new Error(
260
+ `Gecko Driver server is not listening within ${STARTUP_TIMEOUT_MS}ms timeout. ` +
261
+ `Make sure it could be started manually from a terminal`,
262
+ );
232
263
  }
233
264
  throw e;
234
265
  }
@@ -238,15 +269,15 @@ export class GeckoDriverServer {
238
269
  this._process.proc?.on('exit', () => void _.pull(RUNNING_PROCESS_IDS, pid));
239
270
  }
240
271
 
241
- return await this._proxy.command('/session', 'POST', {
272
+ return (await this._proxy.command('/session', 'POST', {
242
273
  capabilities: {
243
274
  firstMatch: [{}],
244
275
  alwaysMatch: geckoCaps,
245
- }
246
- }) as StringRecord;
276
+ },
277
+ })) as StringRecord;
247
278
  }
248
279
 
249
- async stop (): Promise<void> {
280
+ async stop(): Promise<void> {
250
281
  if (!this.isRunning) {
251
282
  this.log.info(`Gecko Driver session cannot be stopped, because the server is not running`);
252
283
  return;
@@ -270,4 +301,3 @@ export class GeckoDriverServer {
270
301
  }
271
302
 
272
303
  export default GeckoDriverServer;
273
-
package/lib/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { GeckoDriver } from './driver';
1
+ import {GeckoDriver} from './driver';
2
2
 
3
3
  export default GeckoDriver;
4
- export { GeckoDriver };
4
+ export {GeckoDriver};
package/lib/logger.ts CHANGED
@@ -1,6 +1,5 @@
1
- import { logger } from 'appium/support';
1
+ import {logger} from 'appium/support';
2
2
 
3
3
  export const log = logger.getLogger('GeckoDriver');
4
4
 
5
5
  export default log;
6
-
package/lib/utils.ts CHANGED
@@ -1,21 +1,24 @@
1
1
  import _ from 'lodash';
2
- import { fs, net, zip, tempDir } from 'appium/support';
2
+ import {fs, net, zip, tempDir} from 'appium/support';
3
3
  import tar from 'tar-stream';
4
4
  import zlib from 'node:zlib';
5
5
  import B from 'bluebird';
6
6
  import path from 'node:path';
7
- import type { StringRecord } from '@appium/types';
8
- import { STANDARD_CAPS } from 'appium/driver';
7
+ import type {StringRecord} from '@appium/types';
8
+ import {STANDARD_CAPS} from 'appium/driver';
9
9
 
10
10
  const GECKO_CAP_PREFIXES = ['moz:'] as const;
11
11
 
12
12
  /**
13
13
  * Format capabilities for Gecko server
14
14
  */
15
- export function formatCapsForServer (caps: StringRecord): StringRecord {
15
+ export function formatCapsForServer(caps: StringRecord): StringRecord {
16
16
  const result: StringRecord = {};
17
17
  for (const [name, value] of _.toPairs(caps)) {
18
- if (GECKO_CAP_PREFIXES.some((prefix) => name.startsWith(prefix)) || STANDARD_CAPS.has(name as any)) {
18
+ if (
19
+ GECKO_CAP_PREFIXES.some((prefix) => name.startsWith(prefix)) ||
20
+ STANDARD_CAPS.has(name as any)
21
+ ) {
19
22
  result[name] = value;
20
23
  }
21
24
  }
@@ -46,7 +49,11 @@ export async function mkdirp(p: string): Promise<void> {
46
49
  /**
47
50
  * Extract a specific file from a tar.gz archive
48
51
  */
49
- export async function extractFileFromTarGz(srcAcrhive: string, fileToExtract: string, dstPath: string): Promise<void> {
52
+ export async function extractFileFromTarGz(
53
+ srcAcrhive: string,
54
+ fileToExtract: string,
55
+ dstPath: string,
56
+ ): Promise<void> {
50
57
  const chunks: Buffer[] = [];
51
58
  const extract = tar.extract();
52
59
  const extractPromise = new B<void>((resolve, reject) => {
@@ -56,7 +63,7 @@ export async function extractFileFromTarGz(srcAcrhive: string, fileToExtract: st
56
63
  chunks.push(chunk);
57
64
  });
58
65
  }
59
- stream.on('end', function() {
66
+ stream.on('end', function () {
60
67
  next();
61
68
  });
62
69
  stream.resume();
@@ -71,16 +78,16 @@ export async function extractFileFromTarGz(srcAcrhive: string, fileToExtract: st
71
78
  }
72
79
  } else {
73
80
  return reject(
74
- new Error(`The file '${fileToExtract}' could not be found in the '${srcAcrhive}' archive`)
81
+ new Error(
82
+ `The file '${fileToExtract}' could not be found in the '${srcAcrhive}' archive`,
83
+ ),
75
84
  );
76
85
  }
77
86
  resolve();
78
87
  });
79
88
  });
80
89
 
81
- fs.createReadStream(srcAcrhive)
82
- .pipe(zlib.createGunzip())
83
- .pipe(extract);
90
+ fs.createReadStream(srcAcrhive).pipe(zlib.createGunzip()).pipe(extract);
84
91
 
85
92
  await extractPromise;
86
93
  }
@@ -88,7 +95,11 @@ export async function extractFileFromTarGz(srcAcrhive: string, fileToExtract: st
88
95
  /**
89
96
  * Extract a specific file from a zip archive
90
97
  */
91
- export async function extractFileFromZip(srcAcrhive: string, fileToExtract: string, dstPath: string): Promise<void> {
98
+ export async function extractFileFromZip(
99
+ srcAcrhive: string,
100
+ fileToExtract: string,
101
+ dstPath: string,
102
+ ): Promise<void> {
92
103
  let didFindEntry = false;
93
104
  await zip.readEntries(srcAcrhive, async ({entry, extractEntryTo}) => {
94
105
  if (didFindEntry || entry.fileName !== fileToExtract) {
@@ -105,7 +116,8 @@ export async function extractFileFromZip(srcAcrhive: string, fileToExtract: stri
105
116
  }
106
117
  });
107
118
  if (!didFindEntry) {
108
- throw new Error(`The file '${fileToExtract}' could not be found in the '${srcAcrhive}' archive`);
119
+ throw new Error(
120
+ `The file '${fileToExtract}' could not be found in the '${srcAcrhive}' archive`,
121
+ );
109
122
  }
110
123
  }
111
-