feat: support stable/dev/beta/canary keywords for chrome and chromium (#10140)

This commit is contained in:
Alex Rudenko 2023-05-08 14:54:44 +02:00 committed by GitHub
parent baf2a86fdd
commit 90ed263eaf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 163 additions and 106 deletions

View File

@ -24,7 +24,7 @@ npx @puppeteer/browsers launch --help # help for the launch command
## Known limitations
1. We support installing and running Firefox and Chrome/Chromium. The `latest` keyword only works during the installation. For the `launch` command you need to specify an exact build ID. The build ID is provided by the `install` command (see `npx @puppeteer/browsers install --help` for the format).
1. We support installing and running Firefox, Chrome and Chromium. The `latest`, `beta`, `dev`, `canary`, `stable` keywords are only supported for the install command. For the `launch` command you need to specify an exact build ID. The build ID is provided by the `install` command (see `npx @puppeteer/browsers install --help` for the format).
2. Launching the system browsers is only possible for Chrome/Chromium.
## API

View File

@ -20,7 +20,7 @@ npx @puppeteer/browsers launch --help # help for the launch command
## Known limitations
1. We support installing and running Firefox and Chrome/Chromium. The `latest` keyword only works during the installation. For the `launch` command you need to specify an exact build ID. The build ID is provided by the `install` command (see `npx @puppeteer/browsers install --help` for the format).
1. We support installing and running Firefox, Chrome and Chromium. The `latest`, `beta`, `dev`, `canary`, `stable` keywords are only supported for the install command. For the `launch` command you need to specify an exact build ID. The build ID is provided by the `install` command (see `npx @puppeteer/browsers install --help` for the format).
2. Launching the system browsers is only possible for Chrome/Chromium.
## API

View File

@ -64,22 +64,74 @@ export async function resolveBuildId(
switch (tag as BrowserTag) {
case BrowserTag.LATEST:
return await firefox.resolveBuildId('FIREFOX_NIGHTLY');
case BrowserTag.BETA:
case BrowserTag.CANARY:
case BrowserTag.DEV:
case BrowserTag.STABLE:
throw new Error(`${tag} is not supported for ${browser}`);
}
case Browser.CHROME:
switch (tag as BrowserTag) {
case BrowserTag.LATEST:
// In CfT beta is the latest version.
return await chrome.resolveBuildId(platform, 'beta');
return await chrome.resolveBuildId(
platform,
ChromeReleaseChannel.CANARY
);
case BrowserTag.BETA:
return await chrome.resolveBuildId(
platform,
ChromeReleaseChannel.BETA
);
case BrowserTag.CANARY:
return await chrome.resolveBuildId(
platform,
ChromeReleaseChannel.CANARY
);
case BrowserTag.DEV:
return await chrome.resolveBuildId(
platform,
ChromeReleaseChannel.DEV
);
case BrowserTag.STABLE:
return await chrome.resolveBuildId(
platform,
ChromeReleaseChannel.STABLE
);
}
case Browser.CHROMEDRIVER:
switch (tag as BrowserTag) {
case BrowserTag.LATEST:
return await chromedriver.resolveBuildId('latest');
case BrowserTag.BETA:
case BrowserTag.CANARY:
case BrowserTag.DEV:
case BrowserTag.STABLE:
throw new Error(`${tag} is not support for ${browser}`);
}
case Browser.CHROMIUM:
switch (tag as BrowserTag) {
case BrowserTag.LATEST:
return await chromium.resolveBuildId(platform, 'latest');
case BrowserTag.BETA:
return await chromium.resolveBuildId(
platform,
ChromeReleaseChannel.BETA
);
case BrowserTag.CANARY:
return await chromium.resolveBuildId(
platform,
ChromeReleaseChannel.CANARY
);
case BrowserTag.DEV:
return await chromium.resolveBuildId(
platform,
ChromeReleaseChannel.DEV
);
case BrowserTag.STABLE:
return await chromium.resolveBuildId(
platform,
ChromeReleaseChannel.STABLE
);
}
}
// We assume the tag is the buildId if it didn't match any keywords.

View File

@ -16,7 +16,7 @@
import path from 'path';
import {httpRequest} from '../httpUtil.js';
import {getJSON} from '../httpUtil.js';
import {BrowserPlatform, ChromeReleaseChannel} from './types.js';
@ -35,21 +35,6 @@ function folder(platform: BrowserPlatform): string {
}
}
function chromiumDashPlatform(platform: BrowserPlatform): string {
switch (platform) {
case BrowserPlatform.LINUX:
return 'linux';
case BrowserPlatform.MAC_ARM:
return 'mac';
case BrowserPlatform.MAC:
return 'mac';
case BrowserPlatform.WIN32:
return 'win';
case BrowserPlatform.WIN64:
return 'win64';
}
}
export function resolveDownloadUrl(
platform: BrowserPlatform,
buildId: string,
@ -86,41 +71,39 @@ export function relativeExecutablePath(
return path.join('chrome-' + folder(platform), 'chrome.exe');
}
}
export async function getLastKnownGoodReleaseForChannel(
channel: ChromeReleaseChannel
): Promise<{version: string; revision: string}> {
const data = (await getJSON(
new URL(
'https://googlechromelabs.github.io/chrome-for-testing/last-known-good-versions.json'
)
)) as {
channels: {
[channel: string]: {version: string};
};
};
for (const channel of Object.keys(data.channels)) {
data.channels[channel.toLowerCase()] = data.channels[channel]!;
delete data.channels[channel];
}
return (
data as {
channels: {
[channel in ChromeReleaseChannel]: {version: string; revision: string};
};
}
).channels[channel];
}
export async function resolveBuildId(
platform: BrowserPlatform,
channel: 'beta' | 'stable' = 'beta'
_platform: BrowserPlatform,
channel: ChromeReleaseChannel
): Promise<string> {
return new Promise((resolve, reject) => {
const request = httpRequest(
new URL(
`https://chromiumdash.appspot.com/fetch_releases?platform=${chromiumDashPlatform(
platform
)}&channel=${channel}`
),
'GET',
response => {
let data = '';
if (response.statusCode && response.statusCode >= 400) {
return reject(new Error(`Got status code ${response.statusCode}`));
}
response.on('data', chunk => {
data += chunk;
});
response.on('end', () => {
try {
const response = JSON.parse(String(data));
return resolve(response[0].version);
} catch {
return reject(new Error('Chrome version not found'));
}
});
},
false
);
request.on('error', err => {
reject(err);
});
});
return (await getLastKnownGoodReleaseForChannel(channel)).version;
}
export function resolveSystemExecutablePath(

View File

@ -16,9 +16,10 @@
import path from 'path';
import {httpRequest} from '../httpUtil.js';
import {getText} from '../httpUtil.js';
import {BrowserPlatform} from './types.js';
import {getLastKnownGoodReleaseForChannel} from './chrome.js';
import {BrowserPlatform, ChromeReleaseChannel} from './types.js';
export {resolveSystemExecutablePath} from './chrome.js';
@ -89,37 +90,16 @@ export function relativeExecutablePath(
}
export async function resolveBuildId(
platform: BrowserPlatform,
// We will need it for other channels/keywords.
_channel: 'latest' = 'latest'
channel: ChromeReleaseChannel | 'latest' = 'latest'
): Promise<string> {
return new Promise((resolve, reject) => {
const request = httpRequest(
if (channel === 'latest') {
return await getText(
new URL(
`https://storage.googleapis.com/chromium-browser-snapshots/${folder(
platform
)}/LAST_CHANGE`
),
'GET',
response => {
let data = '';
if (response.statusCode && response.statusCode >= 400) {
return reject(new Error(`Got status code ${response.statusCode}`));
}
response.on('data', chunk => {
data += chunk;
});
response.on('end', () => {
try {
return resolve(String(data));
} catch {
return reject(new Error('Chrome version not found'));
}
});
},
false
)
);
request.on('error', err => {
reject(err);
});
});
}
return (await getLastKnownGoodReleaseForChannel(channel)).revision;
}

View File

@ -53,6 +53,10 @@ export const downloadUrls = {
* @public
*/
export enum BrowserTag {
CANARY = 'canary',
BETA = 'beta',
DEV = 'dev',
STABLE = 'stable',
LATEST = 'latest',
}

View File

@ -135,3 +135,41 @@ export function downloadFile(
});
});
}
export async function getJSON(url: URL): Promise<unknown> {
const text = await getText(url);
try {
return JSON.parse(text);
} catch {
throw new Error('Could not parse JSON from ' + url.toString());
}
}
export function getText(url: URL): Promise<string> {
return new Promise((resolve, reject) => {
const request = httpRequest(
url,
'GET',
response => {
let data = '';
if (response.statusCode && response.statusCode >= 400) {
return reject(new Error(`Got status code ${response.statusCode}`));
}
response.on('data', chunk => {
data += chunk;
});
response.on('end', () => {
try {
return resolve(String(data));
} catch {
return reject(new Error('Chrome version not found'));
}
});
},
false
);
request.on('error', err => {
reject(err);
});
});
}

View File

@ -425,6 +425,30 @@
"parameters": ["webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[page.spec] Page Page.setContent should work with accents",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[page.spec] Page Page.setContent should work with emojis",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[page.spec] Page Page.setContent should work with newline",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[page.spec] Page Page.setContent should work with tricky content",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[proxy.spec] *",
"platforms": ["darwin", "linux", "win32"],
@ -1769,30 +1793,6 @@
"parameters": ["cdp", "firefox"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[page.spec] Page Page.setContent should work with accents",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[page.spec] Page Page.setContent should work with emojis",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[page.spec] Page Page.setContent should work with newline",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[page.spec] Page Page.setContent should work with tricky content",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[page.spec] Page Page.setGeolocation should work",
"platforms": ["darwin", "linux", "win32"],