From 1308d9aa6a5920b20da02dca8db03c63e43c8b84 Mon Sep 17 00:00:00 2001 From: Alex Rudenko Date: Mon, 25 Apr 2022 13:11:23 +0200 Subject: [PATCH] feat: support chrome headless mode (#8260) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: support chrome headless mode Co-authored-by: Ergün Erdoğmuş --- .github/workflows/main.yml | 36 +++++++++++++++++++++++++++++++++--- docs/api.md | 4 ++-- package.json | 1 + src/node/LaunchOptions.ts | 2 +- src/node/Launcher.ts | 6 +++++- test/mocha-utils.ts | 6 +++--- 6 files changed, 45 insertions(+), 10 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 00779a7b62ffd..f15c876f0a3be 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -201,17 +201,14 @@ jobs: uses: actions/setup-node@v3.1.1 with: node-version: ${{ matrix.node }} - - name: Install dependencies run: | sudo apt-get install xvfb npm install ls .local-chromium - - name: Build run: | npm run build - - name: Run unit tests in headful mode uses: nick-invision/retry@v2 continue-on-error: true @@ -222,3 +219,36 @@ jobs: max_attempts: 1 command: xvfb-run --auto-servernum npm run unit timeout_minutes: 10 + + chrome-headless-checks: + runs-on: ${{ matrix.os }} + strategy: + matrix: + # https://github.com/actions/virtual-environments#available-environments + os: [ubuntu-latest, macos-latest, windows-latest] + node: [16] + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 2 + - name: Set up Node.js + uses: actions/setup-node@v3.1.1 + with: + node-version: ${{ matrix.node }} + - name: Install dependencies + run: | + npm install + ls .local-chromium + - name: Build + run: | + npm run build + - name: Run unit tests + uses: nick-invision/retry@v2 + continue-on-error: true + env: + CHROMIUM: true + with: + max_attempts: 1 + command: npm run chrome-headless-unit + timeout_minutes: 30 diff --git a/docs/api.md b/docs/api.md index b5e2be085d8c4..6e04af656c6cd 100644 --- a/docs/api.md +++ b/docs/api.md @@ -580,7 +580,7 @@ This methods attaches Puppeteer to an existing browser instance. #### puppeteer.defaultArgs([options]) - `options` <[Object]> Set of configurable options to set on the browser. Can have the following fields: - - `headless` <[boolean]> Whether to run browser in [headless mode](https://developers.google.com/web/updates/2017/04/headless-chrome). Defaults to `true` unless the `devtools` option is `true`. + - `headless` <[boolean]|"chrome"> Whether to run browser in [headless mode](https://developers.google.com/web/updates/2017/04/headless-chrome). Defaults to `true` unless the `devtools` option is `true`. "chrome" is a new experimental headless mode (use at your own risk). - `args` <[Array]<[string]>> Additional arguments to pass to the browser instance. The list of Chromium flags can be found [here](http://peter.sh/experiments/chromium-command-line-switches/). - `userDataDir` <[string]> Path to a [User Data Directory](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/user_data_dir.md). - `devtools` <[boolean]> Whether to auto-open a DevTools panel for each tab. If this option is `true`, the `headless` option will be set `false`. @@ -646,7 +646,7 @@ try { - `options` <[Object]> Set of configurable options to set on the browser. Can have the following fields: - `product` <[string]> Which browser to launch. At this time, this is either `chrome` or `firefox`. See also `PUPPETEER_PRODUCT`. - `ignoreHTTPSErrors` <[boolean]> Whether to ignore HTTPS errors during navigation. Defaults to `false`. - - `headless` <[boolean]> Whether to run browser in [headless mode](https://developers.google.com/web/updates/2017/04/headless-chrome). Defaults to `true` unless the `devtools` option is `true`. + - `headless` <[boolean]|"chrome"> Whether to run browser in [headless mode](https://developers.google.com/web/updates/2017/04/headless-chrome). Defaults to `true` unless the `devtools` option is `true`. "chrome" is a new experimental headless mode (use at your own risk). - `channel` <[string]> When specified, Puppeteer will search for the locally installed release channel of Google Chrome and use it to launch. Available values are `chrome`, `chrome-beta`, `chrome-canary`, `chrome-dev`. When channel is specified, `executablePath` cannot be specified. - `executablePath` <[string]> Path to a browser executable to run instead of the bundled Chromium. If `executablePath` is a relative path, then it is resolved relative to [current working directory](https://nodejs.org/api/process.html#process_process_cwd). **BEWARE**: Puppeteer is only [guaranteed to work](https://github.com/puppeteer/puppeteer/#q-why-doesnt-puppeteer-vxxx-work-with-chromium-vyyy) with the bundled Chromium, use at your own risk. - `slowMo` <[number]> Slows down Puppeteer operations by the specified amount of milliseconds. Useful so that you can see what is going on. diff --git a/package.json b/package.json index eb0d4a0a4b2b4..9fdfcc6653a6a 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "test-browser": "wtr", "test-browser-watch": "wtr --watch", "unit": "npm run tsc-cjs && mocha --config mocha-config/puppeteer-unit-tests.js", + "chrome-headless-unit": "cross-env HEADLESS=chrome npm run unit", "unit-debug": "npm run tsc-cjs && mocha --inspect-brk --config mocha-config/puppeteer-unit-tests.js", "unit-with-coverage": "cross-env COVERAGE=1 npm run unit", "assert-unit-coverage": "cross-env COVERAGE=1 mocha --config mocha-config/coverage-tests.js", diff --git a/src/node/LaunchOptions.ts b/src/node/LaunchOptions.ts index 81173b1970625..da9fd650b9246 100644 --- a/src/node/LaunchOptions.ts +++ b/src/node/LaunchOptions.ts @@ -27,7 +27,7 @@ export interface BrowserLaunchArgumentOptions { * Whether to run the browser in headless mode. * @defaultValue true */ - headless?: boolean; + headless?: boolean | 'chrome'; /** * Path to a user data directory. * {@link https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/user_data_dir.md | see the Chromium docs} diff --git a/src/node/Launcher.ts b/src/node/Launcher.ts index 4abae70c734b6..17301d0e07b7e 100644 --- a/src/node/Launcher.ts +++ b/src/node/Launcher.ts @@ -241,7 +241,11 @@ class ChromeLauncher implements ProductLauncher { chromeArguments.push(`--user-data-dir=${path.resolve(userDataDir)}`); if (devtools) chromeArguments.push('--auto-open-devtools-for-tabs'); if (headless) { - chromeArguments.push('--headless', '--hide-scrollbars', '--mute-audio'); + chromeArguments.push( + headless === 'chrome' ? '--headless=chrome' : '--headless', + '--hide-scrollbars', + '--mute-audio' + ); } if (args.every((arg) => arg.startsWith('-'))) chromeArguments.push('about:blank'); diff --git a/test/mocha-utils.ts b/test/mocha-utils.ts index 97909df98f092..abf80397dc279 100644 --- a/test/mocha-utils.ts +++ b/test/mocha-utils.ts @@ -64,8 +64,8 @@ const product = const alternativeInstall = process.env.PUPPETEER_ALT_INSTALL || false; -const isHeadless = - (process.env.HEADLESS || 'true').trim().toLowerCase() === 'true'; +const headless = (process.env.HEADLESS || 'true').trim().toLowerCase(); +const isHeadless = headless === 'true' || headless === 'chrome'; const isFirefox = product === 'firefox'; const isChrome = product === 'Chromium'; @@ -82,7 +82,7 @@ const defaultBrowserOptions = Object.assign( { handleSIGINT: true, executablePath: process.env.BINARY, - headless: isHeadless, + headless: headless === 'chrome' ? ('chrome' as const) : isHeadless, dumpio: !!process.env.DUMPIO, }, extraLaunchOptions