feat: allow installing chrome/chromedriver by milestone and version prefix (#10720)

This commit is contained in:
Alex Rudenko 2023-08-10 13:00:22 +02:00 committed by GitHub
parent 0c59e9a1cb
commit bec2357aee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 136 additions and 48 deletions

View File

@ -132,6 +132,26 @@ export class CLI {
'$0 install chrome@latest', '$0 install chrome@latest',
'Install the latest available build for the Chrome browser.' 'Install the latest available build for the Chrome browser.'
); );
yargs.example(
'$0 install chrome@canary',
'Install the latest available build for the Chrome Canary browser.'
);
yargs.example(
'$0 install chrome@115',
'Install the latest available build for Chrome 115.'
);
yargs.example(
'$0 install chromedriver@canary',
'Install the latest available build for ChromeDriver Canary.'
);
yargs.example(
'$0 install chromedriver@115',
'Install the latest available build for ChromeDriver 115.'
);
yargs.example(
'$0 install chromedriver@115.0.5790',
'Install the latest available patch (115.0.5790.X) build for ChromeDriver.'
);
yargs.example( yargs.example(
'$0 install chromium@1083080', '$0 install chromium@1083080',
'Install the revision 1083080 of the Chromium browser.' 'Install the revision 1083080 of the Chromium browser.'
@ -201,15 +221,15 @@ export class CLI {
default: false, default: false,
}); });
yargs.example( yargs.example(
'$0 launch chrome@1083080', '$0 launch chrome@115.0.5790.170',
'Launch the Chrome browser identified by the revision 1083080.' 'Launch Chrome 115.0.5790.170'
); );
yargs.example( yargs.example(
'$0 launch firefox@112.0a1', '$0 launch firefox@112.0a1',
'Launch the Firefox browser identified by the milestone 112.0a1.' 'Launch the Firefox browser identified by the milestone 112.0a1.'
); );
yargs.example( yargs.example(
'$0 launch chrome@1083080 --detached', '$0 launch chrome@115.0.5790.170 --detached',
'Launch the browser but detach the sub-processes.' 'Launch the browser but detach the sub-processes.'
); );
yargs.example( yargs.example(

View File

@ -72,36 +72,28 @@ export async function resolveBuildId(
`${tag} is not supported for ${browser}. Use 'latest' instead.` `${tag} is not supported for ${browser}. Use 'latest' instead.`
); );
} }
case Browser.CHROME: case Browser.CHROME: {
switch (tag as BrowserTag) { switch (tag as BrowserTag) {
case BrowserTag.LATEST: case BrowserTag.LATEST:
return await chrome.resolveBuildId( return await chrome.resolveBuildId(ChromeReleaseChannel.CANARY);
platform,
ChromeReleaseChannel.CANARY
);
case BrowserTag.BETA: case BrowserTag.BETA:
return await chrome.resolveBuildId( return await chrome.resolveBuildId(ChromeReleaseChannel.BETA);
platform,
ChromeReleaseChannel.BETA
);
case BrowserTag.CANARY: case BrowserTag.CANARY:
return await chrome.resolveBuildId( return await chrome.resolveBuildId(ChromeReleaseChannel.CANARY);
platform,
ChromeReleaseChannel.CANARY
);
case BrowserTag.DEV: case BrowserTag.DEV:
return await chrome.resolveBuildId( return await chrome.resolveBuildId(ChromeReleaseChannel.DEV);
platform,
ChromeReleaseChannel.DEV
);
case BrowserTag.STABLE: case BrowserTag.STABLE:
return await chrome.resolveBuildId( return await chrome.resolveBuildId(ChromeReleaseChannel.STABLE);
platform, default:
ChromeReleaseChannel.STABLE const result = await chrome.resolveBuildId(tag);
); if (result) {
return result;
} }
case Browser.CHROMEDRIVER: }
switch (tag as BrowserTag) { return tag;
}
case Browser.CHROMEDRIVER: {
switch (tag) {
case BrowserTag.LATEST: case BrowserTag.LATEST:
case BrowserTag.CANARY: case BrowserTag.CANARY:
return await chromedriver.resolveBuildId(ChromeReleaseChannel.CANARY); return await chromedriver.resolveBuildId(ChromeReleaseChannel.CANARY);
@ -111,6 +103,13 @@ export async function resolveBuildId(
return await chromedriver.resolveBuildId(ChromeReleaseChannel.DEV); return await chromedriver.resolveBuildId(ChromeReleaseChannel.DEV);
case BrowserTag.STABLE: case BrowserTag.STABLE:
return await chromedriver.resolveBuildId(ChromeReleaseChannel.STABLE); return await chromedriver.resolveBuildId(ChromeReleaseChannel.STABLE);
default:
const result = await chromedriver.resolveBuildId(tag);
if (result) {
return result;
}
}
return tag;
} }
case Browser.CHROMIUM: case Browser.CHROMIUM:
switch (tag as BrowserTag) { switch (tag as BrowserTag) {

View File

@ -97,11 +97,66 @@ export async function getLastKnownGoodReleaseForChannel(
).channels[channel]; ).channels[channel];
} }
export async function getLastKnownGoodReleaseForMilestone(
milestone: string
): Promise<{version: string; revision: string} | undefined> {
const data = (await getJSON(
new URL(
'https://googlechromelabs.github.io/chrome-for-testing/latest-versions-per-milestone.json'
)
)) as {
milestones: Record<string, {version: string; revision: string}>;
};
return data.milestones[milestone] as
| {version: string; revision: string}
| undefined;
}
export async function getLastKnownGoodReleaseForBuild(
/**
* @example `112.0.23`,
*/
buildPrefix: string
): Promise<{version: string; revision: string} | undefined> {
const data = (await getJSON(
new URL(
'https://googlechromelabs.github.io/chrome-for-testing/latest-patch-versions-per-build.json'
)
)) as {
builds: Record<string, {version: string; revision: string}>;
};
return data.builds[buildPrefix] as
| {version: string; revision: string}
| undefined;
}
export async function resolveBuildId( export async function resolveBuildId(
_platform: BrowserPlatform,
channel: ChromeReleaseChannel channel: ChromeReleaseChannel
): Promise<string> { ): Promise<string>;
return (await getLastKnownGoodReleaseForChannel(channel)).version; export async function resolveBuildId(
channel: string
): Promise<string | undefined>;
export async function resolveBuildId(
channel: ChromeReleaseChannel | string
): Promise<string | undefined> {
if (
Object.values(ChromeReleaseChannel).includes(
channel as ChromeReleaseChannel
)
) {
return (
await getLastKnownGoodReleaseForChannel(channel as ChromeReleaseChannel)
).version;
}
if (channel.match(/^\d+$/)) {
// Potentially a milestone.
return (await getLastKnownGoodReleaseForMilestone(channel))?.version;
}
if (channel.match(/^\d+\.\d+\.\d+$/)) {
// Potentially a build prefix without the patch version.
return (await getLastKnownGoodReleaseForBuild(channel))?.version;
}
return;
} }
export function resolveSystemExecutablePath( export function resolveSystemExecutablePath(

View File

@ -15,8 +15,7 @@
*/ */
import path from 'path'; import path from 'path';
import {getLastKnownGoodReleaseForChannel} from './chrome.js'; import {BrowserPlatform} from './types.js';
import {BrowserPlatform, ChromeReleaseChannel} from './types.js';
function folder(platform: BrowserPlatform): string { function folder(platform: BrowserPlatform): string {
switch (platform) { switch (platform) {
@ -63,8 +62,5 @@ export function relativeExecutablePath(
return path.join('chromedriver-' + folder(platform), 'chromedriver.exe'); return path.join('chromedriver-' + folder(platform), 'chromedriver.exe');
} }
} }
export async function resolveBuildId(
channel: ChromeReleaseChannel export {resolveBuildId} from './chrome.js';
): Promise<string> {
return (await getLastKnownGoodReleaseForChannel(channel)).version;
}

View File

@ -25,6 +25,7 @@ import {
resolveDownloadUrl, resolveDownloadUrl,
relativeExecutablePath, relativeExecutablePath,
resolveSystemExecutablePath, resolveSystemExecutablePath,
resolveBuildId,
} from '../../../lib/cjs/browser-data/chrome.js'; } from '../../../lib/cjs/browser-data/chrome.js';
describe('Chrome', () => { describe('Chrome', () => {
@ -117,4 +118,12 @@ describe('Chrome', () => {
); );
}, new Error(`Unable to detect browser executable path for 'canary' on linux.`)); }, new Error(`Unable to detect browser executable path for 'canary' on linux.`));
}); });
it('should resolve milestones', async () => {
assert.strictEqual(await resolveBuildId('115'), '115.0.5790.170');
});
it('should resolve build prefix', async () => {
assert.strictEqual(await resolveBuildId('115.0.5790'), '115.0.5790.170');
});
}); });

