feat: export puppeteer methods (#8493)
This commit is contained in:
parent
b30f3f44cd
commit
465a7c405f
@ -1,6 +1,5 @@
|
||||
test/assets/modernizr.js
|
||||
third_party/*
|
||||
utils/browser/puppeteer-web.js
|
||||
utils/doclint/check_public_api/test/
|
||||
node6/*
|
||||
node6-test/*
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -14,7 +14,6 @@ test-ts-types/**/dist/
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
/node6
|
||||
/utils/browser/puppeteer-web.js
|
||||
/lib
|
||||
test/coverage.json
|
||||
temp/
|
||||
|
@ -121,8 +121,6 @@ lib
|
||||
- vendor <== the output of compiling `vendor/tsconfig.esm.json`
|
||||
```
|
||||
|
||||
The main entry point for the Node module Puppeteer is `cjs-entry.js`. This imports `lib/cjs/puppeteer/index.js` and exposes it to Node users.
|
||||
|
||||
### tsconfig for the tests
|
||||
|
||||
We also maintain `test/tsconfig.test.json`. This is **only used to compile the unit test `*.spec.ts` files**. When the tests are run, we first compile Puppeteer as normal before running the unit tests **against the compiled output**. Doing this lets the test run against the compiled code we ship to users so it gives us more confidence in our compiled output being correct.
|
||||
|
@ -1,29 +0,0 @@
|
||||
/**
|
||||
* Copyright 2020 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* We use `export default puppeteer` in `src/index.ts` to expose the library But
|
||||
* TypeScript in CJS mode compiles that to `exports.default = `. This means that
|
||||
* our CJS Node users would have to use `require('puppeteer').default` which
|
||||
* isn't very nice.
|
||||
*
|
||||
* So instead we expose this file as our entry point. This requires the compiled
|
||||
* Puppeteer output and re-exports the `default` export via `module.exports.`
|
||||
* This means that we can publish to CJS and ESM whilst maintaining the expected
|
||||
* import behaviour for CJS and ESM users.
|
||||
*/
|
||||
const puppeteerExport = require('./lib/cjs/puppeteer/node-puppeteer-core.js');
|
||||
module.exports = puppeteerExport.default;
|
29
cjs-entry.js
29
cjs-entry.js
@ -1,29 +0,0 @@
|
||||
/**
|
||||
* Copyright 2020 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* We use `export default puppeteer` in `src/index.ts` to expose the library But
|
||||
* TypeScript in CJS mode compiles that to `exports.default = `. This means that
|
||||
* our CJS Node users would have to use `require('puppeteer').default` which
|
||||
* isn't very nice.
|
||||
*
|
||||
* So instead we expose this file as our entry point. This requires the compiled
|
||||
* Puppeteer output and re-exports the `default` export via `module.exports.`
|
||||
* This means that we can publish to CJS and ESM whilst maintaining the expected
|
||||
* import behaviour for CJS and ESM users.
|
||||
*/
|
||||
const puppeteerExport = require('./lib/cjs/puppeteer/node.js');
|
||||
module.exports = puppeteerExport.default;
|
17
package.json
17
package.json
@ -9,12 +9,12 @@
|
||||
"automation"
|
||||
],
|
||||
"type": "commonjs",
|
||||
"main": "./cjs-entry.js",
|
||||
"main": "./lib/cjs/puppeteer/puppeteer.js",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./lib/types.d.ts",
|
||||
"import": "./lib/esm/puppeteer/node.js",
|
||||
"require": "./cjs-entry.js"
|
||||
"import": "./lib/esm/puppeteer/puppeteer.js",
|
||||
"require": "./lib/cjs/puppeteer/puppeteer.js"
|
||||
},
|
||||
"./*": {
|
||||
"import": "./*",
|
||||
@ -67,16 +67,9 @@
|
||||
"build-docs-production": "cd website && npm install && npm run build"
|
||||
},
|
||||
"files": [
|
||||
"lib/types.d.ts",
|
||||
"lib/**/*.d.ts",
|
||||
"lib/**/*.d.ts.map",
|
||||
"lib/**/*.js",
|
||||
"lib/**/*.js.map",
|
||||
"lib/**/package.json",
|
||||
"lib",
|
||||
"install.js",
|
||||
"typescript-if-required.js",
|
||||
"cjs-entry.js",
|
||||
"cjs-entry-core.js"
|
||||
"typescript-if-required.js"
|
||||
],
|
||||
"author": "The Chromium Authors",
|
||||
"license": "Apache-2.0",
|
||||
|
@ -40,6 +40,24 @@ import puppeteer from 'puppeteer';
|
||||
})();
|
||||
"
|
||||
|
||||
echo "Testing... Chrome ES Modules Destructuring"
|
||||
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 { 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
|
||||
|
@ -1,19 +0,0 @@
|
||||
module.exports = {
|
||||
extends: '../.eslintrc.js',
|
||||
/**
|
||||
* ESLint rules
|
||||
*
|
||||
* All available rules: http://eslint.org/docs/rules/
|
||||
*
|
||||
* Rules take the following form:
|
||||
* "rule-name", [severity, \{ opts \}]
|
||||
* Severity: 2 == error, 1 == warning, 0 == off.
|
||||
*/
|
||||
rules: {
|
||||
'no-console': [
|
||||
2,
|
||||
{ allow: ['warn', 'error', 'assert', 'timeStamp', 'time', 'timeEnd'] },
|
||||
],
|
||||
'no-debugger': 0,
|
||||
},
|
||||
};
|
@ -117,10 +117,10 @@ export class LifecycleWatcher {
|
||||
helper.addEventListener(
|
||||
frameManager._client,
|
||||
CDPSessionEmittedEvents.Disconnected,
|
||||
() =>
|
||||
this._terminate(
|
||||
new Error('Navigation failed because browser has disconnected!')
|
||||
)
|
||||
this._terminate.bind(
|
||||
this,
|
||||
new Error('Navigation failed because browser has disconnected!')
|
||||
)
|
||||
),
|
||||
helper.addEventListener(
|
||||
this._frameManager,
|
||||
|
@ -66,6 +66,14 @@ export class Puppeteer {
|
||||
*/
|
||||
constructor(settings: CommonPuppeteerSettings) {
|
||||
this._isPuppeteerCore = settings.isPuppeteerCore;
|
||||
|
||||
this.connect = this.connect.bind(this);
|
||||
this.registerCustomQueryHandler =
|
||||
this.registerCustomQueryHandler.bind(this);
|
||||
this.unregisterCustomQueryHandler =
|
||||
this.unregisterCustomQueryHandler.bind(this);
|
||||
this.customQueryHandlerNames = this.customQueryHandlerNames.bind(this);
|
||||
this.clearCustomQueryHandlers = this.clearCustomQueryHandlers.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,24 +0,0 @@
|
||||
/**
|
||||
* Copyright 2020 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 './common/Puppeteer.js';
|
||||
|
||||
export const initializePuppeteerWeb = (packageName: string): Puppeteer => {
|
||||
const isPuppeteerCore = packageName === 'puppeteer-core';
|
||||
return new Puppeteer({
|
||||
isPuppeteerCore,
|
||||
});
|
||||
};
|
@ -14,22 +14,22 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { PuppeteerNode } from './node/Puppeteer.js';
|
||||
import { PUPPETEER_REVISIONS } from './revisions.js';
|
||||
import { sync } from 'pkg-dir';
|
||||
import { Product } from './common/Product.js';
|
||||
import { rootDirname } from './constants.js';
|
||||
import { PuppeteerNode } from './node/Puppeteer.js';
|
||||
import { PUPPETEER_REVISIONS } from './revisions.js';
|
||||
|
||||
export const initializePuppeteerNode = (packageName: string): PuppeteerNode => {
|
||||
export const initializePuppeteer = (packageName: string): PuppeteerNode => {
|
||||
const isPuppeteerCore = packageName === 'puppeteer-core';
|
||||
const puppeteerRootDirectory = sync(rootDirname);
|
||||
let preferredRevision = PUPPETEER_REVISIONS.chromium;
|
||||
const isPuppeteerCore = packageName === 'puppeteer-core';
|
||||
// puppeteer-core ignores environment variables
|
||||
const productName = isPuppeteerCore
|
||||
? undefined
|
||||
: process.env['PUPPETEER_PRODUCT'] ||
|
||||
process.env['npm_config_puppeteer_product'] ||
|
||||
process.env['npm_package_config_puppeteer_product'];
|
||||
const productName = !isPuppeteerCore
|
||||
? ((process.env['PUPPETEER_PRODUCT'] ||
|
||||
process.env['npm_config_puppeteer_product'] ||
|
||||
process.env['npm_package_config_puppeteer_product']) as Product)
|
||||
: undefined;
|
||||
|
||||
if (!isPuppeteerCore && productName === 'firefox')
|
||||
preferredRevision = PUPPETEER_REVISIONS.firefox;
|
||||
@ -38,6 +38,6 @@ export const initializePuppeteerNode = (packageName: string): PuppeteerNode => {
|
||||
projectRoot: puppeteerRootDirectory,
|
||||
preferredRevision,
|
||||
isPuppeteerCore,
|
||||
productName: productName as Product,
|
||||
productName,
|
||||
});
|
||||
};
|
@ -101,6 +101,12 @@ export class PuppeteerNode extends Puppeteer {
|
||||
this._projectRoot = projectRoot;
|
||||
this.__productName = productName;
|
||||
this._preferredRevision = preferredRevision;
|
||||
|
||||
this.connect = this.connect.bind(this);
|
||||
this.launch = this.launch.bind(this);
|
||||
this.executablePath = this.executablePath.bind(this);
|
||||
this.defaultArgs = this.defaultArgs.bind(this);
|
||||
this.createBrowserFetcher = this.createBrowserFetcher.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -17,7 +17,7 @@
|
||||
import https, { RequestOptions } from 'https';
|
||||
import ProgressBar from 'progress';
|
||||
import URL from 'url';
|
||||
import puppeteer from '../node.js';
|
||||
import puppeteer from '../puppeteer.js';
|
||||
import { PUPPETEER_REVISIONS } from '../revisions.js';
|
||||
import { PuppeteerNode } from './Puppeteer.js';
|
||||
import createHttpsProxyAgent, {
|
||||
|
@ -14,12 +14,20 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { isNode } from './environment.js';
|
||||
import { initializePuppeteerNode } from './initialize-node.js';
|
||||
import { initializePuppeteer } from './initializePuppeteer.js';
|
||||
|
||||
if (!isNode) {
|
||||
throw new Error('Cannot run puppeteer-core outside of Node.js');
|
||||
}
|
||||
const puppeteer = initializePuppeteer('puppeteer-core');
|
||||
|
||||
export const {
|
||||
clearCustomQueryHandlers,
|
||||
connect,
|
||||
createBrowserFetcher,
|
||||
customQueryHandlerNames,
|
||||
defaultArgs,
|
||||
executablePath,
|
||||
launch,
|
||||
registerCustomQueryHandler,
|
||||
unregisterCustomQueryHandler,
|
||||
} = puppeteer;
|
||||
|
||||
const puppeteer = initializePuppeteerNode('puppeteer-core');
|
||||
export default puppeteer;
|
@ -14,12 +14,20 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { isNode } from './environment.js';
|
||||
import { initializePuppeteerNode } from './initialize-node.js';
|
||||
import { initializePuppeteer } from './initializePuppeteer.js';
|
||||
|
||||
if (!isNode) {
|
||||
throw new Error('Trying to run Puppeteer-Node in a web environment.');
|
||||
}
|
||||
const puppeteer = initializePuppeteer('puppeteer');
|
||||
|
||||
export const {
|
||||
clearCustomQueryHandlers,
|
||||
connect,
|
||||
createBrowserFetcher,
|
||||
customQueryHandlerNames,
|
||||
defaultArgs,
|
||||
executablePath,
|
||||
launch,
|
||||
registerCustomQueryHandler,
|
||||
unregisterCustomQueryHandler,
|
||||
} = puppeteer;
|
||||
|
||||
const puppeteer = initializePuppeteerNode('puppeteer');
|
||||
export default puppeteer;
|
25
src/web.ts
25
src/web.ts
@ -1,25 +0,0 @@
|
||||
/**
|
||||
* Copyright 2020 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 { isNode } from './environment.js';
|
||||
import { initializePuppeteerWeb } from './initialize-web.js';
|
||||
|
||||
if (isNode) {
|
||||
throw new Error('Trying to run Puppeteer-Web in a Node environment');
|
||||
}
|
||||
|
||||
const puppeteer = initializePuppeteerWeb('puppeteer');
|
||||
export default puppeteer;
|
@ -15,7 +15,7 @@
|
||||
*/
|
||||
import { Connection } from '../lib/esm/puppeteer/common/Connection.js';
|
||||
import { BrowserWebSocketTransport } from '../lib/esm/puppeteer/common/BrowserWebSocketTransport.js';
|
||||
import puppeteer from '../lib/esm/puppeteer/web.js';
|
||||
import puppeteer from '../lib/esm/puppeteer/puppeteer.js';
|
||||
import expect from '../node_modules/expect/build-es5/index.js';
|
||||
import { getWebSocketEndpoint } from './helper.js';
|
||||
|
||||
|
@ -2,6 +2,18 @@ const { describe, it } = require('mocha');
|
||||
const { getCoverageResults } = require('./coverage-utils.js');
|
||||
const expect = require('expect');
|
||||
|
||||
const EXCLUDED_METHODS = new Set([
|
||||
'Puppeteer.registerCustomQueryHandler',
|
||||
'Puppeteer.unregisterCustomQueryHandler',
|
||||
'Puppeteer.customQueryHandlerNames',
|
||||
'Puppeteer.clearCustomQueryHandlers',
|
||||
'PuppeteerNode.connect',
|
||||
'PuppeteerNode.launch',
|
||||
'PuppeteerNode.executablePath',
|
||||
'PuppeteerNode.defaultArgs',
|
||||
'PuppeteerNode.createBrowserFetcher',
|
||||
]);
|
||||
|
||||
describe('API coverage test', () => {
|
||||
it('calls every method', () => {
|
||||
if (!process.env.COVERAGE) return;
|
||||
@ -9,7 +21,8 @@ describe('API coverage test', () => {
|
||||
const coverageMap = getCoverageResults();
|
||||
const missingMethods = [];
|
||||
for (const method of coverageMap.keys()) {
|
||||
if (!coverageMap.get(method)) missingMethods.push(method);
|
||||
if (!coverageMap.get(method) && !EXCLUDED_METHODS.has(method))
|
||||
missingMethods.push(method);
|
||||
}
|
||||
if (missingMethods.length) {
|
||||
console.error(
|
||||
|
@ -148,9 +148,12 @@ describe('Launcher specs', function () {
|
||||
await server.waitForRequest('/one-style.css');
|
||||
remote.disconnect();
|
||||
const error = await navigationPromise;
|
||||
expect(error.message).toBe(
|
||||
'Navigation failed because browser has disconnected!'
|
||||
);
|
||||
expect(
|
||||
[
|
||||
'Navigation failed because browser has disconnected!',
|
||||
'Protocol error (Page.navigate): Target closed.',
|
||||
].includes(error.message)
|
||||
).toBeTruthy();
|
||||
await browser.close();
|
||||
});
|
||||
it('should reject waitForSelector when browser closes', async () => {
|
||||
|
@ -19,7 +19,7 @@ import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import * as os from 'os';
|
||||
import sinon from 'sinon';
|
||||
import puppeteer from '../lib/cjs/puppeteer/node.js';
|
||||
import puppeteer from '../lib/cjs/puppeteer/puppeteer.js';
|
||||
import {
|
||||
Browser,
|
||||
BrowserContext,
|
||||
|
@ -24,8 +24,8 @@ const json = require(packagePath);
|
||||
delete json.scripts.install;
|
||||
|
||||
json.name = 'puppeteer-core';
|
||||
json.main = './cjs-entry-core.js';
|
||||
json.exports['.'].import = './lib/esm/puppeteer/node-puppeteer-core.js';
|
||||
json.exports['.'].require = './cjs-entry-core.js';
|
||||
json.main = './lib/cjs/puppeteer/puppeteer-core.js';
|
||||
json.exports['.'].import = './lib/esm/puppeteer/puppeteer-core.js';
|
||||
json.exports['.'].require = './lib/cjs/puppeteer/puppeteer-core.js';
|
||||
|
||||
fs.writeFileSync(packagePath, JSON.stringify(json, null, ' '));
|
||||
|
Loading…
Reference in New Issue
Block a user