diff --git a/README.md b/README.md index a16559d9..95007756 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,14 @@ In your `package.json` add a new script to invoke the `replay` command: } ``` +Set the `PUPPETEER_HEADLESS` environment variable to control whether the browser is start in a headful or headless mode. For example, + +``` +PUPPETEER_HEADLESS=true npx @puppeteer/replay recording.json # runs in headless mode, the default mode. +PUPPETEER_HEADLESS=false npx @puppeteer/replay recording.json # runs in headful mode. +PUPPETEER_HEADLESS=chrome npx @puppeteer/replay recording.json # runs in the new experimental headless mode. +``` + Using [the replay lib API](/examples/replay-from-file-using-puppeteer/main.js): ```js diff --git a/src/CLIUtils.ts b/src/CLIUtils.ts index ffae9e7c..c723e589 100644 --- a/src/CLIUtils.ts +++ b/src/CLIUtils.ts @@ -16,14 +16,36 @@ import { parse, createRunner } from './main.js'; import { readFileSync } from 'fs'; +import { PuppeteerRunnerOwningBrowserExtension } from './PuppeteerRunnerExtension.js'; export function getFilenames(argv: string[]) { return argv.slice(2); } +export function getHeadlessEnvVar(headless?: string) { + if (!headless) { + return true; + } + switch (headless.toLowerCase()) { + case '1': + case 'true': + return true; + case 'chrome': + return 'chrome'; + case '0': + case 'false': + return false; + default: + throw new Error('PUPPETEER_HEADLESS: unrecognized value'); + } +} + export async function runFiles( files: string[], - opts = { log: false } + opts: { log: boolean; headless: boolean | 'chrome' } = { + log: false, + headless: true, + } ): Promise { for (const file of files) { opts.log && console.log(`Running ${file}...`); @@ -31,7 +53,16 @@ export async function runFiles( const content = readFileSync(file, 'utf-8'); const object = JSON.parse(content); const recording = parse(object); - const runner = await createRunner(recording); + const { default: puppeteer } = await import('puppeteer'); + const browser = await puppeteer.launch({ + headless: opts.headless, + }); + const page = await browser.newPage(); + const extension = new PuppeteerRunnerOwningBrowserExtension( + browser, + page + ); + const runner = await createRunner(recording, extension); await runner.run(); opts.log && console.log(`Finished running ${file}`); } catch (err) { diff --git a/src/cli.ts b/src/cli.ts index 8f1c829a..afea5f75 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -16,12 +16,14 @@ limitations under the License. */ -import { getFilenames, runFiles } from './CLIUtils.js'; +import { getFilenames, getHeadlessEnvVar, runFiles } from './CLIUtils.js'; const recordings = getFilenames(process.argv); if (!recordings.length) { console.log(`Usage: replay filename [filename...]`); } +console.log(process.env.PUPPETEER_HEADLESS); await runFiles(recordings, { log: true, + headless: getHeadlessEnvVar(process.env.PUPPETEER_HEADLESS), }); diff --git a/test/cli_test.ts b/test/cli_test.ts index 688dd230..0a9c5704 100644 --- a/test/cli_test.ts +++ b/test/cli_test.ts @@ -14,7 +14,7 @@ limitations under the License. */ -import { getFilenames, runFiles } from '../src/CLIUtils.js'; +import { getFilenames, runFiles, getHeadlessEnvVar } from '../src/CLIUtils.js'; import { assert } from 'chai'; import path from 'path'; import url from 'url'; @@ -35,6 +35,19 @@ describe('cli', () => { }); }); + describe('getHeadlessEnvVar', () => { + it('extracts the headless parameter from process.argv', () => { + assert.strictEqual(getHeadlessEnvVar(undefined), true); + assert.strictEqual(getHeadlessEnvVar('1'), true); + assert.strictEqual(getHeadlessEnvVar('true'), true); + assert.strictEqual(getHeadlessEnvVar('0'), false); + assert.strictEqual(getHeadlessEnvVar('false'), false); + assert.strictEqual(getHeadlessEnvVar('chrome'), 'chrome'); + assert.strictEqual(getHeadlessEnvVar('True'), true); + assert.strictEqual(getHeadlessEnvVar('False'), false); + }); + }); + describe('runFiles', () => { it('is able to run successfully', async () => { assert.isTrue(