diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a9e7e70bb6852..0d01cb61e89c7 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -19,7 +19,7 @@ jobs: matrix: # Include all major maintenance + active LTS + current Node.js versions. # https://github.com/nodejs/Release#release-schedule - node: [12, 14, 16] + node: [14, 16] steps: - name: Checkout uses: actions/checkout@v3 @@ -111,7 +111,7 @@ jobs: with: # Test only the oldest maintenance LTS Node.js version. # https://github.com/nodejs/Release#release-schedule - node-version: 12 + node-version: 14 - name: Install dependencies run: | @@ -152,7 +152,7 @@ jobs: with: # Test only the oldest maintenance LTS Node.js version. # https://github.com/nodejs/Release#release-schedule - node-version: 12 + node-version: 14 - name: Install dependencies run: | diff --git a/compat/cjs/compat.ts b/compat/cjs/compat.ts index fb3eac99b0e39..6efa3fe9aabe3 100644 --- a/compat/cjs/compat.ts +++ b/compat/cjs/compat.ts @@ -13,6 +13,4 @@ try { puppeteerDirname = __dirname; } -export const rootDirname = dirname(dirname(dirname(puppeteerDirname))); - export { puppeteerDirname }; diff --git a/compat/esm/compat.ts b/compat/esm/compat.ts index 3a95228d20cf7..245c09652e803 100644 --- a/compat/esm/compat.ts +++ b/compat/esm/compat.ts @@ -1,5 +1,6 @@ import { createRequire } from 'module'; import { dirname } from 'path'; +import { fileURLToPath } from 'url'; const require = createRequire(import.meta.url); @@ -13,9 +14,7 @@ try { puppeteerDirname = dirname(require.resolve('./compat')); } catch (error) { // Fallback to __dirname. - puppeteerDirname = __dirname; + puppeteerDirname = dirname(fileURLToPath(import.meta.url)); } -export const rootDirname = dirname(dirname(dirname(puppeteerDirname))); - export { puppeteerDirname }; diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index 688a96e65fc13..c139d1a4d94d7 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -156,7 +156,7 @@ If you get an error that looks like this when trying to launch Chromium: spawn /Users/.../node_modules/puppeteer/.local-chromium/mac-756035/chrome-mac/Chromium.app/Contents/MacOS/Chromium ENOENT ``` -This means that the browser was downloaded but failed to be extracted correctly. The most common cause is a bug in Node.js v14.0.0 which broke `extract-zip`, the module Puppeteer uses to extract browser downloads into the right place. The bug was fixed in Node.js v14.1.0, so please make sure you're running that version or higher. Alternatively, if you cannot upgrade, you could downgrade to Node.js v12, but we recommend upgrading when possible. +This means that the browser was downloaded but failed to be extracted correctly. The most common cause is a bug in Node.js v14.0.0 which broke `extract-zip`, the module Puppeteer uses to extract browser downloads into the right place. The bug was fixed in Node.js v14.1.0, so please make sure you're running that version or higher. ## Setting Up Chrome Linux Sandbox @@ -242,7 +242,7 @@ Running Puppeteer smoothly on CircleCI requires the following steps: like so: ```yaml docker: - - image: circleci/node:12 # Use your desired version + - image: circleci/node:14 # Use your desired version environment: NODE_ENV: development # Only needed if puppeteer is in `devDependencies` ``` @@ -277,7 +277,7 @@ To fix, you'll need to install the missing dependencies and the latest Chromium package in your Dockerfile: ```Dockerfile -FROM node:12-slim +FROM node:14-slim # Install latest chrome dev package and fonts to support major charsets (Chinese, Japanese, Arabic, Hebrew, Thai and a few others) # Note: this installs the necessary libs to make the bundled version of Chromium that Puppeteer diff --git a/package.json b/package.json index 52ab14d01db3e..78017911c238f 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "types": "lib/types.d.ts", "repository": "github:puppeteer/puppeteer", "engines": { - "node": ">=10.18.1" + "node": ">=14.1.0" }, "scripts": { "test-browser": "wtr", @@ -126,7 +126,7 @@ "jpeg-js": "0.4.3", "mime": "3.0.0", "minimist": "1.2.6", - "mocha": "9.2.2", + "mocha": "10.0.0", "ncp": "2.0.0", "pixelmatch": "5.3.0", "pngjs": "6.0.0", diff --git a/scripts/test-install.sh b/scripts/test-install.sh index e6433f3eb0ec9..fd72c4b1df0e6 100755 --- a/scripts/test-install.sh +++ b/scripts/test-install.sh @@ -1,33 +1,34 @@ #!/usr/bin/env sh 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. + +## Puppeter tests + +# Setup ROOTDIR="$(pwd)" -# Pack the module into a tarball npm pack tarball="$(realpath puppeteer-*.tgz)" + +echo "Testing... Chrome CommonJS" TMPDIR="$(mktemp -d)" cd $TMPDIR -# Check we can install from the tarball. -# This emulates installing from npm and ensures that: -# 1. we publish the right files in the `files` list from package.json -# 2. The install script works and correctly exits without errors -# 3. Requiring Puppeteer from Node works. npm install --loglevel silent "${tarball}" node --eval="require('puppeteer')" -node --eval=" -require('puppeteer/lib/cjs/puppeteer/revisions.js'); -" +node --eval="require('puppeteer/lib/cjs/puppeteer/revisions.js');" ls $TMPDIR/node_modules/puppeteer/.local-chromium/ -# Testing ES module features +echo "Testing... Chrome ES Modules" TMPDIR="$(mktemp -d)" cd $TMPDIR echo '{"type":"module"}' >>$TMPDIR/package.json npm install --loglevel silent "${tarball}" node --input-type="module" --eval="import puppeteer from 'puppeteer'" -node --input-type="module" --eval=" -import 'puppeteer/lib/esm/puppeteer/revisions.js'; -" +node --input-type="module" --eval="import 'puppeteer/lib/esm/puppeteer/revisions.js';" node --input-type="module" --eval=" import puppeteer from 'puppeteer'; (async () => { @@ -39,33 +40,53 @@ import puppeteer from 'puppeteer'; })(); " -# Again for Firefox +echo "Testing... Firefox CommonJS" TMPDIR="$(mktemp -d)" cd $TMPDIR PUPPETEER_PRODUCT=firefox npm install --loglevel silent "${tarball}" node --eval="require('puppeteer')" -rm "${tarball}" +node --eval="require('puppeteer/lib/cjs/puppeteer/revisions.js');" ls $TMPDIR/node_modules/puppeteer/.local-firefox/linux-*/firefox/firefox -# Testing ES module features +echo "Testing... Firefox ES Modules" TMPDIR="$(mktemp -d)" cd $TMPDIR echo '{"type":"module"}' >>$TMPDIR/package.json -npm install --loglevel silent "${tarball}" -node --input-type="module" --eval="import puppeteer from 'puppeteer-core'" +PUPPETEER_PRODUCT=firefox npm install --loglevel silent "${tarball}" +node --input-type="module" --eval="import puppeteer from 'puppeteer'" +node --input-type="module" --eval="import 'puppeteer/lib/esm/puppeteer/revisions.js';" +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(); +})(); +" -# Again for puppeteer-core +## Puppeteer Core tests + +# Setup cd $ROOTDIR +rm "${tarball}" node ./utils/prepare_puppeteer_core.js npm pack tarball="$(realpath puppeteer-core-*.tgz)" + +echo "Testing... Puppeteer Core CommonJS" TMPDIR="$(mktemp -d)" cd $TMPDIR -# Check we can install from the tarball. -# This emulates installing from npm and ensures that: -# 1. we publish the right files in the `files` list from package.json -# 2. The install script works and correctly exits without errors -# 3. Requiring Puppeteer Core from Node works. npm install --loglevel silent "${tarball}" node --eval="require('puppeteer-core')" +node --eval="require('puppeteer-core/lib/cjs/puppeteer/revisions.js');" + +echo "Testing... Puppeteer Core ES Modules" +TMPDIR="$(mktemp -d)" +cd $TMPDIR +echo '{"type":"module"}' >>$TMPDIR/package.json +npm install --loglevel silent "${tarball}" +node --input-type="module" --eval="import puppeteer from 'puppeteer-core'" +node --input-type="module" --eval="import 'puppeteer-core/lib/esm/puppeteer/revisions.js';" diff --git a/src/compat.ts b/src/compat.ts index a86c14395268d..873dcea7966e5 100644 --- a/src/compat.ts +++ b/src/compat.ts @@ -1,4 +1,3 @@ declare const puppeteerDirname: string; -declare const rootDirname: string; -export { puppeteerDirname, rootDirname }; +export { puppeteerDirname }; diff --git a/src/constants.ts b/src/constants.ts new file mode 100644 index 0000000000000..e9104f547d89c --- /dev/null +++ b/src/constants.ts @@ -0,0 +1,8 @@ +import { readFileSync } from 'fs'; +import { dirname, join } from 'path'; +import { puppeteerDirname } from './compat.js'; + +export const rootDirname = dirname(dirname(dirname(puppeteerDirname))); +export const packageVersion = JSON.parse( + readFileSync(join(rootDirname, 'package.json'), { encoding: 'utf8' }) +).version; diff --git a/src/initialize-node.ts b/src/initialize-node.ts index 2b2a65585b208..9b55b98975fcf 100644 --- a/src/initialize-node.ts +++ b/src/initialize-node.ts @@ -18,10 +18,10 @@ import { PuppeteerNode } from './node/Puppeteer.js'; import { PUPPETEER_REVISIONS } from './revisions.js'; import { sync } from 'pkg-dir'; import { Product } from './common/Product.js'; -import { puppeteerDirname } from './compat.js'; +import { rootDirname } from './constants.js'; export const initializePuppeteerNode = (packageName: string): PuppeteerNode => { - const puppeteerRootDirectory = sync(puppeteerDirname); + const puppeteerRootDirectory = sync(rootDirname); let preferredRevision = PUPPETEER_REVISIONS.chromium; const isPuppeteerCore = packageName === 'puppeteer-core'; // puppeteer-core ignores environment variables diff --git a/src/node/NodeWebSocketTransport.ts b/src/node/NodeWebSocketTransport.ts index 5684ec278e592..57b72509d1942 100644 --- a/src/node/NodeWebSocketTransport.ts +++ b/src/node/NodeWebSocketTransport.ts @@ -13,16 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { ConnectionTransport } from '../common/ConnectionTransport.js'; import NodeWebSocket from 'ws'; -import { readFileSync } from 'fs'; -import { join } from 'path'; -import { rootDirname } from '../compat.js'; - -// We parse rather than import for ES module compatibility. -const version = JSON.parse( - readFileSync(join(rootDirname, 'package.json'), { encoding: 'utf8' }) -).version; +import { ConnectionTransport } from '../common/ConnectionTransport.js'; +import { packageVersion } from '../constants.js'; export class NodeWebSocketTransport implements ConnectionTransport { static create(url: string): Promise { @@ -32,7 +25,7 @@ export class NodeWebSocketTransport implements ConnectionTransport { perMessageDeflate: false, maxPayload: 256 * 1024 * 1024, // 256Mb headers: { - 'User-Agent': `Puppeteer ${version}`, + 'User-Agent': `Puppeteer ${packageVersion}`, }, });