appium-remote-debugger 15.6.0 → 15.7.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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## [15.7.0](https://github.com/appium/appium-remote-debugger/compare/v15.6.0...v15.7.0) (2026-04-17)
2
+
3
+ ### Features
4
+
5
+ * Add automated atoms compilation script ([#485](https://github.com/appium/appium-remote-debugger/issues/485)) ([aa129f4](https://github.com/appium/appium-remote-debugger/commit/aa129f42beade3f6e1682430d281249eb2f6250d))
6
+
1
7
  ## [15.6.0](https://github.com/appium/appium-remote-debugger/compare/v15.5.0...v15.6.0) (2026-03-10)
2
8
 
3
9
  ### Features
package/README.md CHANGED
@@ -21,23 +21,10 @@ The steps to using the `RemoteDebugger` involve instantiating an object, then ru
21
21
 
22
22
  ## Selenium "atoms"
23
23
 
24
- The remote debugger uses the standard [Selenium Atoms](https://github.com/SeleniumHQ/selenium/tree/master/javascript/atoms)
25
- to interact with web pages. These need to be manually updated when necessary.
26
- To do so, simply update the branch in the `scripts/common.mjs`, by modifying the `SELENIUM_BRANCH`
27
- constant at the top of the file and commit them to explicitly leaves the latest target branch information.
28
- Then run `npm run build:atoms`, test and create a pull request with the resulting changed atoms directory.
29
-
30
- You can set `SELENIUM_GITHUB` and `SELENIUM_BRANCH` environment variables with the npm command to
31
- customize the target repository and the target branch.
32
-
33
- Note that to build the atoms it is required that you have the `bazel` tool installed. Selenium will
34
- also require that it be installed at a particular version relative to the version of Selenium that
35
- has been checked out by our build script. It is most convenient simply to install
36
- [`bazelisk`](https://github.com/bazelbuild/bazelisk) and have it available on your PATH.
37
-
38
- One caveat is that there are some changes that are needed for Appium, that are
39
- not yet in the Selenium codebase. See the [atoms notes](./atoms-notes.md) for
40
- details.
24
+ The remote debugger uses the standard [Selenium JavaScript atoms](https://github.com/SeleniumHQ/selenium/tree/trunk/javascript/atoms)
25
+ to interact with web pages.
26
+
27
+ To refresh the bundled `atoms/` output, use the **Update Selenium Atoms** manual workflow ([`.github/workflows/update-atoms.yml`](./.github/workflows/update-atoms.yml)) in the GitHub Actions tab, or build locally. Full steps, inputs, and tooling are documented in **[docs/update-atoms.md](./docs/update-atoms.md)**.
41
28
 
42
29
  ## Test
43
30
 
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "keywords": [
5
5
  "appium"
6
6
  ],
7
- "version": "15.6.0",
7
+ "version": "15.7.0",
8
8
  "author": "Appium Contributors",
9
9
  "license": "Apache-2.0",
10
10
  "repository": {
@@ -1,4 +1,4 @@
1
- import { fs, logger } from '@appium/support';
1
+ import { fs, logger, util } from '@appium/support';
2
2
  import { glob } from 'glob';
3
3
  import path from 'node:path';
4
4
  import { fileURLToPath } from 'node:url';
@@ -6,12 +6,26 @@ import { exec } from 'teen_process';
6
6
 
7
7
  const log = logger.getLogger('Atoms');
8
8
 
9
- const SELENIUM_BRANCH = process.env.SELENIUM_BRANCH || 'trunk'; // the hash is '9b1e83ce6409086413b1cd7ffe6da502ac9d11f1'
9
+ const SELENIUM_BRANCH = process.env.SELENIUM_BRANCH || 'trunk';
10
10
  const SELENIUM_GITHUB = process.env.SELENIUM_GITHUB || 'https://github.com/SeleniumHQ/selenium.git';
11
11
 
12
+ const BAZEL_ATOMS_TARGET = '//javascript/atoms/...';
12
13
  const BAZEL_WD_ATOMS_TARGET = '//javascript/webdriver/atoms/...';
13
14
  const BAZEL_WD_ATOMS_INJECT_TARGET = '//javascript/webdriver/atoms/inject/...';
14
- const BAZEL_ATOMS_TARGET = '//javascript/atoms/...';
15
+
16
+ // `//javascript/atoms/...` includes browser-backed `closure-test*` targets that fetch pinned
17
+ // Firefox/Safari/etc.; exclude them so local/CI atoms import builds without those repositories.
18
+ const BAZEL_ATOMS_EXCLUDED_TARGETS = [
19
+ '//javascript/atoms:closure-test',
20
+ '//javascript/atoms:closure-test-all-browsers',
21
+ '//javascript/atoms:closure-test-chrome',
22
+ '//javascript/atoms:closure-test-chrome-beta',
23
+ '//javascript/atoms:closure-test-edge',
24
+ '//javascript/atoms:closure-test-firefox',
25
+ '//javascript/atoms:closure-test-firefox-beta',
26
+ '//javascript/atoms:closure-test-safari',
27
+ '//javascript/atoms:closure-test_debug_server',
28
+ ];
15
29
 
16
30
  const WORKING_ROOT_DIR = path.resolve(fileURLToPath(import.meta.url), '..', '..');
17
31
  const TMP_DIRECTORY = path.resolve(WORKING_ROOT_DIR, 'tmp');
@@ -24,6 +38,17 @@ const BAZEL_WD_ATOMS_DIR = path.join(JS_RELATIVE_DIR, 'webdriver', 'atoms');
24
38
  const BAZEL_WD_ATOMS_INJECT_DIR = path.join(BAZEL_WD_ATOMS_DIR, 'inject');
25
39
  const ATOMS_DIRECTORY = path.resolve(WORKING_ROOT_DIR, 'atoms');
26
40
  const LAST_UPDATE_FILE = path.resolve(ATOMS_DIRECTORY, 'lastupdate');
41
+ let bazelCommand;
42
+
43
+ function getBazelEnv() {
44
+ // Selenium atoms build does not require Android SDK. If these env vars are set locally,
45
+ // Bazel may try to auto-configure Android toolchains and fail on host-specific SDK issues.
46
+ const env = {...process.env};
47
+ delete env.ANDROID_HOME;
48
+ delete env.ANDROID_SDK_ROOT;
49
+ delete env.ANDROID_SDK;
50
+ return env;
51
+ }
27
52
 
28
53
  /**
29
54
  * Create a temporary directory to clone selenium repository to build atoms in.
@@ -47,41 +72,74 @@ async function seleniumClean () {
47
72
  export async function seleniumClone () {
48
73
  await seleniumMkdir();
49
74
  await seleniumClean();
50
- log.info(`Cloning branch '${SELENIUM_BRANCH}' from '${SELENIUM_GITHUB}'`);
51
- await exec('git', [
75
+ const cloneArgs = (branch) => ([
52
76
  'clone',
53
- `--branch=${SELENIUM_BRANCH}`,
54
- `--depth=1`,
77
+ `--branch=${branch}`,
78
+ '--depth=1',
55
79
  SELENIUM_GITHUB,
56
80
  SELENIUM_DIRECTORY,
57
81
  ]);
82
+
83
+ log.info(`Cloning branch '${SELENIUM_BRANCH}' from '${SELENIUM_GITHUB}'`);
84
+ await exec('git', cloneArgs(SELENIUM_BRANCH));
58
85
  };
59
86
 
60
87
  /**
61
88
  * Check bazel version if current available bazel version on the host machine
62
- * is good for the target selenium repository's required version.
89
+ * meets Selenium's minimum from `.bazelversion` (newer Bazel is allowed).
63
90
  */
64
91
  async function checkBazel() {
65
- log.info('Checking required Bazel version');
66
- const bazelVersion = (await fs.readFile(BAZEL_VERSION, 'utf8')).trim();
67
- let result;
68
- let err;
92
+ log.info('Checking minimum Bazel version from Selenium .bazelversion');
93
+ const minBazelVersion = (await fs.readFile(BAZEL_VERSION, 'utf8')).trim();
94
+ let bazelVersionResult;
95
+ let bazeliskVersionResult;
96
+ let bazelVersionErr;
97
+ let bazeliskVersionErr;
69
98
  try {
70
- result = await exec('bazel', ['--version']);
99
+ bazelVersionResult = await exec('bazel', ['--version']);
71
100
  } catch (e) {
72
- err = e.stderr || e.message;
101
+ bazelVersionErr = e.stderr || e.message;
102
+ }
103
+ if (!bazelVersionErr && !bazelVersionResult.stderr) {
104
+ // e.g. "bazel 9.0.1"
105
+ const currentBazelVersion = bazelVersionResult.stdout.trim().split(' ')[1];
106
+ let meetsMinimum = false;
107
+ let versionCompareFailed = false;
108
+ try {
109
+ meetsMinimum = util.compareVersions(currentBazelVersion, '>=', minBazelVersion);
110
+ } catch (err) {
111
+ versionCompareFailed = true;
112
+ log.warn(
113
+ `Could not compare Bazel versions (${currentBazelVersion} vs minimum ${minBazelVersion}): ${err.message}. ` +
114
+ `Trying bazelisk...`
115
+ );
116
+ }
117
+ if (meetsMinimum) {
118
+ bazelCommand = 'bazel';
119
+ log.info(`Bazel ${currentBazelVersion} (minimum ${minBazelVersion}) will be used to build atoms.`);
120
+ return;
121
+ }
122
+ if (!versionCompareFailed) {
123
+ log.warn(
124
+ `Found bazel ${currentBazelVersion}, but Selenium needs at least ${minBazelVersion}. Trying bazelisk...`
125
+ );
126
+ }
73
127
  }
74
- if (err || result.stderr) {
75
- throw new Error(`Please setup Bazel ${bazelVersion} runtime environment by following https://bazel.build/install. ` +
76
- `Original error: ${err || result.stderr}`);
128
+ try {
129
+ bazeliskVersionResult = await exec('bazelisk', ['--version']);
130
+ } catch (e) {
131
+ bazeliskVersionErr = e.stderr || e.message;
77
132
  }
78
- // e.g. "bazel 7.4.1"
79
- const currentBazelVersion = result.stdout.trim().split(' ')[1];
80
- if (currentBazelVersion !== bazelVersion) {
81
- throw new Error(`Please setup Bazel ${bazelVersion} runtime environment. ` +
82
- `Current available version is ${currentBazelVersion}`);
133
+ if (bazeliskVersionErr || bazeliskVersionResult.stderr) {
134
+ throw new Error(
135
+ `Please install Bazel ${minBazelVersion} or newer by following https://bazel.build/install, ` +
136
+ `or install bazelisk (https://github.com/bazelbuild/bazelisk). ` +
137
+ `Original errors: bazel='${bazelVersionErr || bazelVersionResult?.stderr || 'unknown'}', ` +
138
+ `bazelisk='${bazeliskVersionErr || bazeliskVersionResult?.stderr || 'unknown'}'`
139
+ );
83
140
  }
84
- log.info(`Bazel ${bazelVersion} will be used to build atoms.`);
141
+ bazelCommand = 'bazelisk';
142
+ log.info(`Bazelisk will be used to build atoms (Selenium minimum Bazel ${minBazelVersion}).`);
85
143
  }
86
144
 
87
145
  /**
@@ -97,7 +155,7 @@ async function atomsCleanDir () {
97
155
  */
98
156
  async function atomsClean () {
99
157
  log.info('Building atoms');
100
- await exec('bazel', ['clean'], {cwd: SELENIUM_DIRECTORY});
158
+ await exec(bazelCommand, ['clean'], {cwd: SELENIUM_DIRECTORY, env: getBazelEnv()});
101
159
  }
102
160
 
103
161
  /**
@@ -133,7 +191,11 @@ async function atomsBuild () {
133
191
  BAZEL_WD_ATOMS_INJECT_TARGET,
134
192
  ]) {
135
193
  log.info(`Running bazel build for ${target}`);
136
- await exec('bazel', ['build', target], {cwd: SELENIUM_DIRECTORY});
194
+ const buildArgs = ['build', target];
195
+ if (target === BAZEL_ATOMS_TARGET) {
196
+ buildArgs.push('--', ...BAZEL_ATOMS_EXCLUDED_TARGETS.map((t) => `-${t}`));
197
+ }
198
+ await exec(bazelCommand, buildArgs, {cwd: SELENIUM_DIRECTORY, env: getBazelEnv()});
137
199
  }
138
200
  log.info(`Bazel builds complete`);
139
201
  }
@@ -160,12 +222,12 @@ async function atomsCopyAtoms (atomsDir) {
160
222
  }
161
223
 
162
224
  /**
163
- * leave timestamp to log when atom build occurred.
225
+ * Record which Selenium revision produced these atoms.
164
226
  */
165
227
  async function atomsTimestamp () {
166
- log.info(`Adding timestamp to atoms build dir`);
228
+ log.info(`Recording Selenium revision in atoms dir`);
167
229
  const {stdout} = await exec('git', ['log', '-n', '1', '--decorate=full'], {cwd: SELENIUM_DIRECTORY});
168
- await fs.writeFile(LAST_UPDATE_FILE, Buffer.from(`${new Date()}\n\n${stdout}`));
230
+ await fs.writeFile(LAST_UPDATE_FILE, Buffer.from(stdout.trimEnd() + '\n'));
169
231
  }
170
232
 
171
233
  export async function importAtoms(shouldClean) {