appium-webdriveragent 11.1.4 → 11.1.6

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 (39) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/WebDriverAgent.xcodeproj/project.pbxproj +14 -5
  3. package/WebDriverAgent.xcodeproj/xcshareddata/xcschemes/IntegrationApp.xcscheme +1 -1
  4. package/WebDriverAgent.xcodeproj/xcshareddata/xcschemes/IntegrationTests_1.xcscheme +1 -1
  5. package/WebDriverAgent.xcodeproj/xcshareddata/xcschemes/IntegrationTests_2.xcscheme +1 -1
  6. package/WebDriverAgent.xcodeproj/xcshareddata/xcschemes/IntegrationTests_3.xcscheme +1 -1
  7. package/WebDriverAgent.xcodeproj/xcshareddata/xcschemes/WebDriverAgentLib.xcscheme +1 -1
  8. package/WebDriverAgent.xcodeproj/xcshareddata/xcschemes/WebDriverAgentLib_tvOS.xcscheme +1 -1
  9. package/WebDriverAgent.xcodeproj/xcshareddata/xcschemes/WebDriverAgentRunner-nodebug.xcscheme +1 -1
  10. package/WebDriverAgent.xcodeproj/xcshareddata/xcschemes/WebDriverAgentRunner.xcscheme +1 -1
  11. package/WebDriverAgent.xcodeproj/xcshareddata/xcschemes/WebDriverAgentRunner_tvOS.xcscheme +1 -1
  12. package/WebDriverAgentLib/Info.plist +2 -2
  13. package/build/lib/check-dependencies.d.ts.map +1 -1
  14. package/build/lib/check-dependencies.js +6 -3
  15. package/build/lib/check-dependencies.js.map +1 -1
  16. package/build/lib/logger.js.map +1 -1
  17. package/build/lib/no-session-proxy.d.ts.map +1 -1
  18. package/build/lib/no-session-proxy.js +1 -1
  19. package/build/lib/no-session-proxy.js.map +1 -1
  20. package/build/lib/types.d.ts.map +1 -1
  21. package/build/lib/utils.d.ts.map +1 -1
  22. package/build/lib/utils.js +8 -9
  23. package/build/lib/utils.js.map +1 -1
  24. package/build/lib/webdriveragent.d.ts.map +1 -1
  25. package/build/lib/webdriveragent.js +21 -20
  26. package/build/lib/webdriveragent.js.map +1 -1
  27. package/build/lib/xcodebuild.d.ts.map +1 -1
  28. package/build/lib/xcodebuild.js +16 -19
  29. package/build/lib/xcodebuild.js.map +1 -1
  30. package/build/tsconfig.tsbuildinfo +1 -1
  31. package/lib/check-dependencies.ts +20 -14
  32. package/lib/constants.ts +0 -1
  33. package/lib/logger.ts +1 -1
  34. package/lib/no-session-proxy.ts +5 -7
  35. package/lib/types.ts +6 -1
  36. package/lib/utils.ts +80 -52
  37. package/lib/webdriveragent.ts +189 -134
  38. package/lib/xcodebuild.ts +62 -54
  39. package/package.json +3 -2
@@ -1,17 +1,18 @@
1
- import { fs } from '@appium/support';
2
- import { exec } from 'teen_process';
1
+ import {fs} from '@appium/support';
2
+ import {exec} from 'teen_process';
3
3
  import path from 'node:path';
4
- import {
5
- WDA_SCHEME, SDK_SIMULATOR, WDA_RUNNER_APP
6
- } from './constants';
7
- import { BOOTSTRAP_PATH } from './utils';
8
- import type { XcodeBuild } from './xcodebuild';
4
+ import {WDA_SCHEME, SDK_SIMULATOR, WDA_RUNNER_APP} from './constants';
5
+ import {BOOTSTRAP_PATH} from './utils';
6
+ import type {XcodeBuild} from './xcodebuild';
9
7
 