View File

@ -21,6 +21,7 @@ import {BrowserPlatform} from '../../../lib/cjs/browser-data/browser-data.js';
import { import {
resolveDownloadUrl, resolveDownloadUrl,
relativeExecutablePath, relativeExecutablePath,
resolveBuildId,
} from '../../../lib/cjs/browser-data/chromedriver.js'; } from '../../../lib/cjs/browser-data/chromedriver.js';
describe('ChromeDriver', () => { describe('ChromeDriver', () => {
@ -47,6 +48,14 @@ describe('ChromeDriver', () => {
); );
}); });
it('should resolve milestones', async () => {
assert.strictEqual(await resolveBuildId('115'), '115.0.5790.170');
});
it('should resolve build prefix', async () => {
assert.strictEqual(await resolveBuildId('115.0.5790'), '115.0.5790.170');
});
it('should resolve executable paths', () => { it('should resolve executable paths', () => {
assert.strictEqual( assert.strictEqual(
relativeExecutablePath(BrowserPlatform.LINUX, '12372323'), relativeExecutablePath(BrowserPlatform.LINUX, '12372323'),

View File

@ -689,6 +689,18 @@
"parameters": ["cdp", "firefox"], "parameters": ["cdp", "firefox"],
"expectations": ["SKIP"] "expectations": ["SKIP"]
}, },
{
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluateOnNewDocument should evaluate before anything else on the page",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluateOnNewDocument should work with CSP",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["PASS"]
},
{ {
"testIdPattern": "[evaluation.spec] Evaluation specs Page.removeScriptToEvaluateOnNewDocument *", "testIdPattern": "[evaluation.spec] Evaluation specs Page.removeScriptToEvaluateOnNewDocument *",
"platforms": ["darwin", "linux", "win32"], "platforms": ["darwin", "linux", "win32"],
@ -4150,17 +4162,5 @@
"platforms": ["darwin", "linux", "win32"], "platforms": ["darwin", "linux", "win32"],
"parameters": ["cdp", "chrome", "headless"], "parameters": ["cdp", "chrome", "headless"],
"expectations": ["FAIL", "PASS"] "expectations": ["FAIL", "PASS"]
},
{
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluateOnNewDocument should evaluate before anything else on the page",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluateOnNewDocument should work with CSP",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["PASS"]
} }
] ]