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
|
@@ -3,24 +3,27 @@ import path from 'path';
|
|
|
3
3
|
import {logger} from '@appium/support';
|
|
4
4
|
import * as semver from 'semver';
|
|
5
5
|
import {ARCH, CPU} from '../constants';
|
|
6
|
+
import type {ChromedriverDetailsMapping} from '../types';
|
|
6
7
|
|
|
7
8
|
const log = logger.getLogger('ChromedriverChromelabsStorageClient');
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
|
-
* Parses
|
|
11
|
-
* that retrieves Chromedriver versions. See
|
|
12
|
-
* https://github.com/GoogleChromeLabs/chrome-for-testing#json-api-endpoints
|
|
13
|
-
* for more details.
|
|
11
|
+
* Parses the output of the JSON API that retrieves Chromedriver versions
|
|
14
12
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
13
|
+
* See https://github.com/GoogleChromeLabs/chrome-for-testing#json-api-endpoints for more details.
|
|
14
|
+
*
|
|
15
|
+
* @param jsonStr - The JSON string from the known-good-versions-with-downloads API
|
|
16
|
+
* @returns A mapping of chromedriver entry keys to their details
|
|
17
|
+
* @throws {Error} if the JSON cannot be parsed or has an unsupported format
|
|
17
18
|
*/
|
|
18
|
-
export function parseKnownGoodVersionsWithDownloadsJson(
|
|
19
|
-
|
|
19
|
+
export function parseKnownGoodVersionsWithDownloadsJson(
|
|
20
|
+
jsonStr: string
|
|
21
|
+
): ChromedriverDetailsMapping {
|
|
22
|
+
let json: KnownGoodVersionsJson;
|
|
20
23
|
try {
|
|
21
24
|
json = JSON.parse(jsonStr);
|
|
22
25
|
} catch (e) {
|
|
23
|
-
const err =
|
|
26
|
+
const err = e as Error;
|
|
24
27
|
throw new Error(`Storage JSON cannot be parsed. Original error: ${err.message}`);
|
|
25
28
|
}
|
|
26
29
|
/**
|
|
@@ -60,8 +63,7 @@ export function parseKnownGoodVersionsWithDownloadsJson(jsonStr) {
|
|
|
60
63
|
* "version":"113.0.5672.35",
|
|
61
64
|
* ...
|
|
62
65
|
*/
|
|
63
|
-
|
|
64
|
-
const mapping = {};
|
|
66
|
+
const mapping: ChromedriverDetailsMapping = {};
|
|
65
67
|
if (!_.isArray(json?.versions)) {
|
|
66
68
|
log.debug(jsonStr);
|
|
67
69
|
throw new Error('The format of the storage JSON is not supported');
|
|
@@ -80,10 +82,13 @@ export function parseKnownGoodVersionsWithDownloadsJson(jsonStr) {
|
|
|
80
82
|
}
|
|
81
83
|
const osNameMatch = /^[a-z]+/i.exec(downloadEntry.platform);
|
|
82
84
|
if (!osNameMatch) {
|
|
83
|
-
log.debug(
|
|
85
|
+
log.debug(
|
|
86
|
+
`The entry '${downloadEntry.url}' does not contain valid platform name. Skipping it`
|
|
87
|
+
);
|
|
84
88
|
continue;
|
|
85
89
|
}
|
|
86
|
-
const key =
|
|
90
|
+
const key =
|
|
91
|
+
`${path.basename(path.dirname(path.dirname(downloadEntry.url)))}/` +
|
|
87
92
|
`${path.basename(downloadEntry.url)}`;
|
|
88
93
|
mapping[key] = {
|
|
89
94
|
url: downloadEntry.url,
|
|
@@ -94,7 +99,7 @@ export function parseKnownGoodVersionsWithDownloadsJson(jsonStr) {
|
|
|
94
99
|
name: osNameMatch[0],
|
|
95
100
|
arch: downloadEntry.platform.includes(ARCH.X64) ? ARCH.X64 : ARCH.X86,
|
|
96
101
|
cpu: downloadEntry.platform.includes(CPU.ARM) ? CPU.ARM : CPU.INTEL,
|
|
97
|
-
}
|
|
102
|
+
},
|
|
98
103
|
};
|
|
99
104
|
}
|
|
100
105
|
}
|
|
@@ -103,20 +108,20 @@ export function parseKnownGoodVersionsWithDownloadsJson(jsonStr) {
|
|
|
103
108
|
}
|
|
104
109
|
|
|
105
110
|
/**
|
|
106
|
-
* Parses
|
|
107
|
-
*
|
|
108
|
-
* https://github.com/GoogleChromeLabs/chrome-for-testing#json-api-endpoints
|
|
109
|
-
* for more details.
|
|
111
|
+
* Parses the output of the JSON API that retrieves the most recent stable Chromedriver version
|
|
112
|
+
*
|
|
113
|
+
* See https://github.com/GoogleChromeLabs/chrome-for-testing#json-api-endpoints for more details.
|
|
110
114
|
*
|
|
111
|
-
* @param
|
|
112
|
-
* @returns
|
|
115
|
+
* @param jsonStr - The JSON string from the last-known-good-versions API
|
|
116
|
+
* @returns The most recent available chromedriver version string
|
|
117
|
+
* @throws {Error} if the JSON cannot be parsed or has an unsupported format
|
|
113
118
|
*/
|
|
114
|
-
export function parseLatestKnownGoodVersionsJson(jsonStr) {
|
|
115
|
-
let json;
|
|
119
|
+
export function parseLatestKnownGoodVersionsJson(jsonStr: string): string {
|
|
120
|
+
let json: LatestKnownGoodVersionsJson;
|
|
116
121
|
try {
|
|
117
122
|
json = JSON.parse(jsonStr);
|
|
118
123
|
} catch (e) {
|
|
119
|
-
const err =
|
|
124
|
+
const err = e as Error;
|
|
120
125
|
throw new Error(`Storage JSON cannot be parsed. Original error: ${err.message}`);
|
|
121
126
|
}
|
|
122
127
|
/**
|
|
@@ -136,6 +141,29 @@ export function parseLatestKnownGoodVersionsJson(jsonStr) {
|
|
|
136
141
|
return json.channels.Stable.version;
|
|
137
142
|
}
|
|
138
143
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
144
|
+
interface VersionEntry {
|
|
145
|
+
version: string;
|
|
146
|
+
revision?: string;
|
|
147
|
+
downloads?: {
|
|
148
|
+
chromedriver?: Array<{
|
|
149
|
+
platform: string;
|
|
150
|
+
url: string;
|
|
151
|
+
}>;
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
interface KnownGoodVersionsJson {
|
|
156
|
+
timestamp?: string;
|
|
157
|
+
versions?: VersionEntry[];
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
interface LatestKnownGoodVersionsJson {
|
|
161
|
+
timestamp?: string;
|
|
162
|
+
channels?: {
|
|
163
|
+
Stable?: {
|
|
164
|
+
channel?: string;
|
|
165
|
+
version?: string;
|
|
166
|
+
revision?: string;
|
|
167
|
+
};
|
|
168
|
+
};
|
|
169
|
+
}
|
|
@@ -12,18 +12,28 @@ import {
|
|
|
12
12
|
} from '../constants';
|
|
13
13
|
import {DOMParser} from '@xmldom/xmldom';
|
|
14
14
|
import path from 'node:path';
|
|
15
|
+
import type {
|
|
16
|
+
AdditionalDriverDetails,
|
|
17
|
+
ChromedriverDetails,
|
|
18
|
+
ChromedriverDetailsMapping,
|
|
19
|
+
} from '../types';
|
|
15
20
|
|
|
16
21
|
const log = logger.getLogger('ChromedriverGoogleapisStorageClient');
|
|
17
22
|
const MAX_PARALLEL_DOWNLOADS = 5;
|
|
18
23
|
|
|
19
24
|
/**
|
|
25
|
+
* Finds a child node in an XML node by name and/or text content
|
|
20
26
|
*
|
|
21
|
-
* @param
|
|
22
|
-
* @param
|
|
23
|
-
* @param
|
|
24
|
-
* @returns
|
|
27
|
+
* @param parent - The parent XML node to search in
|
|
28
|
+
* @param childName - Optional child node name to match
|
|
29
|
+
* @param text - Optional text content to match
|
|
30
|
+
* @returns The matching child node or null if not found
|
|
25
31
|
*/
|
|
26
|
-
export function findChildNode(
|
|
32
|
+
export function findChildNode(
|
|
33
|
+
parent: Node | Attr,
|
|
34
|
+
childName: string | null = null,
|
|
35
|
+
text: string | null = null
|
|
36
|
+
): Node | Attr | null {
|
|
27
37
|
if (!childName && !text) {
|
|
28
38
|
return null;
|
|
29
39
|
}
|
|
@@ -32,7 +42,7 @@ export function findChildNode(parent, childName = null, text = null) {
|
|
|
32
42
|
}
|
|
33
43
|
|
|
34
44
|
for (let childNodeIdx = 0; childNodeIdx < parent.childNodes.length; childNodeIdx++) {
|
|
35
|
-
const childNode =
|
|
45
|
+
const childNode = parent.childNodes[childNodeIdx] as Element | Attr;
|
|
36
46
|
if (childName && !text && childName === childNode.localName) {
|
|
37
47
|
return childNode;
|
|
38
48
|
}
|
|
@@ -52,26 +62,15 @@ export function findChildNode(parent, childName = null, text = null) {
|
|
|
52
62
|
return null;
|
|
53
63
|
}
|
|
54
64
|
|
|
55
|
-
/**
|
|
56
|
-
*
|
|
57
|
-
* @param {Node?} node
|
|
58
|
-
* @returns
|
|
59
|
-
*/
|
|
60
|
-
function extractNodeText(node) {
|
|
61
|
-
return !node?.firstChild || !util.hasValue(node.firstChild.nodeValue)
|
|
62
|
-
? null
|
|
63
|
-
: node.firstChild.nodeValue;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
65
|
/**
|
|
67
66
|
* Gets additional chromedriver details from chromedriver
|
|
68
67
|
* release notes
|
|
69
68
|
*
|
|
70
|
-
* @param
|
|
71
|
-
* @returns
|
|
69
|
+
* @param content - Release notes of the corresponding chromedriver
|
|
70
|
+
* @returns AdditionalDriverDetails
|
|
72
71
|
*/
|
|
73
|
-
export function parseNotes(content) {
|
|
74
|
-
const result = {};
|
|
72
|
+
export function parseNotes(content: string): AdditionalDriverDetails {
|
|
73
|
+
const result: AdditionalDriverDetails = {};
|
|
75
74
|
const versionMatch = /^\s*[-]+ChromeDriver[\D]+([\d.]+)/im.exec(content);
|
|
76
75
|
if (versionMatch) {
|
|
77
76
|
result.version = versionMatch[1];
|
|
@@ -87,27 +86,26 @@ export function parseNotes(content) {
|
|
|
87
86
|
* Parses chromedriver storage XML and returns
|
|
88
87
|
* the parsed results
|
|
89
88
|
*
|
|
90
|
-
* @param
|
|
91
|
-
* @param
|
|
89
|
+
* @param xml - The chromedriver storage XML
|
|
90
|
+
* @param shouldParseNotes [true] - If set to `true`
|
|
92
91
|
* then additional drivers information is going to be parsed
|
|
93
92
|
* and assigned to `this.mapping`
|
|
94
|
-
* @returns
|
|
93
|
+
* @returns Promise<ChromedriverDetailsMapping>
|
|
95
94
|
*/
|
|
96
|
-
export async function parseGoogleapiStorageXml(
|
|
95
|
+
export async function parseGoogleapiStorageXml(
|
|
96
|
+
xml: string,
|
|
97
|
+
shouldParseNotes = true
|
|
98
|
+
): Promise<ChromedriverDetailsMapping> {
|
|
97
99
|
const doc = new DOMParser().parseFromString(xml, 'text/xml');
|
|
98
|
-
const driverNodes =
|
|
99
|
-
// https://github.com/xmldom/xmldom/issues/724
|
|
100
|
-
xpathSelect(`//*[local-name(.)='Contents']`, doc)
|
|
101
|
-
);
|
|
100
|
+
const driverNodes = xpathSelect(`//*[local-name(.)='Contents']`, doc) as Array<Node | Attr>;
|
|
102
101
|
log.debug(`Parsed ${driverNodes.length} entries from storage XML`);
|
|
103
102
|
if (_.isEmpty(driverNodes)) {
|
|
104
103
|
throw new Error('Cannot retrieve any valid Chromedriver entries from the storage config');
|
|
105
104
|
}
|
|
106
105
|
|
|
107
|
-
const promises = [];
|
|
108
|
-
const chunk = [];
|
|
109
|
-
|
|
110
|
-
const mapping = {};
|
|
106
|
+
const promises: Promise<void>[] = [];
|
|
107
|
+
const chunk: Promise<void>[] = [];
|
|
108
|
+
const mapping: ChromedriverDetailsMapping = {};
|
|
111
109
|
for (const driverNode of driverNodes) {
|
|
112
110
|
const k = extractNodeText(findChildNode(driverNode, 'Key'));
|
|
113
111
|
if (!_.includes(k, '/chromedriver_')) {
|
|
@@ -128,17 +126,16 @@ export async function parseGoogleapiStorageXml(xml, shouldParseNotes = true) {
|
|
|
128
126
|
continue;
|
|
129
127
|
}
|
|
130
128
|
|
|
131
|
-
|
|
132
|
-
const cdInfo = {
|
|
129
|
+
const cdInfo: ChromedriverDetails = {
|
|
133
130
|
url: `${GOOGLEAPIS_CDN}/${key}`,
|
|
134
131
|
etag: _.trim(etag, '"'),
|
|
135
|
-
version:
|
|
132
|
+
version: _.first(key.split('/')) as string,
|
|
136
133
|
minBrowserVersion: null,
|
|
137
134
|
os: {
|
|
138
135
|
name: osNameMatch[1],
|
|
139
136
|
arch: filename.includes(ARCH.X64) ? ARCH.X64 : ARCH.X86,
|
|
140
137
|
cpu: APPLE_ARM_SUFFIXES.some((suffix) => filename.includes(suffix)) ? CPU.ARM : CPU.INTEL,
|
|
141
|
-
}
|
|
138
|
+
},
|
|
142
139
|
};
|
|
143
140
|
mapping[key] = cdInfo;
|
|
144
141
|
|
|
@@ -157,13 +154,15 @@ export async function parseGoogleapiStorageXml(xml, shouldParseNotes = true) {
|
|
|
157
154
|
continue;
|
|
158
155
|
}
|
|
159
156
|
|
|
160
|
-
const promise = B.resolve(
|
|
157
|
+
const promise = B.resolve(
|
|
158
|
+
retrieveAdditionalDriverInfo(key, `${GOOGLEAPIS_CDN}/${notesPath}`, cdInfo)
|
|
159
|
+
);
|
|
161
160
|
promises.push(promise);
|
|
162
161
|
chunk.push(promise);
|
|
163
162
|
if (chunk.length >= MAX_PARALLEL_DOWNLOADS) {
|
|
164
163
|
await B.any(chunk);
|
|
165
164
|
}
|
|
166
|
-
_.remove(chunk, (p) => p.isFulfilled());
|
|
165
|
+
_.remove(chunk, (p) => (p as B<void>).isFulfilled());
|
|
167
166
|
}
|
|
168
167
|
await B.all(promises);
|
|
169
168
|
log.info(`The total count of entries in the mapping: ${_.size(mapping)}`);
|
|
@@ -171,17 +170,20 @@ export async function parseGoogleapiStorageXml(xml, shouldParseNotes = true) {
|
|
|
171
170
|
}
|
|
172
171
|
|
|
173
172
|
/**
|
|
174
|
-
* Downloads chromedriver release notes and
|
|
175
|
-
* into the dictionary argument
|
|
173
|
+
* Downloads chromedriver release notes and updates the driver info dictionary
|
|
176
174
|
*
|
|
177
|
-
*
|
|
178
|
-
* @param
|
|
179
|
-
* @param
|
|
180
|
-
* @param
|
|
181
|
-
* @param
|
|
182
|
-
* @throws {Error} if the release notes cannot be downloaded
|
|
175
|
+
* Mutates `infoDict` by setting `minBrowserVersion` if found in notes
|
|
176
|
+
* @param driverKey - Driver version plus archive name
|
|
177
|
+
* @param notesUrl - The URL of chromedriver notes
|
|
178
|
+
* @param infoDict - The dictionary containing driver info (will be mutated)
|
|
179
|
+
* @param timeout - Request timeout in milliseconds
|
|
183
180
|
*/
|
|
184
|
-
async function retrieveAdditionalDriverInfo(
|
|
181
|
+
async function retrieveAdditionalDriverInfo(
|
|
182
|
+
driverKey: string,
|
|
183
|
+
notesUrl: string,
|
|
184
|
+
infoDict: ChromedriverDetails,
|
|
185
|
+
timeout = STORAGE_REQ_TIMEOUT_MS
|
|
186
|
+
): Promise<void> {
|
|
185
187
|
const notes = await retrieveData(
|
|
186
188
|
notesUrl,
|
|
187
189
|
{
|
|
@@ -201,9 +203,8 @@ async function retrieveAdditionalDriverInfo(driverKey, notesUrl, infoDict, timeo
|
|
|
201
203
|
infoDict.minBrowserVersion = minBrowserVersion;
|
|
202
204
|
}
|
|
203
205
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
*/
|
|
206
|
+
function extractNodeText(node: Node | null | undefined): string | null {
|
|
207
|
+
return !node?.firstChild || !util.hasValue(node.firstChild.nodeValue)
|
|
208
|
+
? null
|
|
209
|
+
: node.firstChild.nodeValue;
|
|
210
|
+
}
|