appium-remote-debugger 12.1.5 → 12.1.7

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/index.ts CHANGED
@@ -6,9 +6,9 @@ export function createRemoteDebugger<T extends boolean> (
6
6
  opts: T extends true ? RemoteDebuggerRealDeviceOptions : RemoteDebuggerOptions,
7
7
  realDevice: T
8
8
  ): T extends true ? RemoteDebuggerRealDevice : RemoteDebugger {
9
- // @ts-ignore TS does not understand that
10
9
  return realDevice
11
10
  ? new RemoteDebuggerRealDevice(opts as RemoteDebuggerRealDeviceOptions)
11
+ // @ts-ignore TS does not understand that
12
12
  : new RemoteDebugger(opts);
13
13
  }
14
14
 
@@ -316,9 +316,13 @@ function logApplicationDictionary () {
316
316
  * @returns {string[]}
317
317
  */
318
318
  export function getPossibleDebuggerAppKeys(bundleIds) {
319
+ const appDict = getAppDict(this);
320
+
319
321
  if (bundleIds.includes(WILDCARD_BUNDLE_ID)) {
320
- this.log.debug('Skip checking bundle identifiers because the bundleIds includes a wildcard');
321
- return _.uniq(Object.keys(getAppDict(this)));
322
+ this.log.info(
323
+ 'Returning all apps because the list of matching bundle identifiers includes a wildcard'
324
+ );
325
+ return _.keys(appDict);
322
326
  }
323
327
 
324
328
  // go through the possible bundle identifiers
@@ -327,30 +331,40 @@ export function getPossibleDebuggerAppKeys(bundleIds) {
327
331
  WEB_CONTENT_PROCESS_BUNDLE_ID,
328
332
  SAFARI_VIEW_PROCESS_BUNDLE_ID,
329
333
  SAFARI_VIEW_BUNDLE_ID,
330
- WILDCARD_BUNDLE_ID,
331
334
  ...bundleIds,
332
335
  ]);
333
- this.log.debug(`Checking for bundle identifiers: ${possibleBundleIds.join(', ')}`);
334
- /** @type {Set<string>} */
335
- const proxiedAppIds = new Set();
336
+ this.log.debug(
337
+ `Checking for apps with matching bundle identifiers: ${possibleBundleIds.join(', ')}`
338
+ );
339
+ /** @type {string[]} */
340
+ const proxiedAppIds = [];
336
341
  for (const bundleId of possibleBundleIds) {
337
342
  // now we need to determine if we should pick a proxy for this instead
338
- for (const appId of appIdsForBundle(bundleId, getAppDict(this))) {
339
- proxiedAppIds.add(appId);
343
+ for (const appId of appIdsForBundle(bundleId, appDict)) {
344
+ if (proxiedAppIds.includes(appId)) {
345
+ continue;
346
+ }
347
+
348
+ proxiedAppIds.push(appId);
340
349
  this.log.debug(`Found app id key '${appId}' for bundle '${bundleId}'`);
341
- for (const [key, data] of _.toPairs(getAppDict(this))) {
342
- if (data.isProxy && data.hostId === appId) {
350
+ for (const [key, data] of _.toPairs(appDict)) {
351
+ if (data.isProxy && data.hostId === appId && !proxiedAppIds.includes(key)) {
343
352
  this.log.debug(
344
353
  `Found separate bundleId '${data.bundleId}' ` +
345
354
  `acting as proxy for '${bundleId}', with app id '${key}'`
346
355
  );
347
- proxiedAppIds.add(key);
356
+ proxiedAppIds.push(key);
348
357
  }
349
358
  }
350
359
  }
351
360
  }
352
361
 
353
- return Array.from(proxiedAppIds);
362
+ this.log.debug(
363
+ `You may also consider providing more values to 'additionalWebviewBundleIds' ` +
364
+ `capability to match other applications. Add a wildcard ('*') to match all apps.`
365
+ );
366
+
367
+ return _.uniq(proxiedAppIds);
354
368
  }
355
369
 
356
370
  /**
package/lib/utils.js CHANGED
@@ -82,20 +82,17 @@ export function pageArrayFromDict (pageDict) {
82
82
  * @returns {string[]}
83
83
  */
84
84
  export function appIdsForBundle (bundleId, appDict) {
85
- /** @type {Set<string>} */
86
- const appIds = new Set();
87
- for (const [key, data] of _.toPairs(appDict)) {
88
- if (data.bundleId.endsWith(bundleId)) {
89
- appIds.add(key);
90
- }
91
- }
85
+ /** @type {string[]} */
86
+ const appIds = _.toPairs(appDict)
87
+ .filter(([, data]) => data.bundleId === bundleId)
88
+ .map(([key]) => key);
92
89
 
93
90
  // if nothing is found, try to get the generic app
94
- if (appIds.size === 0 && bundleId !== WEB_CONTENT_BUNDLE_ID) {
91
+ if (appIds.length === 0 && bundleId !== WEB_CONTENT_BUNDLE_ID) {
95
92
  return appIdsForBundle(WEB_CONTENT_BUNDLE_ID, appDict);
96
93
  }
97
94
 
98
- return Array.from(appIds);
95
+ return _.uniq(appIds);
99
96
  }
100
97
 
101
98
  /**
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "keywords": [
5
5
  "appium"
6
6
  ],
7
- "version": "12.1.5",
7
+ "version": "12.1.7",
8
8
  "author": "Appium Contributors",
9
9
  "license": "Apache-2.0",
10
10
  "repository": {
@@ -55,8 +55,8 @@
55
55
  "e2e-test": "mocha --exit --timeout 1m \"./test/functional/**/*-specs.js\"",
56
56
  "inspect-safari": "node build/bin/web_inspector_proxy.js",
57
57
  "build:atoms": "npm run build:selenium && npm run build:atoms:import",
58
- "build:atoms:import": "node scripts/build-atoms.js",
59
- "build:selenium": "node scripts/build-selenium.js"
58
+ "build:atoms:import": "node scripts/build-atoms.mjs",
59
+ "build:selenium": "node scripts/build-selenium.mjs"
60
60
  },
61
61
  "prettier": {
62
62
  "bracketSpacing": false,
@@ -1,4 +1,4 @@
1
- const { importAtoms } = require('./common.js');
1
+ import { importAtoms } from './common.mjs';
2
2
 
3
3
  (async () => {
4
4
  await importAtoms(process.argv.includes('--clean'));
@@ -0,0 +1,4 @@
1
+ import { seleniumClone } from './common.mjs';
2
+
3
+
4
+ (async () => await seleniumClone())();
@@ -0,0 +1,189 @@
1
+ import { fs, logger } from '@appium/support';
2
+ import { glob } from 'glob';
3
+ import path from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { exec } from 'teen_process';
6
+
7
+ const log = logger.getLogger('Atoms');
8
+
9
+ const SELENIUM_BRANCH = process.env.SELENIUM_BRANCH || 'selenium-4.19.0';
10
+ const SELENIUM_GITHUB = process.env.SELENIUM_GITHUB || 'https://github.com/SeleniumHQ/selenium.git';
11
+
12
+ const BAZEL_WD_ATOMS_TARGET = '//javascript/webdriver/atoms/...';
13
+ const BAZEL_WD_ATOMS_INJECT_TARGET = '//javascript/webdriver/atoms/inject/...';
14
+ const BAZEL_ATOMS_TARGET = '//javascript/atoms/...';
15
+
16
+ const WORKING_ROOT_DIR = path.resolve(fileURLToPath(import.meta.url), '..', '..');
17
+ const TMP_DIRECTORY = path.resolve(WORKING_ROOT_DIR, 'tmp');
18
+ const SELENIUM_DIRECTORY = path.resolve(TMP_DIRECTORY, 'selenium');
19
+ const BAZEL_OUT_BASEDIR = path.resolve(SELENIUM_DIRECTORY, 'bazel-out');
20
+ const BAZEL_VERSION = path.resolve(SELENIUM_DIRECTORY, '.bazelversion');
21
+ const JS_RELATIVE_DIR = path.join('bin', 'javascript');
22
+ const BAZEL_FRAGMENTS_DIR = path.join(JS_RELATIVE_DIR, 'atoms', 'fragments');
23
+ const BAZEL_WD_ATOMS_DIR = path.join(JS_RELATIVE_DIR, 'webdriver', 'atoms');
24
+ const BAZEL_WD_ATOMS_INJECT_DIR = path.join(BAZEL_WD_ATOMS_DIR, 'inject');
25
+ const ATOMS_DIRECTORY = path.resolve(WORKING_ROOT_DIR, 'atoms');
26
+ const LAST_UPDATE_FILE = path.resolve(ATOMS_DIRECTORY, 'lastupdate');
27
+
28
+ /**
29
+ * Create a temporary directory to clone selenium repository to build atoms in.
30
+ */
31
+ async function seleniumMkdir () {
32
+ log.info(`Creating '${TMP_DIRECTORY}'`);
33
+ await fs.mkdir(TMP_DIRECTORY, { recursive: true });
34
+ }
35
+
36
+ /**
37
+ * Remove entire the temporary selenium directory on the machine local.
38
+ */
39
+ async function seleniumClean () {
40
+ log.info(`Cleaning '${SELENIUM_DIRECTORY}'`);
41
+ await fs.rimraf(SELENIUM_DIRECTORY);
42
+ }
43
+
44
+ /**
45
+ * Clone the target selenium repository and branch into the temporary directory.
46
+ */
47
+ export async function seleniumClone () {
48
+ await seleniumMkdir();
49
+ await seleniumClean();
50
+ log.info(`Cloning branch '${SELENIUM_BRANCH}' from '${SELENIUM_GITHUB}'`);
51
+ await exec('git', [
52
+ 'clone',
53
+ `--branch=${SELENIUM_BRANCH}`,
54
+ `--depth=1`,
55
+ SELENIUM_GITHUB,
56
+ SELENIUM_DIRECTORY,
57
+ ]);
58
+ };
59
+
60
+ /**
61
+ * Check bazel version if current available bazel version on the host machine
62
+ * is good for the target selenium repository's required version.
63
+ */
64
+ 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;
69
+ try {
70
+ result = await exec('bazel', ['--version']);
71
+ } catch (e) {
72
+ err = e.stderr || e.message;
73
+ }
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}`);
77
+ }
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}`);
83
+ }
84
+ log.info(`Bazel ${bazelVersion} will be used to build atoms.`);
85
+ }
86
+
87
+ /**
88
+ * Remove contents in 'atoms'.
89
+ */
90
+ async function atomsCleanDir () {
91
+ log.info(`Cleaning '${ATOMS_DIRECTORY}'`);
92
+ await fs.rimraf(ATOMS_DIRECTORY);
93
+ }
94
+
95
+ /**
96
+ * Run bazel clean command.
97
+ */
98
+ async function atomsClean () {
99
+ log.info('Building atoms');
100
+ await exec('bazel', ['clean'], {cwd: SELENIUM_DIRECTORY});
101
+ }
102
+
103
+ /**
104
+ * Create a directory for atoms.
105
+ */
106
+ async function atomsMkdir () {
107
+ log.info(`Creating '${ATOMS_DIRECTORY}'`);
108
+ await fs.mkdir(ATOMS_DIRECTORY, { recursive: true });
109
+ }
110
+
111
+ /**
112
+ * Return the path to bazel built result.
113
+ * @returns {Promise<string>}
114
+ */
115
+ async function getBazelOutDir () {
116
+ log.info(`Finding bazel output dir`);
117
+ const outDirMatch = '*-fastbuild';
118
+ const relativeDir = (await glob(outDirMatch, {cwd: BAZEL_OUT_BASEDIR}))[0];
119
+ if (!relativeDir) {
120
+ throw new Error(`Expected architecture-specific Bazel output directory was not found in ` +
121
+ `'${BAZEL_OUT_BASEDIR}'. We looked for something matching '${outDirMatch}`);
122
+ }
123
+ return path.resolve(BAZEL_OUT_BASEDIR, relativeDir);
124
+ }
125
+
126
+ /**
127
+ * Build atoms with bazel command.
128
+ */
129
+ async function atomsBuild () {
130
+ for (const target of [
131
+ BAZEL_ATOMS_TARGET,
132
+ BAZEL_WD_ATOMS_TARGET,
133
+ BAZEL_WD_ATOMS_INJECT_TARGET,
134
+ ]) {
135
+ log.info(`Running bazel build for ${target}`);
136
+ await exec('bazel', ['build', target], {cwd: SELENIUM_DIRECTORY});
137
+ }
138
+ log.info(`Bazel builds complete`);
139
+ }
140
+
141
+ /**
142
+ * Copy atoms in bazel built result to 'atoms' in this repository's main 'atoms' place.
143
+ * @param {string} atomsDir
144
+ * @param {Function} fileFilter
145
+ */
146
+ async function atomsCopyAtoms (atomsDir, fileFilter = () => true) {
147
+ log.info(`Copying any atoms found in ${atomsDir} to atoms dir`);
148
+ const filesToCopy = (await glob('**/*-ios.js', {
149
+ absolute: true,
150
+ strict: false,
151
+ cwd: atomsDir,
152
+ })).filter(fileFilter);
153
+ for (const file of filesToCopy) {
154
+ // convert - to _ for backwards compatibility with old atoms
155
+ const newFileName = path.basename(file).replace('-ios', '').replace(/-/g, '_');
156
+ const to = path.join(ATOMS_DIRECTORY, newFileName);
157
+ log.info(`Copying ${file} to ${to}`);
158
+ await fs.rimraf(to);
159
+ await fs.copyFile(file, to);
160
+ }
161
+ }
162
+
163
+ /**
164
+ * leave timestamp to log when atom build occurred.
165
+ */
166
+ async function atomsTimestamp () {
167
+ log.info(`Adding timestamp to atoms build dir`);
168
+ const {stdout} = await exec('git', ['log', '-n', '1', '--decorate=full'], {cwd: SELENIUM_DIRECTORY});
169
+ await fs.writeFile(LAST_UPDATE_FILE, Buffer.from(`${new Date()}\n\n${stdout}`));
170
+ }
171
+
172
+ export async function importAtoms(shouldClean) {
173
+ await checkBazel();
174
+ await atomsCleanDir();
175
+ if (shouldClean) {
176
+ await atomsClean();
177
+ }
178
+ await atomsMkdir();
179
+ await atomsBuild();
180
+ const bazelOutDir = await getBazelOutDir();
181
+ const atomsDir = path.resolve(bazelOutDir, BAZEL_WD_ATOMS_DIR);
182
+ const atomsInjectDir = path.resolve(bazelOutDir, BAZEL_WD_ATOMS_INJECT_DIR);
183
+ const fragmentsDir = path.resolve(bazelOutDir, BAZEL_FRAGMENTS_DIR);
184
+ await atomsCopyAtoms(fragmentsDir);
185
+ // copy fragments first and atoms later so atoms overwrite fragments
186
+ await atomsCopyAtoms(atomsDir);
187
+ await atomsCopyAtoms(atomsInjectDir);
188
+ await atomsTimestamp();
189
+ };
@@ -1,3 +0,0 @@
1
- const { seleniumClone } = require('./common.js');
2
-
3
- (async () => await seleniumClone())();
package/scripts/common.js DELETED
@@ -1,157 +0,0 @@
1
- const path = require('path');
2
- const {logger} = require('@appium/support');
3
- const fs = require('fs');
4
- const { exec } = require('teen_process');
5
- const { glob } = require('glob');
6
-
7
- const log = logger.getLogger('Atoms');
8
-
9
- const SELENIUM_BRANCH = 'selenium-4.19.0';
10
- const SELENIUM_GITHUB = 'https://github.com/SeleniumHQ/selenium.git';
11
-
12
- const BAZEL_WD_ATOMS_TARGET = '//javascript/webdriver/atoms/...';
13
- const BAZEL_WD_ATOMS_INJECT_TARGET = '//javascript/webdriver/atoms/inject/...';
14
- const BAZEL_ATOMS_TARGET = '//javascript/atoms/...';
15
-
16
- const WORKING_ROOT_DIR = path.resolve(__dirname, '..');
17
- const TMP_DIRECTORY = path.resolve(WORKING_ROOT_DIR, 'tmp');
18
- const SELENIUM_DIRECTORY = path.resolve(TMP_DIRECTORY, 'selenium');
19
- const BAZEL_OUT_BASEDIR = path.resolve(SELENIUM_DIRECTORY, 'bazel-out');
20
- const JS_RELATIVE_DIR = path.join('bin', 'javascript');
21
- const BAZEL_FRAGMENTS_DIR = path.join(JS_RELATIVE_DIR, 'atoms', 'fragments');
22
- const BAZEL_WD_ATOMS_DIR = path.join(JS_RELATIVE_DIR, 'webdriver', 'atoms');
23
- const BAZEL_WD_ATOMS_INJECT_DIR = path.join(BAZEL_WD_ATOMS_DIR, 'inject');
24
- const ATOMS_DIRECTORY = path.resolve(WORKING_ROOT_DIR, 'atoms');
25
- const LAST_UPDATE_FILE = path.resolve(ATOMS_DIRECTORY, 'lastupdate');
26
-
27
- async function rmDir (dir) {
28
- try {
29
- await fs.promises.access(dir, fs.constants.R_OK);
30
- } catch {
31
- return;
32
- }
33
-
34
- const files = await fs.promises.readdir(dir);
35
- for (const file of files) {
36
- const fullPath = path.join(dir, file);
37
- const isDirectory = (await fs.promises.stat(fullPath)).isDirectory();
38
- if (['.', '..'].includes(file)) {
39
- // pass these files
40
- } else if (isDirectory) {
41
- await rmDir(fullPath);
42
- } else {
43
- await fs.promises.unlink(fullPath);
44
- }
45
- }
46
- await fs.promises.rmdir(dir);
47
- }
48
-
49
- async function seleniumMkdir () {
50
- log(`Creating '${TMP_DIRECTORY}'`);
51
- await fs.promises.mkdir(TMP_DIRECTORY, { recursive: true });
52
- }
53
-
54
- async function seleniumClean () {
55
- log(`Cleaning '${SELENIUM_DIRECTORY}'`);
56
- await rmDir(SELENIUM_DIRECTORY);
57
- }
58
-
59
- module.exports.seleniumClone = async function seleniumClone () {
60
- await seleniumMkdir();
61
- await seleniumClean();
62
- log(`Cloning branch '${SELENIUM_BRANCH}' from '${SELENIUM_GITHUB}'`);
63
- await exec('git', [
64
- 'clone',
65
- `--branch=${SELENIUM_BRANCH}`,
66
- `--depth=1`,
67
- SELENIUM_GITHUB,
68
- SELENIUM_DIRECTORY,
69
- ]);
70
- };
71
-
72
- async function atomsCleanDir () {
73
- log(`Cleaning '${ATOMS_DIRECTORY}'`);
74
- await rmDir(ATOMS_DIRECTORY);
75
- }
76
-
77
- async function atomsClean () {
78
- log('Building atoms');
79
- await exec('bazel', ['clean'], {cwd: SELENIUM_DIRECTORY});
80
- }
81
-
82
- async function atomsMkdir () {
83
- log(`Creating '${ATOMS_DIRECTORY}'`);
84
- await fs.promises.mkdir(ATOMS_DIRECTORY, { recursive: true });
85
- }
86
-
87
- async function getBazelOutDir () {
88
- log(`Finding bazel output dir`);
89
- const outDirMatch = '*-fastbuild';
90
- const relativeDir = (await glob(outDirMatch, {cwd: BAZEL_OUT_BASEDIR}))[0];
91
- if (!relativeDir) {
92
- throw new Error(`Expected architecture-specific Bazel output directory was not found in ` +
93
- `'${BAZEL_OUT_BASEDIR}'. We looked for something matching '${outDirMatch}`);
94
- }
95
- return path.resolve(BAZEL_OUT_BASEDIR, relativeDir);
96
- }
97
-
98
- async function atomsBuild () {
99
- for (const target of [
100
- BAZEL_ATOMS_TARGET,
101
- BAZEL_WD_ATOMS_TARGET,
102
- BAZEL_WD_ATOMS_INJECT_TARGET,
103
- ]) {
104
- log(`Running bazel build for ${target}`);
105
- await exec('bazel', ['build', target], {cwd: SELENIUM_DIRECTORY});
106
- }
107
- log(`Bazel builds complete`);
108
- }
109
-
110
- async function atomsCopyAtoms (atomsDir, fileFilter = () => true) {
111
- log(`Copying any atoms found in ${atomsDir} to atoms dir`);
112
- const filesToCopy = (await glob('**/*-ios.js', {
113
- absolute: true,
114
- strict: false,
115
- cwd: atomsDir,
116
- })).filter(fileFilter);
117
- for (const file of filesToCopy) {
118
- // convert - to _ for backwards compatibility with old atoms
119
- const newFileName = path.basename(file).replace('-ios', '').replace(/-/g, '_');
120
- const to = path.join(ATOMS_DIRECTORY, newFileName);
121
- log(`Copying ${file} to ${to}`);
122
- // delete an existing file if it was put here by an earlier run of the function, to enable
123
- // overwriting
124
- try {
125
- await fs.promises.unlink(to);
126
- } catch (err) {
127
- if (!err.message.includes('ENOENT')) {
128
- throw err;
129
- }
130
- }
131
- await fs.promises.copyFile(file, to);
132
- }
133
- }
134
-
135
- async function atomsTimestamp () {
136
- log(`Adding timestamp to atoms build dir`);
137
- const {stdout} = await exec('git', ['log', '-n', '1', '--decorate=full'], {cwd: SELENIUM_DIRECTORY});
138
- await fs.promises.writeFile(LAST_UPDATE_FILE, Buffer.from(`${new Date()}\n\n${stdout}`));
139
- }
140
-
141
- module.exports.importAtoms = async function importAtoms(shouldClean) {
142
- await atomsCleanDir();
143
- if (shouldClean) {
144
- await atomsClean();
145
- }
146
- await atomsMkdir();
147
- await atomsBuild();
148
- const bazelOutDir = await getBazelOutDir();
149
- const atomsDir = path.resolve(bazelOutDir, BAZEL_WD_ATOMS_DIR);
150
- const atomsInjectDir = path.resolve(bazelOutDir, BAZEL_WD_ATOMS_INJECT_DIR);
151
- const fragmentsDir = path.resolve(bazelOutDir, BAZEL_FRAGMENTS_DIR);
152
- await atomsCopyAtoms(fragmentsDir);
153
- // copy fragments first and atoms later so atoms overwrite fragments
154
- await atomsCopyAtoms(atomsDir);
155
- await atomsCopyAtoms(atomsInjectDir);
156
- await atomsTimestamp();
157
- };