chore: use test runner for installation tests (#9110)

This commit is contained in:
jrandolf 2022-10-14 13:37:07 +02:00 committed by GitHub
parent 6a05d8e9c1
commit 8f4902eed9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 2072 additions and 481 deletions

View File

@ -193,8 +193,8 @@ jobs:
- name: Run all tests
run: xvfb-run --auto-servernum npm run test -- --test-suite ${{ matrix.suite }}
pack-packages:
name: Pack packages
installation-test-build:
name: Build installation test
runs-on: ubuntu-latest
steps:
- name: Checkout
@ -206,19 +206,19 @@ jobs:
node-version: latest
- name: Install dependencies
run: npm ci --ignore-scripts
- name: Build libraries
run: npm run build
- name: Pack libraries
run: npm pack --workspaces
- name: Upload packages
- name: Build installation test
run: npm run build --workspace @puppeteer-test/installation
- name: Pack installation test
run: npm pack --workspace @puppeteer-test/installation
- name: Upload installation test
uses: actions/upload-artifact@v3
with:
name: packages
path: ./*.tgz
name: installation-test
path: puppeteer-test-installation-latest.tgz
install-tests:
name: Test installation on ${{ matrix.os }} (${{ matrix.node }})
needs: pack-packages
installation-test:
name: Test ${{ matrix.pkg_manager }} installation on ${{ matrix.os }} (${{ matrix.node }})
needs: installation-test-build
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
@ -226,24 +226,33 @@ jobs:
os:
- ubuntu-latest
- macos-latest
- windows-latest
node:
- 14
- 16
- 18
pkg_manager:
- npm
- yarn
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Download installation test
uses: actions/download-artifact@v3
with:
name: installation-test
- name: Unpack installation test
run: tar -xf puppeteer-test-installation-latest.tgz --strip-components 1 -C .
- name: Set up Node.js
uses: actions/setup-node@v3.4.1
with:
cache: npm
node-version: ${{ matrix.node }}
- name: Download packages
uses: actions/download-artifact@v3
with:
name: packages
- name: Test bundling and installation
run: npm run test-install
- name: Set up ${{ matrix.pkg_manager }}
run: npm install -g ${{ matrix.pkg_manager }}@latest
- name: Install dependencies
run: ${{ matrix.pkg_manager }} install
- name: Test
env:
PKG_MANAGER: ${{ matrix.pkg_manager }}
run: ${{ matrix.pkg_manager }} test
docker-tests:
name: Test Docker image

View File

@ -40,7 +40,6 @@ yarn-error.log*
## [END] Keep in sync with .gitignore
# Prettier-only ignores.
assets/
CHANGELOG.md
package-lock.json
test/assets/

1665
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -23,7 +23,7 @@
"lint": "run-s lint:prettier lint:eslint",
"postinstall": "npm run postinstall --workspaces --if-present",
"prepare": "husky install",
"test-install": "test/test-install.sh",
"test-install": "npm run test --workspace @puppeteer-test/installation",
"test-types": "tsd -t packages/puppeteer",
"test:chrome:headful": "npm test -- --test-suite chrome-headful",
"test:chrome:headless-chrome": "npm test -- --test-suite chrome-new-headless",
@ -104,6 +104,7 @@
},
"workspaces": [
"packages/*",
"test"
"test",
"test/installation"
]
}

1
packages/puppeteer-core/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
README.md

View File

@ -43,9 +43,18 @@
"format:types": "wireit",
"generate:package-json": "wireit",
"generate:sources": "wireit",
"prepack": "cp ../../README.md ./README.md"
"prepack": "wireit"
},
"wireit": {
"prepack": {
"command": "cp ../../README.md README.md",
"files": [
"../../README.md"
],
"output": [
"README.md"
]
},
"build": {
"dependencies": [
"build:third_party",

View File

@ -198,5 +198,7 @@ export function createLauncher(
return new FirefoxLauncher(preferredRevision, isPuppeteerCore);
case 'chrome':
return new ChromeLauncher(preferredRevision, isPuppeteerCore);
default:
throw new Error(`Unknown product: ${product}`);
}
}

1
packages/puppeteer/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
README.md

View File

@ -42,9 +42,18 @@
"generate:package-json": "wireit",
"generate:sources": "wireit",
"postinstall": "node install.js",
"prepack": "cp ../../README.md ./README.md"
"prepack": "wireit"
},
"wireit": {
"prepack": {
"command": "cp ../../README.md README.md",
"files": [
"../../README.md"
],
"output": [
"README.md"
]
},
"build": {
"dependencies": [
"format:types",

View File

@ -0,0 +1,23 @@
// Copyright 2022 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @type {import('mocha').MochaOptions}
*/
module.exports = {
spec: ['build/**/*.spec.js'],
timeout: '240000ms',
// Parallel processing fails on other package managers due to caching.
parallel: (process.env['PKG_MANAGER'] ?? 'npm') === 'npm',
};

View File

@ -0,0 +1,19 @@
/**
* Copyright 2022 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import 'puppeteer-core';
import 'puppeteer-core/internal/revisions.js';
import 'puppeteer-core/lib/esm/puppeteer/revisions.js';

View File

@ -0,0 +1,32 @@
/**
* Copyright 2022 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import puppeteer from 'puppeteer-core';
(async () => {
try {
await puppeteer.launch({
product: '${product}',
executablePath: 'node',
});
} catch (error) {
if (error.message.includes('Failed to launch the browser process')) {
process.exit(0);
}
console.error(error);
process.exit(1);
}
})();

View File

@ -0,0 +1,19 @@
/**
* Copyright 2022 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
require('puppeteer-core');
require('puppeteer-core/internal/revisions.js');
require('puppeteer-core/lib/cjs/puppeteer/revisions.js');

View File

@ -0,0 +1,25 @@
/**
* Copyright 2022 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import puppeteer from 'puppeteer';
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('http://example.com');
await page.$('aria/example');
await page.screenshot({path: 'example.png'});
await browser.close();
})();

View File

@ -0,0 +1,20 @@
/**
* Copyright 2022 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import 'puppeteer';
// Should still be reachable.
import 'puppeteer-core/internal/revisions.js';

View File

@ -0,0 +1,20 @@
/**
* Copyright 2022 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
require('puppeteer');
// Should still be reachable.
require('puppeteer-core/internal/revisions.js');

View File

@ -0,0 +1,25 @@
/**
* Copyright 2022 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export default {
mode: 'production',
entry: './index.js',
target: 'node',
output: {
path: process.cwd(),
filename: 'bundle.js',
},
};

View File

@ -0,0 +1,50 @@
{
"name": "@puppeteer-test/installation",
"version": "latest",
"type": "module",
"private": true,
"scripts": {
"build": "wireit",
"build:packages": "wireit",
"clean": "tsc -b --clean && rimraf build",
"test": "mocha"
},
"wireit": {
"build": {
"command": "tsc -b",
"clean": "if-file-deleted",
"dependencies": [
"build:packages"
],
"files": [
"tsconfig.json",
"src/**"
],
"output": [
"build/**",
"tsconfig.tsbuildinfo"
]
},
"build:packages": {
"command": "npm pack --workspace puppeteer --workspace puppeteer-core",
"dependencies": [
"../../packages/puppeteer:build",
"../../packages/puppeteer-core:build"
],
"files": [],
"output": [
"puppeteer-*.tgz"
]
}
},
"files": [
".mocharc.cjs",
"puppeteer-*.tgz",
"build",
"assets"
],
"dependencies": {
"glob": "8.0.3",
"mocha": "10.0.0"
}
}

View File

@ -0,0 +1,31 @@
/**
* Copyright 2022 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import glob from 'glob';
import {dirname, join, resolve} from 'path';
import {fileURLToPath} from 'url';
export const PUPPETEER_CORE_PACKAGE_PATH = resolve(
glob.sync('puppeteer-core-*.tgz')[0]!
);
export const PUPPETEER_PACKAGE_PATH = resolve(
glob.sync('puppeteer-[0-9]*.tgz')[0]!
);
export const ASSETS_DIR = join(
dirname(fileURLToPath(import.meta.url)),
'..',
'assets'
);

View File

@ -0,0 +1,156 @@
/**
* Copyright 2022 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import assert from 'assert';
import {createHash} from 'crypto';
import {mkdtemp, rm, writeFile} from 'fs/promises';
import {tmpdir} from 'os';
import {join} from 'path';
import {
PUPPETEER_CORE_PACKAGE_PATH,
PUPPETEER_PACKAGE_PATH,
} from './constants.js';
import {execFile} from './util.js';
const PKG_MANAGER = process.env['PKG_MANAGER'] || 'npm';
let ADD_PKG_SUBCOMMAND = 'install';
if (PKG_MANAGER !== 'npm') {
ADD_PKG_SUBCOMMAND = 'add';
}
export interface ItEvaluatesOptions {
commonjs?: boolean;
}
export interface ItEvaluatesFn {
(
title: string,
options: ItEvaluatesOptions,
getScriptContent: (cwd: string) => Promise<string>
): void;
(title: string, getScriptContent: (cwd: string) => Promise<string>): void;
}
export interface DescribeInstallationOptions {
dependencies?: string[];
devDependencies?: string[];
/**
* This should be idempotent.
*/
env?: ((cwd: string) => NodeJS.ProcessEnv) | NodeJS.ProcessEnv;
}
export interface DescribeInstallationContext {
itEvaluates: ItEvaluatesFn;
}
export const describeInstallation = (
title: string,
options: DescribeInstallationOptions,
fn: (context: DescribeInstallationContext) => void
): Mocha.Suite => {
return describe(`${title} installation`, () => {
let sandbox: string;
let dependencies: string[];
let devDependencies: string[];
let env: NodeJS.ProcessEnv;
before(async () => {
sandbox = await mkdtemp(join(tmpdir(), 'puppeteer-'));
dependencies = (options.dependencies ?? []).map(module => {
switch (module) {
case 'puppeteer':
return PUPPETEER_PACKAGE_PATH;
case 'puppeteer-core':
return PUPPETEER_CORE_PACKAGE_PATH;
default:
return module;
}
});
devDependencies = options.devDependencies ?? [];
let getEnv: (cwd: string) => NodeJS.ProcessEnv | undefined;
if (typeof options.env === 'function') {
getEnv = options.env;
} else {
const env = options.env;
getEnv = () => {
return env;
};
}
env = {...process.env, ...getEnv(sandbox)};
});
after(async () => {
if (process.env['KEEP_SANDBOX']) {
await rm(sandbox, {recursive: true, force: true});
}
});
it(`should install ${title}`, async () => {
if (dependencies.length > 0) {
await execFile(PKG_MANAGER, [ADD_PKG_SUBCOMMAND, ...dependencies], {
cwd: sandbox,
env,
shell: true,
});
}
if (devDependencies.length > 0) {
await execFile(
PKG_MANAGER,
[ADD_PKG_SUBCOMMAND, '-D', ...devDependencies],
{
cwd: sandbox,
env,
shell: true,
}
);
}
});
const itEvaluates = (
title: string,
options: ItEvaluatesOptions | ((cwd: string) => Promise<string>),
getScriptContent?: (cwd: string) => Promise<string>
): Mocha.Test => {
let evaluateOptions: ItEvaluatesOptions;
if (typeof options === 'function') {
evaluateOptions = {};
getScriptContent = options;
} else {
evaluateOptions = options;
}
return it(`should evaluate ${title}`, async () => {
const script = join(
sandbox,
`script-${createHash('sha1').update(title, 'utf8').digest('hex')}.${
evaluateOptions.commonjs ? 'cjs' : 'mjs'
}`
);
assert.ok(
getScriptContent,
'Expected `getScriptContent` to be defined'
);
await writeFile(script, await getScriptContent(sandbox));
await execFile('node', [script], {cwd: sandbox, env});
});
};
fn({itEvaluates});
});
};

