Skip to content

Commit c1fb5a4

Browse files
KazuCocoaCopilot
andauthored
feat: add download-wda-sim to download prebuilt WDA for Sim (#2587)
* proto * rename * rename * add docs * add the command * add logs * fix the order * remove @ and redundant implementation * update docs * add type * update entirely * revert a script * add js to fix ERR_MODULE_NOT_FOUND * Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * move the log before the exit code * remvoe redundant new line * modify a bit * rename the logger name * just raise error * rename * update the doc * Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * remove redundant spaces * update docs --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent bab0c3e commit c1fb5a4

7 files changed

Lines changed: 92 additions & 13 deletions

File tree

docs/guides/run-prebuilt-wda.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,3 +112,5 @@ Simulators need everything, so package sizes for simulators are greater than for
112112
The [Release](https://github.com/appium/appium-xcuitest-driver/actions/workflows/publish.js.yml) and
113113
[Building WebDriverAgent](https://github.com/appium/WebDriverAgent/actions/workflows/wda-package.yml)
114114
workflows may help with validating the build script.
115+
116+
`appium driver run xcuitest download-wda-sim` command helps to download the prebuilt WDA.

docs/reference/scripts.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,5 @@ appium driver run xcuitest <script-name>
2121
|`tunnel-creation --udid=<device-udid>` or `-u <device-udid>`|Creates a tunnel for a specific iOS device with the given UDID|
2222
|`tunnel-creation --packet-stream-base-port=<port>`|Specifies the base port for packet stream servers (default: 50000)|
2323
|`tunnel-creation --tunnel-registry-port=<port>`|Specifies the port for the tunnel registry server (default: 42314)|
24+
|`download-wda-sim --outdir=/path/to/dir`|Download corresponding version's prebuilt WDA for iOS matched with the host machine architecture from [GitHub WebDriver release page](https://github.com/appium/WebDriverAgent/releases) into `--outdir` directory. The downloaded package name will be `WebDriverAgentRunner-Runner.app`.|
25+
|`download-wda-sim --platform=tvos --outdir=/path/to/dir`|Download corresponding version's prebuilt WDA for `--platform` into `--outdir` directory. If `--platform=tvos` is provided, the download module will be for tvOS (`WebDriverAgentRunner_tvOS-Runner.app`), otherwise the command will download iOS.|

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@
3333
"scripts": {
3434
"build-wda": "./scripts/build-wda.js",
3535
"open-wda": "./scripts/open-wda.js",
36-
"tunnel-creation": "./scripts/tunnel-creation.mjs"
36+
"tunnel-creation": "./scripts/tunnel-creation.mjs",
37+
"download-wda-sim": "./scripts/download-wda-sim.mjs"
3738
},
3839
"schema": {
3940
"$schema": "http://json-schema.org/draft-07/schema",

scripts/build-wda.js

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,10 @@ const xcode = require('appium-xcode');
33
const {Simctl} = require('node-simctl');
44
const {getSimulator} = require('appium-ios-simulator');
55
const {logger} = require('appium/support');
6+
const {parseArgValue} = require('./utils');
67

78
const log = logger.getLogger('WDA');
89

9-
function parseArgValue(argName) {
10-
const argNamePattern = new RegExp(`^--${argName}\\b`);
11-
for (let i = 1; i < process.argv.length; ++i) {
12-
const arg = process.argv[i];
13-
if (argNamePattern.test(arg)) {
14-
return arg.includes('=') ? arg.split('=')[1] : process.argv[i + 1];
15-
}
16-
}
17-
return null;
18-
}
19-
2010
async function build() {
2111
const customDevice = parseArgValue('name');
2212
const xcodeVersion = await xcode.getVersion(true);

scripts/download-wda-sim.mjs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import {fs, logger, zip, net, node} from 'appium/support.js';
2+
import _ from 'lodash';
3+
import os from 'os';
4+
import path from 'path';
5+
import {parseArgValue} from './utils.js';
6+
7+
const log = logger.getLogger('download-wda-sim');
8+
const wdaUrl = (version, zipFileName) =>
9+
`https://github.com/appium/WebDriverAgent/releases/download/v${version}/${zipFileName}`;
10+
const destZip = (platform) => {
11+
const scheme = `WebDriverAgentRunner${_.toLower(platform) === 'tvos' ? '_tvOS' : ''}`;
12+
return `${scheme}-Build-Sim-${os.arch() === 'arm64' ? 'arm64' : 'x86_64'}.zip`;
13+
};
14+
15+
/**
16+
* Return installed appium-webdriveragent package version
17+
* @returns {number}
18+
*/
19+
async function webdriveragentPkgVersion() {
20+
const pkgPath = path.join(
21+
node.getModuleRootSync('appium-xcuitest-driver', import.meta.url),
22+
'node_modules',
23+
'appium-webdriveragent',
24+
'package.json'
25+
);
26+
return JSON.parse(await fs.readFile(pkgPath, 'utf8')).version;
27+
};
28+
29+
/**
30+
* Prepare the working root directory.
31+
* @returns {string} Root directory to download and unzip.
32+
*/
33+
async function prepareRootDir() {
34+
const destDirRoot = parseArgValue('outdir');
35+
if (!destDirRoot) {
36+
throw new Error(`--outdir is required`);
37+
}
38+
const destDir = path.resolve(process.cwd(), destDirRoot);
39+
if (await fs.exists(destDir)) {
40+
throw new Error(`${destDir} already exists`);
41+
}
42+
await fs.mkdir(destDir, {recursive: true});
43+
return destDir;
44+
}
45+
46+
async function getWDAPrebuiltPackage() {
47+
const destDir = await prepareRootDir();
48+
const platform = parseArgValue('platform');
49+
const zipFileName = destZip(platform);
50+
const wdaVersion = await webdriveragentPkgVersion();
51+
const urlToDownload = wdaUrl(wdaVersion, zipFileName);
52+
const downloadedZipFile = path.join(destDir, zipFileName);
53+
try {
54+
log.info(`Downloading ${urlToDownload}`);
55+
await net.downloadFile(urlToDownload, downloadedZipFile);
56+
57+
log.info(`Unpacking ${downloadedZipFile} into ${destDir}`);
58+
await zip.extractAllTo(downloadedZipFile, destDir);
59+
60+
log.info(`Deleting ${downloadedZipFile}`);
61+
} finally {
62+
if (await fs.exists(downloadedZipFile)) {
63+
await fs.unlink(downloadedZipFile);
64+
}
65+
}
66+
}
67+
68+
(async () => await getWDAPrebuiltPackage())();

scripts/tunnel-creation.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Test script for creating lockdown service, starting CoreDeviceProxy, and creating tunnel
44
* This script demonstrates the tunnel creation workflow for all connected devices
55
*/
6-
import {logger, node} from '@appium/support';
6+
import {logger, node} from 'appium/support.js';
77
import _ from 'lodash';
88
/* eslint-disable import/no-unresolved */
99
import {

scripts/utils.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/**
2+
* Get the value of the given argument name.
3+
*
4+
* @param {string} argName
5+
* @returns {string?} The value of the given 'argName'.
6+
*/
7+
export function parseArgValue(argName) {
8+
const argNamePattern = new RegExp(`^--${argName}\\b`);
9+
for (let i = 1; i < process.argv.length; ++i) {
10+
const arg = process.argv[i];
11+
if (argNamePattern.test(arg)) {
12+
return arg.includes('=') ? arg.split('=')[1] : process.argv[i + 1];
13+
}
14+
}
15+
return null;
16+
}

0 commit comments

Comments
 (0)