10
- async function buildWDASim (): Promise<void> {
8
+ async function buildWDASim(): Promise<void> {
11
9
  const args = [
12
- '-project', path.join(BOOTSTRAP_PATH, 'WebDriverAgent.xcodeproj'),
13
- '-scheme', WDA_SCHEME,
14
- '-sdk', SDK_SIMULATOR,
10
+ '-project',
11
+ path.join(BOOTSTRAP_PATH, 'WebDriverAgent.xcodeproj'),
12
+ '-scheme',
13
+ WDA_SCHEME,
14
+ '-sdk',
15
+ SDK_SIMULATOR,
15
16
  'CODE_SIGN_IDENTITY=""',
16
17
  'CODE_SIGNING_REQUIRED="NO"',
17
18
  'GCC_TREAT_WARNINGS_AS_ERRORS=0',
@@ -19,16 +20,21 @@ async function buildWDASim (): Promise<void> {
19
20
  await exec('xcodebuild', args);
20
21
  }
21
22
 
22
- export async function bundleWDASim (xcodebuild: XcodeBuild): Promise<string> {
23
+ export async function bundleWDASim(xcodebuild: XcodeBuild): Promise<string> {
23
24
  const derivedDataPath = await xcodebuild.retrieveDerivedDataPath();
24
25
  if (!derivedDataPath) {
25
26
  throw new Error('Cannot retrieve the path to the Xcode derived data folder');
26
27
  }
27
- const wdaBundlePath = path.join(derivedDataPath, 'Build', 'Products', 'Debug-iphonesimulator', WDA_RUNNER_APP);
28
+ const wdaBundlePath = path.join(
29
+ derivedDataPath,
30
+ 'Build',
31
+ 'Products',
32
+ 'Debug-iphonesimulator',
33
+ WDA_RUNNER_APP,
34
+ );
28
35
  if (await fs.exists(wdaBundlePath)) {
29
36
  return wdaBundlePath;
30
37
  }
31
38
  await buildWDASim();
32
39
  return wdaBundlePath;
33
40
  }
34
-
package/lib/constants.ts CHANGED
@@ -15,4 +15,3 @@ export const SDK_SIMULATOR = 'iphonesimulator';
15
15
  export const SDK_DEVICE = 'iphoneos';
16
16
 
17
17
  export const WDA_UPGRADE_TIMESTAMP_PATH = path.join('.appium', 'webdriveragent', 'upgrade.time');
18
-
package/lib/logger.ts CHANGED
@@ -1,3 +1,3 @@
1
- import { logger } from '@appium/support';
1
+ import {logger} from '@appium/support';
2
2
 
3
3
  export const log = logger.getLogger('WebDriverAgent');
@@ -1,19 +1,18 @@
1
- import { JWProxy } from '@appium/base-driver';
2
- import type { ProxyOptions } from '@appium/types';
3
-
1
+ import {JWProxy} from '@appium/base-driver';
2
+ import type {ProxyOptions} from '@appium/types';
4
3
 
5
4
  export class NoSessionProxy extends JWProxy {
6
- constructor (opts: ProxyOptions = {}) {
5
+ constructor(opts: ProxyOptions = {}) {
7
6
  super(opts);
8
7
  }
9
8
 
10
- override getUrlForProxy (url: string): string {
9
+ override getUrlForProxy(url: string): string {
11
10
  if (url === '') {
12
11
  url = '/';
13
12
  }
14
13
  const proxyBase = `${this.scheme}://${this.server}:${this.port}${this.base}`;
15
14
  let remainingUrl = '';
16
- if ((new RegExp('^/')).test(url)) {
15
+ if (new RegExp('^/').test(url)) {
17
16
  remainingUrl = url;
18
17
  } else {
19
18
  throw new Error(`Did not know what to do with url '${url}'`);
@@ -22,4 +21,3 @@ export class NoSessionProxy extends JWProxy {
22
21
  return proxyBase + remainingUrl;
23
22
  }
24
23
  }
25
-
package/lib/types.ts CHANGED
@@ -21,7 +21,12 @@ export interface WDASettings {
21
21
  defaultAlertAction?: 'accept' | 'dismiss';
22
22
  acceptAlertButtonSelector?: string;
23
23
  dismissAlertButtonSelector?: string;
24
- screenshotOrientation?: 'auto' | 'portrait' | 'portraitUpsideDown' | 'landscapeRight' | 'landscapeLeft'
24
+ screenshotOrientation?:
25
+ | 'auto'
26
+ | 'portrait'
27
+ | 'portraitUpsideDown'
28
+ | 'landscapeRight'
29
+ | 'landscapeLeft';
25
30
  waitForIdleTimeout?: number;
26
31
  animationCoolOffTimeout?: number;
27
32
  maxTypingFrequency?: number;
package/lib/utils.ts CHANGED
@@ -1,15 +1,15 @@
1
- import { fs, plist } from '@appium/support';
2
- import { exec, SubProcess } from 'teen_process';
3
- import path, { dirname } from 'node:path';
4
- import { fileURLToPath } from 'node:url';
5
- import { log } from './logger';
1
+ import {fs, plist} from '@appium/support';
2
+ import {exec, SubProcess} from 'teen_process';
3
+ import path, {dirname} from 'node:path';
4
+ import {fileURLToPath} from 'node:url';
5
+ import {log} from './logger';
6
6
  import _ from 'lodash';
7
- import { PLATFORM_NAME_TVOS } from './constants';
7
+ import {PLATFORM_NAME_TVOS} from './constants';
8
8
  import B from 'bluebird';
9
9
  import _fs from 'node:fs';
10
- import { waitForCondition } from 'asyncbox';
11
- import { arch } from 'node:os';
12
- import type { DeviceInfo } from './types';
10
+ import {waitForCondition} from 'asyncbox';
11
+ import {arch} from 'node:os';
12
+ import type {DeviceInfo} from './types';
13
13
 
14
14
  // Get current filename - works in both CommonJS and ESM
15
15
  const currentFilename =
@@ -25,14 +25,16 @@ const currentDirname = dirname(currentFilename);
25
25
  * @returns {string} The full path to module root
26
26
  * @throws {Error} If the current module root folder cannot be determined
27
27
  */
28
- const getModuleRoot = _.memoize(function getModuleRoot (): string {
28
+ const getModuleRoot = _.memoize(function getModuleRoot(): string {
29
29
  let currentDir = currentDirname;
30
30
  let isAtFsRoot = false;
31
31
  while (!isAtFsRoot) {
32
32
  const manifestPath = path.join(currentDir, 'package.json');
33
33
  try {
34
- if (_fs.existsSync(manifestPath) &&
35
- JSON.parse(_fs.readFileSync(manifestPath, 'utf8')).name === 'appium-webdriveragent') {
34
+ if (
35
+ _fs.existsSync(manifestPath) &&
36
+ JSON.parse(_fs.readFileSync(manifestPath, 'utf8')).name === 'appium-webdriveragent'
37
+ ) {
36
38
  return currentDir;
37
39
  }
38
40
  } catch {}
@@ -44,7 +46,7 @@ const getModuleRoot = _.memoize(function getModuleRoot (): string {
44
46
 
45
47
  export const BOOTSTRAP_PATH = getModuleRoot();
46
48
 
47
- export async function killAppUsingPattern (pgrepPattern: string): Promise<void> {
49
+ export async function killAppUsingPattern(pgrepPattern: string): Promise<void> {
48
50
  const signals = [2, 15, 9];
49
51
  for (const signal of signals) {
50
52
  const matchedPids = await getPIDsUsingPattern(pgrepPattern);
@@ -62,20 +64,22 @@ export async function killAppUsingPattern (pgrepPattern: string): Promise<void>
62
64
  return;
63
65
  }
64
66
  try {
65
- await waitForCondition(async () => {
66
- const pidCheckPromises = matchedPids
67
- .map((pid) => exec('kill', ['-0', pid])
68
- // the process is still alive
69
- .then(() => false)
70
- // the process is dead
71
- .catch(() => true)
67
+ await waitForCondition(
68
+ async () => {
69
+ const pidCheckPromises = matchedPids.map((pid) =>
70
+ exec('kill', ['-0', pid])
71
+ // the process is still alive
72
+ .then(() => false)
73
+ // the process is dead
74
+ .catch(() => true),
72
75
  );
73
- return (await B.all(pidCheckPromises))
74
- .every((x) => x === true);
75
- }, {
76
- waitMs: 1000,
77
- intervalMs: 100,
78
- });
76
+ return (await B.all(pidCheckPromises)).every((x) => x === true);
77
+ },
78
+ {
79
+ waitMs: 1000,
80
+ intervalMs: 100,
81
+ },
82
+ );
79
83
  return;
80
84
  } catch {
81
85
  // try the next signal
@@ -88,11 +92,14 @@ export async function killAppUsingPattern (pgrepPattern: string): Promise<void>
88
92
  * @param platformName The name of the platorm
89
93
  * @returns Return true if the platformName is tvOS
90
94
  */
91
- export function isTvOS (platformName: string): boolean {
95
+ export function isTvOS(platformName: string): boolean {
92
96
  return _.toLower(platformName) === _.toLower(PLATFORM_NAME_TVOS);
93
97
  }
94
98
 
95
- export async function setRealDeviceSecurity (keychainPath: string, keychainPassword: string): Promise<void> {
99
+ export async function setRealDeviceSecurity(
100
+ keychainPath: string,
101
+ keychainPassword: string,
102
+ ): Promise<void> {
96
103
  log.debug('Setting security for iOS device');
97
104
  await exec('security', ['-v', 'list-keychains', '-s', keychainPath]);
98
105
  await exec('security', ['-v', 'unlock-keychain', '-p', keychainPassword, keychainPath]);
@@ -124,11 +131,15 @@ export interface XctestrunFileArgs {
124
131
  * or WebDriverAgentRunner_iphonesimulator${sdkVersion|platformVersion}-x86_64.xctestrun for simulator is not found @bootstrapPath,
125
132
  * then it will throw a file not found exception
126
133
  */
127
- export async function setXctestrunFile (args: XctestrunFileArgs): Promise<string> {
134
+ export async function setXctestrunFile(args: XctestrunFileArgs): Promise<string> {
128
135
  const {deviceInfo, sdkVersion, bootstrapPath, wdaRemotePort, wdaBindingIP} = args;
129
136
  const xctestrunFilePath = await getXctestrunFilePath(deviceInfo, sdkVersion, bootstrapPath);
130
137
  const xctestRunContent = await plist.parsePlistFile(xctestrunFilePath);
131
- const updateWDAPort = getAdditionalRunContent(deviceInfo.platformName, wdaRemotePort, wdaBindingIP);
138
+ const updateWDAPort = getAdditionalRunContent(
139
+ deviceInfo.platformName,
140
+ wdaRemotePort,
141
+ wdaBindingIP,
142
+ );
132
143
  const newXctestRunContent = _.merge(xctestRunContent, updateWDAPort);
133
144
  await plist.updatePlistFile(xctestrunFilePath, newXctestRunContent, true);
134
145
 
@@ -142,16 +153,20 @@ export async function setXctestrunFile (args: XctestrunFileArgs): Promise<string
142
153
  * @param wdaBindingIP - The IP address to bind to. If not given, it binds to all interfaces.
143
154
  * @return returns a runner object which has USE_PORT and optionally USE_IP
144
155
  */
145
- export function getAdditionalRunContent (platformName: string, wdaRemotePort: number | string, wdaBindingIP?: string): Record<string, any> {
156
+ export function getAdditionalRunContent(
157
+ platformName: string,
158
+ wdaRemotePort: number | string,
159
+ wdaBindingIP?: string,
160
+ ): Record<string, any> {
146
161
  const runner = `WebDriverAgentRunner${isTvOS(platformName) ? '_tvOS' : ''}`;
147
162
  return {
148
163
  [runner]: {
149
164
  EnvironmentVariables: {
150
165
  // USE_PORT must be 'string'
151
166
  USE_PORT: `${wdaRemotePort}`,
152
- ...(wdaBindingIP ? { USE_IP: wdaBindingIP } : {}),
153
- }
154
- }
167
+ ...(wdaBindingIP ? {USE_IP: wdaBindingIP} : {}),
168
+ },
169
+ },
155
170
  };
156
171
  }
157
172
 
@@ -161,7 +176,11 @@ export function getAdditionalRunContent (platformName: string, wdaRemotePort: nu
161
176
  * @param sdkVersion - The Xcode SDK version of OS.
162
177
  * @param bootstrapPath - The folder path containing xctestrun file.
163
178
  */
164
- export async function getXctestrunFilePath (deviceInfo: DeviceInfo, sdkVersion: string, bootstrapPath: string): Promise<string> {
179
+ export async function getXctestrunFilePath(
180
+ deviceInfo: DeviceInfo,
181
+ sdkVersion: string,
182
+ bootstrapPath: string,
183
+ ): Promise<string> {
165
184
  // First try the SDK path, for Xcode 10 (at least)
166
185
  const sdkBased: [string, string] = [
167
186
  path.resolve(bootstrapPath, `${deviceInfo.udid}_${sdkVersion}.xctestrun`),
@@ -178,7 +197,10 @@ export async function getXctestrunFilePath (deviceInfo: DeviceInfo, sdkVersion:
178
197
  log.info(`Using '${filePath}' as xctestrun file`);
179
198
  return filePath;
180
199
  }
181
- const originalXctestrunFile = path.resolve(bootstrapPath, getXctestrunFileName(deviceInfo, version));
200
+ const originalXctestrunFile = path.resolve(
201
+ bootstrapPath,
202
+ getXctestrunFileName(deviceInfo, version),
203
+ );
182
204
  if (await fs.exists(originalXctestrunFile)) {
183
205
  // If this is first time run for given device, then first generate xctestrun file for device.
184
206
  // We need to have a xctestrun file **per device** because we cant not have same wda port for all devices.
@@ -190,19 +212,18 @@ export async function getXctestrunFilePath (deviceInfo: DeviceInfo, sdkVersion:
190
212
 
191
213
  throw new Error(
192
214
  `If you are using 'useXctestrunFile' capability then you ` +
193
- `need to have a xctestrun file (expected: ` +
194
- `'${path.resolve(bootstrapPath, getXctestrunFileName(deviceInfo, sdkVersion))}')`
215
+ `need to have a xctestrun file (expected: ` +
216
+ `'${path.resolve(bootstrapPath, getXctestrunFileName(deviceInfo, sdkVersion))}')`,
195
217
  );
196
218
  }
197
219
 
198
-
199
220
  /**
200
221
  * Return the name of xctestrun file
201
222
  * @param deviceInfo
202
223
  * @param version - The Xcode SDK version of OS.
203
224
  * @return returns xctestrunFilePath for given device
204
225
  */
205
- export function getXctestrunFileName (deviceInfo: DeviceInfo, version: string): string {
226
+ export function getXctestrunFileName(deviceInfo: DeviceInfo, version: string): string {
206
227
  const archSuffix = deviceInfo.isRealDevice
207
228
  ? `os${version}-arm64`
208
229
  : `simulator${version}-${arch() === 'arm64' ? 'arm64' : 'x86_64'}`;
@@ -212,7 +233,10 @@ export function getXctestrunFileName (deviceInfo: DeviceInfo, version: string):
212
233
  /**
213
234
  * Ensures the process is killed after the timeout
214
235
  */
215
- export async function killProcess (name: string, proc: SubProcess | null | undefined): Promise<void> {
236
+ export async function killProcess(
237
+ name: string,
238
+ proc: SubProcess | null | undefined,
239
+ ): Promise<void> {
216
240
  if (!proc || !proc.isRunning) {
217
241
  return;
218
242
  }
@@ -245,16 +269,16 @@ export async function killProcess (name: string, proc: SubProcess | null | undef
245
269
  /**
246
270
  * Generate a random integer in range [low, high). `low` is inclusive and `high` is exclusive.
247
271
  */
248
- export function randomInt (low: number, high: number): number {
272
+ export function randomInt(low: number, high: number): number {
249
273
  return Math.floor(Math.random() * (high - low) + low);
250
274
  }
251
275
 
252
276
  /**
253
277
  * Retrieves WDA upgrade timestamp. The manifest only gets modified on package upgrade.
254
278
  */
255
- export async function getWDAUpgradeTimestamp (): Promise<number | null> {
279
+ export async function getWDAUpgradeTimestamp(): Promise<number | null> {
256
280
  const packageManifest = path.resolve(getModuleRoot(), 'package.json');
257
- if (!await fs.exists(packageManifest)) {
281
+ if (!(await fs.exists(packageManifest))) {
258
282
  return null;
259
283
  }
260
284
  const {mtime} = await fs.stat(packageManifest);
@@ -264,7 +288,7 @@ export async function getWDAUpgradeTimestamp (): Promise<number | null> {
264
288
  /**
265
289
  * Kills running XCTest processes for the particular device.
266
290
  */
267
- export async function resetTestProcesses (udid: string, isSimulator: boolean): Promise<void> {
291
+ export async function resetTestProcesses(udid: string, isSimulator: boolean): Promise<void> {
268
292
  const processPatterns = [`xcodebuild.*${udid}`];
269
293
  if (isSimulator) {
270
294
  processPatterns.push(`${udid}.*XCTRunner`);
@@ -288,12 +312,15 @@ export async function resetTestProcesses (udid: string, isSimulator: boolean): P
288
312
  * from the resulting array.
289
313
  * @returns - the list of matched process ids.
290
314
  */
291
- export async function getPIDsListeningOnPort (port: string | number, filteringFunc: ((cmdline: string) => boolean | Promise<boolean>) | null = null): Promise<string[]> {
315
+ export async function getPIDsListeningOnPort(
316
+ port: string | number,
317
+ filteringFunc: ((cmdline: string) => boolean | Promise<boolean>) | null = null,
318
+ ): Promise<string[]> {
292
319
  const result: string[] = [];
293
320
  try {
294
321
  // This only works since Mac OS X El Capitan
295
322
  const {stdout} = await exec('lsof', ['-ti', `tcp:${port}`]);
296
- result.push(...(stdout.trim().split(/\n+/)));
323
+ result.push(...stdout.trim().split(/\n+/));
297
324
  } catch (e: any) {
298
325
  if (e.code !== 1) {
299
326
  // code 1 means no processes. Other errors need reporting
@@ -322,21 +349,22 @@ export async function getPIDsListeningOnPort (port: string | number, filteringFu
322
349
 
323
350
  // Private functions
324
351
 
325
- async function getPIDsUsingPattern (pattern: string): Promise<string[]> {
352
+ async function getPIDsUsingPattern(pattern: string): Promise<string[]> {
326
353
  const args = [
327
354
  '-if', // case insensitive, full cmdline match
328
355
  pattern,
329
356
  ];
330
357
  try {
331
358
  const {stdout} = await exec('pgrep', args);
332
- return stdout.split(/\s+/)
359
+ return stdout
360
+ .split(/\s+/)
333
361
  .map((x) => parseInt(x, 10))
334
362
  .filter(_.isInteger)
335
363
  .map((x) => `${x}`);
336
364
  } catch (err: any) {
337
- log.debug(`'pgrep ${args.join(' ')}' didn't detect any matching processes. Return code: ${err.code}`);
365
+ log.debug(
366
+ `'pgrep ${args.join(' ')}' didn't detect any matching processes. Return code: ${err.code}`,
367
+ );
338
368
  return [];
339
369
  }
340
370
  }
341
-
342
-