View File

@ -0,0 +1,44 @@
/**
* Copyright 2022 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {describeInstallation} from './describeInstallation.js';
import {readAsset} from './util.js';
describeInstallation(
'`puppeteer-core`',
{dependencies: ['puppeteer-core']},
({itEvaluates}) => {
itEvaluates('CommonJS', {commonjs: true}, async () => {
return readAsset('puppeteer-core', 'requires.cjs');
});
itEvaluates('ES modules', async () => {
return readAsset('puppeteer-core', 'imports.js');
});
for (const product of ['firefox', 'chrome']) {
itEvaluates(
`\`launch\` for \`${product}\` with a bad \`executablePath\``,
async () => {
return (await readAsset('puppeteer-core', 'launch.js')).replace(
'${product}',
product
);
}
);
}
}
);

View File

@ -0,0 +1,47 @@
/**
* Copyright 2022 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import assert from 'assert';
import {readdir} from 'fs/promises';
import {join} from 'path';
import {describeInstallation} from './describeInstallation.js';
import {readAsset} from './util.js';
describeInstallation(
'`puppeteer` with Firefox',
{
dependencies: ['puppeteer-core', 'puppeteer'],
env: cwd => {
return {
PUPPETEER_CACHE_DIR: join(cwd, '.cache', 'puppeteer'),
PUPPETEER_PRODUCT: 'firefox',
};
},
},
({itEvaluates}) => {
itEvaluates('CommonJS', {commonjs: true}, async cwd => {
const files = await readdir(join(cwd, '.cache', 'puppeteer'));
assert.equal(files.length, 1);
assert.equal(files[0], 'firefox');
return readAsset('puppeteer-core', 'requires.cjs');
});
itEvaluates('ES modules', async () => {
return readAsset('puppeteer-core', 'imports.js');
});
}
);

View File

@ -0,0 +1,57 @@
/**
* Copyright 2022 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {readFile, rm, writeFile} from 'fs/promises';
import {join} from 'path';
import {describeInstallation} from './describeInstallation.js';
import {execFile, readAsset} from './util.js';
describeInstallation(
'`puppeteer` with Webpack',
{
dependencies: ['puppeteer-core', 'puppeteer'],
devDependencies: ['webpack', 'webpack-cli'],
env: cwd => {
return {
PUPPETEER_CACHE_DIR: join(cwd, '.cache', 'puppeteer'),
};
},
},
({itEvaluates}) => {
itEvaluates('Webpack bundles', {commonjs: true}, async cwd => {
// Write a Webpack configuration.
await writeFile(
join(cwd, 'webpack.config.mjs'),
await readAsset('puppeteer', 'webpack', 'webpack.config.js')
);
// Write the source code.
await writeFile(
join(cwd, 'index.js'),
await readAsset('puppeteer', 'basic.js')
);
// Bundle.
await execFile('npx', ['webpack'], {cwd, shell: true});
// Remove `node_modules` to test independence.
await rm('node_modules', {recursive: true, force: true});
// Read the bundled file.
return await readFile(join(cwd, 'bundle.js'), 'utf-8');
});
}
);

View File

@ -0,0 +1,46 @@
/**
* Copyright 2022 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import assert from 'assert';
import {readdir} from 'fs/promises';
import {join} from 'path';
import {describeInstallation} from './describeInstallation.js';
import {readAsset} from './util.js';
describeInstallation(
'`puppeteer`',
{
dependencies: ['puppeteer-core', 'puppeteer'],
env: cwd => {
return {
PUPPETEER_CACHE_DIR: join(cwd, '.cache', 'puppeteer'),
};
},
},
({itEvaluates}) => {
itEvaluates('CommonJS', {commonjs: true}, async cwd => {
const files = await readdir(join(cwd, '.cache', 'puppeteer'));
assert.equal(files.length, 1);
assert.equal(files[0], 'chrome');
return readAsset('puppeteer-core', 'requires.cjs');
});
itEvaluates('ES modules', async () => {
return readAsset('puppeteer-core', 'imports.js');
});
}
);

View File

@ -0,0 +1,26 @@
/**
* Copyright 2022 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {promisify} from 'util';
import {execFile as execFileAsync} from 'child_process';
import {join} from 'path';
import {ASSETS_DIR} from './constants.js';
import {readFile} from 'fs/promises';
export const execFile = promisify(execFileAsync);
export const readAsset = (...components: string[]): Promise<string> => {
return readFile(join(ASSETS_DIR, ...components), 'utf8');
};

View File

@ -0,0 +1,10 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"module": "NodeNext",
"moduleResolution": "NodeNext",
"outDir": "build",
"rootDir": "src"
},
"include": ["src"]
}

View File

@ -1,4 +1,6 @@
{
"name": "@puppeteer-test/test",
"version": "latest",
"private": true,
"scripts": {
"build": "wireit",

View File

@ -1,153 +0,0 @@
#!/usr/bin/env bash
set -e
# All tests are headed by a echo 'Test'.
# The general schema is:
# 1. Check we can install from the tarball.
# 2. The install script works and correctly exits without errors
# 3. Requiring/importing Puppeteer from Node works.
# macOS doesn't support realpath
realpath() {
[[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"
}
ROOTDIR="$(pwd)"
if [[ -z $(realpath puppeteer-[0-9]*.tgz) ]]; then
npm pack --workspaces
fi
puppeteer_tarball=$(realpath puppeteer-[0-9]*.tgz)
puppeteer_core_tarball=$(realpath puppeteer-core-*.tgz)
echo "Puppeteer Core Test Suite"
echo "Testing... CommonJS"
TMPDIR="$(mktemp -d)"
cd $TMPDIR
npm install --loglevel silent "${puppeteer_core_tarball}"
node --eval="require('puppeteer-core')"
node --eval="require('puppeteer-core/lib/cjs/puppeteer/revisions.js');"
echo "Testing... ES Modules"
TMPDIR="$(mktemp -d)"
cd $TMPDIR
echo '{"type":"module"}' >>$TMPDIR/package.json
npm install --loglevel silent "${puppeteer_core_tarball}"
node --input-type="module" --eval="import puppeteer from 'puppeteer-core'"
node --input-type="module" --eval="import 'puppeteer-core/lib/esm/puppeteer/revisions.js';"
echo "Testing...launch with executablePath"
TMPDIR="$(mktemp -d)"
cd "$TMPDIR"
echo '{"type":"module"}' >>"$TMPDIR/package.json"
npm install --loglevel silent "${puppeteer_core_tarball}"
# The test tries to launch the node process because
# real browsers are not downloaded by puppeteer-core.
# The expected error is "Failed to launch the browser process"
# so the test verifies that it does not fail for other reasons.
node --input-type="module" --eval="
import puppeteer from 'puppeteer-core';
(async () => {
puppeteer.launch({
product: 'firefox',
executablePath: 'node'
}).catch(error => error.message.includes('Failed to launch the browser process') ? process.exit(0) : process.exit(1));
})();
"
node --input-type="module" --eval="
import puppeteer from 'puppeteer-core';
(async () => {
puppeteer.launch({
product: 'chrome',
executablePath: 'node'
}).catch(error => error.message.includes('Failed to launch the browser process') ? process.exit(0) : process.exit(1));
})();
"
echo "Puppeteer Test Suite"
echo "Testing... Chrome CommonJS"
TMPDIR="$(mktemp -d)"
cd $TMPDIR
npm install --loglevel silent $puppeteer_core_tarball $puppeteer_tarball
node --eval="require('puppeteer')"
ls ~/.cache/puppeteer/chrome
echo "Testing... Chrome ES Modules"
TMPDIR="$(mktemp -d)"
cd $TMPDIR
echo '{"type":"module"}' >>$TMPDIR/package.json
npm install --loglevel silent $puppeteer_core_tarball $puppeteer_tarball
node --input-type="module" --eval="import puppeteer from 'puppeteer'"
node --input-type="module" --eval="
import puppeteer from 'puppeteer';
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('http://example.com');
await page.screenshot({ path: 'example.png' });
await browser.close();
})();
"
echo "Testing... Chrome ES Modules Destructuring"
TMPDIR="$(mktemp -d)"
cd $TMPDIR
echo '{"type":"module"}' >>$TMPDIR/package.json
npm install --loglevel silent $puppeteer_core_tarball $puppeteer_tarball
node --input-type="module" --eval="import puppeteer from 'puppeteer'"
node --input-type="module" --eval="
import { launch } from 'puppeteer';
(async () => {
const browser = await launch();
const page = await browser.newPage();
await page.goto('http://example.com');
await page.screenshot({ path: 'example.png' });
await browser.close();
})();
"
echo "Testing... Chrome Webpack ES Modules"
TMPDIR="$(mktemp -d)"
cd $TMPDIR
echo '{"type": "module"}' >>$TMPDIR/package.json
npm install --loglevel silent $puppeteer_core_tarball $puppeteer_tarball
npm install -D --loglevel silent webpack webpack-cli@4.9.2
echo 'export default {
mode: "production",
entry: "./index.js",
target: "node",
output: {
filename: "bundle.cjs",
},
};' >>$TMPDIR/webpack.config.js
echo "
import puppeteer from 'puppeteer';
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('http://example.com');
await page.\$('aria/example');
await page.screenshot({ path: 'example.png' });
await browser.close();
})();
" >>$TMPDIR/index.js
npx webpack
cp -r ~/.cache/puppeteer/chrome .
rm -rf node_modules
node dist/bundle.cjs
echo "Testing... Firefox CommonJS"
TMPDIR="$(mktemp -d)"
cd $TMPDIR
PUPPETEER_PRODUCT=firefox npm install --loglevel silent $puppeteer_core_tarball $puppeteer_tarball
node --eval="require('puppeteer')"
ls ~/.cache/puppeteer/firefox
echo "Testing... Firefox ES Modules"
TMPDIR="$(mktemp -d)"
cd $TMPDIR
echo '{"type":"module"}' >>$TMPDIR/package.json
PUPPETEER_PRODUCT=firefox npm install --loglevel silent $puppeteer_core_tarball $puppeteer_tarball
node --input-type="module" --eval="import puppeteer from 'puppeteer'"
ls ~/.cache/puppeteer/firefox