chore: update headless shell treatment (#33603)

This commit is contained in:
Dmitry Gozman 2024-11-14 12:20:44 +00:00 коммит произвёл GitHub
Родитель 9f59dbdc57
Коммит 31a2b7bbdc
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
16 изменённых файлов: 84 добавлений и 101 удалений

31
.github/workflows/tests_secondary.yml поставляемый
Просмотреть файл

@ -268,29 +268,8 @@ jobs:
- run: npx playwright install-deps
- run: utils/build/build-playwright-driver.sh
test_linux_chromium_headless_shell:
name: Chromium Headless Shell
environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }}
strategy:
fail-fast: false
matrix:
runs-on: [ubuntu-latest]
runs-on: ${{ matrix.runs-on }}
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/run-test
with:
browsers-to-install: chromium chromium-headless-shell
command: npm run ctest
bot-name: "headless-shell-${{ matrix.runs-on }}"
flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }}
flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }}
flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }}
env:
PWTEST_CHANNEL: chromium-headless-shell
test_chromium_next:
name: Test chromium-next channel
test_channel_chromium:
name: Test channel=chromium
environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }}
strategy:
fail-fast: false
@ -301,11 +280,13 @@ jobs:
- uses: actions/checkout@v4
- uses: ./.github/actions/run-test
with:
# TODO: this should pass --no-shell.
# However, codegen tests do not inherit the channel and try to launch headless shell.
browsers-to-install: chromium
command: npm run ctest
bot-name: "chromium-next-${{ matrix.runs-on }}"
bot-name: "channel-chromium-${{ matrix.runs-on }}"
flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }}
flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }}
flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }}
env:
PWTEST_CHANNEL: chromium-next
PWTEST_CHANNEL: chromium

Просмотреть файл

@ -24,4 +24,4 @@ try {
}
if (install)
install(['chromium', 'ffmpeg']);
install(['chromium', 'chromium-headless-shell', 'ffmpeg']);

Просмотреть файл

@ -24,4 +24,4 @@ try {
}
if (install)
install(['chromium', 'ffmpeg']);
install(['chromium', 'chromium-headless-shell', 'ffmpeg']);

Просмотреть файл

