appium-chromedriver 8.0.30 → 8.1.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 +12 -0
- package/build/lib/chromedriver.d.ts +3 -1
- package/build/lib/chromedriver.d.ts.map +1 -1
- package/build/lib/chromedriver.js +3 -1
- package/build/lib/chromedriver.js.map +1 -1
- package/build/lib/storage-client/chromelabs.d.ts +15 -15
- package/build/lib/storage-client/chromelabs.d.ts.map +1 -1
- package/build/lib/storage-client/chromelabs.js +15 -19
- package/build/lib/storage-client/chromelabs.js.map +1 -1
- package/build/lib/storage-client/googleapis.d.ts +14 -16
- package/build/lib/storage-client/googleapis.d.ts.map +1 -1
- package/build/lib/storage-client/googleapis.js +25 -41
- package/build/lib/storage-client/googleapis.js.map +1 -1
- package/build/lib/storage-client/storage-client.d.ts +41 -56
- package/build/lib/storage-client/storage-client.d.ts.map +1 -1
- package/build/lib/storage-client/storage-client.js +118 -137
- package/build/lib/storage-client/storage-client.js.map +1 -1
- package/lib/chromedriver.js +5 -1
- package/lib/storage-client/{chromelabs.js → chromelabs.ts} +54 -26
- package/lib/storage-client/{googleapis.js → googleapis.ts} +55 -54
- package/lib/storage-client/{storage-client.js → storage-client.ts} +188 -182
- package/package.json +2 -3
|
@@ -22,66 +22,78 @@ import {parseGoogleapiStorageXml} from './googleapis';
|
|
|
22
22
|
import {parseKnownGoodVersionsWithDownloadsJson, parseLatestKnownGoodVersionsJson} from './chromelabs';
|
|
23
23
|
import {compareVersions} from 'compare-versions';
|
|
24
24
|
import * as semver from 'semver';
|
|
25
|
+
import type {
|
|
26
|
+
ChromedriverStorageClientOpts,
|
|
27
|
+
SyncOptions,
|
|
28
|
+
OSInfo,
|
|
29
|
+
ChromedriverDetailsMapping,
|
|
30
|
+
} from '../types';
|
|
25
31
|
|
|
26
32
|
const MAX_PARALLEL_DOWNLOADS = 5;
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
|
|
34
|
+
interface StorageInfo {
|
|
35
|
+
url: string;
|
|
36
|
+
accept: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const STORAGE_INFOS: readonly StorageInfo[] = [
|
|
40
|
+
{
|
|
41
|
+
url: GOOGLEAPIS_CDN,
|
|
42
|
+
accept: 'application/xml',
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
url: `${CHROMELABS_URL}/chrome-for-testing/known-good-versions-with-downloads.json`,
|
|
46
|
+
accept: 'application/json',
|
|
47
|
+
},
|
|
48
|
+
];
|
|
34
49
|
|
|
35
50
|
const CHROME_FOR_TESTING_LAST_GOOD_VERSIONS = `${CHROMELABS_URL}/chrome-for-testing/last-known-good-versions.json`;
|
|
36
51
|
|
|
37
52
|
const log = logger.getLogger('ChromedriverStorageClient');
|
|
38
53
|
|
|
39
|
-
|
|
40
|
-
*
|
|
41
|
-
* @param {string} src
|
|
42
|
-
* @param {string} checksum
|
|
43
|
-
* @returns {Promise<boolean>}
|
|
44
|
-
*/
|
|
45
|
-
async function isCrcOk(src, checksum) {
|
|
54
|
+
async function isCrcOk(src: string, checksum: string): Promise<boolean> {
|
|
46
55
|
const md5 = await fs.hash(src, 'md5');
|
|
47
56
|
return _.toLower(md5) === _.toLower(checksum);
|
|
48
57
|
}
|
|
49
58
|
|
|
50
59
|
export class ChromedriverStorageClient {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
constructor(args = {}) {
|
|
60
|
+
readonly chromedriverDir: string;
|
|
61
|
+
readonly timeout: number;
|
|
62
|
+
private mapping: ChromedriverDetailsMapping;
|
|
63
|
+
|
|
64
|
+
constructor(args: ChromedriverStorageClientOpts = {}) {
|
|
56
65
|
const {chromedriverDir = getChromedriverDir(), timeout = STORAGE_REQ_TIMEOUT_MS} = args;
|
|
57
66
|
this.chromedriverDir = chromedriverDir;
|
|
58
67
|
this.timeout = timeout;
|
|
59
|
-
/** @type {ChromedriverDetailsMapping} */
|
|
60
68
|
this.mapping = {};
|
|
61
69
|
}
|
|
62
70
|
|
|
63
71
|
/**
|
|
64
72
|
* Retrieves chromedriver mapping from the storage
|
|
65
73
|
*
|
|
66
|
-
* @param
|
|
74
|
+
* @param shouldParseNotes [true] - if set to `true`
|
|
67
75
|
* then additional chromedrivers info is going to be retrieved and
|
|
68
76
|
* parsed from release notes
|
|
69
|
-
* @returns
|
|
77
|
+
* @returns Promise<ChromedriverDetailsMapping>
|
|
70
78
|
*/
|
|
71
|
-
async retrieveMapping(shouldParseNotes = true) {
|
|
72
|
-
|
|
73
|
-
const retrieveResponseSafely = async (/** @type {StorageInfo} */ {url, accept}) => {
|
|
79
|
+
async retrieveMapping(shouldParseNotes = true): Promise<ChromedriverDetailsMapping> {
|
|
80
|
+
const retrieveResponseSafely = async ({url, accept}: StorageInfo): Promise<string | undefined> => {
|
|
74
81
|
try {
|
|
75
|
-
return await retrieveData(
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
82
|
+
return await retrieveData(
|
|
83
|
+
url,
|
|
84
|
+
{
|
|
85
|
+
'user-agent': USER_AGENT,
|
|
86
|
+
accept: `${accept}, */*`,
|
|
87
|
+
},
|
|
88
|
+
{timeout: this.timeout}
|
|
89
|
+
);
|
|
79
90
|
} catch (e) {
|
|
80
|
-
|
|
91
|
+
const err = e as Error;
|
|
92
|
+
log.debug(err.stack);
|
|
81
93
|
log.warn(
|
|
82
94
|
`Cannot retrieve Chromedrivers info from ${url}. ` +
|
|
83
|
-
|
|
84
|
-
|
|
95
|
+
`Make sure this URL is accessible from your network. ` +
|
|
96
|
+
`Original error: ${err.message}`
|
|
85
97
|
);
|
|
86
98
|
}
|
|
87
99
|
};
|
|
@@ -91,9 +103,9 @@ export class ChromedriverStorageClient {
|
|
|
91
103
|
if (!xmlStr && !jsonStr) {
|
|
92
104
|
throw new Error(
|
|
93
105
|
`Cannot retrieve the information about available Chromedrivers from ` +
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
106
|
+
`${STORAGE_INFOS.map(({url}) => url)}. Please make sure these URLs are available ` +
|
|
107
|
+
`within your local network, check Appium server logs and/or ` +
|
|
108
|
+
`consult the driver troubleshooting guide.`
|
|
97
109
|
);
|
|
98
110
|
}
|
|
99
111
|
this.mapping = xmlStr ? await parseGoogleapiStorageXml(xmlStr, shouldParseNotes) : {};
|
|
@@ -104,47 +116,102 @@ export class ChromedriverStorageClient {
|
|
|
104
116
|
}
|
|
105
117
|
|
|
106
118
|
/**
|
|
107
|
-
*
|
|
108
|
-
* into the given destination
|
|
119
|
+
* Retrieves chromedrivers from the remote storage to the local file system
|
|
109
120
|
*
|
|
110
|
-
* @param
|
|
111
|
-
* @
|
|
121
|
+
* @param opts - Synchronization options (versions, minBrowserVersion, osInfo)
|
|
122
|
+
* @throws {Error} if there was a problem while retrieving the drivers
|
|
123
|
+
* @returns The list of successfully synchronized driver keys
|
|
112
124
|
*/
|
|
113
|
-
async
|
|
114
|
-
|
|
125
|
+
async syncDrivers(opts: SyncOptions = {}): Promise<string[]> {
|
|
126
|
+
if (_.isEmpty(this.mapping)) {
|
|
127
|
+
await this.retrieveMapping(!!opts.minBrowserVersion);
|
|
128
|
+
}
|
|
129
|
+
if (_.isEmpty(this.mapping)) {
|
|
130
|
+
throw new Error('Cannot retrieve chromedrivers mapping from Google storage');
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const driversToSync = this.selectMatchingDrivers(opts.osInfo ?? (await getOsInfo()), opts);
|
|
134
|
+
if (_.isEmpty(driversToSync)) {
|
|
135
|
+
log.debug(`There are no drivers to sync. Exiting`);
|
|
136
|
+
return [];
|
|
137
|
+
}
|
|
138
|
+
log.debug(
|
|
139
|
+
`Got ${util.pluralize('driver', driversToSync.length, true)} to sync: ` +
|
|
140
|
+
JSON.stringify(driversToSync, null, 2)
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
const synchronizedDrivers: string[] = [];
|
|
144
|
+
const promises: Promise<void>[] = [];
|
|
145
|
+
const chunk: Promise<void>[] = [];
|
|
146
|
+
const archivesRoot = await tempDir.openDir();
|
|
115
147
|
try {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
if (!chromedriverPath) {
|
|
124
|
-
throw new Error(
|
|
125
|
-
'The archive was unzipped properly, but we could not find any chromedriver executable'
|
|
148
|
+
for (const [idx, driverKey] of driversToSync.entries()) {
|
|
149
|
+
const promise = B.resolve(
|
|
150
|
+
(async () => {
|
|
151
|
+
if (await this.retrieveDriver(idx, driverKey, archivesRoot, !_.isEmpty(opts))) {
|
|
152
|
+
synchronizedDrivers.push(driverKey);
|
|
153
|
+
}
|
|
154
|
+
})()
|
|
126
155
|
);
|
|
156
|
+
promises.push(promise);
|
|
157
|
+
chunk.push(promise);
|
|
158
|
+
if (chunk.length >= MAX_PARALLEL_DOWNLOADS) {
|
|
159
|
+
await B.any(chunk);
|
|
160
|
+
}
|
|
161
|
+
_.remove(chunk, (p) => (p as B<void>).isFulfilled());
|
|
127
162
|
}
|
|
128
|
-
|
|
129
|
-
await fs.mv(chromedriverPath, dst, {
|
|
130
|
-
mkdirp: true,
|
|
131
|
-
});
|
|
163
|
+
await B.all(promises);
|
|
132
164
|
} finally {
|
|
133
|
-
await fs.rimraf(
|
|
165
|
+
await fs.rimraf(archivesRoot);
|
|
166
|
+
}
|
|
167
|
+
if (!_.isEmpty(synchronizedDrivers)) {
|
|
168
|
+
log.info(
|
|
169
|
+
`Successfully synchronized ` +
|
|
170
|
+
`${util.pluralize('chromedriver', synchronizedDrivers.length, true)}`
|
|
171
|
+
);
|
|
172
|
+
} else {
|
|
173
|
+
log.info(`No chromedrivers were synchronized`);
|
|
134
174
|
}
|
|
175
|
+
return synchronizedDrivers;
|
|
135
176
|
}
|
|
136
177
|
|
|
137
178
|
/**
|
|
138
|
-
*
|
|
139
|
-
* chromedriver entries by operating system information
|
|
140
|
-
* and/or additional synchronization options (if provided)
|
|
179
|
+
* Returns the latest chromedriver version for Chrome for Testing
|
|
141
180
|
*
|
|
142
|
-
* @
|
|
143
|
-
* @
|
|
144
|
-
* @returns {Array<String>} The list of filtered chromedriver
|
|
145
|
-
* entry names (version/archive name)
|
|
181
|
+
* @returns The latest stable chromedriver version string
|
|
182
|
+
* @throws {Error} if the version cannot be fetched from the remote API
|
|
146
183
|
*/
|
|
147
|
-
|
|
184
|
+
async getLatestKnownGoodVersion(): Promise<string> {
|
|
185
|
+
let jsonStr: string;
|
|
186
|
+
try {
|
|
187
|
+
jsonStr = await retrieveData(
|
|
188
|
+
CHROME_FOR_TESTING_LAST_GOOD_VERSIONS,
|
|
189
|
+
{
|
|
190
|
+
'user-agent': USER_AGENT,
|
|
191
|
+
accept: `application/json, */*`,
|
|
192
|
+
},
|
|
193
|
+
{timeout: STORAGE_REQ_TIMEOUT_MS}
|
|
194
|
+
);
|
|
195
|
+
} catch (e) {
|
|
196
|
+
const err = e as Error;
|
|
197
|
+
throw new Error(
|
|
198
|
+
`Cannot fetch the latest Chromedriver version. ` +
|
|
199
|
+
`Make sure you can access ${CHROME_FOR_TESTING_LAST_GOOD_VERSIONS} from your machine or provide a mirror by setting ` +
|
|
200
|
+
`a custom value to CHROMELABS_URL environment variable. Original error: ${err.message}`
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
return parseLatestKnownGoodVersionsJson(jsonStr);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Filters `this.mapping` to only select matching chromedriver entries
|
|
208
|
+
* by operating system information and/or additional synchronization options
|
|
209
|
+
*
|
|
210
|
+
* @param osInfo - Operating system information to match against
|
|
211
|
+
* @param opts - Synchronization options (versions, minBrowserVersion)
|
|
212
|
+
* @returns The list of filtered chromedriver entry names (version/archive name)
|
|
213
|
+
*/
|
|
214
|
+
private selectMatchingDrivers(osInfo: OSInfo, opts: SyncOptions = {}): string[] {
|
|
148
215
|
const {minBrowserVersion, versions = []} = opts;
|
|
149
216
|
let driversToSync = _.keys(this.mapping);
|
|
150
217
|
|
|
@@ -205,15 +272,23 @@ export class ChromedriverStorageClient {
|
|
|
205
272
|
let result = driversToSync.filter((cdName) => this.doesMatchForOsInfo(cdName, osInfo));
|
|
206
273
|
if (_.isEmpty(result) && arch === ARCH.X64 && cpu === CPU.INTEL) {
|
|
207
274
|
// Fallback to X86 if X64 architecture is not available for this driver
|
|
208
|
-
result = driversToSync.filter((cdName) =>
|
|
209
|
-
|
|
210
|
-
|
|
275
|
+
result = driversToSync.filter((cdName) =>
|
|
276
|
+
this.doesMatchForOsInfo(cdName, {
|
|
277
|
+
name,
|
|
278
|
+
arch: ARCH.X86,
|
|
279
|
+
cpu,
|
|
280
|
+
})
|
|
281
|
+
);
|
|
211
282
|
}
|
|
212
283
|
if (_.isEmpty(result) && name === OS.MAC && cpu === CPU.ARM) {
|
|
213
284
|
// Fallback to Intel/Rosetta if ARM architecture is not available for this driver
|
|
214
|
-
result = driversToSync.filter((cdName) =>
|
|
215
|
-
|
|
216
|
-
|
|
285
|
+
result = driversToSync.filter((cdName) =>
|
|
286
|
+
this.doesMatchForOsInfo(cdName, {
|
|
287
|
+
name,
|
|
288
|
+
arch,
|
|
289
|
+
cpu: CPU.INTEL,
|
|
290
|
+
})
|
|
291
|
+
);
|
|
217
292
|
}
|
|
218
293
|
driversToSync = result;
|
|
219
294
|
log.debug(`Got ${util.pluralize('item', driversToSync.length, true)}`);
|
|
@@ -221,12 +296,11 @@ export class ChromedriverStorageClient {
|
|
|
221
296
|
|
|
222
297
|
if (!_.isEmpty(driversToSync)) {
|
|
223
298
|
log.debug('Excluding older patches if present');
|
|
224
|
-
|
|
225
|
-
const patchesMap = {};
|
|
299
|
+
const patchesMap: {[key: string]: string[]} = {};
|
|
226
300
|
// Older chromedrivers must not be excluded as they follow a different
|
|
227
301
|
// versioning pattern
|
|
228
302
|
const versionWithPatchPattern = /\d+\.\d+\.\d+\.\d+/;
|
|
229
|
-
const selectedVersions = new Set();
|
|
303
|
+
const selectedVersions = new Set<string>();
|
|
230
304
|
for (const cdName of driversToSync) {
|
|
231
305
|
const cdVersion = this.mapping[cdName].version;
|
|
232
306
|
if (!versionWithPatchPattern.test(cdVersion)) {
|
|
@@ -246,17 +320,15 @@ export class ChromedriverStorageClient {
|
|
|
246
320
|
if (patchesMap[majorVersion].length <= 1) {
|
|
247
321
|
continue;
|
|
248
322
|
}
|
|
249
|
-
patchesMap[majorVersion].sort(
|
|
250
|
-
(/** @type {string} */ a, /** @type {string}} */ b) => compareVersions(b, a)
|
|
251
|
-
);
|
|
323
|
+
patchesMap[majorVersion].sort((a: string, b: string) => compareVersions(b, a));
|
|
252
324
|
}
|
|
253
325
|
if (!_.isEmpty(patchesMap)) {
|
|
254
326
|
log.debug('Versions mapping: ' + JSON.stringify(patchesMap, null, 2));
|
|
255
327
|
for (const sortedVersions of _.values(patchesMap)) {
|
|
256
328
|
selectedVersions.add(sortedVersions[0]);
|
|
257
329
|
}
|
|
258
|
-
driversToSync = driversToSync.filter(
|
|
259
|
-
|
|
330
|
+
driversToSync = driversToSync.filter((cdName) =>
|
|
331
|
+
selectedVersions.has(this.mapping[cdName].version)
|
|
260
332
|
);
|
|
261
333
|
}
|
|
262
334
|
}
|
|
@@ -267,11 +339,11 @@ export class ChromedriverStorageClient {
|
|
|
267
339
|
/**
|
|
268
340
|
* Checks whether the given chromedriver matches the operating system to run on
|
|
269
341
|
*
|
|
270
|
-
* @param
|
|
271
|
-
* @param
|
|
272
|
-
* @returns
|
|
342
|
+
* @param cdName - The chromedriver entry key in the mapping
|
|
343
|
+
* @param osInfo - Operating system information to match against
|
|
344
|
+
* @returns True if the chromedriver matches the OS info
|
|
273
345
|
*/
|
|
274
|
-
doesMatchForOsInfo(cdName, {name, arch, cpu}) {
|
|
346
|
+
private doesMatchForOsInfo(cdName: string, {name, arch, cpu}: OSInfo): boolean {
|
|
275
347
|
const cdInfo = this.mapping[cdName];
|
|
276
348
|
if (!cdInfo) {
|
|
277
349
|
return false;
|
|
@@ -291,18 +363,23 @@ export class ChromedriverStorageClient {
|
|
|
291
363
|
* Retrieves the given chromedriver from the storage
|
|
292
364
|
* and unpacks it into `this.chromedriverDir` folder
|
|
293
365
|
*
|
|
294
|
-
* @param
|
|
295
|
-
* @param
|
|
296
|
-
* @param
|
|
366
|
+
* @param index - The unique driver index
|
|
367
|
+
* @param driverKey - The driver key in `this.mapping`
|
|
368
|
+
* @param archivesRoot - The temporary folder path to extract
|
|
297
369
|
* downloaded archives to
|
|
298
|
-
* @param
|
|
370
|
+
* @param isStrict [true] - Whether to throw an error (`true`)
|
|
299
371
|
* or return a boolean result if the driver retrieval process fails
|
|
300
372
|
* @throws {Error} if there was a failure while retrieving the driver
|
|
301
373
|
* and `isStrict` is set to `true`
|
|
302
|
-
* @returns
|
|
374
|
+
* @returns if `true` then the chromedriver is successfully
|
|
303
375
|
* downloaded and extracted.
|
|
304
376
|
*/
|
|
305
|
-
async retrieveDriver(
|
|
377
|
+
private async retrieveDriver(
|
|
378
|
+
index: number,
|
|
379
|
+
driverKey: string,
|
|
380
|
+
archivesRoot: string,
|
|
381
|
+
isStrict = false
|
|
382
|
+
): Promise<boolean> {
|
|
306
383
|
const {url, etag, version} = this.mapping[driverKey];
|
|
307
384
|
const archivePath = path.resolve(archivesRoot, `${index}.zip`);
|
|
308
385
|
log.debug(`Retrieving '${url}' to '${archivePath}'`);
|
|
@@ -312,7 +389,7 @@ export class ChromedriverStorageClient {
|
|
|
312
389
|
timeout: STORAGE_REQ_TIMEOUT_MS,
|
|
313
390
|
});
|
|
314
391
|
} catch (e) {
|
|
315
|
-
const err =
|
|
392
|
+
const err = e as Error;
|
|
316
393
|
const msg = `Cannot download chromedriver archive. Original error: ${err.message}`;
|
|
317
394
|
if (isStrict) {
|
|
318
395
|
throw new Error(msg);
|
|
@@ -335,7 +412,7 @@ export class ChromedriverStorageClient {
|
|
|
335
412
|
await fs.chmod(targetPath, 0o755);
|
|
336
413
|
log.debug(`Permissions of the file '${targetPath}' have been changed to 755`);
|
|
337
414
|
} catch (e) {
|
|
338
|
-
const err =
|
|
415
|
+
const err = e as Error;
|
|
339
416
|
if (isStrict) {
|
|
340
417
|
throw err;
|
|
341
418
|
}
|
|
@@ -346,105 +423,34 @@ export class ChromedriverStorageClient {
|
|
|
346
423
|
}
|
|
347
424
|
|
|
348
425
|
/**
|
|
349
|
-
*
|
|
350
|
-
*
|
|
426
|
+
* Extracts downloaded chromedriver archive
|
|
427
|
+
* into the given destination
|
|
351
428
|
*
|
|
352
|
-
* @param
|
|
353
|
-
* @
|
|
354
|
-
* the drivers
|
|
355
|
-
* @returns {Promise<string[]>} The list of successfully synchronized driver keys
|
|
429
|
+
* @param src - The source archive path
|
|
430
|
+
* @param dst - The destination chromedriver path
|
|
356
431
|
*/
|
|
357
|
-
async
|
|
358
|
-
|
|
359
|
-
await this.retrieveMapping(!!opts.minBrowserVersion);
|
|
360
|
-
}
|
|
361
|
-
if (_.isEmpty(this.mapping)) {
|
|
362
|
-
throw new Error('Cannot retrieve chromedrivers mapping from Google storage');
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
const driversToSync = this.selectMatchingDrivers(opts.osInfo ?? (await getOsInfo()), opts);
|
|
366
|
-
if (_.isEmpty(driversToSync)) {
|
|
367
|
-
log.debug(`There are no drivers to sync. Exiting`);
|
|
368
|
-
return [];
|
|
369
|
-
}
|
|
370
|
-
log.debug(
|
|
371
|
-
`Got ${util.pluralize('driver', driversToSync.length, true)} to sync: ` +
|
|
372
|
-
JSON.stringify(driversToSync, null, 2)
|
|
373
|
-
);
|
|
374
|
-
|
|
375
|
-
/**
|
|
376
|
-
* @type {string[]}
|
|
377
|
-
*/
|
|
378
|
-
const synchronizedDrivers = [];
|
|
379
|
-
const promises = [];
|
|
380
|
-
const chunk = [];
|
|
381
|
-
const archivesRoot = await tempDir.openDir();
|
|
432
|
+
private async unzipDriver(src: string, dst: string): Promise<void> {
|
|
433
|
+
const tmpRoot = await tempDir.openDir();
|
|
382
434
|
try {
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
435
|
+
await zip.extractAllTo(src, tmpRoot);
|
|
436
|
+
const chromedriverPath = await fs.walkDir(
|
|
437
|
+
tmpRoot,
|
|
438
|
+
true,
|
|
439
|
+
(itemPath, isDirectory) =>
|
|
440
|
+
!isDirectory && _.toLower(path.parse(itemPath).name) === 'chromedriver'
|
|
441
|
+
);
|
|
442
|
+
if (!chromedriverPath) {
|
|
443
|
+
throw new Error(
|
|
444
|
+
'The archive was unzipped properly, but we could not find any chromedriver executable'
|
|
390
445
|
);
|
|
391
|
-
promises.push(promise);
|
|
392
|
-
chunk.push(promise);
|
|
393
|
-
if (chunk.length >= MAX_PARALLEL_DOWNLOADS) {
|
|
394
|
-
await B.any(chunk);
|
|
395
|
-
}
|
|
396
|
-
_.remove(chunk, (p) => p.isFulfilled());
|
|
397
446
|
}
|
|
398
|
-
|
|
447
|
+
log.debug(`Moving the extracted '${path.basename(chromedriverPath)}' to '${dst}'`);
|
|
448
|
+
await fs.mv(chromedriverPath, dst, {
|
|
449
|
+
mkdirp: true,
|
|
450
|
+
});
|
|
399
451
|
} finally {
|
|
400
|
-
await fs.rimraf(
|
|
401
|
-
}
|
|
402
|
-
if (!_.isEmpty(synchronizedDrivers)) {
|
|
403
|
-
log.info(
|
|
404
|
-
`Successfully synchronized ` +
|
|
405
|
-
`${util.pluralize('chromedriver', synchronizedDrivers.length, true)}`
|
|
406
|
-
);
|
|
407
|
-
} else {
|
|
408
|
-
log.info(`No chromedrivers were synchronized`);
|
|
409
|
-
}
|
|
410
|
-
return synchronizedDrivers;
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
/**
|
|
414
|
-
* Return latest chromedriver version for Chrome for Testing.
|
|
415
|
-
* @returns {Promise<string>}
|
|
416
|
-
*/
|
|
417
|
-
async getLatestKnownGoodVersion() {
|
|
418
|
-
let jsonStr;
|
|
419
|
-
try {
|
|
420
|
-
jsonStr = await retrieveData(
|
|
421
|
-
CHROME_FOR_TESTING_LAST_GOOD_VERSIONS,
|
|
422
|
-
{
|
|
423
|
-
'user-agent': USER_AGENT,
|
|
424
|
-
accept: `application/json, */*`,
|
|
425
|
-
}, {timeout: STORAGE_REQ_TIMEOUT_MS}
|
|
426
|
-
);
|
|
427
|
-
} catch (e) {
|
|
428
|
-
const err = /** @type {Error} */ (e);
|
|
429
|
-
throw new Error(`Cannot fetch the latest Chromedriver version. ` +
|
|
430
|
-
`Make sure you can access ${CHROME_FOR_TESTING_LAST_GOOD_VERSIONS} from your machine or provide a mirror by setting ` +
|
|
431
|
-
`a custom value to CHROMELABS_URL environment variable. Original error: ${err.message}`);
|
|
452
|
+
await fs.rimraf(tmpRoot);
|
|
432
453
|
}
|
|
433
|
-
return parseLatestKnownGoodVersionsJson(jsonStr);
|
|
434
454
|
}
|
|
435
455
|
}
|
|
436
456
|
|
|
437
|
-
export default ChromedriverStorageClient;
|
|
438
|
-
|
|
439
|
-
/**
|
|
440
|
-
* @typedef {import('../types').SyncOptions} SyncOptions
|
|
441
|
-
* @typedef {import('../types').OSInfo} OSInfo
|
|
442
|
-
* @typedef {import('../types').ChromedriverDetails} ChromedriverDetails
|
|
443
|
-
* @typedef {import('../types').ChromedriverDetailsMapping} ChromedriverDetailsMapping
|
|
444
|
-
*/
|
|
445
|
-
|
|
446
|
-
/**
|
|
447
|
-
* @typedef {Object} StorageInfo
|
|
448
|
-
* @property {string} url
|
|
449
|
-
* @property {string} accept
|
|
450
|
-
*/
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"chrome",
|
|
7
7
|
"android"
|
|
8
8
|
],
|
|
9
|
-
"version": "8.0
|
|
9
|
+
"version": "8.1.0",
|
|
10
10
|
"author": "Appium Contributors",
|
|
11
11
|
"license": "Apache-2.0",
|
|
12
12
|
"repository": {
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"compare-versions": "^6.0.0",
|
|
52
52
|
"lodash": "^4.17.4",
|
|
53
53
|
"semver": "^7.0.0",
|
|
54
|
-
"teen_process": "^
|
|
54
|
+
"teen_process": "^4.0.4",
|
|
55
55
|
"xpath": "^0.x"
|
|
56
56
|
},
|
|
57
57
|
"scripts": {
|
|
@@ -78,7 +78,6 @@
|
|
|
78
78
|
"@types/node": "^25.0.0",
|
|
79
79
|
"@types/semver": "^7.0.0",
|
|
80
80
|
"@types/sinon": "^21.0.0",
|
|
81
|
-
"@types/teen_process": "^2.0.0",
|
|
82
81
|
"chai": "^6.0.0",
|
|
83
82
|
"chai-as-promised": "^8.0.0",
|
|
84
83
|
"conventional-changelog-conventionalcommits": "^9.0.0",
|