appium-xcuitest-driver 10.13.3 → 10.13.4

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.
@@ -2,34 +2,42 @@ import B from 'bluebird';
2
2
  import {logger} from 'appium/support';
3
3
  import _ from 'lodash';
4
4
  import {errors} from 'appium/driver';
5
+ import type {XCUITestDriver} from '../driver';
6
+ import type {XCTestResult, RunXCTestResult} from './types';
7
+ import type {StringRecord} from '@appium/types';
8
+ import type IDB from 'appium-idb';
5
9
 
6
10
  const XCTEST_TIMEOUT = 360000; // 60 minute timeout
7
11
 
8
12
  const xctestLog = logger.getLogger('XCTest');
9
13
 
10
14
  /**
11
- * Asserts that IDB is present and that launchWithIDB was used
15
+ * Asserts that IDB is present and that launchWithIDB was used.
12
16
  *
13
- * @param {XCUITestDriver['opts']} opts Opts object from the driver instance
17
+ * @param opts - Opts object from the driver instance
18
+ * @returns The IDB instance
19
+ * @throws {Error} If IDB is not available or launchWithIDB is not enabled
14
20
  */
15
- export function assertIDB(opts) {
16
- if (!this.device?.idb || !opts.launchWithIDB) {
21
+ export function assertIDB(this: XCUITestDriver, opts: XCUITestDriver['opts']): IDB {
22
+ const device = this.device as any;
23
+ if (!device?.idb || !opts.launchWithIDB) {
17
24
  throw new Error(
18
25
  `To use XCTest runner, IDB (https://github.com/facebook/idb) must be installed ` +
19
26
  `and sessions must be run with the "launchWithIDB" capability`,
20
27
  );
21
28
  }
22
- return this.device.idb;
29
+ return device.idb;
23
30
  }
24
31
 
25
32
  /**
26
- * Parse the stdout of XC test log
27
- * @param {string} stdout A line of standard out from `idb xctest run ...`
28
- * @returns {XCTestResult[]|string[]} results The final output of the XCTest run
33
+ * Parse the stdout of XC test log.
34
+ *
35
+ * @param stdout - A line of standard out from `idb xctest run ...`
36
+ * @returns The final output of the XCTest run
29
37
  */
30
- export function parseXCTestStdout(stdout) {
38
+ export function parseXCTestStdout(stdout: string): XCTestResult[] | string[] {
31
39
  // Parses a 'key' into JSON format
32
- function parseKey(name) {
40
+ function parseKey(name: string): string {
33
41
  const words = name.split(' ');
34
42
  let out = '';
35
43
  for (const word of words) {
@@ -39,7 +47,7 @@ export function parseXCTestStdout(stdout) {
39
47
  }
40
48
 
41
49
  // Parses a 'value' into JSON format
42
- function parseValue(value) {
50
+ function parseValue(value: string): any {
43
51
  value = value || '';
44
52
  switch (value.toLowerCase()) {
45
53
  case 'true':
@@ -51,7 +59,7 @@ export function parseXCTestStdout(stdout) {
51
59
  default:
52
60
  break;
53
61
  }
54
- if (!isNaN(value)) {
62
+ if (!isNaN(Number(value))) {
55
63
  if (!_.isString(value)) {
56
64
  return 0;
57
65
  } else if (value.indexOf('.') > 0) {
@@ -73,16 +81,14 @@ export function parseXCTestStdout(stdout) {
73
81
  return [lines[0]];
74
82
  }
75
83
 
76
- /** @type {XCTestResult[]} */
77
- const results = [];
84
+ const results: XCTestResult[] = [];
78
85
  for (const line of lines) {
79
86
  // The properties are split up by pipes and each property
80
87
  // has the format "Some Key : Some Value"
81
88
  const properties = line.split('|');
82
89
 
83
90
  // Parse each property
84
- /** @type {XCTestResult} */
85
- const output = /** @type {any} */ ({});
91
+ const output: any = {};
86
92
  let entryIndex = 0;
87
93
  for (const prop of properties) {
88
94
  if (entryIndex === 0) {
@@ -94,7 +100,7 @@ export function parseXCTestStdout(stdout) {
94
100
  // e.g. Location /path/to/XCTesterAppUITests/XCTesterAppUITests.swift:36
95
101
  output.location = prop.substring(prop.indexOf('Location') + 8).trim();
96
102
  } else {
97
- let [key, value] = prop.split(':');
103
+ const [key, value] = prop.split(':');
98
104
  output[parseKey(key.trim())] = parseValue(value ? value.trim() : '');
99
105
  }
100
106
  entryIndex++;
@@ -123,12 +129,13 @@ export function parseXCTestStdout(stdout) {
123
129
  }
124
130
 
125
131
  /**
126
- * @typedef {Error} XCUITestError
127
- *
128
- * @property {number} code Subprocess exit code
129
- * @property {string} signal The signal (SIG*) that caused the process to fail
130
- * @property {XCTestResult[]} results The output of the failed test (if there is output)
132
+ * Error thrown when XCTest subprocess returns non-zero exit code.
131
133
  */
134
+ export interface XCUITestError extends Error {
135
+ code: number;
136
+ signal?: string;
137
+ result?: XCTestResult[];
138
+ }
132
139
 
133
140
  /**
134
141
  * Run a native XCTest script.
@@ -137,36 +144,36 @@ export function parseXCTestStdout(stdout) {
137
144
  *
138
145
  * **Facebook's [IDB](https://github.com/facebook/idb) tool is required** to run such tests; see [the idb docs](https://fbidb.io/docs/test-execution/) for reference.
139
146
  *
140
- * @param {string} testRunnerBundleId - Test app bundle (e.g.: `io.appium.XCTesterAppUITests.xctrunner`)
141
- * @param {string} appUnderTestBundleId - App-under-test bundle
142
- * @param {string} xcTestBundleId - XCTest bundle ID
143
- * @param {string[]} args - Launch arguments to start the test with (see [reference documentation](https://developer.apple.com/documentation/xctest/xcuiapplication/1500477-launcharguments))
144
- * @param {'app'|'ui'|'logic'} testType - XC test type
145
- * @param {import('@appium/types').StringRecord} [env] - Environment variables passed to test
146
- * @param {number} timeout - Timeout (in ms) for session completion.
147
+ * @param testRunnerBundleId - Test app bundle (e.g.: `io.appium.XCTesterAppUITests.xctrunner`)
148
+ * @param appUnderTestBundleId - App-under-test bundle
149
+ * @param xcTestBundleId - XCTest bundle ID
150
+ * @param args - Launch arguments to start the test with (see [reference documentation](https://developer.apple.com/documentation/xctest/xcuiapplication/1500477-launcharguments))
151
+ * @param testType - XC test type
152
+ * @param env - Environment variables passed to test
153
+ * @param timeout - Timeout (in ms) for session completion
154
+ * @returns The array of test results
147
155
  * @throws {XCUITestError} Error thrown if subprocess returns non-zero exit code
148
- * @returns {Promise<import('./types').RunXCTestResult>} The array of test results
149
- * @this {XCUITestDriver}
150
156
  */
151
157
  export async function mobileRunXCTest(
152
- testRunnerBundleId,
153
- appUnderTestBundleId,
154
- xcTestBundleId,
155
- args = [],
156
- testType = 'ui',
157
- env,
158
+ this: XCUITestDriver,
159
+ testRunnerBundleId: string,
160
+ appUnderTestBundleId: string,
161
+ xcTestBundleId: string,
162
+ args: string[] = [],
163
+ testType: 'app' | 'ui' | 'logic' = 'ui',
164
+ env?: StringRecord,
158
165
  timeout = XCTEST_TIMEOUT,
159
- ) {
160
- const subproc = await assertIDB(this.opts).runXCUITest(
166
+ ): Promise<RunXCTestResult> {
167
+ const subproc = await assertIDB.call(this, this.opts).runXCUITest(
161
168
  testRunnerBundleId,
162
169
  appUnderTestBundleId,
163
170
  xcTestBundleId,
164
171
  {env, args, testType},
165
172
  );
166
173
  return await new B((resolve, reject) => {
167
- let mostRecentLogObject = null;
168
- let xctestTimeout;
169
- let lastErrorMessage = null;
174
+ let mostRecentLogObject: XCTestResult[] | string[] | null = null;
175
+ let xctestTimeout: NodeJS.Timeout | undefined;
176
+ let lastErrorMessage: string | null = null;
170
177
  if (timeout > 0) {
171
178
  xctestTimeout = setTimeout(
172
179
  () =>
@@ -179,11 +186,11 @@ export async function mobileRunXCTest(
179
186
  );
180
187
  }
181
188
 
182
- subproc.on('output', (stdout, stderr) => {
189
+ subproc.on('output', (stdout: string, stderr: string) => {
183
190
  if (stdout) {
184
191
  try {
185
192
  mostRecentLogObject = parseXCTestStdout(stdout);
186
- } catch (err) {
193
+ } catch (err: any) {
187
194
  // Fails if log parsing fails.
188
195
  // This is in case IDB changes the way that logs are formatted and
189
196
  // it breaks 'parseXCTestStdout'. If that happens we still want the process
@@ -202,23 +209,25 @@ export async function mobileRunXCTest(
202
209
  }
203
210
  });
204
211
 
205
- subproc.on('exit', (code, signal) => {
206
- clearTimeout(xctestTimeout);
212
+ subproc.on('exit', (code: number | null, signal: string | null) => {
213
+ if (xctestTimeout) {
214
+ clearTimeout(xctestTimeout);
215
+ }
207
216
  if (code !== 0) {
208
- const err = /** @type {any} */ (new Error(lastErrorMessage || mostRecentLogObject));
209
- err.code = code;
217
+ const err = new Error(lastErrorMessage || String(mostRecentLogObject)) as XCUITestError;
218
+ err.code = code ?? -1;
210
219
  if (signal != null) {
211
220
  err.signal = signal;
212
221
  }
213
222
  if (mostRecentLogObject) {
214
- err.result = mostRecentLogObject;
223
+ err.result = mostRecentLogObject as XCTestResult[];
215
224
  }
216
225
  return reject(err);
217
226
  }
218
227
  resolve({
219
- code,
220
- signal,
221
- results: mostRecentLogObject,
228
+ code: code ?? 0,
229
+ signal: signal ?? null,
230
+ results: mostRecentLogObject as XCTestResult[],
222
231
  passed: true,
223
232
  });
224
233
  });
@@ -230,11 +239,12 @@ export async function mobileRunXCTest(
230
239
  *
231
240
  * **Facebook's [IDB](https://github.com/facebook/idb) tool is required** for this command to work.
232
241
  *
233
- * @param {string} xctestApp - Path of the XCTest app (URL or filename with extension `.app`)
234
- * @returns {Promise<void>}
235
- * @this {XCUITestDriver}
242
+ * @param xctestApp - Path of the XCTest app (URL or filename with extension `.app`)
236
243
  */
237
- export async function mobileInstallXCTestBundle(xctestApp) {
244
+ export async function mobileInstallXCTestBundle(
245
+ this: XCUITestDriver,
246
+ xctestApp: string,
247
+ ): Promise<void> {
238
248
  if (!_.isString(xctestApp)) {
239
249
  throw new errors.InvalidArgumentError(
240
250
  `'xctestApp' is a required parameter for 'installXCTestBundle' and ` +
@@ -242,7 +252,7 @@ export async function mobileInstallXCTestBundle(xctestApp) {
242
252
  );
243
253
  }
244
254
  xctestLog.info(`Installing bundle '${xctestApp}'`);
245
- const idb = assertIDB(this.opts);
255
+ const idb = assertIDB.call(this, this.opts);
246
256
  const res = await this.helpers.configureApp(xctestApp, '.xctest');
247
257
  await idb.installXCTestBundle(res);
248
258
  }
@@ -252,34 +262,31 @@ export async function mobileInstallXCTestBundle(xctestApp) {
252
262
  *
253
263
  * **Facebook's [IDB](https://github.com/facebook/idb) tool is required** for this command to work.
254
264
  *
255
- * @returns {Promise<string[]>} List of XCTest bundles (e.g.: `XCTesterAppUITests.XCTesterAppUITests/testLaunchPerformance`)
256
- * @this {XCUITestDriver}
265
+ * @returns List of XCTest bundles (e.g.: `XCTesterAppUITests.XCTesterAppUITests/testLaunchPerformance`)
257
266
  */
258
- export async function mobileListXCTestBundles() {
259
- return await assertIDB(this.opts).listXCTestBundles();
267
+ export async function mobileListXCTestBundles(this: XCUITestDriver): Promise<string[]> {
268
+ return await assertIDB.call(this, this.opts).listXCTestBundles();
260
269
  }
261
270
 
262
271
  /**
263
- * List XCTests in a test bundle
272
+ * List XCTests in a test bundle.
264
273
  *
265
274
  * **Facebook's [IDB](https://github.com/facebook/idb) tool is required** for this command to work.
266
- * @param {string} bundle - Bundle ID of the XCTest
267
275
  *
268
- * @returns {Promise<string[]>} The list of xctests in the test bundle (e.g., `['XCTesterAppUITests.XCTesterAppUITests/testExample', 'XCTesterAppUITests.XCTesterAppUITests/testLaunchPerformance']`)
269
- * @this {XCUITestDriver}
276
+ * @param bundle - Bundle ID of the XCTest
277
+ * @returns The list of xctests in the test bundle (e.g., `['XCTesterAppUITests.XCTesterAppUITests/testExample', 'XCTesterAppUITests.XCTesterAppUITests/testLaunchPerformance']`)
270
278
  */
271
- export async function mobileListXCTestsInTestBundle(bundle) {
279
+ export async function mobileListXCTestsInTestBundle(
280
+ this: XCUITestDriver,
281
+ bundle: string,
282
+ ): Promise<string[]> {
272
283
  if (!_.isString(bundle)) {
273
284
  throw new errors.InvalidArgumentError(
274
285
  `'bundle' is a required parameter for 'listXCTestsInTestBundle' and ` +
275
286
  `must be a string. Found '${bundle}'`,
276
287
  );
277
288
  }
278
- const idb = assertIDB(this.opts);
289
+ const idb = assertIDB.call(this, this.opts);
279
290
  return await idb.listXCTestsInTestBundle(bundle);
280
291
  }
281
292
 
282
- /**
283
- * @typedef {import('../driver').XCUITestDriver} XCUITestDriver
284
- * @typedef {import('./types').XCTestResult} XCTestResult
285
- */
@@ -252,7 +252,6 @@ export const executeMethodMap = {
252
252
  command: 'mobileListCertificates',
253
253
  },
254
254
  'mobile: startLogsBroadcast': {
255
- // @ts-expect-error Class field assignment - method exists on XCUITestDriver
256
255
  command: 'mobileStartLogsBroadcast',
257
256
  },
258
257
  'mobile: stopLogsBroadcast': {
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "appium-xcuitest-driver",
3
- "version": "10.13.3",
3
+ "version": "10.13.4",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "appium-xcuitest-driver",
9
- "version": "10.13.3",
9
+ "version": "10.13.4",
10
10
  "license": "Apache-2.0",
11
11
  "dependencies": {
12
12
  "@appium/strongbox": "^1.0.0-rc.1",
@@ -773,9 +773,9 @@
773
773
  }
774
774
  },
775
775
  "node_modules/appium-webdriveragent": {
776
- "version": "11.0.2",
777
- "resolved": "https://registry.npmjs.org/appium-webdriveragent/-/appium-webdriveragent-11.0.2.tgz",
778
- "integrity": "sha512-Wu/kMQG9DS6w0abw1AOoz43C6uwA2KbhzEhVoHgvlLQ7Jhbpz/rc4D2/MMylax9J2LMNsNaOkkZdQLiPQyhx6w==",
776
+ "version": "11.1.0",
777
+ "resolved": "https://registry.npmjs.org/appium-webdriveragent/-/appium-webdriveragent-11.1.0.tgz",
778
+ "integrity": "sha512-Ve9n+QIM4JUwTvKKeuaVvyra1k02JAcNsmgTtbx3fNItEzuC/s4LjEvqoxdr5KAjGAIz/Np5Efqn6S1WyvEiZQ==",
779
779
  "license": "Apache-2.0",
780
780
  "dependencies": {
781
781
  "@appium/base-driver": "^10.0.0-rc.1",
@@ -3550,9 +3550,9 @@
3550
3550
  "license": "MIT"
3551
3551
  },
3552
3552
  "node_modules/qs": {
3553
- "version": "6.14.0",
3554
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz",
3555
- "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==",
3553
+ "version": "6.14.1",
3554
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz",
3555
+ "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==",
3556
3556
  "license": "BSD-3-Clause",
3557
3557
  "dependencies": {
3558
3558
  "side-channel": "^1.1.0"
package/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "xcuitest",
9
9
  "xctest"
10
10
  ],
11
- "version": "10.13.3",
11
+ "version": "10.13.4",
12
12
  "author": "Appium Contributors",
13
13
  "license": "Apache-2.0",
14
14
  "repository": {