@ -96,16 +96,42 @@ function suggestedBrowsersToInstall() {
return registry.executables().filter(e => e.installType !== 'none' && e.type !== 'tool').map(e => e.name).join(', ');
}
function checkBrowsersToInstall(args: string[]): Executable[] {
function defaultBrowsersToInstall(options: { noShell?: boolean, onlyShell?: boolean }): Executable[] {
let executables = registry.defaultExecutables();
if (options.noShell)
executables = executables.filter(e => e.name !== 'chromium-headless-shell');
if (options.onlyShell)
executables = executables.filter(e => e.name !== 'chromium');
return executables;
}
function checkBrowsersToInstall(args: string[], options: { noShell?: boolean, onlyShell?: boolean }): Executable[] {
if (options.noShell && options.onlyShell)
throw new Error(`Only one of --no-shell and --only-shell can be specified`);
const faultyArguments: string[] = [];
const executables: Executable[] = [];
for (const arg of args) {
const handleArgument = (arg: string) => {
const executable = registry.findExecutable(arg);
if (!executable || executable.installType === 'none')
faultyArguments.push(arg);
else
executables.push(executable);
if (executable?.browserName === 'chromium')
executables.push(registry.findExecutable('ffmpeg')!);
};
for (const arg of args) {
if (arg === 'chromium') {
if (!options.onlyShell)
handleArgument('chromium');
if (!options.noShell)
handleArgument('chromium-headless-shell');
} else {
handleArgument(arg);
}
}
if (faultyArguments.length)
throw new Error(`Invalid installation targets: ${faultyArguments.map(name => `'${name}'`).join(', ')}. Expecting one of: ${suggestedBrowsersToInstall()}`);
return executables;
@ -118,7 +144,12 @@ program
.option('--with-deps', 'install system dependencies for browsers')
.option('--dry-run', 'do not execute installation, only print information')
.option('--force', 'force reinstall of stable browser channels')
.action(async function(args: string[], options: { withDeps?: boolean, force?: boolean, dryRun?: boolean }) {
.option('--only-shell', 'only install headless shell when installing chromium')
.option('--no-shell', 'do not install chromium headless shell')
.action(async function(args: string[], options: { withDeps?: boolean, force?: boolean, dryRun?: boolean, shell?: boolean, noShell?: boolean, onlyShell?: boolean }) {
// For '--no-shell' option, commander sets `shell: false` instead.
if (options.shell === false)
options.noShell = true;
if (isLikelyNpxGlobal()) {
console.error(wrapInASCIIBox([
`WARNING: It looks like you are running 'npx playwright install' without first`,
@ -141,7 +172,7 @@ program
}
try {
const hasNoArguments = !args.length;
const executables = hasNoArguments ? registry.defaultExecutables() : checkBrowsersToInstall(args);
const executables = hasNoArguments ? defaultBrowsersToInstall(options) : checkBrowsersToInstall(args, options);
if (options.withDeps)
await registry.installDeps(executables, !!options.dryRun);
if (options.dryRun) {
@ -199,9 +230,9 @@ program
.action(async function(args: string[], options: { dryRun?: boolean }) {
try {
if (!args.length)
await registry.installDeps(registry.defaultExecutables(), !!options.dryRun);
await registry.installDeps(defaultBrowsersToInstall({}), !!options.dryRun);
else
await registry.installDeps(checkBrowsersToInstall(args), !!options.dryRun);
await registry.installDeps(checkBrowsersToInstall(args, {}), !!options.dryRun);
} catch (e) {
console.log(`Failed to install browser dependencies\n${e}`);
gracefullyProcessExitDoNotHang(1);

Просмотреть файл

@ -19,7 +19,6 @@ export {
registry,
registryDirectory,
Registry,
installDefaultBrowsersForNpmInstall,
installBrowsersForNpmInstall,
writeDockerVersion } from './registry';

Просмотреть файл

@ -79,7 +79,7 @@ const EXECUTABLE_PATHS = {
};
type DownloadPaths = Record<HostPlatform, string | undefined>;
const DOWNLOAD_PATHS: Record<BrowserName | InternalTool | 'chromium-headless-shell', DownloadPaths> = {
const DOWNLOAD_PATHS: Record<BrowserName | InternalTool, DownloadPaths> = {
'chromium': {
'<unknown>': undefined,
'ubuntu18.04-x64': undefined,
@ -403,9 +403,9 @@ function readDescriptors(browsersJSON: BrowsersJSON): BrowsersJSONDescriptor[] {
}
export type BrowserName = 'chromium' | 'firefox' | 'webkit' | 'bidi';
type InternalTool = 'ffmpeg' | 'firefox-beta' | 'chromium-tip-of-tree' | 'android';
type InternalTool = 'ffmpeg' | 'firefox-beta' | 'chromium-tip-of-tree' | 'chromium-headless-shell' | 'android';
type BidiChannel = 'bidi-firefox-stable' | 'bidi-firefox-beta' | 'bidi-firefox-nightly' | 'bidi-chrome-canary' | 'bidi-chrome-stable' | 'bidi-chromium';
type ChromiumChannel = 'chrome' | 'chrome-beta' | 'chrome-dev' | 'chrome-canary' | 'chromium-headless-shell' | 'chromium-next' | 'msedge' | 'msedge-beta' | 'msedge-dev' | 'msedge-canary';
type ChromiumChannel = 'chrome' | 'chrome-beta' | 'chrome-dev' | 'chrome-canary' | 'msedge' | 'msedge-beta' | 'msedge-dev' | 'msedge-canary';
const allDownloadable = ['android', 'chromium', 'firefox', 'webkit', 'ffmpeg', 'firefox-beta', 'chromium-tip-of-tree', 'chromium-headless-shell'];
export interface Executable {
@ -488,21 +488,6 @@ export class Registry {
_dependencyGroup: 'chromium',
_isHermeticInstallation: true,
});
this._executables.push({
type: 'channel',
name: 'chromium-next',
browserName: 'chromium',
directory: chromium.dir,
executablePath: () => chromiumExecutable,
executablePathOrDie: (sdkLanguage: string) => executablePathOrDie('chromium-next', chromiumExecutable, chromium.installByDefault, sdkLanguage),
installType: 'download-on-demand',
_validateHostRequirements: (sdkLanguage: string) => this._validateHostRequirements(sdkLanguage, chromium.dir, ['chrome-linux'], [], ['chrome-win']),
downloadURLs: this._downloadURLs(chromium),
browserVersion: chromium.browserVersion,
_install: () => this._downloadExecutable(chromium, chromiumExecutable),
_dependencyGroup: 'chromium',
_isHermeticInstallation: true,
});
const chromiumHeadlessShell = descriptors.find(d => d.name === 'chromium-headless-shell')!;
const chromiumHeadlessShellExecutable = findExecutablePath(chromiumHeadlessShell.dir, 'chromium-headless-shell');
@ -512,7 +497,7 @@ export class Registry {
browserName: 'chromium',
directory: chromiumHeadlessShell.dir,
executablePath: () => chromiumHeadlessShellExecutable,
executablePathOrDie: (sdkLanguage: string) => executablePathOrDie('chromium-headless-shell', chromiumHeadlessShellExecutable, false, sdkLanguage),
executablePathOrDie: (sdkLanguage: string) => executablePathOrDie('chromium', chromiumHeadlessShellExecutable, chromiumHeadlessShell.installByDefault, sdkLanguage),
installType: chromiumHeadlessShell.installByDefault ? 'download-by-default' : 'download-on-demand',
_validateHostRequirements: (sdkLanguage: string) => this._validateHostRequirements(sdkLanguage, chromiumHeadlessShell.dir, ['chrome-linux'], [], ['chrome-win']),
downloadURLs: this._downloadURLs(chromiumHeadlessShell),
@ -894,16 +879,8 @@ export class Registry {
return this._executables.filter(e => e.installType === 'download-by-default');
}
private _addRequirementsAndDedupe(executables: Executable[]): ExecutableImpl[] {
const set = new Set<ExecutableImpl>();
for (const executable of executables as ExecutableImpl[]) {
set.add(executable);
if (executable.browserName === 'chromium')
set.add(this.findExecutable('ffmpeg')!);
if (executable.name === 'chromium')
set.add(this.findExecutable('chromium-headless-shell')!);
}
return Array.from(set);
private _dedupe(executables: Executable[]): ExecutableImpl[] {
return Array.from(new Set(executables as ExecutableImpl[]));
}
private async _validateHostRequirements(sdkLanguage: string, browserDirectory: string, linuxLddDirectories: string[], dlOpenLibraries: string[], windowsExeAndDllDirectories: string[]) {
@ -914,7 +891,7 @@ export class Registry {
}
async installDeps(executablesToInstallDeps: Executable[], dryRun: boolean) {
const executables = this._addRequirementsAndDedupe(executablesToInstallDeps);
const executables = this._dedupe(executablesToInstallDeps);
const targets = new Set<DependencyGroup>();
for (const executable of executables) {
if (executable._dependencyGroup)
@ -928,7 +905,7 @@ export class Registry {
}
async install(executablesToInstall: Executable[], forceReinstall: boolean) {
const executables = this._addRequirementsAndDedupe(executablesToInstall);
const executables = this._dedupe(executablesToInstall);
await fs.promises.mkdir(registryDirectory, { recursive: true });
const lockfilePath = path.join(registryDirectory, '__dirlock');
const linksDir = path.join(registryDirectory, '.links');
@ -1224,11 +1201,6 @@ export function buildPlaywrightCLICommand(sdkLanguage: string, parameters: strin
}
}
export async function installDefaultBrowsersForNpmInstall() {
const defaultBrowserNames = registry.defaultExecutables().map(e => e.name);
return installBrowsersForNpmInstall(defaultBrowserNames);
}
export async function installBrowsersForNpmInstall(browsers: string[]) {
// PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD should have a value of 0 or 1
if (getAsBooleanFromENV('PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD')) {

Просмотреть файл

@ -35,6 +35,7 @@ export type BrowserTestWorkerFixtures = PageWorkerFixtures & {
browserType: BrowserType;
isAndroid: boolean;
isElectron: boolean;
isHeadlessShell: boolean;
nodeVersion: { major: number, minor: number, patch: number };
bidiTestSkipPredicate: (info: TestInfo) => boolean;
};
@ -97,6 +98,10 @@ const test = baseTest.extend<BrowserTestTestFixtures, BrowserTestWorkerFixtures>
electronMajorVersion: [0, { scope: 'worker' }],
isWebView2: [false, { scope: 'worker' }],
isHeadlessShell: [async ({ browserName, channel, headless }, use) => {
await use(browserName === 'chromium' && (channel === 'chromium-headless-shell' || (!channel && headless)));
}, { scope: 'worker' }],
contextFactory: async ({ _contextFactory }: any, run) => {
await run(_contextFactory);
},

Просмотреть файл

@ -76,15 +76,24 @@ test(`playwright should work`, async ({ exec, installedSoftwareOnDisk }) => {
await exec('node esm-playwright.mjs');
});
test(`playwright should work with chromium-next`, async ({ exec, installedSoftwareOnDisk }) => {
test(`playwright should work with chromium --no-shell`, async ({ exec, installedSoftwareOnDisk }) => {
const result1 = await exec('npm i --foreground-scripts playwright');
expect(result1).toHaveLoggedSoftwareDownload([]);
expect(await installedSoftwareOnDisk()).toEqual([]);
const result2 = await exec('npx playwright install chromium-next');
const result2 = await exec('npx playwright install chromium --no-shell');
expect(result2).toHaveLoggedSoftwareDownload(['chromium', 'ffmpeg']);
expect(await installedSoftwareOnDisk()).toEqual(['chromium', 'ffmpeg']);
});
test(`playwright should work with chromium --only-shell`, async ({ exec, installedSoftwareOnDisk }) => {
const result1 = await exec('npm i --foreground-scripts playwright');
expect(result1).toHaveLoggedSoftwareDownload([]);
expect(await installedSoftwareOnDisk()).toEqual([]);
const result2 = await exec('npx playwright install --only-shell');
expect(result2).toHaveLoggedSoftwareDownload(['chromium-headless-shell', 'ffmpeg', 'firefox', 'webkit']);
expect(await installedSoftwareOnDisk()).toEqual(['chromium-headless-shell', 'ffmpeg', 'firefox', 'webkit']);
});
test('@playwright/test should work', async ({ exec, installedSoftwareOnDisk }) => {
const result1 = await exec('npm i --foreground-scripts @playwright/test');
expect(result1).toHaveLoggedSoftwareDownload([]);

Просмотреть файл

@ -18,8 +18,7 @@
import { browserTest as base, expect } from '../config/browserTest';
const it = base.extend<{ failsOn401: boolean }>({
failsOn401: async ({ browserName, headless, channel }, use) => {
const isHeadlessShell = channel === 'chromium-headless-shell' || (!channel && headless);
failsOn401: async ({ browserName, isHeadlessShell }, use) => {
await use(browserName === 'chromium' && !isHeadlessShell);
},
});

Просмотреть файл

@ -52,8 +52,7 @@ it('should open devtools when "devtools: true" option is given', async ({ browse
await browser.close();
});
it('should return background pages', async ({ browserType, createUserDataDir, asset, headless, channel }) => {
const isHeadlessShell = channel === 'chromium-headless-shell' || (!channel && headless);
it('should return background pages', async ({ browserType, createUserDataDir, asset, isHeadlessShell }) => {
it.skip(isHeadlessShell, 'Headless Shell has no support for extensions');
const userDataDir = await createUserDataDir();
@ -78,8 +77,7 @@ it('should return background pages', async ({ browserType, createUserDataDir, as
expect(context.backgroundPages().length).toBe(0);
});
it('should return background pages when recording video', async ({ browserType, createUserDataDir, asset, headless, channel }, testInfo) => {
const isHeadlessShell = channel === 'chromium-headless-shell' || (!channel && headless);
it('should return background pages when recording video', async ({ browserType, createUserDataDir, asset, isHeadlessShell }, testInfo) => {
it.skip(isHeadlessShell, 'Headless Shell has no support for extensions');
const userDataDir = await createUserDataDir();
@ -105,8 +103,7 @@ it('should return background pages when recording video', async ({ browserType,
await context.close();
});
it('should support request/response events when using backgroundPage()', async ({ browserType, createUserDataDir, asset, server, headless, channel }) => {
const isHeadlessShell = channel === 'chromium-headless-shell' || (!channel && headless);
it('should support request/response events when using backgroundPage()', async ({ browserType, createUserDataDir, asset, server, isHeadlessShell }) => {
it.skip(isHeadlessShell, 'Headless Shell has no support for extensions');
server.setRoute('/empty.html', (req, res) => {
@ -157,8 +154,7 @@ it('should support request/response events when using backgroundPage()', async (
it('should report console messages from content script', {
annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/32762' }
}, async ({ browserType, createUserDataDir, asset, server, headless, channel }) => {
const isHeadlessShell = channel === 'chromium-headless-shell' || (!channel && headless);
}, async ({ browserType, createUserDataDir, asset, server, isHeadlessShell }) => {
it.skip(isHeadlessShell, 'Headless Shell has no support for extensions');
const userDataDir = await createUserDataDir();

Просмотреть файл

@ -636,8 +636,7 @@ it('should be able to download a inline PDF file via response interception', asy
await page.close();
});
it('should be able to download a inline PDF file via navigation', async ({ browser, server, asset, browserName, channel, headless }) => {
const isHeadlessShell = channel === 'chromium-headless-shell' || (!channel && headless);
it('should be able to download a inline PDF file via navigation', async ({ browser, server, asset, browserName, isHeadlessShell }) => {
it.skip(browserName === 'chromium' && !isHeadlessShell, 'We expect PDF Viewer to open up in headed Chromium');
const page = await browser.newPage();

Просмотреть файл

@ -101,10 +101,9 @@ it('should change document.activeElement', async ({ page, server }) => {
expect(active).toEqual(['INPUT', 'TEXTAREA']);
});
it('should not affect screenshots', async ({ page, server, browserName, headless, isWindows, channel }) => {
it('should not affect screenshots', async ({ page, server, browserName, headless, isWindows, isHeadlessShell }) => {
it.skip(browserName === 'webkit' && isWindows && !headless, 'WebKit/Windows/headed has a larger minimal viewport. See https://github.com/microsoft/playwright/issues/22616');
it.skip(browserName === 'firefox' && !headless, 'Firefox headed produces a different image');
const isHeadlessShell = channel === 'chromium-headless-shell' || (!channel && headless);
it.fixme(browserName === 'chromium' && !isHeadlessShell, 'https://github.com/microsoft/playwright/issues/33330');
const page2 = await page.context().newPage();

Просмотреть файл

@ -145,7 +145,7 @@ it.describe('permissions', () => {
});
});
it('should support clipboard read', async ({ page, context, server, browserName, isWindows, isLinux, headless, channel }) => {
it('should support clipboard read', async ({ page, context, server, browserName, isWindows, isLinux, headless, isHeadlessShell }) => {
it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/27475' });
it.fail(browserName === 'firefox', 'No such permissions (requires flag) in Firefox');
it.fixme(browserName === 'webkit' && isWindows, 'WebPasteboardProxy::allPasteboardItemInfo not implemented for Windows.');
@ -156,8 +156,7 @@ it('should support clipboard read', async ({ page, context, server, browserName,
if (browserName !== 'webkit')
expect(await getPermission(page, 'clipboard-read')).toBe('prompt');
const isHeadlessShell = channel === 'chromium-headless-shell' || (!channel && headless);
if (browserName === 'chromium' && isHeadlessShell) {
if (isHeadlessShell) {
// Chromium (but not headless-shell) shows a dialog and does not resolve the promise.
const error = await page.evaluate(() => navigator.clipboard.readText()).catch(e => e);
expect(error.toString()).toContain('denied');

Просмотреть файл

@ -22,8 +22,7 @@ import { verifyViewport } from '../config/utils';
browserTest.describe('page screenshot', () => {
browserTest.skip(({ browserName, headless }) => browserName === 'firefox' && !headless, 'Firefox headed produces a different image.');
browserTest('should run in parallel in multiple pages', async ({ server, contextFactory, browserName, headless, channel }) => {
const isHeadlessShell = channel === 'chromium-headless-shell' || (!channel && headless);
browserTest('should run in parallel in multiple pages', async ({ server, contextFactory, browserName, isHeadlessShell }) => {
browserTest.fixme(browserName === 'chromium' && !isHeadlessShell, 'https://github.com/microsoft/playwright/issues/33330');
const context = await contextFactory();

Просмотреть файл

@ -429,8 +429,7 @@ for (const params of [
height: 768,
}
]) {
browserTest(`should produce screencast frames ${params.id}`, async ({ video, contextFactory, browserName, platform, headless, channel }, testInfo) => {
const isHeadlessShell = channel === 'chromium-headless-shell' || (!channel && headless);
browserTest(`should produce screencast frames ${params.id}`, async ({ video, contextFactory, browserName, platform, headless, isHeadlessShell }, testInfo) => {
browserTest.skip(browserName === 'chromium' && video === 'on', 'Same screencast resolution conflicts');
browserTest.fixme(browserName === 'chromium' && !isHeadlessShell, 'Chromium (but not headless-shell) screencast has a min width issue');
browserTest.fixme(params.id === 'fit' && browserName === 'chromium' && platform === 'darwin', 'High DPI maxes image at 600x600');

Просмотреть файл

@ -473,9 +473,8 @@ it.describe('screencast', () => {
expect(videoFiles.length).toBe(2);
});
it('should scale frames down to the requested size ', async ({ browser, browserName, server, headless, channel }, testInfo) => {
it('should scale frames down to the requested size ', async ({ browser, browserName, server, headless, isHeadlessShell }, testInfo) => {
it.fixme(!headless, 'Fails on headed');
const isHeadlessShell = channel === 'chromium-headless-shell' || (!channel && headless);
it.fixme(browserName === 'chromium' && !isHeadlessShell, 'Chromium (but not headless shell) has a min width issue');
const context = await browser.newContext({
@ -723,9 +722,8 @@ it.describe('screencast', () => {
expect(files.length).toBe(1);
});
it('should capture full viewport', async ({ browserType, browserName, isWindows, headless, channel }, testInfo) => {
it('should capture full viewport', async ({ browserType, browserName, isWindows, headless, isHeadlessShell }, testInfo) => {
it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/22411' });
const isHeadlessShell = channel === 'chromium-headless-shell' || (!channel && headless);
it.fixme(browserName === 'chromium' && !isHeadlessShell, 'The square is not on the video');
it.fixme(browserName === 'firefox' && isWindows, 'https://github.com/microsoft/playwright/issues/14405');
const size = { width: 600, height: 400 };
@ -759,9 +757,8 @@ it.describe('screencast', () => {
expectAll(pixels, almostRed);
});
it('should capture full viewport on hidpi', async ({ browserType, browserName, headless, isWindows, isLinux, channel }, testInfo) => {
it('should capture full viewport on hidpi', async ({ browserType, browserName, headless, isWindows, isLinux, isHeadlessShell }, testInfo) => {
it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/22411' });
const isHeadlessShell = channel === 'chromium-headless-shell' || (!channel && headless);
it.fixme(browserName === 'chromium' && !isHeadlessShell, 'The square is not on the video');
it.fixme(browserName === 'firefox' && isWindows, 'https://github.com/microsoft/playwright/issues/14405');
it.fixme(browserName === 'webkit' && isLinux && !headless, 'https://github.com/microsoft/playwright/issues/22617');
@ -797,10 +794,9 @@ it.describe('screencast', () => {
expectAll(pixels, almostRed);
});
it('should work with video+trace', async ({ browser, trace, headless, browserName, channel }, testInfo) => {
it('should work with video+trace', async ({ browser, trace, headless, browserName, isHeadlessShell }, testInfo) => {
it.skip(trace === 'on');
it.fixme(!headless, 'different trace screencast image size on all browsers');
const isHeadlessShell = channel === 'chromium-headless-shell' || (!channel && headless);
it.fixme(browserName === 'chromium' && !isHeadlessShell, 'different trace screencast image size');
const size = { width: 500, height: 400 };