From 82f6c15e6a443e6d7ce043c7129d184e101939b6 Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Mon, 4 Nov 2024 03:56:00 -0800 Subject: [PATCH] feat(chromium): switch to headless=new by default (#33262) Co-authored-by: Max Schmitt --- .github/workflows/tests_secondary.yml | 17 ----------- .../src/server/bidi/bidiChromium.ts | 5 +--- .../src/server/chromium/chromium.ts | 5 +--- .../browsercontext-credentials.spec.ts | 29 +++++++------------ tests/library/download.spec.ts | 4 +-- tests/library/emulation-focus.spec.ts | 4 ++- tests/library/permissions.spec.ts | 7 ++--- tests/library/playwright.config.ts | 8 +---- tests/library/screenshot.spec.ts | 4 ++- tests/library/tracing.spec.ts | 4 +-- tests/library/video.spec.ts | 19 ++++++------ tests/page/page-focus.spec.ts | 10 +++---- 12 files changed, 41 insertions(+), 75 deletions(-) diff --git a/.github/workflows/tests_secondary.yml b/.github/workflows/tests_secondary.yml index 71c7ed105f..6f47843edf 100644 --- a/.github/workflows/tests_secondary.yml +++ b/.github/workflows/tests_secondary.yml @@ -268,23 +268,6 @@ jobs: - run: npx playwright install-deps - run: utils/build/build-playwright-driver.sh - test_linux_chromium_headless_new: - name: Linux Chromium Headless New - environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }} - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: ./.github/actions/run-test - with: - browsers-to-install: chromium - command: npm run ctest - bot-name: "headless-new" - 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: - PLAYWRIGHT_CHROMIUM_USE_HEADLESS_NEW: 1 - test_linux_chromium_headless_shell: name: Chromium Headless Shell environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }} diff --git a/packages/playwright-core/src/server/bidi/bidiChromium.ts b/packages/playwright-core/src/server/bidi/bidiChromium.ts index 32751bd51a..9572ac71ed 100644 --- a/packages/playwright-core/src/server/bidi/bidiChromium.ts +++ b/packages/playwright-core/src/server/bidi/bidiChromium.ts @@ -112,10 +112,7 @@ export class BidiChromium extends BrowserType { if (options.devtools) chromeArguments.push('--auto-open-devtools-for-tabs'); if (options.headless) { - if (process.env.PLAYWRIGHT_CHROMIUM_USE_HEADLESS_NEW) - chromeArguments.push('--headless=new'); - else - chromeArguments.push('--headless=old'); + chromeArguments.push('--headless'); chromeArguments.push( '--hide-scrollbars', diff --git a/packages/playwright-core/src/server/chromium/chromium.ts b/packages/playwright-core/src/server/chromium/chromium.ts index 023ee0b7d1..2bae0eaf5a 100644 --- a/packages/playwright-core/src/server/chromium/chromium.ts +++ b/packages/playwright-core/src/server/chromium/chromium.ts @@ -309,10 +309,7 @@ export class Chromium extends BrowserType { if (options.devtools) chromeArguments.push('--auto-open-devtools-for-tabs'); if (options.headless) { - if (process.env.PLAYWRIGHT_CHROMIUM_USE_HEADLESS_NEW) - chromeArguments.push('--headless=new'); - else - chromeArguments.push('--headless=old'); + chromeArguments.push('--headless'); chromeArguments.push( '--hide-scrollbars', diff --git a/tests/library/browsercontext-credentials.spec.ts b/tests/library/browsercontext-credentials.spec.ts index 7783b65aea..c061ffb067 100644 --- a/tests/library/browsercontext-credentials.spec.ts +++ b/tests/library/browsercontext-credentials.spec.ts @@ -15,33 +15,26 @@ * limitations under the License. */ -import { browserTest as base, expect } from '../config/browserTest'; +import { browserTest as it, expect } from '../config/browserTest'; -const it = base.extend<{ isChromiumHeadedLike: boolean }>({ - isChromiumHeadedLike: async ({ browserName, headless }, use) => { - const isChromiumHeadedLike = browserName === 'chromium' && (!headless || !!process.env.PLAYWRIGHT_CHROMIUM_USE_HEADLESS_NEW); - await use(isChromiumHeadedLike); - }, -}); - -it('should fail without credentials', async ({ browser, server, isChromiumHeadedLike }) => { +it('should fail without credentials', async ({ browser, server, browserName, channel }) => { server.setAuth('/empty.html', 'user', 'pass'); const context = await browser.newContext(); const page = await context.newPage(); const responseOrError = await page.goto(server.EMPTY_PAGE).catch(e => e); - if (isChromiumHeadedLike) + if (browserName === 'chromium' && channel !== 'chromium-headless-shell') expect(responseOrError.message).toContain('net::ERR_INVALID_AUTH_CREDENTIALS'); else expect(responseOrError.status()).toBe(401); }); -it('should work with setHTTPCredentials', async ({ browser, server, isChromiumHeadedLike }) => { +it('should work with setHTTPCredentials', async ({ browser, server, browserName, channel }) => { server.setAuth('/empty.html', 'user', 'pass'); const context = await browser.newContext(); const page = await context.newPage(); let responseOrError = await page.goto(server.EMPTY_PAGE).catch(e => e); - if (isChromiumHeadedLike) + if (browserName === 'chromium' && channel !== 'chromium-headless-shell') expect(responseOrError.message).toContain('net::ERR_INVALID_AUTH_CREDENTIALS'); else expect(responseOrError.status()).toBe(401); @@ -109,21 +102,21 @@ it('should work with correct credentials and matching origin case insensitive', await context.close(); }); -it('should fail with correct credentials and mismatching scheme', async ({ browser, server, isChromiumHeadedLike }) => { +it('should fail with correct credentials and mismatching scheme', async ({ browser, server, browserName, channel }) => { server.setAuth('/empty.html', 'user', 'pass'); const context = await browser.newContext({ httpCredentials: { username: 'user', password: 'pass', origin: server.PREFIX.replace('http://', 'https://') } }); const page = await context.newPage(); const responseOrError = await page.goto(server.EMPTY_PAGE).catch(e => e); - if (isChromiumHeadedLike) + if (browserName === 'chromium' && channel !== 'chromium-headless-shell') expect(responseOrError.message).toContain('net::ERR_INVALID_AUTH_CREDENTIALS'); else expect(responseOrError.status()).toBe(401); await context.close(); }); -it('should fail with correct credentials and mismatching hostname', async ({ browser, server, isChromiumHeadedLike }) => { +it('should fail with correct credentials and mismatching hostname', async ({ browser, server, browserName, channel }) => { server.setAuth('/empty.html', 'user', 'pass'); const hostname = new URL(server.PREFIX).hostname; const origin = server.PREFIX.replace(hostname, 'mismatching-hostname'); @@ -132,14 +125,14 @@ it('should fail with correct credentials and mismatching hostname', async ({ bro }); const page = await context.newPage(); const responseOrError = await page.goto(server.EMPTY_PAGE).catch(e => e); - if (isChromiumHeadedLike) + if (browserName === 'chromium' && channel !== 'chromium-headless-shell') expect(responseOrError.message).toContain('net::ERR_INVALID_AUTH_CREDENTIALS'); else expect(responseOrError.status()).toBe(401); await context.close(); }); -it('should fail with correct credentials and mismatching port', async ({ browser, server, isChromiumHeadedLike }) => { +it('should fail with correct credentials and mismatching port', async ({ browser, server, browserName, channel }) => { server.setAuth('/empty.html', 'user', 'pass'); const origin = server.PREFIX.replace(server.PORT.toString(), (server.PORT + 1).toString()); const context = await browser.newContext({ @@ -147,7 +140,7 @@ it('should fail with correct credentials and mismatching port', async ({ browser }); const page = await context.newPage(); const responseOrError = await page.goto(server.EMPTY_PAGE).catch(e => e); - if (isChromiumHeadedLike) + if (browserName === 'chromium' && channel !== 'chromium-headless-shell') expect(responseOrError.message).toContain('net::ERR_INVALID_AUTH_CREDENTIALS'); else expect(responseOrError.status()).toBe(401); diff --git a/tests/library/download.spec.ts b/tests/library/download.spec.ts index 33e33f21b4..74b008c51b 100644 --- a/tests/library/download.spec.ts +++ b/tests/library/download.spec.ts @@ -636,8 +636,8 @@ 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, headless }) => { - it.fixme(((!headless || !!process.env.PLAYWRIGHT_CHROMIUM_USE_HEADLESS_NEW) && browserName === 'chromium')); +it('should be able to download a inline PDF file via navigation', async ({ browser, server, asset, browserName, channel }) => { + it.skip(browserName === 'chromium' && channel !== 'chromium-headless-shell', 'We expect PDF Viewer to open up in Chromium'); const page = await browser.newPage(); await page.goto(server.EMPTY_PAGE); await page.setContent(` diff --git a/tests/library/emulation-focus.spec.ts b/tests/library/emulation-focus.spec.ts index 5f6b5b741f..e9a0480a67 100644 --- a/tests/library/emulation-focus.spec.ts +++ b/tests/library/emulation-focus.spec.ts @@ -101,9 +101,11 @@ it('should change document.activeElement', async ({ page, server }) => { expect(active).toEqual(['INPUT', 'TEXTAREA']); }); -it('should not affect screenshots', async ({ page, server, browserName, headless, isWindows }) => { +it('should not affect screenshots', async ({ page, server, browserName, headless, isWindows, channel }) => { 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'); + // TODO: We want to see test results + // it.fixme(browserName === 'chromium' && channel !== 'chromium-headless-shell', 'https://github.com/microsoft/playwright/issues/33330'); const page2 = await page.context().newPage(); await Promise.all([ diff --git a/tests/library/permissions.spec.ts b/tests/library/permissions.spec.ts index f9f7fdd7ce..451149878c 100644 --- a/tests/library/permissions.spec.ts +++ b/tests/library/permissions.spec.ts @@ -145,20 +145,19 @@ it.describe('permissions', () => { }); }); -it('should support clipboard read', async ({ page, context, server, browserName, isWindows, isLinux, headless }) => { +it('should support clipboard read', async ({ page, context, server, browserName, isWindows, isLinux, headless, channel }) => { 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.'); it.fixme(browserName === 'webkit' && isLinux && headless, 'WebPasteboardProxy::allPasteboardItemInfo not implemented for WPE.'); - const isChromiumHeadedLike = browserName === 'chromium' && (!headless || !!process.env.PLAYWRIGHT_CHROMIUM_USE_HEADLESS_NEW); await page.goto(server.EMPTY_PAGE); // There is no 'clipboard-read' permission in WebKit Web API. if (browserName !== 'webkit') expect(await getPermission(page, 'clipboard-read')).toBe('prompt'); - if (!isChromiumHeadedLike) { - // Headed Chromium shows a dialog and does not resolve the promise. + if (browserName === 'chromium' && channel === 'chromium-headless-shell') { + // Chromium 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'); } diff --git a/tests/library/playwright.config.ts b/tests/library/playwright.config.ts index 759dc70edc..399eec1b6b 100644 --- a/tests/library/playwright.config.ts +++ b/tests/library/playwright.config.ts @@ -126,13 +126,7 @@ for (const browserName of browserNames) { metadata: { platform: process.platform, docker: !!process.env.INSIDE_DOCKER, - headless: (() => { - if (process.env.PLAYWRIGHT_CHROMIUM_USE_HEADLESS_NEW) - return 'headless-new'; - if (headed) - return 'headed'; - return 'headless'; - })(), + headless: headed ? 'headed' : 'headless', browserName, channel, mode, diff --git a/tests/library/screenshot.spec.ts b/tests/library/screenshot.spec.ts index e8bdac3313..3e0b1921fc 100644 --- a/tests/library/screenshot.spec.ts +++ b/tests/library/screenshot.spec.ts @@ -22,7 +22,9 @@ 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 }) => { + browserTest('should run in parallel in multiple pages', async ({ server, contextFactory, browserName, channel }) => { + // TODO: We want to see test results + // browserTest.fixme(browserName === 'chromium' && channel !== 'chromium-headless-shell', 'https://github.com/microsoft/playwright/issues/33330'); const context = await contextFactory(); const N = 5; const pages = await Promise.all(Array(N).fill(0).map(async () => { diff --git a/tests/library/tracing.spec.ts b/tests/library/tracing.spec.ts index dc077ccd04..b13ed1b84a 100644 --- a/tests/library/tracing.spec.ts +++ b/tests/library/tracing.spec.ts @@ -407,9 +407,9 @@ for (const params of [ height: 768, } ]) { - browserTest(`should produce screencast frames ${params.id}`, async ({ video, contextFactory, browserName, platform, headless }, testInfo) => { + browserTest(`should produce screencast frames ${params.id}`, async ({ video, contextFactory, browserName, platform, headless, channel }, testInfo) => { browserTest.skip(browserName === 'chromium' && video === 'on', 'Same screencast resolution conflicts'); - browserTest.fixme(browserName === 'chromium' && (!headless || !!process.env.PLAYWRIGHT_CHROMIUM_USE_HEADLESS_NEW), 'Chromium screencast on headed has a min width issue'); + browserTest.fixme(browserName === 'chromium' && channel !== 'chromium-headless-shell', 'Chromium screencast has a min width issue'); browserTest.fixme(params.id === 'fit' && browserName === 'chromium' && platform === 'darwin', 'High DPI maxes image at 600x600'); browserTest.fixme(params.id === 'fit' && browserName === 'webkit' && platform === 'linux', 'Image size is flaky'); browserTest.fixme(browserName === 'firefox' && !headless, 'Image size is different'); diff --git a/tests/library/video.spec.ts b/tests/library/video.spec.ts index 39dcaecbc6..c6b8de24fb 100644 --- a/tests/library/video.spec.ts +++ b/tests/library/video.spec.ts @@ -473,9 +473,9 @@ it.describe('screencast', () => { expect(videoFiles.length).toBe(2); }); - it('should scale frames down to the requested size ', async ({ browser, browserName, server, headless, trace }, testInfo) => { - const isChromiumHeadlessNew = browserName === 'chromium' && !!headless && !!process.env.PLAYWRIGHT_CHROMIUM_USE_HEADLESS_NEW; - it.fixme(!headless || isChromiumHeadlessNew, 'Fails on headed'); + it('should scale frames down to the requested size ', async ({ browser, browserName, server, headless, channel }, testInfo) => { + it.fixme(!headless, 'Fails on headed'); + it.fixme(browserName === 'chromium' && channel !== 'chromium-headless-shell', 'Fails on Chromiums'); const context = await browser.newContext({ recordVideo: { @@ -722,9 +722,9 @@ it.describe('screencast', () => { expect(files.length).toBe(1); }); - it('should capture full viewport', async ({ browserType, browserName, headless, isWindows }, testInfo) => { + it('should capture full viewport', async ({ browserType, browserName, isWindows, channel }, testInfo) => { it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/22411' }); - it.fixme(browserName === 'chromium' && (!headless || !!process.env.PLAYWRIGHT_CHROMIUM_USE_HEADLESS_NEW), 'The square is not on the video'); + it.fixme(browserName === 'chromium' && channel !== 'chromium-headless-shell', '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 }; const browser = await browserType.launch(); @@ -757,9 +757,9 @@ it.describe('screencast', () => { expectAll(pixels, almostRed); }); - it('should capture full viewport on hidpi', async ({ browserType, browserName, headless, isWindows, isLinux }, testInfo) => { + it('should capture full viewport on hidpi', async ({ browserType, browserName, headless, isWindows, isLinux, channel }, testInfo) => { it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/22411' }); - it.fixme(browserName === 'chromium' && (!headless || !!process.env.PLAYWRIGHT_CHROMIUM_USE_HEADLESS_NEW), 'The square is not on the video'); + it.fixme(browserName === 'chromium' && channel !== 'chromium-headless-shell', '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'); const size = { width: 600, height: 400 }; @@ -794,9 +794,10 @@ it.describe('screencast', () => { expectAll(pixels, almostRed); }); - it('should work with video+trace', async ({ browser, trace, headless }, testInfo) => { + it('should work with video+trace', async ({ browser, trace, headless, browserName, channel }, testInfo) => { it.skip(trace === 'on'); - it.fixme(!headless || !!process.env.PLAYWRIGHT_CHROMIUM_USE_HEADLESS_NEW, 'different trace screencast image size on all browsers'); + it.fixme(!headless, 'different trace screencast image size on all browsers'); + it.fixme(browserName === 'chromium' && channel !== 'chromium-headless-shell', 'different trace screencast image size on Chromium'); const size = { width: 500, height: 400 }; const traceFile = testInfo.outputPath('trace.zip'); diff --git a/tests/page/page-focus.spec.ts b/tests/page/page-focus.spec.ts index 020526380f..67e3e883b4 100644 --- a/tests/page/page-focus.spec.ts +++ b/tests/page/page-focus.spec.ts @@ -119,9 +119,8 @@ it('clicking checkbox should activate it', async ({ page, browserName, headless, it('tab should cycle between single input and browser', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/32339' } -}, async ({ page, browserName, headless }) => { - it.fixme(browserName === 'chromium' && (!headless || !!process.env.PLAYWRIGHT_CHROMIUM_USE_HEADLESS_NEW), - 'Chromium in headful mode keeps input focused.'); +}, async ({ page, browserName, channel }) => { + it.fixme(browserName === 'chromium' && channel !== 'chromium-headless-shell', 'Chromium keeps input focused.'); it.fixme(browserName !== 'chromium'); await page.setContent(` @@ -147,9 +146,8 @@ it('tab should cycle between single input and browser', { it('tab should cycle between document elements and browser', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/32339' } -}, async ({ page, browserName, headless }) => { - it.fixme(browserName === 'chromium' && (!headless || !!process.env.PLAYWRIGHT_CHROMIUM_USE_HEADLESS_NEW), - 'Chromium in headful mode keeps last input focused.'); +}, async ({ page, browserName, channel }) => { + it.fixme(browserName === 'chromium' && channel !== 'chromium-headless-shell', 'Chromium keeps last input focused.'); it.fixme(browserName !== 'chromium'); await page.setContent(`