mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 23:31:56 +00:00
Bug 1694506 - [puppeteer] Sync vendored puppeteer to v8.0.0 r=remote-protocol-reviewers,whimboo
Generated by running ./mach remote vendor-puppeteer and replacing itFailsFirefox to it etc... Differential Revision: https://phabricator.services.mozilla.com/D108099
This commit is contained in:
parent
bf279d8795
commit
3eac4f3ce3
@ -1,17 +0,0 @@
|
||||
FROM node:10
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get -y install xvfb gconf-service libasound2 libatk1.0-0 libc6 libcairo2 libcups2 \
|
||||
libdbus-1-3 libexpat1 libfontconfig1 libgbm1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 \
|
||||
libgtk-3-0 libnspr4 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 \
|
||||
libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 \
|
||||
libxtst6 ca-certificates fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Add user so we don't need --no-sandbox.
|
||||
RUN groupadd -r pptruser && useradd -r -g pptruser -G audio,video pptruser \
|
||||
&& mkdir -p /home/pptruser/Downloads \
|
||||
&& chown -R pptruser:pptruser /home/pptruser
|
||||
|
||||
# Run everything after as non-privileged user.
|
||||
USER pptruser
|
@ -1,17 +0,0 @@
|
||||
FROM node:12
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get -y install xvfb gconf-service libasound2 libatk1.0-0 libc6 libcairo2 libcups2 \
|
||||
libdbus-1-3 libexpat1 libfontconfig1 libgbm1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 \
|
||||
libgtk-3-0 libnspr4 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 \
|
||||
libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 \
|
||||
libxtst6 ca-certificates fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Add user so we don't need --no-sandbox.
|
||||
RUN groupadd -r pptruser && useradd -r -g pptruser -G audio,video pptruser \
|
||||
&& mkdir -p /home/pptruser/Downloads \
|
||||
&& chown -R pptruser:pptruser /home/pptruser
|
||||
|
||||
# Run everything after as non-privileged user.
|
||||
USER pptruser
|
@ -12,3 +12,4 @@ lib/
|
||||
utils/doclint/generate_types/test/test.ts
|
||||
vendor/
|
||||
web-test-runner.config.mjs
|
||||
test-ts-types/
|
||||
|
157
remote/test/puppeteer/.github/workflows/main.yml
vendored
Normal file
157
remote/test/puppeteer/.github/workflows/main.yml
vendored
Normal file
@ -0,0 +1,157 @@
|
||||
name: run-checks
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
linux-main-checks:
|
||||
# https://github.com/actions/virtual-environments#available-environments
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
# Include all major maintenance + active LTS Node.js versions.
|
||||
# https://github.com/nodejs/Release#release-schedule
|
||||
node: [10, 12, 14]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node }}
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get install xvfb
|
||||
# Ensure both a Chromium and a Firefox binary are available.
|
||||
PUPPETEER_PRODUCT=firefox npm install
|
||||
npm install
|
||||
ls .local-chromium .local-firefox
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
npm run build
|
||||
|
||||
- name: Run code checks
|
||||
run: |
|
||||
npm run lint
|
||||
npm run generate-docs
|
||||
npm run ensure-correct-devtools-protocol-revision
|
||||
npm run test-types-file
|
||||
|
||||
- name: Run unit tests
|
||||
env:
|
||||
CHROMIUM: true
|
||||
run: |
|
||||
xvfb-run --auto-servernum npm run unit
|
||||
|
||||
- name: Run unit tests with coverage
|
||||
env:
|
||||
CHROMIUM: true
|
||||
run: |
|
||||
xvfb-run --auto-servernum npm run unit-with-coverage
|
||||
xvfb-run --auto-servernum npm run assert-unit-coverage
|
||||
|
||||
- name: Run unit tests on Firefox
|
||||
env:
|
||||
FIREFOX: true
|
||||
MOZ_WEBRENDER: 0
|
||||
run: |
|
||||
xvfb-run --auto-servernum npm run funit
|
||||
- name: Run browser tests
|
||||
run: |
|
||||
npm run test-browser
|
||||
|
||||
- name: Test bundling and installation
|
||||
env:
|
||||
CHROMIUM: true
|
||||
run: |
|
||||
# Note: this modifies package.json to test puppeteer-core.
|
||||
npm run test-install
|
||||
# Undo those changes.
|
||||
git checkout --force
|
||||
|
||||
macos:
|
||||
# https://github.com/actions/virtual-environments#available-environments
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
# Test only the oldest maintenance LTS Node.js version.
|
||||
# https://github.com/nodejs/Release#release-schedule
|
||||
node-version: 10
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
# Test platform-specific browser binary fetching for both
|
||||
# Chromium and Firefox.
|
||||
PUPPETEER_PRODUCT=firefox npm install
|
||||
npm install
|
||||
ls .local-chromium .local-firefox
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
npm run build
|
||||
|
||||
- name: Run unit tests
|
||||
env:
|
||||
CHROMIUM: true
|
||||
run: |
|
||||
npm run unit
|
||||
|
||||
- name: Run unit tests on Firefox
|
||||
env:
|
||||
FIREFOX: true
|
||||
MOZ_WEBRENDER: 0
|
||||
run: |
|
||||
npm run funit
|
||||
|
||||
windows:
|
||||
# https://github.com/actions/virtual-environments#available-environments
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
# Test only the oldest maintenance LTS Node.js version.
|
||||
# https://github.com/nodejs/Release#release-schedule
|
||||
node-version: 10
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
# Test platform-specific browser binary fetching for both
|
||||
# Chromium and Firefox.
|
||||
$env:PUPPETEER_PRODUCT='firefox'
|
||||
npm install
|
||||
Remove-Item Env:\PUPPETEER_PRODUCT
|
||||
npm install
|
||||
Get-ChildItem -Path .local-chromium,.local-firefox
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
npm run build
|
||||
|
||||
- name: Run unit tests
|
||||
env:
|
||||
CHROMIUM: true
|
||||
run: |
|
||||
npm run unit
|
@ -3,7 +3,7 @@ name: publish-on-tag
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*'
|
||||
- '*'
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
@ -19,6 +19,7 @@ jobs:
|
||||
env:
|
||||
NPM_TOKEN: ${{secrets.NPM_TOKEN_PUPPETEER}}
|
||||
run: |
|
||||
npm config set registry 'https://wombat-dressing-room.appspot.com/'
|
||||
npm config set '//wombat-dressing-room.appspot.com/:_authToken' '${NPM_TOKEN}'
|
||||
npm publish
|
||||
- name: Publish puppeteer-core
|
||||
@ -26,5 +27,6 @@ jobs:
|
||||
NPM_TOKEN: ${{secrets.NPM_TOKEN_PUPPETEER_CORE}}
|
||||
run: |
|
||||
utils/prepare_puppeteer_core.js
|
||||
npm config set registry 'https://wombat-dressing-room.appspot.com/'
|
||||
npm config set '//wombat-dressing-room.appspot.com/:_authToken' '${NPM_TOKEN}'
|
||||
npm publish
|
||||
|
@ -1,2 +1 @@
|
||||
registry=https://wombat-dressing-room.appspot.com/
|
||||
access=public
|
||||
|
@ -1,118 +0,0 @@
|
||||
language: node_js
|
||||
services: xvfb
|
||||
|
||||
# Throughout this file, the following `node_js` versions are being used:
|
||||
#
|
||||
# - node_js: '10' # The maintenance LTS version.
|
||||
# - node_js: '12' # The oldest major active LTS version.
|
||||
# - node_js: '14' # The newest major active LTS version.
|
||||
|
||||
jobs:
|
||||
include:
|
||||
- os: 'osx'
|
||||
name: 'Unit tests: macOS/Chromium'
|
||||
node_js: '10' # The maintenance LTS version.
|
||||
osx_image: xcode11.4
|
||||
env:
|
||||
- CHROMIUM=true
|
||||
before_install:
|
||||
- PUPPETEER_PRODUCT=firefox npm install
|
||||
script:
|
||||
- ls .local-chromium .local-firefox
|
||||
- npm run tsc
|
||||
- npm run unit
|
||||
|
||||
- os: 'windows'
|
||||
name: 'Unit tests: Windows/Chromium'
|
||||
node_js: '10' # The maintenance LTS version.
|
||||
env:
|
||||
- CHROMIUM=true
|
||||
before_install:
|
||||
- PUPPETEER_PRODUCT=firefox npm install
|
||||
script:
|
||||
- ls .local-chromium .local-firefox
|
||||
- npm run tsc
|
||||
- travis_retry npm run unit
|
||||
|
||||
# Node <10.17's fs.promises module was experimental and doesn't behave as
|
||||
# expected. This problem was fixed in Node 10.19, but we run the unit tests
|
||||
# through on 10.15 to make sure we don't cause any regressions when using
|
||||
# fs.promises. See https://github.com/puppeteer/puppeteer/issues/6548 for an
|
||||
# example.
|
||||
- node_js: '10.15.0'
|
||||
name: 'Node 10.15 Unit tests: Linux/Chromium'
|
||||
env:
|
||||
- CHROMIUM=true
|
||||
before_install:
|
||||
- PUPPETEER_PRODUCT=firefox npm install
|
||||
script:
|
||||
- npm run unit
|
||||
|
||||
- node_js: '10' # The maintenance LTS version.
|
||||
name: 'Unit tests [with coverage]: Linux/Chromium'
|
||||
env:
|
||||
- CHROMIUM=true
|
||||
before_install:
|
||||
- PUPPETEER_PRODUCT=firefox npm install
|
||||
script:
|
||||
- travis_retry npm run unit-with-coverage
|
||||
- npm run assert-unit-coverage
|
||||
|
||||
- node_js: '12' # The oldest major active LTS version.
|
||||
name: 'Unit tests [Node 12]: Linux/Chromium'
|
||||
env:
|
||||
- CHROMIUM=true
|
||||
before_install:
|
||||
- PUPPETEER_PRODUCT=firefox npm install
|
||||
script:
|
||||
- npm run unit
|
||||
|
||||
- node_js: '14' # The newest major active LTS version.
|
||||
name: 'Unit tests [Node 14]: Linux/Chromium'
|
||||
env:
|
||||
- CHROMIUM=true
|
||||
before_install:
|
||||
- PUPPETEER_PRODUCT=firefox npm install
|
||||
script:
|
||||
- npm run unit
|
||||
|
||||
- node_js: '12' # The oldest major active LTS version.
|
||||
name: 'Browser tests: Linux/Chromium'
|
||||
addons:
|
||||
chrome: stable
|
||||
env:
|
||||
- CHROMIUM=true
|
||||
script:
|
||||
- npm run test-browser
|
||||
|
||||
# This bot runs all the extra checks that aren't the main Puppeteer unit tests.
|
||||
- node_js: '10' # The maintenance LTS version.
|
||||
name: 'Extra tests: Linux/Chromium'
|
||||
env:
|
||||
- CHROMIUM=true
|
||||
script:
|
||||
- npm run lint
|
||||
# Ensure that we can generate the new docs without erroring
|
||||
- npm run generate-docs
|
||||
- npm run ensure-correct-devtools-protocol-revision
|
||||
|
||||
# This bot runs separately as it changes package.json to test puppeteer-core
|
||||
# and we don't want that leaking into other bots and causing issues.
|
||||
- node_js: '10' # The maintenance LTS version.
|
||||
name: 'Test bundling and install of packages'
|
||||
env:
|
||||
- CHROMIUM=true
|
||||
script:
|
||||
- npm run test-install
|
||||
|
||||
- node_js: '10' # The maintenance LTS version.
|
||||
name: 'Unit tests: Linux/Firefox'
|
||||
env:
|
||||
- FIREFOX=true
|
||||
before_install:
|
||||
- PUPPETEER_PRODUCT=firefox npm install
|
||||
script:
|
||||
- npm run funit
|
||||
|
||||
notifications:
|
||||
email: false
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"releaseCommitMessageFormat": "chore(release): mark v{{currentTag}}"
|
||||
}
|
26
remote/test/puppeteer/.versionrc.js
Normal file
26
remote/test/puppeteer/.versionrc.js
Normal file
@ -0,0 +1,26 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
releaseCommitMessageFormat: 'chore(release): mark v{{currentTag}}',
|
||||
skip: {
|
||||
tag: true,
|
||||
},
|
||||
scripts: {
|
||||
prerelease: 'node utils/remove_version_suffix.js',
|
||||
postbump: 'IS_RELEASE=true npm run doc && git add --update',
|
||||
},
|
||||
};
|
@ -2,6 +2,109 @@
|
||||
|
||||
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
||||
|
||||
## [8.0.0](https://github.com/puppeteer/puppeteer/compare/v7.1.0...v8.0.0) (2021-02-26)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
* renamed type `ChromeArgOptions` to `BrowserLaunchArgumentOptions`
|
||||
* renamed type `BrowserOptions` to `BrowserConnectOptions`
|
||||
|
||||
### Features
|
||||
|
||||
* **chromium:** roll Chromium to r856583 ([#6927](https://github.com/puppeteer/puppeteer/issues/6927)) ([0c688bd](https://github.com/puppeteer/puppeteer/commit/0c688bd75ef1d1fc3afd14cbe8966757ecda68fb))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* explicit HTTPRequest.resourceType type defs ([#6882](https://github.com/puppeteer/puppeteer/issues/6882)) ([ff26c62](https://github.com/puppeteer/puppeteer/commit/ff26c62647b60cd0d8d7ea66ee998adaadc3fcc2)), closes [#6854](https://github.com/puppeteer/puppeteer/issues/6854)
|
||||
* expose `Viewport` type ([#6881](https://github.com/puppeteer/puppeteer/issues/6881)) ([be7c229](https://github.com/puppeteer/puppeteer/commit/be7c22933c1dcf5eee797d61463171bd0ef44582))
|
||||
* improve TS types for launching browsers ([#6888](https://github.com/puppeteer/puppeteer/issues/6888)) ([98c8145](https://github.com/puppeteer/puppeteer/commit/98c81458c27f378eb66c38e1620e79e2ffde418e))
|
||||
* move CI npm config out of .npmrc ([#6901](https://github.com/puppeteer/puppeteer/issues/6901)) ([f7de60b](https://github.com/puppeteer/puppeteer/commit/f7de60be22d9bc6433ada7bfefeaa7f6f6f62047))
|
||||
|
||||
## [7.1.0](https://github.com/puppeteer/puppeteer/compare/v7.0.4...v7.1.0) (2021-02-12)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **page:** add color-gamut support to Page.emulateMediaFeatures ([#6857](https://github.com/puppeteer/puppeteer/issues/6857)) ([ad59357](https://github.com/puppeteer/puppeteer/commit/ad5935738d869cfce386a0d28b4bc6131457f962)), closes [#6761](https://github.com/puppeteer/puppeteer/issues/6761)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add favicon test asset ([#6868](https://github.com/puppeteer/puppeteer/issues/6868)) ([a63f53c](https://github.com/puppeteer/puppeteer/commit/a63f53c9380545550503f5539494c72c607e19ac))
|
||||
* expose `ScreenshotOptions` type in type defs ([#6869](https://github.com/puppeteer/puppeteer/issues/6869)) ([63d48b2](https://github.com/puppeteer/puppeteer/commit/63d48b2ecba317b6c0a3acad87a7a3671c769dbc)), closes [#6866](https://github.com/puppeteer/puppeteer/issues/6866)
|
||||
* expose puppeteer.Permission type ([#6856](https://github.com/puppeteer/puppeteer/issues/6856)) ([a5e174f](https://github.com/puppeteer/puppeteer/commit/a5e174f696eb192c541db64a603ea5cdf385a643))
|
||||
* jsonValue() type is generic ([#6865](https://github.com/puppeteer/puppeteer/issues/6865)) ([bdaba78](https://github.com/puppeteer/puppeteer/commit/bdaba7829da366aabbc81885d84bb2401ab3eaff))
|
||||
* wider compat TS types and CI checks to ensure correct type defs ([#6855](https://github.com/puppeteer/puppeteer/issues/6855)) ([6a0eb78](https://github.com/puppeteer/puppeteer/commit/6a0eb7841fd82493903b0b9fa153d2de181350eb))
|
||||
|
||||
### [7.0.4](https://github.com/puppeteer/puppeteer/compare/v7.0.3...v7.0.4) (2021-02-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* make publish bot run full build, not just tsc ([#6848](https://github.com/puppeteer/puppeteer/issues/6848)) ([f718b14](https://github.com/puppeteer/puppeteer/commit/f718b14b64df8be492d344ddd35e40961ff750c5))
|
||||
|
||||
### [7.0.3](https://github.com/puppeteer/puppeteer/compare/v7.0.2...v7.0.3) (2021-02-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* include lib/types.d.ts in files list ([#6844](https://github.com/puppeteer/puppeteer/issues/6844)) ([e34f317](https://github.com/puppeteer/puppeteer/commit/e34f317b37533256a063c1238609b488d263b998))
|
||||
|
||||
### [7.0.2](https://github.com/puppeteer/puppeteer/compare/v7.0.1...v7.0.2) (2021-02-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* much better TypeScript definitions ([#6837](https://github.com/puppeteer/puppeteer/issues/6837)) ([f1b46ab](https://github.com/puppeteer/puppeteer/commit/f1b46ab5faa262f893c17923579d0cf52268a764))
|
||||
* **domworld:** reset bindings when context changes ([#6766](https://github.com/puppeteer/puppeteer/issues/6766)) ([#6836](https://github.com/puppeteer/puppeteer/issues/6836)) ([4e8d074](https://github.com/puppeteer/puppeteer/commit/4e8d074c2f8384a2f283f5edf9ef69c40bd8464f))
|
||||
* **launcher:** output correct error message for browser ([#6815](https://github.com/puppeteer/puppeteer/issues/6815)) ([6c61874](https://github.com/puppeteer/puppeteer/commit/6c618747979c3a08f2727e9e22fe45cade8c926a))
|
||||
|
||||
### [7.0.1](https://github.com/puppeteer/puppeteer/compare/v7.0.0...v7.0.1) (2021-02-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **typescript:** ship .d.ts file in npm package ([#6811](https://github.com/puppeteer/puppeteer/issues/6811)) ([a7e3c2e](https://github.com/puppeteer/puppeteer/commit/a7e3c2e09e9163eee2f15221aafa4400e6a75f91))
|
||||
|
||||
## [7.0.0](https://github.com/puppeteer/puppeteer/compare/v6.0.0...v7.0.0) (2021-02-03)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
* - `page.screenshot` makes a screenshot with the clip dimensions, not cutting it by the ViewPort size.
|
||||
* **chromium:** - `page.screenshot` cuts screenshot content by the ViewPort size, not ViewPort position.
|
||||
|
||||
### Features
|
||||
|
||||
* use `captureBeyondViewport` in `Page.captureScreenshot` ([#6805](https://github.com/puppeteer/puppeteer/issues/6805)) ([401d84e](https://github.com/puppeteer/puppeteer/commit/401d84e4a3508f9ca5c24dbfcad2a71571b1b8eb))
|
||||
* **chromium:** roll Chromium to r848005 ([#6801](https://github.com/puppeteer/puppeteer/issues/6801)) ([890d5c2](https://github.com/puppeteer/puppeteer/commit/890d5c2e57cdee7d73915a878bda86b72e26b608))
|
||||
|
||||
## [6.0.0](https://github.com/puppeteer/puppeteer/compare/v5.5.0...v6.0.0) (2021-02-02)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
* **chromium:** The built-in `aria/` selector query handler doesn’t return ignored elements anymore.
|
||||
|
||||
### Features
|
||||
|
||||
* **chromium:** roll Chromium to r843427 ([#6797](https://github.com/puppeteer/puppeteer/issues/6797)) ([8f9fbdb](https://github.com/puppeteer/puppeteer/commit/8f9fbdbae68254600a9c73ab05f36146c975dba6)), closes [#6758](https://github.com/puppeteer/puppeteer/issues/6758)
|
||||
* add page.emulateNetworkConditions ([#6759](https://github.com/puppeteer/puppeteer/issues/6759)) ([5ea76e9](https://github.com/puppeteer/puppeteer/commit/5ea76e9333c42ab5a751ca01aa5676a662f6c063))
|
||||
* **types:** expose typedefs to consumers ([#6745](https://github.com/puppeteer/puppeteer/issues/6745)) ([ebd087a](https://github.com/puppeteer/puppeteer/commit/ebd087a31661a1b701650d0be3e123cc5a813bd8))
|
||||
* add iPhone 11 models to DeviceDescriptors ([#6467](https://github.com/puppeteer/puppeteer/issues/6467)) ([50b810d](https://github.com/puppeteer/puppeteer/commit/50b810dab7fae5950ba086295462788f91ff1e6f))
|
||||
* support fetching and launching on Apple M1 ([9a8479a](https://github.com/puppeteer/puppeteer/commit/9a8479a52a7d8b51690b0732b2a10816cd1b8aef)), closes [#6495](https://github.com/puppeteer/puppeteer/issues/6495) [#6634](https://github.com/puppeteer/puppeteer/issues/6634) [#6641](https://github.com/puppeteer/puppeteer/issues/6641) [#6614](https://github.com/puppeteer/puppeteer/issues/6614)
|
||||
* support promise as return value for page.waitForResponse predicate ([#6624](https://github.com/puppeteer/puppeteer/issues/6624)) ([b57f3fc](https://github.com/puppeteer/puppeteer/commit/b57f3fcd5393c68f51d82e670b004f5b116dcbc3))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **domworld:** fix waitfor bindings ([#6766](https://github.com/puppeteer/puppeteer/issues/6766)) ([#6775](https://github.com/puppeteer/puppeteer/issues/6775)) ([cac540b](https://github.com/puppeteer/puppeteer/commit/cac540be3ab8799a1d77b0951b16bc22ea1c2adb))
|
||||
* **launcher:** rename TranslateUI to Translate to match Chrome ([#6692](https://github.com/puppeteer/puppeteer/issues/6692)) ([d901696](https://github.com/puppeteer/puppeteer/commit/d901696e0d8901bcb23cf676a5e5ac562f821a0d))
|
||||
* do not use old utility world ([#6528](https://github.com/puppeteer/puppeteer/issues/6528)) ([fb85911](https://github.com/puppeteer/puppeteer/commit/fb859115c0e2829bae1d1b32edbf642988e2ef76)), closes [#6527](https://github.com/puppeteer/puppeteer/issues/6527)
|
||||
* update to https-proxy-agent@^5.0.0 to fix `ERR_INVALID_PROTOCOL` ([#6555](https://github.com/puppeteer/puppeteer/issues/6555)) ([3bf5a55](https://github.com/puppeteer/puppeteer/commit/3bf5a552890ee80cc4326b1e430424b0fdad4363))
|
||||
|
||||
## [5.5.0](https://github.com/puppeteer/puppeteer/compare/v5.4.1...v5.5.0) (2020-11-16)
|
||||
|
||||
|
||||
|
@ -183,7 +183,7 @@ There are additional considerations for dependencies that are environment agonis
|
||||
- Tests should not depend on external services.
|
||||
- Tests should work on all three platforms: Mac, Linux and Win. This is especially important for screenshot tests.
|
||||
|
||||
Puppeteer tests are located in the test directory ([`test`](https://github.com/puppeteer/puppeteer/blob/main/test/) and are written using Mocha. See [`test/README.md`](https://github.com/puppeteer/puppeteer/blob/main/test/) for more details.
|
||||
Puppeteer tests are located in [the `test` directory](https://github.com/puppeteer/puppeteer/blob/main/test/) and are written using Mocha. See [`test/README.md`](https://github.com/puppeteer/puppeteer/blob/main/test/README.md) for more details.
|
||||
|
||||
Despite being named 'unit', these are integration tests, making sure public API methods and events work as expected.
|
||||
|
||||
@ -276,9 +276,8 @@ node utils/bisect.js --good 686378 --bad 706915 script.js
|
||||
Releasing to npm consists of the following phases:
|
||||
|
||||
1. Source Code: mark a release.
|
||||
1. Run `npm run release` to bump the version number in `package.json` and populate the changelog.
|
||||
1. Run `npm run doc` to update the docs accordingly.
|
||||
1. Send a PR titled `'chore(release): mark vXXX.YYY.ZZZ'` ([example](https://github.com/puppeteer/puppeteer/pull/5078)).
|
||||
1. Run `npm run release`. (This automatically bumps the version number in `package.json`, populates the changelog, updates the docs, and creates a Git commit for the next step.)
|
||||
1. Send a PR for the commit created in the previous step.
|
||||
1. Make sure the PR passes **all checks**.
|
||||
- **WHY**: there are linters in place that help to avoid unnecessary errors, e.g. [like this](https://github.com/puppeteer/puppeteer/pull/2446)
|
||||
1. Merge the PR.
|
||||
@ -286,5 +285,5 @@ Releasing to npm consists of the following phases:
|
||||
- **NOTE**: tag names are prefixed with `'v'`, e.g. for version `1.4.0` the tag is `v1.4.0`.
|
||||
1. As soon as the Git tag is created by completing the previous step, our CI automatically `npm publish`es the new releases for both the `puppeteer` and `puppeteer-core` packages.
|
||||
1. Source Code: mark post-release.
|
||||
1. Bump `package.json` version to the `-post` version, run `npm run doc` to update the “released APIs” section at the top of `docs/api.md` accordingly, and send a PR titled `'chore: bump version to vXXX.YYY.ZZZ-post'` ([example](https://github.com/puppeteer/puppeteer/commit/d02440d1eac98028e29f4e1cf55413062a259156))
|
||||
1. Bump `package.json` version to the `-post` version, run `npm run doc` to update the “released APIs” section at the top of `docs/api.md` accordingly, and send a PR titled `'chore: bump version to vXXX.YYY.ZZZ-post'` ([example](https://github.com/puppeteer/puppeteer/pull/6808))
|
||||
- **NOTE**: no other commits should be landed in-between release commit and bump commit.
|
||||
|
@ -1,31 +1,35 @@
|
||||
# Puppeteer
|
||||
|
||||
<!-- [START badges] -->
|
||||
[![Build status](https://img.shields.io/travis/com/puppeteer/puppeteer/main.svg)](https://travis-ci.com/puppeteer/puppeteer) [![npm puppeteer package](https://img.shields.io/npm/v/puppeteer.svg)](https://npmjs.org/package/puppeteer) [![Issue resolution status](https://isitmaintained.com/badge/resolution/puppeteer/puppeteer.svg)](https://github.com/puppeteer/puppeteer/issues)
|
||||
|
||||
[![Build status](https://github.com/puppeteer/puppeteer/workflows/run-checks/badge.svg)](https://github.com/puppeteer/puppeteer/actions?query=workflow%3Arun-checks) [![npm puppeteer package](https://img.shields.io/npm/v/puppeteer.svg)](https://npmjs.org/package/puppeteer)
|
||||
|
||||
<!-- [END badges] -->
|
||||
|
||||
<img src="https://user-images.githubusercontent.com/10379601/29446482-04f7036a-841f-11e7-9872-91d1fc2ea683.png" height="200" align="right">
|
||||
|
||||
###### [API](https://github.com/puppeteer/puppeteer/blob/v5.5.0/docs/api.md) | [FAQ](#faq) | [Contributing](https://github.com/puppeteer/puppeteer/blob/main/CONTRIBUTING.md) | [Troubleshooting](https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md)
|
||||
###### [API](https://github.com/puppeteer/puppeteer/blob/v8.0.0/docs/api.md) | [FAQ](#faq) | [Contributing](https://github.com/puppeteer/puppeteer/blob/main/CONTRIBUTING.md) | [Troubleshooting](https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md)
|
||||
|
||||
> Puppeteer is a Node library which provides a high-level API to control Chrome or Chromium over the [DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/). Puppeteer runs [headless](https://developers.google.com/web/updates/2017/04/headless-chrome) by default, but can be configured to run full (non-headless) Chrome or Chromium.
|
||||
|
||||
<!-- [START usecases] -->
|
||||
|
||||
###### What can I do?
|
||||
|
||||
Most things that you can do manually in the browser can be done using Puppeteer! Here are a few examples to get you started:
|
||||
|
||||
* Generate screenshots and PDFs of pages.
|
||||
* Crawl a SPA (Single-Page Application) and generate pre-rendered content (i.e. "SSR" (Server-Side Rendering)).
|
||||
* Automate form submission, UI testing, keyboard input, etc.
|
||||
* Create an up-to-date, automated testing environment. Run your tests directly in the latest version of Chrome using the latest JavaScript and browser features.
|
||||
* Capture a [timeline trace](https://developers.google.com/web/tools/chrome-devtools/evaluate-performance/reference) of your site to help diagnose performance issues.
|
||||
* Test Chrome Extensions.
|
||||
- Generate screenshots and PDFs of pages.
|
||||
- Crawl a SPA (Single-Page Application) and generate pre-rendered content (i.e. "SSR" (Server-Side Rendering)).
|
||||
- Automate form submission, UI testing, keyboard input, etc.
|
||||
- Create an up-to-date, automated testing environment. Run your tests directly in the latest version of Chrome using the latest JavaScript and browser features.
|
||||
- Capture a [timeline trace](https://developers.google.com/web/tools/chrome-devtools/evaluate-performance/reference) of your site to help diagnose performance issues.
|
||||
- Test Chrome Extensions.
|
||||
<!-- [END usecases] -->
|
||||
|
||||
Give it a spin: https://try-puppeteer.appspot.com/
|
||||
|
||||
<!-- [START getstarted] -->
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Installation
|
||||
@ -37,8 +41,7 @@ npm i puppeteer
|
||||
# or "yarn add puppeteer"
|
||||
```
|
||||
|
||||
Note: When you install Puppeteer, it downloads a recent version of Chromium (~170MB Mac, ~282MB Linux, ~280MB Win) that is guaranteed to work with the API. To skip the download, or to download a different browser, see [Environment variables](https://github.com/puppeteer/puppeteer/blob/v5.5.0/docs/api.md#environment-variables).
|
||||
|
||||
Note: When you install Puppeteer, it downloads a recent version of Chromium (~170MB Mac, ~282MB Linux, ~280MB Win) that is guaranteed to work with the API. To skip the download, or to download a different browser, see [Environment variables](https://github.com/puppeteer/puppeteer/blob/v8.0.0/docs/api.md#environment-variables).
|
||||
|
||||
### puppeteer-core
|
||||
|
||||
@ -63,9 +66,9 @@ Note: Prior to v1.18.1, Puppeteer required at least Node v6.4.0. Versions from v
|
||||
Node 8.9.0+. Starting from v3.0.0 Puppeteer starts to rely on Node 10.18.1+. All examples below use async/await which is only supported in Node v7.6.0 or greater.
|
||||
|
||||
Puppeteer will be familiar to people using other browser testing frameworks. You create an instance
|
||||
of `Browser`, open pages, and then manipulate them with [Puppeteer's API](https://github.com/puppeteer/puppeteer/blob/v5.5.0/docs/api.md#).
|
||||
of `Browser`, open pages, and then manipulate them with [Puppeteer's API](https://github.com/puppeteer/puppeteer/blob/v8.0.0/docs/api.md#).
|
||||
|
||||
**Example** - navigating to https://example.com and saving a screenshot as *example.png*:
|
||||
**Example** - navigating to https://example.com and saving a screenshot as _example.png_:
|
||||
|
||||
Save file as **example.js**
|
||||
|
||||
@ -76,7 +79,7 @@ const puppeteer = require('puppeteer');
|
||||
const browser = await puppeteer.launch();
|
||||
const page = await browser.newPage();
|
||||
await page.goto('https://example.com');
|
||||
await page.screenshot({path: 'example.png'});
|
||||
await page.screenshot({ path: 'example.png' });
|
||||
|
||||
await browser.close();
|
||||
})();
|
||||
@ -88,7 +91,7 @@ Execute script on the command line
|
||||
node example.js
|
||||
```
|
||||
|
||||
Puppeteer sets an initial page size to 800×600px, which defines the screenshot size. The page size can be customized with [`Page.setViewport()`](https://github.com/puppeteer/puppeteer/blob/v5.5.0/docs/api.md#pagesetviewportviewport).
|
||||
Puppeteer sets an initial page size to 800×600px, which defines the screenshot size. The page size can be customized with [`Page.setViewport()`](https://github.com/puppeteer/puppeteer/blob/v8.0.0/docs/api.md#pagesetviewportviewport).
|
||||
|
||||
**Example** - create a PDF.
|
||||
|
||||
@ -100,8 +103,10 @@ const puppeteer = require('puppeteer');
|
||||
(async () => {
|
||||
const browser = await puppeteer.launch();
|
||||
const page = await browser.newPage();
|
||||
await page.goto('https://news.ycombinator.com', {waitUntil: 'networkidle2'});
|
||||
await page.pdf({path: 'hn.pdf', format: 'A4'});
|
||||
await page.goto('https://news.ycombinator.com', {
|
||||
waitUntil: 'networkidle2',
|
||||
});
|
||||
await page.pdf({ path: 'hn.pdf', format: 'a4' });
|
||||
|
||||
await browser.close();
|
||||
})();
|
||||
@ -113,7 +118,7 @@ Execute script on the command line
|
||||
node hn.js
|
||||
```
|
||||
|
||||
See [`Page.pdf()`](https://github.com/puppeteer/puppeteer/blob/v5.5.0/docs/api.md#pagepdfoptions) for more information about creating pdfs.
|
||||
See [`Page.pdf()`](https://github.com/puppeteer/puppeteer/blob/v8.0.0/docs/api.md#pagepdfoptions) for more information about creating pdfs.
|
||||
|
||||
**Example** - evaluate script in the context of the page
|
||||
|
||||
@ -132,7 +137,7 @@ const puppeteer = require('puppeteer');
|
||||
return {
|
||||
width: document.documentElement.clientWidth,
|
||||
height: document.documentElement.clientHeight,
|
||||
deviceScaleFactor: window.devicePixelRatio
|
||||
deviceScaleFactor: window.devicePixelRatio,
|
||||
};
|
||||
});
|
||||
|
||||
@ -148,19 +153,20 @@ Execute script on the command line
|
||||
node get-dimensions.js
|
||||
```
|
||||
|
||||
See [`Page.evaluate()`](https://github.com/puppeteer/puppeteer/blob/v5.5.0/docs/api.md#pageevaluatepagefunction-args) for more information on `evaluate` and related methods like `evaluateOnNewDocument` and `exposeFunction`.
|
||||
See [`Page.evaluate()`](https://github.com/puppeteer/puppeteer/blob/v8.0.0/docs/api.md#pageevaluatepagefunction-args) for more information on `evaluate` and related methods like `evaluateOnNewDocument` and `exposeFunction`.
|
||||
|
||||
<!-- [END getstarted] -->
|
||||
|
||||
<!-- [START runtimesettings] -->
|
||||
|
||||
## Default runtime settings
|
||||
|
||||
**1. Uses Headless mode**
|
||||
|
||||
Puppeteer launches Chromium in [headless mode](https://developers.google.com/web/updates/2017/04/headless-chrome). To launch a full version of Chromium, set the [`headless` option](https://github.com/puppeteer/puppeteer/blob/v5.5.0/docs/api.md#puppeteerlaunchoptions) when launching a browser:
|
||||
Puppeteer launches Chromium in [headless mode](https://developers.google.com/web/updates/2017/04/headless-chrome). To launch a full version of Chromium, set the [`headless` option](https://github.com/puppeteer/puppeteer/blob/v8.0.0/docs/api.md#puppeteerlaunchoptions) when launching a browser:
|
||||
|
||||
```js
|
||||
const browser = await puppeteer.launch({headless: false}); // default is true
|
||||
const browser = await puppeteer.launch({ headless: false }); // default is true
|
||||
```
|
||||
|
||||
**2. Runs a bundled version of Chromium**
|
||||
@ -170,10 +176,10 @@ is guaranteed to work out of the box. To use Puppeteer with a different version
|
||||
pass in the executable's path when creating a `Browser` instance:
|
||||
|
||||
```js
|
||||
const browser = await puppeteer.launch({executablePath: '/path/to/Chrome'});
|
||||
const browser = await puppeteer.launch({ executablePath: '/path/to/Chrome' });
|
||||
```
|
||||
|
||||
You can also use Puppeteer with Firefox Nightly (experimental support). See [`Puppeteer.launch()`](https://github.com/puppeteer/puppeteer/blob/v5.5.0/docs/api.md#puppeteerlaunchoptions) for more information.
|
||||
You can also use Puppeteer with Firefox Nightly (experimental support). See [`Puppeteer.launch()`](https://github.com/puppeteer/puppeteer/blob/v8.0.0/docs/api.md#puppeteerlaunchoptions) for more information.
|
||||
|
||||
See [`this article`](https://www.howtogeek.com/202825/what%E2%80%99s-the-difference-between-chromium-and-chrome/) for a description of the differences between Chromium and Chrome. [`This article`](https://chromium.googlesource.com/chromium/src/+/master/docs/chromium_browser_vs_google_chrome.md) describes some differences for Linux users.
|
||||
|
||||
@ -185,43 +191,42 @@ Puppeteer creates its own browser user profile which it **cleans up on every run
|
||||
|
||||
## Resources
|
||||
|
||||
- [API Documentation](https://github.com/puppeteer/puppeteer/blob/v5.5.0/docs/api.md)
|
||||
- [API Documentation](https://github.com/puppeteer/puppeteer/blob/v8.0.0/docs/api.md)
|
||||
- [Examples](https://github.com/puppeteer/puppeteer/tree/main/examples/)
|
||||
- [Community list of Puppeteer resources](https://github.com/transitive-bullshit/awesome-puppeteer)
|
||||
|
||||
|
||||
<!-- [START debugging] -->
|
||||
|
||||
## Debugging tips
|
||||
|
||||
1. Turn off headless mode - sometimes it's useful to see what the browser is
|
||||
displaying. Instead of launching in headless mode, launch a full version of
|
||||
the browser using `headless: false`:
|
||||
1. Turn off headless mode - sometimes it's useful to see what the browser is
|
||||
displaying. Instead of launching in headless mode, launch a full version of
|
||||
the browser using `headless: false`:
|
||||
|
||||
```js
|
||||
const browser = await puppeteer.launch({headless: false});
|
||||
const browser = await puppeteer.launch({ headless: false });
|
||||
```
|
||||
|
||||
2. Slow it down - the `slowMo` option slows down Puppeteer operations by the
|
||||
specified amount of milliseconds. It's another way to help see what's going on.
|
||||
2. Slow it down - the `slowMo` option slows down Puppeteer operations by the
|
||||
specified amount of milliseconds. It's another way to help see what's going on.
|
||||
|
||||
```js
|
||||
const browser = await puppeteer.launch({
|
||||
headless: false,
|
||||
slowMo: 250 // slow down by 250ms
|
||||
slowMo: 250, // slow down by 250ms
|
||||
});
|
||||
```
|
||||
|
||||
3. Capture console output - You can listen for the `console` event.
|
||||
This is also handy when debugging code in `page.evaluate()`:
|
||||
3. Capture console output - You can listen for the `console` event.
|
||||
This is also handy when debugging code in `page.evaluate()`:
|
||||
|
||||
```js
|
||||
page.on('console', msg => console.log('PAGE LOG:', msg.text()));
|
||||
page.on('console', (msg) => console.log('PAGE LOG:', msg.text()));
|
||||
|
||||
await page.evaluate(() => console.log(`url is ${location.href}`));
|
||||
```
|
||||
|
||||
4. Use debugger in application code browser
|
||||
4. Use debugger in application code browser
|
||||
|
||||
There are two execution context: node.js that is running test code, and the browser
|
||||
running application code being tested. This lets you debug code in the
|
||||
@ -230,26 +235,28 @@ Puppeteer creates its own browser user profile which it **cleans up on every run
|
||||
- Use `{devtools: true}` when launching Puppeteer:
|
||||
|
||||
```js
|
||||
const browser = await puppeteer.launch({devtools: true});
|
||||
const browser = await puppeteer.launch({ devtools: true });
|
||||
```
|
||||
|
||||
- Change default test timeout:
|
||||
|
||||
jest: `jest.setTimeout(100000);`
|
||||
jest: `jest.setTimeout(100000);`
|
||||
|
||||
jasmine: `jasmine.DEFAULT_TIMEOUT_INTERVAL = 100000;`
|
||||
jasmine: `jasmine.DEFAULT_TIMEOUT_INTERVAL = 100000;`
|
||||
|
||||
mocha: `this.timeout(100000);` (don't forget to change test to use [function and not '=>'](https://stackoverflow.com/a/23492442))
|
||||
mocha: `this.timeout(100000);` (don't forget to change test to use [function and not '=>'](https://stackoverflow.com/a/23492442))
|
||||
|
||||
- Add an evaluate statement with `debugger` inside / add `debugger` to an existing evaluate statement:
|
||||
- Add an evaluate statement with `debugger` inside / add `debugger` to an existing evaluate statement:
|
||||
|
||||
```js
|
||||
await page.evaluate(() => {debugger;});
|
||||
await page.evaluate(() => {
|
||||
debugger;
|
||||
});
|
||||
```
|
||||
|
||||
The test will now stop executing in the above evaluate statement, and chromium will stop in debug mode.
|
||||
The test will now stop executing in the above evaluate statement, and chromium will stop in debug mode.
|
||||
|
||||
5. Use debugger in node.js
|
||||
5. Use debugger in node.js
|
||||
|
||||
This will let you debug test code. For example, you can step over `await page.click()` in the node.js script and see the click happen in the application code browser.
|
||||
|
||||
@ -270,37 +277,36 @@ Puppeteer creates its own browser user profile which it **cleans up on every run
|
||||
- In the newly opened test browser, type `F8` to resume test execution
|
||||
- Now your `debugger` will be hit and you can debug in the test browser
|
||||
|
||||
6. Enable verbose logging - internal DevTools protocol traffic
|
||||
will be logged via the [`debug`](https://github.com/visionmedia/debug) module under the `puppeteer` namespace.
|
||||
|
||||
6. Enable verbose logging - internal DevTools protocol traffic
|
||||
will be logged via the [`debug`](https://github.com/visionmedia/debug) module under the `puppeteer` namespace.
|
||||
# Basic verbose logging
|
||||
env DEBUG="puppeteer:*" node script.js
|
||||
|
||||
# Basic verbose logging
|
||||
env DEBUG="puppeteer:*" node script.js
|
||||
# Protocol traffic can be rather noisy. This example filters out all Network domain messages
|
||||
env DEBUG="puppeteer:*" env DEBUG_COLORS=true node script.js 2>&1 | grep -v '"Network'
|
||||
|
||||
# Protocol traffic can be rather noisy. This example filters out all Network domain messages
|
||||
env DEBUG="puppeteer:*" env DEBUG_COLORS=true node script.js 2>&1 | grep -v '"Network'
|
||||
7. Debug your Puppeteer (node) code easily, using [ndb](https://github.com/GoogleChromeLabs/ndb)
|
||||
|
||||
7. Debug your Puppeteer (node) code easily, using [ndb](https://github.com/GoogleChromeLabs/ndb)
|
||||
- `npm install -g ndb` (or even better, use [npx](https://github.com/zkat/npx)!)
|
||||
|
||||
- `npm install -g ndb` (or even better, use [npx](https://github.com/zkat/npx)!)
|
||||
- add a `debugger` to your Puppeteer (node) code
|
||||
|
||||
- add a `debugger` to your Puppeteer (node) code
|
||||
- add `ndb` (or `npx ndb`) before your test command. For example:
|
||||
|
||||
- add `ndb` (or `npx ndb`) before your test command. For example:
|
||||
`ndb jest` or `ndb mocha` (or `npx ndb jest` / `npx ndb mocha`)
|
||||
|
||||
`ndb jest` or `ndb mocha` (or `npx ndb jest` / `npx ndb mocha`)
|
||||
|
||||
- debug your test inside chromium like a boss!
|
||||
- debug your test inside chromium like a boss!
|
||||
|
||||
<!-- [END debugging] -->
|
||||
|
||||
|
||||
<!-- [START typescript] -->
|
||||
|
||||
## Usage with TypeScript
|
||||
|
||||
We have recently completed a migration to move the Puppeteer source code from JavaScript to TypeScript and we're currently working on shipping type definitions for TypeScript with Puppeteer's npm package.
|
||||
We have recently completed a migration to move the Puppeteer source code from JavaScript to TypeScript and as of version 7.0.1 we ship our own built-in type definitions.
|
||||
|
||||
Until this work is complete we recommend installing the Puppeteer type definitions from the [DefinitelyTyped](https://definitelytyped.org/) repository:
|
||||
If you are on a version older than 7, we recommend installing the Puppeteer type definitions from the [DefinitelyTyped](https://definitelytyped.org/) repository:
|
||||
|
||||
```bash
|
||||
npm install --save-dev @types/puppeteer
|
||||
@ -310,7 +316,6 @@ The types that you'll see appearing in the Puppeteer source code are based off t
|
||||
|
||||
<!-- [END typescript] -->
|
||||
|
||||
|
||||
## Contributing to Puppeteer
|
||||
|
||||
Check out [contributing guide](https://github.com/puppeteer/puppeteer/blob/main/CONTRIBUTING.md) to get an overview of Puppeteer development.
|
||||
@ -328,7 +333,7 @@ See [Contributing](https://github.com/puppeteer/puppeteer/blob/main/CONTRIBUTING
|
||||
|
||||
Official Firefox support is currently experimental. The ongoing collaboration with Mozilla aims to support common end-to-end testing use cases, for which developers expect cross-browser coverage. The Puppeteer team needs input from users to stabilize Firefox support and to bring missing APIs to our attention.
|
||||
|
||||
From Puppeteer v2.1.0 onwards you can specify [`puppeteer.launch({product: 'firefox'})`](https://github.com/puppeteer/puppeteer/blob/v5.5.0/docs/api.md#puppeteerlaunchoptions) to run your Puppeteer scripts in Firefox Nightly, without any additional custom patches. While [an older experiment](https://www.npmjs.com/package/puppeteer-firefox) required a patched version of Firefox, [the current approach](https://wiki.mozilla.org/Remote) works with “stock” Firefox.
|
||||
From Puppeteer v2.1.0 onwards you can specify [`puppeteer.launch({product: 'firefox'})`](https://github.com/puppeteer/puppeteer/blob/v8.0.0/docs/api.md#puppeteerlaunchoptions) to run your Puppeteer scripts in Firefox Nightly, without any additional custom patches. While [an older experiment](https://www.npmjs.com/package/puppeteer-firefox) required a patched version of Firefox, [the current approach](https://wiki.mozilla.org/Remote) works with “stock” Firefox.
|
||||
|
||||
We will continue to collaborate with other browser vendors to bring Puppeteer support to browsers such as Safari.
|
||||
This effort includes exploration of a standard for executing cross-browser commands (instead of relying on the non-standard DevTools Protocol used by Chrome).
|
||||
@ -344,6 +349,7 @@ The goals of the project are:
|
||||
- Learn more about the pain points of automated browser testing and help fill those gaps.
|
||||
|
||||
We adapt [Chromium principles](https://www.chromium.org/developers/core-principles) to help us drive product decisions:
|
||||
|
||||
- **Speed**: Puppeteer has almost zero performance overhead over an automated page.
|
||||
- **Security**: Puppeteer operates off-process with respect to Chromium, making it safe to automate potentially malicious pages.
|
||||
- **Stability**: Puppeteer should not be flaky and should not leak memory.
|
||||
@ -352,6 +358,7 @@ We adapt [Chromium principles](https://www.chromium.org/developers/core-principl
|
||||
#### Q: Is Puppeteer replacing Selenium/WebDriver?
|
||||
|
||||
**No**. Both projects are valuable for very different reasons:
|
||||
|
||||
- Selenium/WebDriver focuses on cross-browser automation; its value proposition is a single standard API that works across all major browsers.
|
||||
- Puppeteer focuses on Chromium; its value proposition is richer functionality and higher reliability.
|
||||
|
||||
@ -367,6 +374,7 @@ That said, you **can** use Puppeteer to run tests against Chromium, e.g. using t
|
||||
We see Puppeteer as an **indivisible entity** with Chromium. Each version of Puppeteer bundles a specific version of Chromium – **the only** version it is guaranteed to work with.
|
||||
|
||||
This is not an artificial constraint: A lot of work on Puppeteer is actually taking place in the Chromium repository. Here’s a typical story:
|
||||
|
||||
- A Puppeteer bug is reported: https://github.com/puppeteer/puppeteer/issues/2709
|
||||
- It turned out this is an issue with the DevTools protocol, so we’re fixing it in Chromium: https://chromium-review.googlesource.com/c/chromium/src/+/1102154
|
||||
- Once the upstream fix is landed, we roll updated Chromium into Puppeteer: https://github.com/puppeteer/puppeteer/pull/2769
|
||||
@ -374,6 +382,7 @@ This is not an artificial constraint: A lot of work on Puppeteer is actually tak
|
||||
However, oftentimes it is desirable to use Puppeteer with the official Google Chrome rather than Chromium. For this to work, you should install a `puppeteer-core` version that corresponds to the Chrome version.
|
||||
|
||||
For example, in order to drive Chrome 71 with puppeteer-core, use `chrome-71` npm tag:
|
||||
|
||||
```bash
|
||||
npm install puppeteer-core@chrome-71
|
||||
```
|
||||
@ -382,7 +391,6 @@ npm install puppeteer-core@chrome-71
|
||||
|
||||
Look for the `chromium` entry in [revisions.ts](https://github.com/puppeteer/puppeteer/blob/main/src/revisions.ts). To find the corresponding Chromium commit and version number, search for the revision prefixed by an `r` in [OmahaProxy](https://omahaproxy.appspot.com/)'s "Find Releases" section.
|
||||
|
||||
|
||||
#### Q: Which Firefox version does Puppeteer use?
|
||||
|
||||
Since Firefox support is experimental, Puppeteer downloads the latest [Firefox Nightly](https://wiki.mozilla.org/Nightly) when the `PUPPETEER_PRODUCT` environment variable is set to `firefox`. That's also why the value of `firefox` in [revisions.ts](https://github.com/puppeteer/puppeteer/blob/main/src/revisions.ts) is `latest` -- Puppeteer isn't tied to a particular Firefox version.
|
||||
@ -409,6 +417,7 @@ In browsers, input events could be divided into two big groups: trusted vs. untr
|
||||
- **Untrusted event**: events generated by Web APIs, e.g. `document.createEvent` or `element.click()` methods.
|
||||
|
||||
Websites can distinguish between these two groups:
|
||||
|
||||
- using an [`Event.isTrusted`](https://developer.mozilla.org/en-US/docs/Web/API/Event/isTrusted) event flag
|
||||
- sniffing for accompanying events. For example, every trusted `'click'` event is preceded by `'mousedown'` and `'mouseup'` events.
|
||||
|
||||
@ -424,10 +433,11 @@ await page.evaluate(() => {
|
||||
|
||||
You may find that Puppeteer does not behave as expected when controlling pages that incorporate audio and video. (For example, [video playback/screenshots is likely to fail](https://github.com/puppeteer/puppeteer/issues/291).) There are two reasons for this:
|
||||
|
||||
* Puppeteer is bundled with Chromium — not Chrome — and so by default, it inherits all of [Chromium's media-related limitations](https://www.chromium.org/audio-video). This means that Puppeteer does not support licensed formats such as AAC or H.264. (However, it is possible to force Puppeteer to use a separately-installed version Chrome instead of Chromium via the [`executablePath` option to `puppeteer.launch`](https://github.com/puppeteer/puppeteer/blob/v5.5.0/docs/api.md#puppeteerlaunchoptions). You should only use this configuration if you need an official release of Chrome that supports these media formats.)
|
||||
* Since Puppeteer (in all configurations) controls a desktop version of Chromium/Chrome, features that are only supported by the mobile version of Chrome are not supported. This means that Puppeteer [does not support HTTP Live Streaming (HLS)](https://caniuse.com/#feat=http-live-streaming).
|
||||
- Puppeteer is bundled with Chromium — not Chrome — and so by default, it inherits all of [Chromium's media-related limitations](https://www.chromium.org/audio-video). This means that Puppeteer does not support licensed formats such as AAC or H.264. (However, it is possible to force Puppeteer to use a separately-installed version Chrome instead of Chromium via the [`executablePath` option to `puppeteer.launch`](https://github.com/puppeteer/puppeteer/blob/v8.0.0/docs/api.md#puppeteerlaunchoptions). You should only use this configuration if you need an official release of Chrome that supports these media formats.)
|
||||
- Since Puppeteer (in all configurations) controls a desktop version of Chromium/Chrome, features that are only supported by the mobile version of Chrome are not supported. This means that Puppeteer [does not support HTTP Live Streaming (HLS)](https://caniuse.com/#feat=http-live-streaming).
|
||||
|
||||
#### Q: I am having trouble installing / running Puppeteer in my test environment. Where should I look for help?
|
||||
|
||||
We have a [troubleshooting](https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md) guide for various operating systems that lists the required dependencies.
|
||||
|
||||
#### Q: How do I try/test a prerelease version of Puppeteer?
|
||||
@ -443,11 +453,11 @@ Please note that prerelease may be unstable and contain bugs.
|
||||
#### Q: I have more questions! Where do I ask?
|
||||
|
||||
There are many ways to get help on Puppeteer:
|
||||
|
||||
- [bugtracker](https://github.com/puppeteer/puppeteer/issues)
|
||||
- [Stack Overflow](https://stackoverflow.com/questions/tagged/puppeteer)
|
||||
- [slack channel](https://join.slack.com/t/puppeteer/shared_invite/enQtMzU4MjIyMDA5NTM4LWI0YTE0MjM0NWQzYmE2MTRmNjM1ZTBkN2MxNmJmNTIwNTJjMmFhOWFjMGExMDViYjk2YjU2ZmYzMmE1NmExYzc)
|
||||
|
||||
Make sure to search these channels before posting your question.
|
||||
|
||||
|
||||
<!-- [END faq] -->
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
|
||||
"mainEntryPointFilePath": "<projectFolder>/lib/cjs/puppeteer/api-docs-entry.d.ts",
|
||||
"bundledPackages": [ "devtools-protocol" ],
|
||||
"bundledPackages": ["devtools-protocol"],
|
||||
|
||||
"apiReport": {
|
||||
"enabled": false
|
||||
@ -12,7 +12,8 @@
|
||||
},
|
||||
|
||||
"dtsRollup": {
|
||||
"enabled": false
|
||||
"enabled": true,
|
||||
"untrimmedFilePath": "lib/types.d.ts"
|
||||
},
|
||||
|
||||
"tsdocMetadata": {
|
||||
@ -41,5 +42,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -18,7 +18,11 @@ const base = require('./base');
|
||||
|
||||
module.exports = {
|
||||
...base,
|
||||
require: ['./test/mocha-ts-require', './test/mocha-utils.ts'],
|
||||
require: [
|
||||
'./test/mocha-ts-require',
|
||||
'./test/mocha-utils.ts',
|
||||
'source-map-support/register',
|
||||
],
|
||||
spec: 'test/*.spec.ts',
|
||||
extension: ['js', 'ts'],
|
||||
retries: process.env.CI ? 2 : 0,
|
||||
|
@ -5,6 +5,6 @@ origin:
|
||||
description: Headless Chrome Node API
|
||||
license: Apache-2.0
|
||||
name: puppeteer
|
||||
release: a5dedb7
|
||||
url: https://github.com/mjzffr/puppeteer.git
|
||||
release: v8.0.0
|
||||
url: /Users/jdescottes/Development/git/puppeteer
|
||||
schema: 1
|
||||
|
5105
remote/test/puppeteer/package-lock.json
generated
5105
remote/test/puppeteer/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,8 +1,9 @@
|
||||
{
|
||||
"name": "puppeteer",
|
||||
"version": "5.5.0",
|
||||
"version": "8.0.0",
|
||||
"description": "A high-level API to control headless Chrome over the DevTools Protocol",
|
||||
"main": "./cjs-entry.js",
|
||||
"types": "lib/types.d.ts",
|
||||
"repository": "github:puppeteer/puppeteer",
|
||||
"engines": {
|
||||
"node": ">=10.18.1"
|
||||
@ -17,27 +18,33 @@
|
||||
"funit": "PUPPETEER_PRODUCT=firefox npm run unit",
|
||||
"test": "npm run tsc && npm run lint --silent && npm run unit-with-coverage && npm run test-browser",
|
||||
"prepare": "node typescript-if-required.js",
|
||||
"prepublishOnly": "npm run tsc",
|
||||
"prepublishOnly": "npm run build",
|
||||
"dev-install": "npm run tsc && node install.js",
|
||||
"install": "node install.js",
|
||||
"eslint": "([ \"$CI\" = true ] && eslint --ext js --ext ts --quiet -f codeframe . || eslint --ext js --ext ts .)",
|
||||
"eslint-fix": "eslint --ext js --ext ts --fix .",
|
||||
"commitlint": "commitlint --from=HEAD~1",
|
||||
"lint": "npm run eslint && npm run tsc && npm run doc && npm run commitlint",
|
||||
"lint": "npm run eslint && npm run build && npm run doc && npm run commitlint",
|
||||
"doc": "node utils/doclint/cli.js",
|
||||
"clean-lib": "rm -rf lib",
|
||||
"build": "npm run tsc",
|
||||
"build": "npm run tsc && npm run generate-d-ts",
|
||||
"tsc": "npm run clean-lib && tsc --version && npm run tsc-cjs && npm run tsc-esm",
|
||||
"tsc-cjs": "tsc -b src/tsconfig.cjs.json",
|
||||
"tsc-esm": "tsc -b src/tsconfig.esm.json",
|
||||
"apply-next-version": "node utils/apply_next_version.js",
|
||||
"test-install": "scripts/test-install.sh",
|
||||
"generate-docs": "npm run tsc && api-extractor run --local --verbose && api-documenter markdown -i temp -o new-docs",
|
||||
"generate-d-ts": "api-extractor run --local --verbose",
|
||||
"generate-docs": "npm run generate-d-ts && api-documenter markdown -i temp -o new-docs",
|
||||
"ensure-correct-devtools-protocol-revision": "ts-node -s scripts/ensure-correct-devtools-protocol-package",
|
||||
"release": "standard-version"
|
||||
"test-types-file": "ts-node -s scripts/test-ts-definition-files.ts",
|
||||
"release": "node utils/remove_version_suffix.js && standard-version --commit-all"
|
||||
},
|
||||
"files": [
|
||||
"lib/",
|
||||
"lib/types.d.ts",
|
||||
"lib/**/*.d.ts",
|
||||
"lib/**/*.d.ts.map",
|
||||
"lib/**/*.js",
|
||||
"lib/**/*.js.map",
|
||||
"install.js",
|
||||
"typescript-if-required.js",
|
||||
"cjs-entry.js",
|
||||
@ -47,13 +54,13 @@
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"debug": "^4.1.0",
|
||||
"devtools-protocol": "0.0.818844",
|
||||
"devtools-protocol": "0.0.854822",
|
||||
"extract-zip": "^2.0.0",
|
||||
"https-proxy-agent": "^4.0.0",
|
||||
"https-proxy-agent": "^5.0.0",
|
||||
"node-fetch": "^2.6.1",
|
||||
"pkg-dir": "^4.2.0",
|
||||
"progress": "^2.0.1",
|
||||
"proxy-from-env": "^1.0.0",
|
||||
"proxy-from-env": "^1.1.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"tar-fs": "^2.0.0",
|
||||
"unbzip2-stream": "^1.3.3",
|
||||
@ -62,8 +69,8 @@
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^11.0.0",
|
||||
"@commitlint/config-conventional": "^11.0.0",
|
||||
"@microsoft/api-documenter": "7.9.7",
|
||||
"@microsoft/api-extractor": "7.10.4",
|
||||
"@microsoft/api-documenter": "^7.12.7",
|
||||
"@microsoft/api-extractor": "^7.13.1",
|
||||
"@types/debug": "0.0.31",
|
||||
"@types/mime": "^2.0.0",
|
||||
"@types/mocha": "^7.0.2",
|
||||
@ -75,7 +82,7 @@
|
||||
"@types/ws": "^7.2.4",
|
||||
"@typescript-eslint/eslint-plugin": "^4.4.0",
|
||||
"@typescript-eslint/parser": "^4.4.0",
|
||||
"@web/test-runner": "^0.9.2",
|
||||
"@web/test-runner": "^0.12.15",
|
||||
"commonmark": "^0.28.1",
|
||||
"cross-env": "^7.0.2",
|
||||
"eslint": "^7.10.0",
|
||||
@ -96,20 +103,15 @@
|
||||
"pngjs": "^5.0.0",
|
||||
"prettier": "^2.1.2",
|
||||
"sinon": "^9.0.2",
|
||||
"source-map-support": "^0.5.19",
|
||||
"standard-version": "^9.0.0",
|
||||
"text-diff": "^1.0.1",
|
||||
"ts-node": "^9.0.0",
|
||||
"typescript": "3.9.5"
|
||||
"typescript": "^4.1.5"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"commit-msg": "commitlint --env HUSKY_GIT_PARAMS"
|
||||
}
|
||||
},
|
||||
"standard-version": {
|
||||
"skip": {
|
||||
"commit": true,
|
||||
"tag": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
208
remote/test/puppeteer/scripts/test-ts-definition-files.ts
Normal file
208
remote/test/puppeteer/scripts/test-ts-definition-files.ts
Normal file
@ -0,0 +1,208 @@
|
||||
import { spawnSync } from 'child_process';
|
||||
import { version } from '../package.json';
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
const PROJECT_FOLDERS_ROOT = 'test-ts-types';
|
||||
const EXPECTED_ERRORS = new Map<string, string[]>([
|
||||
[
|
||||
'ts-esm-import-esm-output',
|
||||
[
|
||||
"bad.ts(6,35): error TS2551: Property 'launh' does not exist on type",
|
||||
"bad.ts(8,29): error TS2551: Property 'devics' does not exist on type",
|
||||
'bad.ts(12,39): error TS2554: Expected 0 arguments, but got 1.',
|
||||
],
|
||||
],
|
||||
[
|
||||
'ts-esm-import-cjs-output',
|
||||
[
|
||||
"bad.ts(6,35): error TS2551: Property 'launh' does not exist on type",
|
||||
"bad.ts(8,29): error TS2551: Property 'devics' does not exist on type",
|
||||
'bad.ts(12,39): error TS2554: Expected 0 arguments, but got 1.',
|
||||
],
|
||||
],
|
||||
[
|
||||
'ts-cjs-import-cjs-output',
|
||||
[
|
||||
"bad.ts(5,35): error TS2551: Property 'launh' does not exist on type",
|
||||
"bad.ts(7,29): error TS2551: Property 'devics' does not exist on type",
|
||||
'bad.ts(11,39): error TS2554: Expected 0 arguments, but got 1.',
|
||||
],
|
||||
],
|
||||
[
|
||||
'js-esm-import-cjs-output',
|
||||
[
|
||||
"bad.js(5,35): error TS2551: Property 'launh' does not exist on type",
|
||||
"bad.js(7,29): error TS2551: Property 'devics' does not exist on type",
|
||||
'bad.js(11,39): error TS2554: Expected 0 arguments, but got 1.',
|
||||
"bad.js(15,9): error TS2322: Type 'ElementHandle<Element> | null' is not assignable to type 'ElementHandle<HTMLElement>'",
|
||||
],
|
||||
],
|
||||
[
|
||||
'js-cjs-import-esm-output',
|
||||
[
|
||||
"bad.js(5,35): error TS2551: Property 'launh' does not exist on type",
|
||||
"bad.js(7,29): error TS2551: Property 'devics' does not exist on type",
|
||||
'bad.js(11,39): error TS2554: Expected 0 arguments, but got 1.',
|
||||
"bad.js(15,9): error TS2322: Type 'ElementHandle<Element> | null' is not assignable to type 'ElementHandle<HTMLElement>'",
|
||||
],
|
||||
],
|
||||
[
|
||||
'js-esm-import-esm-output',
|
||||
[
|
||||
"bad.js(5,35): error TS2551: Property 'launh' does not exist on type",
|
||||
"bad.js(7,29): error TS2551: Property 'devics' does not exist on type",
|
||||
'bad.js(11,39): error TS2554: Expected 0 arguments, but got 1.',
|
||||
"bad.js(15,9): error TS2322: Type 'ElementHandle<Element> | null' is not assignable to type 'ElementHandle<HTMLElement>'",
|
||||
],
|
||||
],
|
||||
[
|
||||
'js-cjs-import-cjs-output',
|
||||
[
|
||||
"bad.js(5,35): error TS2551: Property 'launh' does not exist on type",
|
||||
"bad.js(7,29): error TS2551: Property 'devics' does not exist on type",
|
||||
'bad.js(11,39): error TS2554: Expected 0 arguments, but got 1.',
|
||||
"bad.js(15,9): error TS2322: Type 'ElementHandle<Element> | null' is not assignable to type 'ElementHandle<HTMLElement>'",
|
||||
],
|
||||
],
|
||||
]);
|
||||
const PROJECT_FOLDERS = [...EXPECTED_ERRORS.keys()];
|
||||
|
||||
function packPuppeteer() {
|
||||
console.log('Packing Puppeteer');
|
||||
const result = spawnSync('npm', ['pack'], {
|
||||
encoding: 'utf-8',
|
||||
});
|
||||
if (result.status !== 0) {
|
||||
console.log('Failed to pack Puppeteer', result.stderr);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Move from puppeteer-X.Y.Z.tgz to puppeteer.tgz so we don't have to update
|
||||
// it when versions change.
|
||||
const moveResult = spawnSync('mv', [
|
||||
`puppeteer-${version}.tgz`,
|
||||
'puppeteer.tgz',
|
||||
]);
|
||||
if (moveResult.status !== 0) {
|
||||
console.log('Failed to rename Puppeteer tar', moveResult.stderr);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
return `puppeteer.tgz`;
|
||||
}
|
||||
|
||||
const tar = packPuppeteer();
|
||||
const tarPath = path.join(process.cwd(), tar);
|
||||
|
||||
function compileAndCatchErrors(projectLocation) {
|
||||
const { status, stdout, stderr } = spawnSync('npm', ['run', 'compile'], {
|
||||
cwd: projectLocation,
|
||||
encoding: 'utf-8',
|
||||
});
|
||||
const tsErrorMesssage = stdout.split('\n');
|
||||
|
||||
if (status === 0) {
|
||||
console.error(
|
||||
`Running tsc on ${projectLocation} succeeded without triggering the expected errors.`
|
||||
);
|
||||
console.log(stdout, stderr);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
return {
|
||||
tsErrorMesssage,
|
||||
};
|
||||
}
|
||||
|
||||
function testProject(folder: string) {
|
||||
console.log('\nTesting:', folder);
|
||||
const projectLocation = path.join(
|
||||
process.cwd(),
|
||||
PROJECT_FOLDERS_ROOT,
|
||||
folder
|
||||
);
|
||||
|
||||
const tarLocation = path.relative(projectLocation, tarPath);
|
||||
console.log('===> Clearing left over node_modules to ensure clean slate');
|
||||
try {
|
||||
fs.rmdirSync(path.join(projectLocation, 'node_modules'), {
|
||||
recursive: true,
|
||||
});
|
||||
} catch (_error) {
|
||||
// We don't care if this errors because if it did it's most likely because
|
||||
// there was no node_modules folder, which is fine.
|
||||
}
|
||||
console.log('===> Installing Puppeteer from tar file', tarLocation);
|
||||
const { status, stderr, stdout } = spawnSync(
|
||||
'npm',
|
||||
['install', tarLocation],
|
||||
{
|
||||
env: {
|
||||
...process.env,
|
||||
PUPPETEER_SKIP_DOWNLOAD: '1',
|
||||
},
|
||||
cwd: projectLocation,
|
||||
encoding: 'utf-8',
|
||||
}
|
||||
);
|
||||
|
||||
if (status > 0) {
|
||||
console.error(
|
||||
'Installing the tar file unexpectedly failed',
|
||||
stdout,
|
||||
stderr
|
||||
);
|
||||
process.exit(status);
|
||||
}
|
||||
console.log('===> Running compile to ensure expected errors only.');
|
||||
const result = compileAndCatchErrors(projectLocation);
|
||||
const expectedErrors = EXPECTED_ERRORS.get(folder) || [];
|
||||
if (
|
||||
result.tsErrorMesssage.find(
|
||||
(line) => line.includes('good.ts') || line.includes('good.js')
|
||||
)
|
||||
) {
|
||||
console.error(
|
||||
`Error for ${projectLocation} contained unexpected failures in good.ts/good.js:\n${result.tsErrorMesssage.join(
|
||||
'\n'
|
||||
)}`
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
const errorsInTsMessage = result.tsErrorMesssage.filter(
|
||||
(line) => line.includes('bad.ts') || line.includes('bad.js')
|
||||
);
|
||||
const expectedErrorsThatHaveOccurred = new Set<string>();
|
||||
const unexpectedErrors = errorsInTsMessage.filter((message) => {
|
||||
const isExpected = expectedErrors.some((expectedError) => {
|
||||
const isExpected = message.startsWith(expectedError);
|
||||
if (isExpected) {
|
||||
expectedErrorsThatHaveOccurred.add(expectedError);
|
||||
}
|
||||
return isExpected;
|
||||
});
|
||||
return !isExpected;
|
||||
});
|
||||
|
||||
if (unexpectedErrors.length) {
|
||||
console.error(
|
||||
`${projectLocation} had unexpected TS errors: ${unexpectedErrors.join(
|
||||
'\n'
|
||||
)}`
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
expectedErrors.forEach((expected) => {
|
||||
if (!expectedErrorsThatHaveOccurred.has(expected)) {
|
||||
console.error(
|
||||
`${projectLocation} expected error that was not thrown: ${expected}`
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
console.log('===> ✅ Type-checked correctly.');
|
||||
}
|
||||
|
||||
PROJECT_FOLDERS.forEach((folder) => {
|
||||
testProject(folder);
|
||||
});
|
@ -14,6 +14,19 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
LaunchOptions,
|
||||
BrowserLaunchArgumentOptions,
|
||||
} from './node/LaunchOptions.js';
|
||||
import { BrowserConnectOptions } from './common/BrowserConnector.js';
|
||||
import { Product } from './common/Product.js';
|
||||
import { Browser } from './common/Browser.js';
|
||||
import { ConnectOptions } from './common/Puppeteer.js';
|
||||
import { DevicesMap } from './common/DeviceDescriptors.js';
|
||||
import { PuppeteerErrors } from './common/Errors.js';
|
||||
import { PredefinedNetworkConditions } from './common/NetworkConditions.js';
|
||||
import { CustomQueryHandler } from './common/QueryHandler.js';
|
||||
|
||||
/*
|
||||
* This file re-exports any APIs that we want to have documentation generated
|
||||
* for. It is used by API Extractor to determine what parts of the system to
|
||||
@ -30,6 +43,7 @@ export * from './common/Accessibility.js';
|
||||
export * from './common/Browser.js';
|
||||
export * from './node/BrowserFetcher.js';
|
||||
export * from './node/Puppeteer.js';
|
||||
export * from './common/Coverage.js';
|
||||
export * from './common/Connection.js';
|
||||
export * from './common/ConsoleMessage.js';
|
||||
export * from './common/Coverage.js';
|
||||
@ -41,6 +55,7 @@ export * from './common/ExecutionContext.js';
|
||||
export * from './common/EventEmitter.js';
|
||||
export * from './common/FileChooser.js';
|
||||
export * from './common/FrameManager.js';
|
||||
export * from './common/PuppeteerViewport.js';
|
||||
export * from './common/Input.js';
|
||||
export * from './common/Page.js';
|
||||
export * from './common/Product.js';
|
||||
@ -62,4 +77,75 @@ export * from './common/PDFOptions.js';
|
||||
export * from './common/TimeoutSettings.js';
|
||||
export * from './common/LifecycleWatcher.js';
|
||||
export * from './common/QueryHandler.js';
|
||||
export * from './common/NetworkConditions.js';
|
||||
export * from 'devtools-protocol/types/protocol';
|
||||
|
||||
/*
|
||||
* We maintain a namespace that emulates the API of the Puppeteer instance you
|
||||
* get when you `import puppeteer from 'puppeteer'.
|
||||
*
|
||||
* We do this as a namespace because export = PuppeteerDefault where
|
||||
* PuppeteerDefault is a namespace seems to make sure that the types work in
|
||||
* both ESM and CJS contexts.
|
||||
*
|
||||
* This namespace must be kept in sync with the public API offered by the
|
||||
* PuppeteerNode class.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @public
|
||||
* {@inheritDoc PuppeteerNode.launch}
|
||||
*/
|
||||
export declare function launch(
|
||||
options?: LaunchOptions &
|
||||
BrowserLaunchArgumentOptions &
|
||||
BrowserConnectOptions & {
|
||||
product?: Product;
|
||||
extraPrefsFirefox?: Record<string, unknown>;
|
||||
}
|
||||
): Promise<Browser>;
|
||||
|
||||
/**
|
||||
* @public
|
||||
* {@inheritDoc PuppeteerNode.connect}
|
||||
*/
|
||||
export declare function connect(options: ConnectOptions): Promise<Browser>;
|
||||
|
||||
/**
|
||||
* @public
|
||||
* {@inheritDoc Puppeteer.devices}
|
||||
*/
|
||||
export let devices: DevicesMap;
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export let errors: PuppeteerErrors;
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export let networkConditions: PredefinedNetworkConditions;
|
||||
|
||||
/**
|
||||
* @public
|
||||
* {@inheritDoc Puppeteer.registerCustomQueryHandler}
|
||||
*/
|
||||
export declare function registerCustomQueryHandler(
|
||||
name: string,
|
||||
queryHandler: CustomQueryHandler
|
||||
): void;
|
||||
|
||||
/**
|
||||
* @public
|
||||
* {@inheritDoc Puppeteer.unregisterCustomQueryHandler}
|
||||
*/
|
||||
export declare function unregisterCustomQueryHandler(name: string): void;
|
||||
/**
|
||||
* @public
|
||||
* {@inheritDoc Puppeteer.customQueryHandlerNames}
|
||||
*/
|
||||
export declare function customQueryHandlerNames(): string[];
|
||||
/**
|
||||
* @public
|
||||
* {@inheritDoc Puppeteer.clearCustomQueryHandlers}
|
||||
*/
|
||||
export declare function clearCustomQueryHandlers(): void;
|
||||
|
@ -26,6 +26,52 @@ import { Viewport } from './PuppeteerViewport.js';
|
||||
|
||||
type BrowserCloseCallback = () => Promise<void> | void;
|
||||
|
||||
const WEB_PERMISSION_TO_PROTOCOL_PERMISSION = new Map<
|
||||
Permission,
|
||||
Protocol.Browser.PermissionType
|
||||
>([
|
||||
['geolocation', 'geolocation'],
|
||||
['midi', 'midi'],
|
||||
['notifications', 'notifications'],
|
||||
// TODO: push isn't a valid type?
|
||||
// ['push', 'push'],
|
||||
['camera', 'videoCapture'],
|
||||
['microphone', 'audioCapture'],
|
||||
['background-sync', 'backgroundSync'],
|
||||
['ambient-light-sensor', 'sensors'],
|
||||
['accelerometer', 'sensors'],
|
||||
['gyroscope', 'sensors'],
|
||||
['magnetometer', 'sensors'],
|
||||
['accessibility-events', 'accessibilityEvents'],
|
||||
['clipboard-read', 'clipboardReadWrite'],
|
||||
['clipboard-write', 'clipboardReadWrite'],
|
||||
['payment-handler', 'paymentHandler'],
|
||||
['idle-detection', 'idleDetection'],
|
||||
// chrome-specific permissions we have.
|
||||
['midi-sysex', 'midiSysex'],
|
||||
]);
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export type Permission =
|
||||
| 'geolocation'
|
||||
| 'midi'
|
||||
| 'notifications'
|
||||
| 'camera'
|
||||
| 'microphone'
|
||||
| 'background-sync'
|
||||
| 'ambient-light-sensor'
|
||||
| 'accelerometer'
|
||||
| 'gyroscope'
|
||||
| 'magnetometer'
|
||||
| 'accessibility-events'
|
||||
| 'clipboard-read'
|
||||
| 'clipboard-write'
|
||||
| 'payment-handler'
|
||||
| 'idle-detection'
|
||||
| 'midi-sysex';
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
@ -650,34 +696,12 @@ export class BrowserContext extends EventEmitter {
|
||||
*/
|
||||
async overridePermissions(
|
||||
origin: string,
|
||||
permissions: string[]
|
||||
permissions: Permission[]
|
||||
): Promise<void> {
|
||||
const webPermissionToProtocol = new Map<
|
||||
string,
|
||||
Protocol.Browser.PermissionType
|
||||
>([
|
||||
['geolocation', 'geolocation'],
|
||||
['midi', 'midi'],
|
||||
['notifications', 'notifications'],
|
||||
// TODO: push isn't a valid type?
|
||||
// ['push', 'push'],
|
||||
['camera', 'videoCapture'],
|
||||
['microphone', 'audioCapture'],
|
||||
['background-sync', 'backgroundSync'],
|
||||
['ambient-light-sensor', 'sensors'],
|
||||
['accelerometer', 'sensors'],
|
||||
['gyroscope', 'sensors'],
|
||||
['magnetometer', 'sensors'],
|
||||
['accessibility-events', 'accessibilityEvents'],
|
||||
['clipboard-read', 'clipboardReadWrite'],
|
||||
['clipboard-write', 'clipboardReadWrite'],
|
||||
['payment-handler', 'paymentHandler'],
|
||||
['idle-detection', 'idleDetection'],
|
||||
// chrome-specific permissions we have.
|
||||
['midi-sysex', 'midiSysex'],
|
||||
]);
|
||||
const protocolPermissions = permissions.map((permission) => {
|
||||
const protocolPermission = webPermissionToProtocol.get(permission);
|
||||
const protocolPermission = WEB_PERMISSION_TO_PROTOCOL_PERMISSION.get(
|
||||
permission
|
||||
);
|
||||
if (!protocolPermission)
|
||||
throw new Error('Unknown permission: ' + permission);
|
||||
return protocolPermission;
|
||||
|
@ -24,12 +24,24 @@ import { Viewport } from './PuppeteerViewport.js';
|
||||
import { isNode } from '../environment.js';
|
||||
|
||||
/**
|
||||
* Generic browser options that can be passed when launching any browser.
|
||||
* Generic browser options that can be passed when launching any browser or when
|
||||
* connecting to an existing browser instance.
|
||||
* @public
|
||||
*/
|
||||
export interface BrowserOptions {
|
||||
export interface BrowserConnectOptions {
|
||||
/**
|
||||
* Whether to ignore HTTPS errors during navigation.
|
||||
* @defaultValue false
|
||||
*/
|
||||
ignoreHTTPSErrors?: boolean;
|
||||
/**
|
||||
* Sets the viewport for each page.
|
||||
*/
|
||||
defaultViewport?: Viewport;
|
||||
/**
|
||||
* Slows down Puppeteer operations by the specified amount of milliseconds to
|
||||
* aid debugging.
|
||||
*/
|
||||
slowMo?: number;
|
||||
}
|
||||
|
||||
@ -46,7 +58,7 @@ const getWebSocketTransportClass = async () => {
|
||||
* @internal
|
||||
*/
|
||||
export const connectToBrowser = async (
|
||||
options: BrowserOptions & {
|
||||
options: BrowserConnectOptions & {
|
||||
browserWSEndpoint?: string;
|
||||
browserURL?: string;
|
||||
transport?: ConnectionTransport;
|
||||
|
@ -115,6 +115,7 @@ export class DOMWorld {
|
||||
|
||||
async _setContext(context?: ExecutionContext): Promise<void> {
|
||||
if (context) {
|
||||
this._ctxBindings.clear();
|
||||
this._contextResolveCallback.call(null, context);
|
||||
this._contextResolveCallback = null;
|
||||
for (const waitTask of this._waitTasks) waitTask.rerun();
|
||||
@ -512,9 +513,12 @@ export class DOMWorld {
|
||||
const bind = async (name: string) => {
|
||||
const expression = helper.pageBindingInitString('internal', name);
|
||||
try {
|
||||
// TODO: In theory, it would be enough to call this just once
|
||||
await context._client.send('Runtime.addBinding', {
|
||||
name,
|
||||
executionContextId: context._contextId,
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore The protocol definition is not up to date.
|
||||
executionContextName: context._contextName,
|
||||
});
|
||||
await context.evaluate(expression);
|
||||
} catch (error) {
|
||||
|
@ -548,6 +548,84 @@ const devices: Device[] = [
|
||||
isLandscape: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'iPhone 11',
|
||||
userAgent:
|
||||
'Mozilla/5.0 (iPhone; CPU iPhone OS 13_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1 Mobile/15E148 Safari/604.1',
|
||||
viewport: {
|
||||
width: 414,
|
||||
height: 828,
|
||||
deviceScaleFactor: 2,
|
||||
isMobile: true,
|
||||
hasTouch: true,
|
||||
isLandscape: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'iPhone 11 landscape',
|
||||
userAgent:
|
||||
'Mozilla/5.0 (iPhone; CPU iPhone OS 13_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1 Mobile/15E148 Safari/604.1',
|
||||
viewport: {
|
||||
width: 828,
|
||||
height: 414,
|
||||
deviceScaleFactor: 2,
|
||||
isMobile: true,
|
||||
hasTouch: true,
|
||||
isLandscape: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'iPhone 11 Pro',
|
||||
userAgent:
|
||||
'Mozilla/5.0 (iPhone; CPU iPhone OS 13_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1 Mobile/15E148 Safari/604.1',
|
||||
viewport: {
|
||||
width: 375,
|
||||
height: 812,
|
||||
deviceScaleFactor: 3,
|
||||
isMobile: true,
|
||||
hasTouch: true,
|
||||
isLandscape: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'iPhone 11 Pro landscape',
|
||||
userAgent:
|
||||
'Mozilla/5.0 (iPhone; CPU iPhone OS 13_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1 Mobile/15E148 Safari/604.1',
|
||||
viewport: {
|
||||
width: 812,
|
||||
height: 375,
|
||||
deviceScaleFactor: 3,
|
||||
isMobile: true,
|
||||
hasTouch: true,
|
||||
isLandscape: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'iPhone 11 Pro Max',
|
||||
userAgent:
|
||||
'Mozilla/5.0 (iPhone; CPU iPhone OS 13_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1 Mobile/15E148 Safari/604.1',
|
||||
viewport: {
|
||||
width: 414,
|
||||
height: 896,
|
||||
deviceScaleFactor: 3,
|
||||
isMobile: true,
|
||||
hasTouch: true,
|
||||
isLandscape: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'iPhone 11 Pro Max landscape',
|
||||
userAgent:
|
||||
'Mozilla/5.0 (iPhone; CPU iPhone OS 13_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1 Mobile/15E148 Safari/604.1',
|
||||
viewport: {
|
||||
width: 896,
|
||||
height: 414,
|
||||
deviceScaleFactor: 3,
|
||||
isMobile: true,
|
||||
hasTouch: true,
|
||||
isLandscape: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'JioPhone 2',
|
||||
userAgent:
|
||||
|
@ -19,9 +19,7 @@ import { JSHandle, ElementHandle } from './JSHandle.js';
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export type EvaluateFn<T = unknown> =
|
||||
| string
|
||||
| ((arg1: T, ...args: unknown[]) => unknown);
|
||||
export type EvaluateFn<T = any> = string | ((arg1: T, ...args: any[]) => any);
|
||||
|
||||
export type UnwrapPromiseLike<T> = T extends PromiseLike<infer U> ? U : T;
|
||||
|
||||
@ -29,15 +27,15 @@ export type UnwrapPromiseLike<T> = T extends PromiseLike<infer U> ? U : T;
|
||||
* @public
|
||||
*/
|
||||
export type EvaluateFnReturnType<T extends EvaluateFn> = T extends (
|
||||
...args: unknown[]
|
||||
...args: any[]
|
||||
) => infer R
|
||||
? R
|
||||
: unknown;
|
||||
: any;
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export type EvaluateHandleFn = string | ((...args: unknown[]) => unknown);
|
||||
export type EvaluateHandleFn = string | ((...args: any[]) => any);
|
||||
|
||||
/**
|
||||
* @public
|
||||
|
@ -56,6 +56,10 @@ export class ExecutionContext {
|
||||
* @internal
|
||||
*/
|
||||
_contextId: number;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_contextName: string;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
@ -68,6 +72,7 @@ export class ExecutionContext {
|
||||
this._client = client;
|
||||
this._world = world;
|
||||
this._contextId = contextPayload.id;
|
||||
this._contextName = contextPayload.name;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -322,18 +322,19 @@ export class FrameManager extends EventEmitter {
|
||||
await this._client.send('Page.addScriptToEvaluateOnNewDocument', {
|
||||
source: `//# sourceURL=${EVALUATION_SCRIPT_URL}`,
|
||||
worldName: name,
|
||||
}),
|
||||
await Promise.all(
|
||||
this.frames().map((frame) =>
|
||||
this._client
|
||||
.send('Page.createIsolatedWorld', {
|
||||
frameId: frame._id,
|
||||
grantUniveralAccess: true,
|
||||
worldName: name,
|
||||
})
|
||||
.catch(debugError)
|
||||
)
|
||||
); // frames might be removed before we send this
|
||||
});
|
||||
// Frames might be removed before we send this.
|
||||
await Promise.all(
|
||||
this.frames().map((frame) =>
|
||||
this._client
|
||||
.send('Page.createIsolatedWorld', {
|
||||
frameId: frame._id,
|
||||
worldName: name,
|
||||
grantUniveralAccess: true,
|
||||
})
|
||||
.catch(debugError)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
_onFrameNavigatedWithinDocument(frameId: string, url: string): void {
|
||||
@ -369,8 +370,6 @@ export class FrameManager extends EventEmitter {
|
||||
world = frame._secondaryWorld;
|
||||
}
|
||||
}
|
||||
if (contextPayload.auxData && contextPayload.auxData['type'] === 'isolated')
|
||||
this._isolatedWorlds.add(contextPayload.name);
|
||||
const context = new ExecutionContext(this._client, contextPayload, world);
|
||||
if (world) world._setContext(context);
|
||||
this._contextIdToContext.set(contextPayload.id, context);
|
||||
|
@ -45,6 +45,13 @@ export interface ResponseForRequest {
|
||||
body: string | Buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resource types for HTTPRequests as perceived by the rendering engine.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type ResourceType = Lowercase<Protocol.Network.ResourceType>;
|
||||
|
||||
/**
|
||||
*
|
||||
* Represents an HTTP request sent by a page.
|
||||
@ -108,7 +115,7 @@ export class HTTPRequest {
|
||||
private _allowInterception: boolean;
|
||||
private _interceptionHandled = false;
|
||||
private _url: string;
|
||||
private _resourceType: string;
|
||||
private _resourceType: ResourceType;
|
||||
|
||||
private _method: string;
|
||||
private _postData?: string;
|
||||
@ -133,7 +140,7 @@ export class HTTPRequest {
|
||||
this._interceptionId = interceptionId;
|
||||
this._allowInterception = allowInterception;
|
||||
this._url = event.request.url;
|
||||
this._resourceType = event.type.toLowerCase();
|
||||
this._resourceType = event.type.toLowerCase() as ResourceType;
|
||||
this._method = event.request.method;
|
||||
this._postData = event.request.postData;
|
||||
this._frame = frame;
|
||||
@ -153,17 +160,8 @@ export class HTTPRequest {
|
||||
/**
|
||||
* Contains the request's resource type as it was perceived by the rendering
|
||||
* engine.
|
||||
* @remarks
|
||||
* @returns one of the following: `document`, `stylesheet`, `image`, `media`,
|
||||
* `font`, `script`, `texttrack`, `xhr`, `fetch`, `eventsource`, `websocket`,
|
||||
* `manifest`, `other`.
|
||||
*/
|
||||
resourceType(): string {
|
||||
// TODO (@jackfranklin): protocol.d.ts has a type for this, but all the
|
||||
// string values are uppercase. The Puppeteer docs explicitly say the
|
||||
// potential values are all lower case, and the constructor takes the event
|
||||
// type and calls toLowerCase() on it, so we can't reuse the type from the
|
||||
// protocol.d.ts. Why do we lower case?
|
||||
resourceType(): ResourceType {
|
||||
return this._resourceType;
|
||||
}
|
||||
|
||||
|
@ -243,7 +243,7 @@ export class JSHandle {
|
||||
* on the object in page and consequent {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse | JSON.parse} in puppeteer.
|
||||
* **NOTE** The method throws if the referenced object is not stringifiable.
|
||||
*/
|
||||
async jsonValue(): Promise<Record<string, unknown>> {
|
||||
async jsonValue<T = unknown>(): Promise<T> {
|
||||
if (this._remoteObject.objectId) {
|
||||
const response = await this._client.send('Runtime.callFunctionOn', {
|
||||
functionDeclaration: 'function() { return this; }',
|
||||
@ -251,9 +251,9 @@ export class JSHandle {
|
||||
returnByValue: true,
|
||||
awaitPromise: true,
|
||||
});
|
||||
return helper.valueFromRemoteObject(response.result);
|
||||
return helper.valueFromRemoteObject(response.result) as T;
|
||||
}
|
||||
return helper.valueFromRemoteObject(this._remoteObject);
|
||||
return helper.valueFromRemoteObject(this._remoteObject) as T;
|
||||
}
|
||||
|
||||
/**
|
||||
|
38
remote/test/puppeteer/src/common/NetworkConditions.ts
Normal file
38
remote/test/puppeteer/src/common/NetworkConditions.ts
Normal file
@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright 2021 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 { NetworkConditions } from './NetworkManager.js';
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export type PredefinedNetworkConditions = { [name: string]: NetworkConditions };
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export const networkConditions: PredefinedNetworkConditions = {
|
||||
'Slow 3G': {
|
||||
download: ((500 * 1000) / 8) * 0.8,
|
||||
upload: ((500 * 1000) / 8) * 0.8,
|
||||
latency: 400 * 5,
|
||||
},
|
||||
'Fast 3G': {
|
||||
download: ((1.6 * 1000 * 1000) / 8) * 0.9,
|
||||
upload: ((750 * 1000) / 8) * 0.9,
|
||||
latency: 150 * 3.75,
|
||||
},
|
||||
};
|
@ -30,6 +30,22 @@ export interface Credentials {
|
||||
password: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface NetworkConditions {
|
||||
// Download speed (bytes/s)
|
||||
download: number;
|
||||
// Upload speed (bytes/s)
|
||||
upload: number;
|
||||
// Latency (ms)
|
||||
latency: number;
|
||||
}
|
||||
|
||||
export interface InternalNetworkConditions extends NetworkConditions {
|
||||
offline: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* We use symbols to prevent any external parties listening to these events.
|
||||
* They are internal to Puppeteer.
|
||||
@ -56,13 +72,18 @@ export class NetworkManager extends EventEmitter {
|
||||
Protocol.Network.RequestWillBeSentEvent
|
||||
>();
|
||||
_extraHTTPHeaders: Record<string, string> = {};
|
||||
_offline = false;
|
||||
_credentials?: Credentials = null;
|
||||
_attemptedAuthentications = new Set<string>();
|
||||
_userRequestInterceptionEnabled = false;
|
||||
_protocolRequestInterceptionEnabled = false;
|
||||
_userCacheDisabled = false;
|
||||
_requestIdToInterceptionId = new Map<string, string>();
|
||||
_emulatedNetworkConditions: InternalNetworkConditions = {
|
||||
offline: false,
|
||||
upload: -1,
|
||||
download: -1,
|
||||
latency: 0,
|
||||
};
|
||||
|
||||
constructor(
|
||||
client: CDPSession,
|
||||
@ -130,14 +151,32 @@ export class NetworkManager extends EventEmitter {
|
||||
}
|
||||
|
||||
async setOfflineMode(value: boolean): Promise<void> {
|
||||
if (this._offline === value) return;
|
||||
this._offline = value;
|
||||
this._emulatedNetworkConditions.offline = value;
|
||||
await this._updateNetworkConditions();
|
||||
}
|
||||
|
||||
async emulateNetworkConditions(
|
||||
networkConditions: NetworkConditions | null
|
||||
): Promise<void> {
|
||||
this._emulatedNetworkConditions.upload = networkConditions
|
||||
? networkConditions.upload
|
||||
: -1;
|
||||
this._emulatedNetworkConditions.download = networkConditions
|
||||
? networkConditions.download
|
||||
: -1;
|
||||
this._emulatedNetworkConditions.latency = networkConditions
|
||||
? networkConditions.latency
|
||||
: 0;
|
||||
|
||||
await this._updateNetworkConditions();
|
||||
}
|
||||
|
||||
async _updateNetworkConditions(): Promise<void> {
|
||||
await this._client.send('Network.emulateNetworkConditions', {
|
||||
offline: this._offline,
|
||||
// values of 0 remove any active throttling. crbug.com/456324#c9
|
||||
latency: 0,
|
||||
downloadThroughput: -1,
|
||||
uploadThroughput: -1,
|
||||
offline: this._emulatedNetworkConditions.offline,
|
||||
latency: this._emulatedNetworkConditions.latency,
|
||||
uploadThroughput: this._emulatedNetworkConditions.upload,
|
||||
downloadThroughput: this._emulatedNetworkConditions.download,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,11 @@ import { Browser, BrowserContext } from './Browser.js';
|
||||
import { Target } from './Target.js';
|
||||
import { createJSHandle, JSHandle, ElementHandle } from './JSHandle.js';
|
||||
import { Viewport } from './PuppeteerViewport.js';
|
||||
import { Credentials, NetworkManagerEmittedEvents } from './NetworkManager.js';
|
||||
import {
|
||||
Credentials,
|
||||
NetworkConditions,
|
||||
NetworkManagerEmittedEvents,
|
||||
} from './NetworkManager.js';
|
||||
import { HTTPRequest } from './HTTPRequest.js';
|
||||
import { HTTPResponse } from './HTTPResponse.js';
|
||||
import { Accessibility } from './Accessibility.js';
|
||||
@ -131,21 +135,54 @@ interface MediaFeature {
|
||||
value: string;
|
||||
}
|
||||
|
||||
interface ScreenshotClip {
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface ScreenshotClip {
|
||||
x: number;
|
||||
y: number;
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
interface ScreenshotOptions {
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface ScreenshotOptions {
|
||||
/**
|
||||
* @defaultValue 'png'
|
||||
*/
|
||||
type?: 'png' | 'jpeg';
|
||||
/**
|
||||
* The file path to save the image to. The screenshot type will be inferred
|
||||
* from file extension. If path is a relative path, then it is resolved
|
||||
* relative to current working directory. If no path is provided, the image
|
||||
* won't be saved to the disk.
|
||||
*/
|
||||
path?: string;
|
||||
/**
|
||||
* When true, takes a screenshot of the full page.
|
||||
* @defaultValue false
|
||||
*/
|
||||
fullPage?: boolean;
|
||||
/**
|
||||
* An object which specifies the clipping region of the page.
|
||||
*/
|
||||
clip?: ScreenshotClip;
|
||||
/**
|
||||
* Quality of the image, between 0-100. Not applicable to `png` images.
|
||||
*/
|
||||
quality?: number;
|
||||
/**
|
||||
* Hides default white background and allows capturing screenshots with transparency.
|
||||
* @defaultValue false
|
||||
*/
|
||||
omitBackground?: boolean;
|
||||
encoding?: string;
|
||||
/**
|
||||
* Encoding of the image.
|
||||
* @defaultValue 'binary'
|
||||
*/
|
||||
encoding?: 'base64' | 'binary';
|
||||
}
|
||||
|
||||
/**
|
||||
@ -693,6 +730,14 @@ export class Page extends EventEmitter {
|
||||
return this._frameManager.networkManager().setOfflineMode(enabled);
|
||||
}
|
||||
|
||||
emulateNetworkConditions(
|
||||
networkConditions: NetworkConditions | null
|
||||
): Promise<void> {
|
||||
return this._frameManager
|
||||
.networkManager()
|
||||
.emulateNetworkConditions(networkConditions);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param timeout - Maximum navigation time in milliseconds.
|
||||
*/
|
||||
@ -1298,11 +1343,11 @@ export class Page extends EventEmitter {
|
||||
return helper.waitForEvent(
|
||||
this._frameManager.networkManager(),
|
||||
NetworkManagerEmittedEvents.Response,
|
||||
(response) => {
|
||||
async (response) => {
|
||||
if (helper.isString(urlOrPredicate))
|
||||
return urlOrPredicate === response.url();
|
||||
if (typeof urlOrPredicate === 'function')
|
||||
return !!urlOrPredicate(response);
|
||||
return !!(await urlOrPredicate(response));
|
||||
return false;
|
||||
},
|
||||
timeout,
|
||||
@ -1375,7 +1420,9 @@ export class Page extends EventEmitter {
|
||||
features.every((mediaFeature) => {
|
||||
const name = mediaFeature.name;
|
||||
assert(
|
||||
/^prefers-(?:color-scheme|reduced-motion)$/.test(name),
|
||||
/^(?:prefers-(?:color-scheme|reduced-motion)|color-gamut)$/.test(
|
||||
name
|
||||
),
|
||||
'Unsupported media feature: ' + name
|
||||
);
|
||||
return true;
|
||||
@ -1668,20 +1715,8 @@ export class Page extends EventEmitter {
|
||||
const width = Math.ceil(metrics.contentSize.width);
|
||||
const height = Math.ceil(metrics.contentSize.height);
|
||||
|
||||
// Overwrite clip for full page at all times.
|
||||
// Overwrite clip for full page.
|
||||
clip = { x: 0, y: 0, width, height, scale: 1 };
|
||||
const { isMobile = false, deviceScaleFactor = 1, isLandscape = false } =
|
||||
this._viewport || {};
|
||||
const screenOrientation: Protocol.Emulation.ScreenOrientation = isLandscape
|
||||
? { angle: 90, type: 'landscapePrimary' }
|
||||
: { angle: 0, type: 'portraitPrimary' };
|
||||
await this._client.send('Emulation.setDeviceMetricsOverride', {
|
||||
mobile: isMobile,
|
||||
width,
|
||||
height,
|
||||
deviceScaleFactor,
|
||||
screenOrientation,
|
||||
});
|
||||
}
|
||||
const shouldSetDefaultBackground =
|
||||
options.omitBackground && format === 'png';
|
||||
@ -1693,6 +1728,7 @@ export class Page extends EventEmitter {
|
||||
format,
|
||||
quality: options.quality,
|
||||
clip,
|
||||
captureBeyondViewport: true,
|
||||
});
|
||||
if (shouldSetDefaultBackground)
|
||||
await this._client.send('Emulation.setDefaultBackgroundColorOverride');
|
||||
|
@ -25,7 +25,11 @@ import {
|
||||
CustomQueryHandler,
|
||||
} from './QueryHandler.js';
|
||||
import { Product } from './Product.js';
|
||||
import { connectToBrowser, BrowserOptions } from './BrowserConnector.js';
|
||||
import { connectToBrowser, BrowserConnectOptions } from './BrowserConnector.js';
|
||||
import {
|
||||
PredefinedNetworkConditions,
|
||||
networkConditions,
|
||||
} from './NetworkConditions.js';
|
||||
|
||||
/**
|
||||
* Settings that are common to the Puppeteer class, regardless of enviroment.
|
||||
@ -35,7 +39,7 @@ export interface CommonPuppeteerSettings {
|
||||
isPuppeteerCore: boolean;
|
||||
}
|
||||
|
||||
export interface ConnectOptions extends BrowserOptions {
|
||||
export interface ConnectOptions extends BrowserConnectOptions {
|
||||
browserWSEndpoint?: string;
|
||||
browserURL?: string;
|
||||
transport?: ConnectionTransport;
|
||||
@ -125,6 +129,31 @@ export class Puppeteer {
|
||||
return puppeteerErrors;
|
||||
}
|
||||
|
||||
/**
|
||||
* @remarks
|
||||
* Returns a list of network conditions to be used with `page.emulateNetworkConditions(networkConditions)`. Actual list of predefined conditions can be found in {@link https://github.com/puppeteer/puppeteer/blob/main/src/common/NetworkConditions.ts | src/common/NetworkConditions.ts}.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* ```js
|
||||
* const puppeteer = require('puppeteer');
|
||||
* const slow3G = puppeteer.networkConditions['Slow 3G'];
|
||||
*
|
||||
* (async () => {
|
||||
* const browser = await puppeteer.launch();
|
||||
* const page = await browser.newPage();
|
||||
* await page.emulateNetworkConditions(slow3G);
|
||||
* await page.goto('https://www.google.com');
|
||||
* // other actions...
|
||||
* await browser.close();
|
||||
* })();
|
||||
* ```
|
||||
*
|
||||
*/
|
||||
get networkConditions(): PredefinedNetworkConditions {
|
||||
return networkConditions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a {@link CustomQueryHandler | custom query handler}. After
|
||||
* registration, the handler can be used everywhere where a selector is
|
||||
|
@ -13,11 +13,39 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/**
|
||||
*
|
||||
* Sets the viewport of the page.
|
||||
* @public
|
||||
*/
|
||||
export interface Viewport {
|
||||
/**
|
||||
* The page width in pixels.
|
||||
*/
|
||||
width: number;
|
||||
/**
|
||||
* The page height in pixels.
|
||||
*/
|
||||
height: number;
|
||||
/**
|
||||
* Specify device scale factor.
|
||||
* See {@link https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio | devicePixelRatio} for more info.
|
||||
* @defaultValue 1
|
||||
*/
|
||||
deviceScaleFactor?: number;
|
||||
/**
|
||||
* Whether the `meta viewport` tag is taken into account.
|
||||
* @defaultValue false
|
||||
*/
|
||||
isMobile?: boolean;
|
||||
/**
|
||||
* Specifies if the viewport is in landscape mode.
|
||||
* @defaultValue false
|
||||
*/
|
||||
isLandscape?: boolean;
|
||||
/**
|
||||
* Specify if the viewport supports touch events.
|
||||
* @defaultValue false
|
||||
*/
|
||||
hasTouch?: boolean;
|
||||
}
|
||||
|
@ -124,7 +124,7 @@ function isNumber(obj: unknown): obj is number {
|
||||
async function waitForEvent<T extends any>(
|
||||
emitter: CommonEventEmitter,
|
||||
eventName: string | symbol,
|
||||
predicate: (event: T) => boolean,
|
||||
predicate: (event: T) => Promise<boolean> | boolean,
|
||||
timeout: number,
|
||||
abortPromise: Promise<Error>
|
||||
): Promise<T> {
|
||||
@ -133,8 +133,8 @@ async function waitForEvent<T extends any>(
|
||||
resolveCallback = resolve;
|
||||
rejectCallback = reject;
|
||||
});
|
||||
const listener = addEventListener(emitter, eventName, (event) => {
|
||||
if (!predicate(event)) return;
|
||||
const listener = addEventListener(emitter, eventName, async (event) => {
|
||||
if (!(await predicate(event))) return;
|
||||
resolveCallback(event);
|
||||
});
|
||||
if (timeout) {
|
||||
|
@ -28,7 +28,10 @@ import { debug } from '../common/Debug.js';
|
||||
import { promisify } from 'util';
|
||||
import removeRecursive from 'rimraf';
|
||||
import * as URL from 'url';
|
||||
import ProxyAgent from 'https-proxy-agent';
|
||||
import createHttpsProxyAgent, {
|
||||
HttpsProxyAgent,
|
||||
HttpsProxyAgentOptions,
|
||||
} from 'https-proxy-agent';
|
||||
import { getProxyForUrl } from 'proxy-from-env';
|
||||
import { assert } from '../common/assert.js';
|
||||
|
||||
@ -108,10 +111,15 @@ function downloadURL(
|
||||
function handleArm64(): void {
|
||||
fs.stat('/usr/bin/chromium-browser', function (err, stats) {
|
||||
if (stats === undefined) {
|
||||
console.error(`The chromium binary is not available for arm64: `);
|
||||
console.error(`If you are on Ubuntu, you can install with: `);
|
||||
console.error(`\n apt-get install chromium-browser\n`);
|
||||
throw new Error();
|
||||
fs.stat('/usr/bin/chromium', function (err, stats) {
|
||||
if (stats === undefined) {
|
||||
console.error(`The chromium binary is not available for arm64.`);
|
||||
console.error(`If you are on Ubuntu, you can install with: `);
|
||||
console.error(`\n sudo apt install chromium\n`);
|
||||
console.error(`\n sudo apt install chromium-browser\n`);
|
||||
throw new Error();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -557,7 +565,7 @@ function httpRequest(
|
||||
|
||||
type Options = Partial<URL.UrlWithStringQuery> & {
|
||||
method?: string;
|
||||
agent?: ProxyAgent;
|
||||
agent?: HttpsProxyAgent;
|
||||
rejectUnauthorized?: boolean;
|
||||
};
|
||||
|
||||
@ -581,9 +589,9 @@ function httpRequest(
|
||||
const proxyOptions = {
|
||||
...parsedProxyURL,
|
||||
secureProxy: parsedProxyURL.protocol === 'https:',
|
||||
} as ProxyAgent.HttpsProxyAgentOptions;
|
||||
} as HttpsProxyAgentOptions;
|
||||
|
||||
options.agent = new ProxyAgent(proxyOptions);
|
||||
options.agent = createHttpsProxyAgent(proxyOptions);
|
||||
options.rejectUnauthorized = false;
|
||||
}
|
||||
}
|
||||
|
@ -13,16 +13,37 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { BrowserConnectOptions } from '../common/BrowserConnector.js';
|
||||
import { Product } from '../common/Product.js';
|
||||
|
||||
/**
|
||||
* Launcher options that only apply to Chrome.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface ChromeArgOptions {
|
||||
export interface BrowserLaunchArgumentOptions {
|
||||
/**
|
||||
* Whether to run the browser in headless mode.
|
||||
* @defaultValue true
|
||||
*/
|
||||
headless?: boolean;
|
||||
args?: string[];
|
||||
/**
|
||||
* Path to a user data directory.
|
||||
* {@link https://chromium.googlesource.com/chromium/src/+/master/docs/user_data_dir.md | see the Chromium docs}
|
||||
* for more info.
|
||||
*/
|
||||
userDataDir?: string;
|
||||
/**
|
||||
* Whether to auto-open a DevTools panel for each tab. If this is set to
|
||||
* `true`, then `headless` will be set to `false` automatically.
|
||||
* @defaultValue `false`
|
||||
*/
|
||||
devtools?: boolean;
|
||||
/**
|
||||
* Additional command line arguments to pass to the browser instance.
|
||||
*/
|
||||
args?: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -30,13 +51,72 @@ export interface ChromeArgOptions {
|
||||
* @public
|
||||
*/
|
||||
export interface LaunchOptions {
|
||||
/**
|
||||
* Path to a browser executable to use instead of the bundled Chromium. Note
|
||||
* that Puppeteer is only guaranteed to work with the bundled Chromium, so use
|
||||
* this setting at your own risk.
|
||||
*/
|
||||
executablePath?: string;
|
||||
/**
|
||||
* If `true`, do not use `puppeteer.defaultArgs()` when creating a browser. If
|
||||
* an array is provided, these args will be filtered out. Use this with care -
|
||||
* you probably want the default arguments Puppeteer uses.
|
||||
* @defaultValue false
|
||||
*/
|
||||
ignoreDefaultArgs?: boolean | string[];
|
||||
/**
|
||||
* Close the browser process on `Ctrl+C`.
|
||||
* @defaultValue `true`
|
||||
*/
|
||||
handleSIGINT?: boolean;
|
||||
/**
|
||||
* Close the browser process on `SIGTERM`.
|
||||
* @defaultValue `true`
|
||||
*/
|
||||
handleSIGTERM?: boolean;
|
||||
/**
|
||||
* Close the browser process on `SIGHUP`.
|
||||
* @defaultValue `true`
|
||||
*/
|
||||
handleSIGHUP?: boolean;
|
||||
/**
|
||||
* Maximum time in milliseconds to wait for the browser to start.
|
||||
* Pass `0` to disable the timeout.
|
||||
* @defaultValue 30000 (30 seconds).
|
||||
*/
|
||||
timeout?: number;
|
||||
/**
|
||||
* If true, pipes the browser process stdout and stderr to `process.stdout`
|
||||
* and `process.stderr`.
|
||||
* @defaultValue false
|
||||
*/
|
||||
dumpio?: boolean;
|
||||
/**
|
||||
* Specify environment variables that will be visible to the browser.
|
||||
* @defaultValue The contents of `process.env`.
|
||||
*/
|
||||
env?: Record<string, string | undefined>;
|
||||
/**
|
||||
* Connect to a browser over a pipe instead of a WebSocket.
|
||||
* @defaultValue false
|
||||
*/
|
||||
pipe?: boolean;
|
||||
/**
|
||||
* Which browser to launch.
|
||||
* @defaultValue `chrome`
|
||||
*/
|
||||
product?: Product;
|
||||
/**
|
||||
* {@link https://developer.mozilla.org/en-US/docs/Mozilla/Preferences/Preference_reference | Additional preferences } that can be passed when launching with Firefox.
|
||||
*/
|
||||
extraPrefsFirefox?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility type exposed to enable users to define options that can be passed to
|
||||
* `puppeteer.launch` without having to list the set of all types.
|
||||
* @public
|
||||
*/
|
||||
export type PuppeteerNodeLaunchOptions = BrowserLaunchArgumentOptions &
|
||||
LaunchOptions &
|
||||
BrowserConnectOptions;
|
||||
|
@ -25,8 +25,10 @@ import { promisify } from 'util';
|
||||
const mkdtempAsync = promisify(fs.mkdtemp);
|
||||
const writeFileAsync = promisify(fs.writeFile);
|
||||
|
||||
import { ChromeArgOptions, LaunchOptions } from './LaunchOptions.js';
|
||||
import { BrowserOptions } from '../common/BrowserConnector.js';
|
||||
import {
|
||||
BrowserLaunchArgumentOptions,
|
||||
PuppeteerNodeLaunchOptions,
|
||||
} from './LaunchOptions.js';
|
||||
import { Product } from '../common/Product.js';
|
||||
|
||||
/**
|
||||
@ -34,9 +36,9 @@ import { Product } from '../common/Product.js';
|
||||
* @public
|
||||
*/
|
||||
export interface ProductLauncher {
|
||||
launch(object);
|
||||
launch(object: PuppeteerNodeLaunchOptions);
|
||||
executablePath: () => string;
|
||||
defaultArgs(object);
|
||||
defaultArgs(object: BrowserLaunchArgumentOptions);
|
||||
product: Product;
|
||||
}
|
||||
|
||||
@ -58,9 +60,7 @@ class ChromeLauncher implements ProductLauncher {
|
||||
this._isPuppeteerCore = isPuppeteerCore;
|
||||
}
|
||||
|
||||
async launch(
|
||||
options: LaunchOptions & ChromeArgOptions & BrowserOptions = {}
|
||||
): Promise<Browser> {
|
||||
async launch(options: PuppeteerNodeLaunchOptions = {}): Promise<Browser> {
|
||||
const {
|
||||
ignoreDefaultArgs = false,
|
||||
args = [],
|
||||
@ -104,12 +104,14 @@ class ChromeLauncher implements ProductLauncher {
|
||||
}
|
||||
|
||||
let chromeExecutable = executablePath;
|
||||
if (os.arch() === 'arm64') {
|
||||
chromeExecutable = '/usr/bin/chromium-browser';
|
||||
} else if (!executablePath) {
|
||||
const { missingText, executablePath } = resolveExecutablePath(this);
|
||||
if (missingText) throw new Error(missingText);
|
||||
chromeExecutable = executablePath;
|
||||
if (!executablePath) {
|
||||
if (os.arch() === 'arm64') {
|
||||
chromeExecutable = '/usr/bin/chromium-browser';
|
||||
} else {
|
||||
const { missingText, executablePath } = resolveExecutablePath(this);
|
||||
if (missingText) throw new Error(missingText);
|
||||
chromeExecutable = executablePath;
|
||||
}
|
||||
}
|
||||
|
||||
const usePipe = chromeArguments.includes('--remote-debugging-pipe');
|
||||
@ -150,11 +152,7 @@ class ChromeLauncher implements ProductLauncher {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {!Launcher.ChromeArgOptions=} options
|
||||
* @returns {!Array<string>}
|
||||
*/
|
||||
defaultArgs(options: ChromeArgOptions = {}): string[] {
|
||||
defaultArgs(options: BrowserLaunchArgumentOptions = {}): string[] {
|
||||
const chromeArguments = [
|
||||
'--disable-background-networking',
|
||||
'--enable-features=NetworkService,NetworkServiceInProcess',
|
||||
@ -166,7 +164,7 @@ class ChromeLauncher implements ProductLauncher {
|
||||
'--disable-default-apps',
|
||||
'--disable-dev-shm-usage',
|
||||
'--disable-extensions',
|
||||
'--disable-features=TranslateUI',
|
||||
'--disable-features=Translate',
|
||||
'--disable-hang-monitor',
|
||||
'--disable-ipc-flooding-protection',
|
||||
'--disable-popup-blocking',
|
||||
@ -228,13 +226,7 @@ class FirefoxLauncher implements ProductLauncher {
|
||||
this._isPuppeteerCore = isPuppeteerCore;
|
||||
}
|
||||
|
||||
async launch(
|
||||
options: LaunchOptions &
|
||||
ChromeArgOptions &
|
||||
BrowserOptions & {
|
||||
extraPrefsFirefox?: { [x: string]: unknown };
|
||||
} = {}
|
||||
): Promise<Browser> {
|
||||
async launch(options: PuppeteerNodeLaunchOptions = {}): Promise<Browser> {
|
||||
const {
|
||||
ignoreDefaultArgs = false,
|
||||
args = [],
|
||||
@ -344,7 +336,7 @@ class FirefoxLauncher implements ProductLauncher {
|
||||
return 'firefox';
|
||||
}
|
||||
|
||||
defaultArgs(options: ChromeArgOptions = {}): string[] {
|
||||
defaultArgs(options: BrowserLaunchArgumentOptions = {}): string[] {
|
||||
const firefoxArguments = ['--no-remote', '--foreground'];
|
||||
if (os.platform().startsWith('win')) {
|
||||
firefoxArguments.push('--wait-for-browser');
|
||||
@ -611,6 +603,7 @@ function resolveExecutablePath(
|
||||
product: launcher.product,
|
||||
path: downloadPath,
|
||||
});
|
||||
|
||||
if (!launcher._isPuppeteerCore && launcher.product === 'chrome') {
|
||||
const revision = process.env['PUPPETEER_CHROMIUM_REVISION'];
|
||||
if (revision) {
|
||||
@ -623,8 +616,13 @@ function resolveExecutablePath(
|
||||
}
|
||||
}
|
||||
const revisionInfo = browserFetcher.revisionInfo(launcher._preferredRevision);
|
||||
|
||||
const firefoxHelp = `Run \`PUPPETEER_PRODUCT=firefox npm install\` to download a supported Firefox browser binary.`;
|
||||
const chromeHelp = `Run \`npm install\` to download the correct Chromium revision (${launcher._preferredRevision}).`;
|
||||
const missingText = !revisionInfo.local
|
||||
? `Could not find browser revision ${launcher._preferredRevision}. Run "PUPPETEER_PRODUCT=firefox npm install" or "PUPPETEER_PRODUCT=firefox yarn install" to download a supported Firefox browser binary.`
|
||||
? `Could not find expected browser (${launcher.product}) locally. ${
|
||||
launcher.product === 'chrome' ? chromeHelp : firefoxHelp
|
||||
}`
|
||||
: null;
|
||||
return { executablePath: revisionInfo.executablePath, missingText };
|
||||
}
|
||||
|
@ -20,8 +20,11 @@ import {
|
||||
ConnectOptions,
|
||||
} from '../common/Puppeteer.js';
|
||||
import { BrowserFetcher, BrowserFetcherOptions } from './BrowserFetcher.js';
|
||||
import { LaunchOptions, ChromeArgOptions } from './LaunchOptions.js';
|
||||
import { BrowserOptions } from '../common/BrowserConnector.js';
|
||||
import {
|
||||
LaunchOptions,
|
||||
BrowserLaunchArgumentOptions,
|
||||
} from './LaunchOptions.js';
|
||||
import { BrowserConnectOptions } from '../common/BrowserConnector.js';
|
||||
import { Browser } from '../common/Browser.js';
|
||||
import Launcher, { ProductLauncher } from './Launcher.js';
|
||||
import { PUPPETEER_REVISIONS } from '../revisions.js';
|
||||
@ -146,8 +149,8 @@ export class PuppeteerNode extends Puppeteer {
|
||||
*/
|
||||
launch(
|
||||
options: LaunchOptions &
|
||||
ChromeArgOptions &
|
||||
BrowserOptions & {
|
||||
BrowserLaunchArgumentOptions &
|
||||
BrowserConnectOptions & {
|
||||
product?: Product;
|
||||
extraPrefsFirefox?: Record<string, unknown>;
|
||||
} = {}
|
||||
@ -215,7 +218,7 @@ export class PuppeteerNode extends Puppeteer {
|
||||
* @param options - Set of configurable options to set on the browser.
|
||||
* @returns The default flags that Chromium will be launched with.
|
||||
*/
|
||||
defaultArgs(options: ChromeArgOptions = {}): string[] {
|
||||
defaultArgs(options: BrowserLaunchArgumentOptions = {}): string[] {
|
||||
return this._launcher.defaultArgs(options);
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,6 @@ type Revisions = Readonly<{
|
||||
}>;
|
||||
|
||||
export const PUPPETEER_REVISIONS: Revisions = {
|
||||
chromium: '818858',
|
||||
chromium: '856583',
|
||||
firefox: 'latest',
|
||||
};
|
||||
|
@ -5,7 +5,5 @@
|
||||
"outDir": "../lib/esm/puppeteer",
|
||||
"module": "esnext"
|
||||
},
|
||||
"references": [
|
||||
{ "path": "../vendor/tsconfig.esm.json"}
|
||||
]
|
||||
"references": [{ "path": "../vendor/tsconfig.esm.json" }]
|
||||
}
|
||||
|
@ -0,0 +1,18 @@
|
||||
const puppeteer = require('puppeteer');
|
||||
|
||||
async function run() {
|
||||
// Typo in "launch"
|
||||
const browser = await puppeteer.launh();
|
||||
// Typo: "devices"
|
||||
const devices = puppeteer.devics;
|
||||
console.log(devices);
|
||||
const browser2 = await puppeteer.launch();
|
||||
// 'foo' is invalid argument
|
||||
const page = await browser2.newPage('foo');
|
||||
/**
|
||||
* @type {puppeteer.ElementHandle<HTMLElement>}
|
||||
*/
|
||||
const div = await page.$('div');
|
||||
console.log('got a div!', div);
|
||||
}
|
||||
run();
|
@ -0,0 +1,17 @@
|
||||
const puppeteer = require('puppeteer');
|
||||
|
||||
async function run() {
|
||||
const browser = await puppeteer.launch();
|
||||
const devices = puppeteer.devices;
|
||||
console.log(devices);
|
||||
const page = await browser.newPage();
|
||||
const div = await page.$('div');
|
||||
if (div) {
|
||||
/**
|
||||
* @type {puppeteer.ElementHandle<HTMLAnchorElement>}
|
||||
*/
|
||||
const newDiv = div;
|
||||
console.log('got a div!', newDiv);
|
||||
}
|
||||
}
|
||||
run();
|
@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "test-ts-types-ts-esm",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"description": "Test project with TypeScript, ESM output",
|
||||
"scripts": {
|
||||
"compile": "../../node_modules/.bin/tsc"
|
||||
},
|
||||
"dependencies": {
|
||||
"puppeteer": "file:../../puppeteer.tgz"
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"checkJs": true,
|
||||
"allowJs": true,
|
||||
"strict": true,
|
||||
"outDir": "dist",
|
||||
"moduleResolution": "node"
|
||||
},
|
||||
"files": ["good.js", "bad.js"]
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
const puppeteer = require('puppeteer');
|
||||
|
||||
async function run() {
|
||||
// Typo in "launch"
|
||||
const browser = await puppeteer.launh();
|
||||
// Typo: "devices"
|
||||
const devices = puppeteer.devics;
|
||||
console.log(devices);
|
||||
const browser2 = await puppeteer.launch();
|
||||
// 'foo' is invalid argument
|
||||
const page = await browser2.newPage('foo');
|
||||
/**
|
||||
* @type {puppeteer.ElementHandle<HTMLElement>}
|
||||
*/
|
||||
const div = await page.$('div');
|
||||
console.log('got a div!', div);
|
||||
}
|
||||
run();
|
@ -0,0 +1,17 @@
|
||||
const puppeteer = require('puppeteer');
|
||||
|
||||
async function run() {
|
||||
const browser = await puppeteer.launch();
|
||||
const devices = puppeteer.devices;
|
||||
console.log(devices);
|
||||
const page = await browser.newPage();
|
||||
const div = await page.$('div');
|
||||
if (div) {
|
||||
/**
|
||||
* @type {puppeteer.ElementHandle<HTMLAnchorElement>}
|
||||
*/
|
||||
const newDiv = div;
|
||||
console.log('got a div!', newDiv);
|
||||
}
|
||||
}
|
||||
run();
|
@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "test-ts-types-ts-esm",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"description": "Test project with TypeScript, ESM output",
|
||||
"scripts": {
|
||||
"compile": "../../node_modules/.bin/tsc"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^4.1.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"puppeteer": "file:../../puppeteer.tgz"
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "esnext",
|
||||
"checkJs": true,
|
||||
"allowJs": true,
|
||||
"strict": true,
|
||||
"outDir": "dist",
|
||||
"moduleResolution": "node"
|
||||
},
|
||||
"files": ["good.js", "bad.js"]
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
import * as puppeteer from 'puppeteer';
|
||||
|
||||
async function run() {
|
||||
// Typo in "launch"
|
||||
const browser = await puppeteer.launh();
|
||||
// Typo: "devices"
|
||||
const devices = puppeteer.devics;
|
||||
console.log(devices);
|
||||
const browser2 = await puppeteer.launch();
|
||||
// 'foo' is invalid argument
|
||||
const page = await browser2.newPage('foo');
|
||||
/**
|
||||
* @type {puppeteer.ElementHandle<HTMLElement>}
|
||||
*/
|
||||
const div = await page.$('div');
|
||||
console.log('got a div!', div);
|
||||
}
|
||||
run();
|
@ -0,0 +1,17 @@
|
||||
import * as puppeteer from 'puppeteer';
|
||||
|
||||
async function run() {
|
||||
const browser = await puppeteer.launch();
|
||||
const devices = puppeteer.devices;
|
||||
console.log(devices);
|
||||
const page = await browser.newPage();
|
||||
const div = await page.$('div');
|
||||
if (div) {
|
||||
/**
|
||||
* @type {puppeteer.ElementHandle<HTMLAnchorElement>}
|
||||
*/
|
||||
const newDiv = div;
|
||||
console.log('got a div!', newDiv);
|
||||
}
|
||||
}
|
||||
run();
|
@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "test-ts-types-ts-esm",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"description": "Test project with TypeScript, ESM output",
|
||||
"scripts": {
|
||||
"compile": "../../node_modules/.bin/tsc"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^4.1.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"puppeteer": "file:../../puppeteer.tgz"
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"checkJs": true,
|
||||
"allowJs": true,
|
||||
"strict": true,
|
||||
"outDir": "dist",
|
||||
"moduleResolution": "node"
|
||||
},
|
||||
"files": ["good.js", "bad.js"]
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
import * as puppeteer from 'puppeteer';
|
||||
|
||||
async function run() {
|
||||
// Typo in "launch"
|
||||
const browser = await puppeteer.launh();
|
||||
// Typo: "devices"
|
||||
const devices = puppeteer.devics;
|
||||
console.log(devices);
|
||||
const browser2 = await puppeteer.launch();
|
||||
// 'foo' is invalid argument
|
||||
const page = await browser2.newPage('foo');
|
||||
/**
|
||||
* @type {puppeteer.ElementHandle<HTMLElement>}
|
||||
*/
|
||||
const div = await page.$('div');
|
||||
console.log('got a div!', div);
|
||||
}
|
||||
run();
|
@ -0,0 +1,17 @@
|
||||
import * as puppeteer from 'puppeteer';
|
||||
|
||||
async function run() {
|
||||
const browser = await puppeteer.launch();
|
||||
const devices = puppeteer.devices;
|
||||
console.log(devices);
|
||||
const page = await browser.newPage();
|
||||
const div = await page.$('div');
|
||||
if (div) {
|
||||
/**
|
||||
* @type {puppeteer.ElementHandle<HTMLAnchorElement>}
|
||||
*/
|
||||
const newDiv = div;
|
||||
console.log('got a div!', newDiv);
|
||||
}
|
||||
}
|
||||
run();
|
@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "test-ts-types-ts-esm",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"description": "Test project with TypeScript, ESM output",
|
||||
"scripts": {
|
||||
"compile": "../../node_modules/.bin/tsc"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^4.1.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"puppeteer": "file:../../puppeteer.tgz"
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "esnext",
|
||||
"checkJs": true,
|
||||
"allowJs": true,
|
||||
"strict": true,
|
||||
"outDir": "dist",
|
||||
"moduleResolution": "node"
|
||||
},
|
||||
"files": ["good.js", "bad.js"]
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
import puppeteer = require('puppeteer');
|
||||
|
||||
async function run() {
|
||||
// Typo in "launch"
|
||||
const browser = await puppeteer.launh();
|
||||
// Typo: "devices"
|
||||
const devices = puppeteer.devics;
|
||||
console.log(devices);
|
||||
const browser2 = await puppeteer.launch();
|
||||
// 'foo' is invalid argument
|
||||
const page = await browser2.newPage('foo');
|
||||
const div = (await page.$('div')) as puppeteer.ElementHandle<
|
||||
HTMLAnchorElement
|
||||
>;
|
||||
console.log('got a div!', div);
|
||||
}
|
||||
run();
|
@ -0,0 +1,13 @@
|
||||
import puppeteer = require('puppeteer');
|
||||
|
||||
async function run() {
|
||||
const browser = await puppeteer.launch();
|
||||
const devices = puppeteer.devices;
|
||||
console.log(devices);
|
||||
const page = await browser.newPage();
|
||||
const div = (await page.$('div')) as puppeteer.ElementHandle<
|
||||
HTMLAnchorElement
|
||||
>;
|
||||
console.log('got a div!', div);
|
||||
}
|
||||
run();
|
@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "test-ts-types-ts-esm",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"description": "Test project with TypeScript, ESM output",
|
||||
"scripts": {
|
||||
"compile": "../../node_modules/.bin/tsc"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^4.1.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"puppeteer": "file:../../puppeteer.tgz"
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"strict": true,
|
||||
"outDir": "dist",
|
||||
"moduleResolution": "node"
|
||||
},
|
||||
"files": ["good.ts", "bad.ts"]
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
// eslint-disable-next-line import/extensions
|
||||
import * as puppeteer from 'puppeteer';
|
||||
|
||||
async function run() {
|
||||
// Typo in "launch"
|
||||
const browser = await puppeteer.launh();
|
||||
// Typo: "devices"
|
||||
const devices = puppeteer.devics;
|
||||
console.log(devices);
|
||||
const browser2 = await puppeteer.launch();
|
||||
// 'foo' is invalid argument
|
||||
const page = await browser2.newPage('foo');
|
||||
const div = (await page.$('div')) as puppeteer.ElementHandle<
|
||||
HTMLAnchorElement
|
||||
>;
|
||||
console.log('got a div!', div);
|
||||
}
|
||||
run();
|
@ -0,0 +1,13 @@
|
||||
// eslint-disable-next-line import/extensions
|
||||
import * as puppeteer from 'puppeteer';
|
||||
import type { ElementHandle } from 'puppeteer';
|
||||
|
||||
async function run() {
|
||||
const browser = await puppeteer.launch();
|
||||
const devices = puppeteer.devices;
|
||||
console.log(devices);
|
||||
const page = await browser.newPage();
|
||||
const div = (await page.$('div')) as ElementHandle<HTMLAnchorElement>;
|
||||
console.log('got a div!', div);
|
||||
}
|
||||
run();
|
@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "test-ts-types-ts-esm",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"description": "Test project with TypeScript, ESM output",
|
||||
"scripts": {
|
||||
"compile": "../../node_modules/.bin/tsc"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^4.1.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"puppeteer": "file:../../puppeteer.tgz"
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"strict": true,
|
||||
"outDir": "dist",
|
||||
"moduleResolution": "node"
|
||||
},
|
||||
"files": ["good.ts", "bad.ts"]
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
// eslint-disable-next-line import/extensions
|
||||
import * as puppeteer from 'puppeteer';
|
||||
|
||||
async function run() {
|
||||
// Typo in "launch"
|
||||
const browser = await puppeteer.launh();
|
||||
// Typo: "devices"
|
||||
const devices = puppeteer.devics;
|
||||
console.log(devices);
|
||||
const browser2 = await puppeteer.launch();
|
||||
// 'foo' is invalid argument
|
||||
const page = await browser2.newPage('foo');
|
||||
const div = (await page.$('div')) as puppeteer.ElementHandle<
|
||||
HTMLAnchorElement
|
||||
>;
|
||||
console.log('got a div!', div);
|
||||
}
|
||||
run();
|
@ -0,0 +1,13 @@
|
||||
// eslint-disable-next-line import/extensions
|
||||
import * as puppeteer from 'puppeteer';
|
||||
import type { ElementHandle } from 'puppeteer';
|
||||
|
||||
async function run() {
|
||||
const browser = await puppeteer.launch();
|
||||
const devices = puppeteer.devices;
|
||||
console.log(devices);
|
||||
const page = await browser.newPage();
|
||||
const div = (await page.$('div')) as ElementHandle<HTMLAnchorElement>;
|
||||
console.log('got a div!', div);
|
||||
}
|
||||
run();
|
@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "test-ts-types-ts-esm",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"description": "Test project with TypeScript, ESM output",
|
||||
"scripts": {
|
||||
"compile": "../../node_modules/.bin/tsc"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^4.1.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"puppeteer": "file:../../puppeteer.tgz"
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "esnext",
|
||||
"strict": true,
|
||||
"outDir": "dist",
|
||||
"moduleResolution": "node"
|
||||
},
|
||||
"files": ["good.ts", "bad.ts"]
|
||||
}
|
@ -185,6 +185,32 @@ describeChromeOnly('AriaQueryHandler', () => {
|
||||
await page.waitForSelector('aria/[role="button"]');
|
||||
});
|
||||
|
||||
it('should persist query handler bindings across reloads', async () => {
|
||||
const { page, server } = getTestState();
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
await page.evaluate(addElement, 'button');
|
||||
await page.waitForSelector('aria/[role="button"]');
|
||||
await page.reload();
|
||||
await page.evaluate(addElement, 'button');
|
||||
await page.waitForSelector('aria/[role="button"]');
|
||||
});
|
||||
|
||||
it('should persist query handler bindings across navigations', async () => {
|
||||
const { page, server } = getTestState();
|
||||
|
||||
// Reset page but make sure that execution context ids start with 1.
|
||||
await page.goto('data:text/html,');
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
await page.evaluate(addElement, 'button');
|
||||
await page.waitForSelector('aria/[role="button"]');
|
||||
|
||||
// Reset page but again make sure that execution context ids start with 1.
|
||||
await page.goto('data:text/html,');
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
await page.evaluate(addElement, 'button');
|
||||
await page.waitForSelector('aria/[role="button"]');
|
||||
});
|
||||
|
||||
it('should work independently of `exposeFunction`', async () => {
|
||||
const { page, server } = getTestState();
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
@ -553,13 +579,13 @@ describeChromeOnly('AriaQueryHandler', () => {
|
||||
const { page } = getTestState();
|
||||
const found = await page.$$('aria/[role="heading"]');
|
||||
const ids = await getIds(found);
|
||||
expect(ids).toEqual(['shown', 'hidden', 'node11', 'node13']);
|
||||
expect(ids).toEqual(['shown', 'node11', 'node13']);
|
||||
});
|
||||
it('should find both ignored and unignored', async () => {
|
||||
it('should not find ignored', async () => {
|
||||
const { page } = getTestState();
|
||||
const found = await page.$$('aria/title');
|
||||
const ids = await getIds(found);
|
||||
expect(ids).toEqual(['shown', 'hidden']);
|
||||
expect(ids).toEqual(['shown']);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,3 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<style>
|
||||
button {
|
||||
position: absolute;
|
||||
@ -29,8 +30,9 @@
|
||||
<button id=btn9>9</button>
|
||||
<button id=btn10>10</button>
|
||||
<script>
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
for (const button of Array.from(document.querySelectorAll('button')))
|
||||
button.addEventListener('click', () => console.log('button #' + button.textContent + ' clicked'), false);
|
||||
}, false);
|
||||
for (const button of document.querySelectorAll('button')) {
|
||||
button.addEventListener('click', () => {
|
||||
console.log(`button #${button.textContent} clicked`);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
@ -43,11 +43,14 @@ describe('Cookie specs', () => {
|
||||
value: 'John Doe',
|
||||
domain: 'localhost',
|
||||
path: '/',
|
||||
sameParty: false,
|
||||
expires: -1,
|
||||
size: 16,
|
||||
httpOnly: false,
|
||||
secure: false,
|
||||
session: true,
|
||||
sourcePort: 8907,
|
||||
sourceScheme: 'NonSecure',
|
||||
},
|
||||
]);
|
||||
});
|
||||
@ -99,22 +102,28 @@ describe('Cookie specs', () => {
|
||||
value: '1234',
|
||||
domain: 'localhost',
|
||||
path: '/',
|
||||
sameParty: false,
|
||||
expires: -1,
|
||||
size: 12,
|
||||
httpOnly: false,
|
||||
secure: false,
|
||||
session: true,
|
||||
sourcePort: 8907,
|
||||
sourceScheme: 'NonSecure',
|
||||
},
|
||||
{
|
||||
name: 'username',
|
||||
value: 'John Doe',
|
||||
domain: 'localhost',
|
||||
path: '/',
|
||||
sameParty: false,
|
||||
expires: -1,
|
||||
size: 16,
|
||||
httpOnly: false,
|
||||
secure: false,
|
||||
session: true,
|
||||
sourcePort: 8907,
|
||||
sourceScheme: 'NonSecure',
|
||||
},
|
||||
]);
|
||||
});
|
||||
@ -145,22 +154,28 @@ describe('Cookie specs', () => {
|
||||
value: 'tweets',
|
||||
domain: 'baz.com',
|
||||
path: '/',
|
||||
sameParty: false,
|
||||
expires: -1,
|
||||
size: 11,
|
||||
httpOnly: false,
|
||||
secure: true,
|
||||
session: true,
|
||||
sourcePort: 443,
|
||||
sourceScheme: 'Secure',
|
||||
},
|
||||
{
|
||||
name: 'doggo',
|
||||
value: 'woofs',
|
||||
domain: 'foo.com',
|
||||
path: '/',
|
||||
sameParty: false,
|
||||
expires: -1,
|
||||
size: 10,
|
||||
httpOnly: false,
|
||||
secure: true,
|
||||
session: true,
|
||||
sourcePort: 443,
|
||||
sourceScheme: 'Secure',
|
||||
},
|
||||
]);
|
||||
});
|
||||
@ -248,11 +263,14 @@ describe('Cookie specs', () => {
|
||||
value: '123456',
|
||||
domain: 'localhost',
|
||||
path: '/',
|
||||
sameParty: false,
|
||||
expires: -1,
|
||||
size: 14,
|
||||
httpOnly: false,
|
||||
secure: false,
|
||||
session: true,
|
||||
sourcePort: 80,
|
||||
sourceScheme: 'NonSecure',
|
||||
},
|
||||
]);
|
||||
});
|
||||
@ -271,11 +289,14 @@ describe('Cookie specs', () => {
|
||||
value: 'GRID',
|
||||
domain: 'localhost',
|
||||
path: '/grid.html',
|
||||
sameParty: false,
|
||||
expires: -1,
|
||||
size: 14,
|
||||
httpOnly: false,
|
||||
secure: false,
|
||||
session: true,
|
||||
sourcePort: 80,
|
||||
sourceScheme: 'NonSecure',
|
||||
},
|
||||
]);
|
||||
expect(await page.evaluate('document.cookie')).toBe('gridcookie=GRID');
|
||||
@ -376,11 +397,14 @@ describe('Cookie specs', () => {
|
||||
value: 'best',
|
||||
domain: 'www.example.com',
|
||||
path: '/',
|
||||
sameParty: false,
|
||||
expires: -1,
|
||||
size: 18,
|
||||
httpOnly: false,
|
||||
secure: true,
|
||||
session: true,
|
||||
sourcePort: 443,
|
||||
sourceScheme: 'Secure',
|
||||
},
|
||||
]);
|
||||
});
|
||||
@ -414,11 +438,14 @@ describe('Cookie specs', () => {
|
||||
value: 'best',
|
||||
domain: 'localhost',
|
||||
path: '/',
|
||||
sameParty: false,
|
||||
expires: -1,
|
||||
size: 20,
|
||||
httpOnly: false,
|
||||
secure: false,
|
||||
session: true,
|
||||
sourcePort: 80,
|
||||
sourceScheme: 'NonSecure',
|
||||
},
|
||||
]);
|
||||
|
||||
@ -428,11 +455,14 @@ describe('Cookie specs', () => {
|
||||
value: 'worst',
|
||||
domain: '127.0.0.1',
|
||||
path: '/',
|
||||
sameParty: false,
|
||||
expires: -1,
|
||||
size: 15,
|
||||
httpOnly: false,
|
||||
secure: false,
|
||||
session: true,
|
||||
sourcePort: 80,
|
||||
sourceScheme: 'NonSecure',
|
||||
},
|
||||
]);
|
||||
});
|
||||
@ -479,12 +509,15 @@ describe('Cookie specs', () => {
|
||||
value: 'best',
|
||||
domain: '127.0.0.1',
|
||||
path: '/',
|
||||
sameParty: false,
|
||||
expires: -1,
|
||||
size: 24,
|
||||
httpOnly: false,
|
||||
sameSite: 'None',
|
||||
secure: true,
|
||||
session: true,
|
||||
sourcePort: 443,
|
||||
sourceScheme: 'Secure',
|
||||
},
|
||||
]);
|
||||
} finally {
|
||||
|
@ -37,11 +37,14 @@ describe('DefaultBrowserContext', function () {
|
||||
value: 'John Doe',
|
||||
domain: 'localhost',
|
||||
path: '/',
|
||||
sameParty: false,
|
||||
expires: -1,
|
||||
size: 16,
|
||||
httpOnly: false,
|
||||
secure: false,
|
||||
session: true,
|
||||
sourcePort: 8907,
|
||||
sourceScheme: 'NonSecure',
|
||||
},
|
||||
]);
|
||||
});
|
||||
@ -62,11 +65,14 @@ describe('DefaultBrowserContext', function () {
|
||||
value: 'John Doe',
|
||||
domain: 'localhost',
|
||||
path: '/',
|
||||
sameParty: false,
|
||||
expires: -1,
|
||||
size: 16,
|
||||
httpOnly: false,
|
||||
secure: false,
|
||||
session: true,
|
||||
sourcePort: 80,
|
||||
sourceScheme: 'NonSecure',
|
||||
},
|
||||
]);
|
||||
});
|
||||
@ -93,11 +99,14 @@ describe('DefaultBrowserContext', function () {
|
||||
value: '1',
|
||||
domain: 'localhost',
|
||||
path: '/',
|
||||
sameParty: false,
|
||||
expires: -1,
|
||||
size: 8,
|
||||
httpOnly: false,
|
||||
secure: false,
|
||||
session: true,
|
||||
sourcePort: 80,
|
||||
sourceScheme: 'NonSecure',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
@ -240,6 +240,38 @@ describe('Emulation', () => {
|
||||
() => matchMedia('(prefers-color-scheme: dark)').matches
|
||||
)
|
||||
).toBe(false);
|
||||
await page.emulateMediaFeatures([{ name: 'color-gamut', value: 'srgb' }]);
|
||||
expect(
|
||||
await page.evaluate(() => matchMedia('(color-gamut: p3)').matches)
|
||||
).toBe(false);
|
||||
expect(
|
||||
await page.evaluate(() => matchMedia('(color-gamut: srgb)').matches)
|
||||
).toBe(true);
|
||||
expect(
|
||||
await page.evaluate(() => matchMedia('(color-gamut: rec2020)').matches)
|
||||
).toBe(false);
|
||||
await page.emulateMediaFeatures([{ name: 'color-gamut', value: 'p3' }]);
|
||||
expect(
|
||||
await page.evaluate(() => matchMedia('(color-gamut: p3)').matches)
|
||||
).toBe(true);
|
||||
expect(
|
||||
await page.evaluate(() => matchMedia('(color-gamut: srgb)').matches)
|
||||
).toBe(true);
|
||||
expect(
|
||||
await page.evaluate(() => matchMedia('(color-gamut: rec2020)').matches)
|
||||
).toBe(false);
|
||||
await page.emulateMediaFeatures([
|
||||
{ name: 'color-gamut', value: 'rec2020' },
|
||||
]);
|
||||
expect(
|
||||
await page.evaluate(() => matchMedia('(color-gamut: p3)').matches)
|
||||
).toBe(true);
|
||||
expect(
|
||||
await page.evaluate(() => matchMedia('(color-gamut: srgb)').matches)
|
||||
).toBe(true);
|
||||
expect(
|
||||
await page.evaluate(() => matchMedia('(color-gamut: rec2020)').matches)
|
||||
).toBe(true);
|
||||
});
|
||||
it('should throw in case of bad argument', async () => {
|
||||
const { page } = getTestState();
|
||||
|
@ -276,7 +276,7 @@ describe('Evaluation specs', function () {
|
||||
|
||||
const windowHandle = await page.evaluateHandle(() => window);
|
||||
const errorText = await windowHandle
|
||||
.jsonValue()
|
||||
.jsonValue<string>()
|
||||
.catch((error_) => error_.message);
|
||||
const error = await page
|
||||
.evaluate<(errorText: string) => Error>((errorText) => {
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 326 B After Width: | Height: | Size: 266 B |
Binary file not shown.
Before Width: | Height: | Size: 326 B After Width: | Height: | Size: 279 B |
@ -15,9 +15,7 @@
|
||||
*/
|
||||
|
||||
import expect from 'expect';
|
||||
import {
|
||||
getTestState,
|
||||
} from './mocha-utils'; // eslint-disable-line import/extensions
|
||||
import { getTestState } from './mocha-utils'; // eslint-disable-line import/extensions
|
||||
|
||||
describe('ignoreHTTPSErrors', function () {
|
||||
/* Note that this test creates its own browser rather than use
|
||||
|
@ -113,9 +113,26 @@ describe('JSHandle', function () {
|
||||
const { page } = getTestState();
|
||||
|
||||
const aHandle = await page.evaluateHandle(() => ({ foo: 'bar' }));
|
||||
const json = await aHandle.jsonValue();
|
||||
const json = await aHandle.jsonValue<Record<string, string>>();
|
||||
expect(json).toEqual({ foo: 'bar' });
|
||||
});
|
||||
|
||||
it('works with jsonValues that are not objects', async () => {
|
||||
const { page } = getTestState();
|
||||
|
||||
const aHandle = await page.evaluateHandle(() => ['a', 'b']);
|
||||
const json = await aHandle.jsonValue<string[]>();
|
||||
expect(json).toEqual(['a', 'b']);
|
||||
});
|
||||
|
||||
it('works with jsonValues that are primitives', async () => {
|
||||
const { page } = getTestState();
|
||||
|
||||
const aHandle = await page.evaluateHandle(() => 'foo');
|
||||
const json = await aHandle.jsonValue<string>();
|
||||
expect(json).toEqual('foo');
|
||||
});
|
||||
|
||||
it('should not work with dates', async () => {
|
||||
const { page } = getTestState();
|
||||
|
||||
|
@ -21,6 +21,7 @@ import { promisify } from 'util';
|
||||
import {
|
||||
getTestState,
|
||||
itOnlyRegularInstall,
|
||||
itFailsWindows,
|
||||
} from './mocha-utils'; // eslint-disable-line import/extensions
|
||||
import utils from './utils.js';
|
||||
import expect from 'expect';
|
||||
@ -472,7 +473,7 @@ describe('Launcher specs', function () {
|
||||
* combo of that plus it running on CI, but it's hard to track down.
|
||||
* See comment here: https://github.com/puppeteer/puppeteer/issues/5673#issuecomment-670141377.
|
||||
*/
|
||||
itOnlyRegularInstall('should be able to launch Firefox', async function () {
|
||||
itFailsWindows('should be able to launch Firefox', async function () {
|
||||
this.timeout(FIREFOX_TIMEOUT);
|
||||
const { puppeteer } = getTestState();
|
||||
const browser = await puppeteer.launch({ product: 'firefox' });
|
||||
@ -587,6 +588,25 @@ describe('Launcher specs', function () {
|
||||
await browserOne.close();
|
||||
}
|
||||
);
|
||||
// @see https://github.com/puppeteer/puppeteer/issues/6527
|
||||
it('should be able to reconnect', async () => {
|
||||
const { puppeteer, server } = getTestState();
|
||||
const browserOne = await puppeteer.launch();
|
||||
const browserWSEndpoint = browserOne.wsEndpoint();
|
||||
const pageOne = await browserOne.newPage();
|
||||
await pageOne.goto(server.EMPTY_PAGE);
|
||||
browserOne.disconnect();
|
||||
|
||||
const browserTwo = await puppeteer.connect({ browserWSEndpoint });
|
||||
const pages = await browserTwo.pages();
|
||||
const pageTwo = pages.find((page) => page.url() === server.EMPTY_PAGE);
|
||||
await pageTwo.reload();
|
||||
const bodyHandle = await pageTwo.waitForSelector('body', {
|
||||
timeout: 10000,
|
||||
});
|
||||
await bodyHandle.dispose();
|
||||
await browserTwo.close();
|
||||
});
|
||||
});
|
||||
describe('Puppeteer.executablePath', function () {
|
||||
itOnlyRegularInstall('should work', async () => {
|
||||
|
@ -611,7 +611,7 @@ describe('navigation', function () {
|
||||
server.PREFIX + '/frames/one-frame.html'
|
||||
);
|
||||
const frame = await utils.waitEvent(page, 'frameattached');
|
||||
await new Promise((fulfill) => {
|
||||
await new Promise<void>((fulfill) => {
|
||||
page.on('framenavigated', (f) => {
|
||||
if (f === frame) fulfill();
|
||||
});
|
||||
|
@ -172,7 +172,7 @@ describe('Page', function () {
|
||||
expect(await page.evaluate(() => !!window.opener)).toBe(false);
|
||||
expect(await popup.evaluate(() => !!window.opener)).toBe(false);
|
||||
});
|
||||
it('should work with clicking target=_blank', async () => {
|
||||
it('should work with clicking target=_blank and without rel=opener', async () => {
|
||||
const { page, server } = getTestState();
|
||||
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
@ -182,6 +182,20 @@ describe('Page', function () {
|
||||
page.click('a'),
|
||||
]);
|
||||
expect(await page.evaluate(() => !!window.opener)).toBe(false);
|
||||
expect(await popup.evaluate(() => !!window.opener)).toBe(false);
|
||||
});
|
||||
it('should work with clicking target=_blank and with rel=opener', async () => {
|
||||
const { page, server } = getTestState();
|
||||
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
await page.setContent(
|
||||
'<a target=_blank rel=opener href="/one-style.html">yo</a>'
|
||||
);
|
||||
const [popup] = await Promise.all([
|
||||
new Promise<Page>((x) => page.once('popup', x)),
|
||||
page.click('a'),
|
||||
]);
|
||||
expect(await page.evaluate(() => !!window.opener)).toBe(false);
|
||||
expect(await popup.evaluate(() => !!window.opener)).toBe(true);
|
||||
});
|
||||
it('should work with fake-clicking target=_blank and rel=noopener', async () => {
|
||||
@ -242,6 +256,7 @@ describe('Page', function () {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
let error = null;
|
||||
await context
|
||||
// @ts-expect-error purposeful bad input for test
|
||||
.overridePermissions(server.EMPTY_PAGE, ['foo'])
|
||||
.catch((error_) => (error = error_));
|
||||
expect(error.message).toBe('Unknown permission: foo');
|
||||
@ -384,6 +399,28 @@ describe('Page', function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Page.emulateNetworkConditions', function () {
|
||||
it('should change navigator.connection.effectiveType', async () => {
|
||||
const { page, puppeteer } = getTestState();
|
||||
|
||||
const slow3G = puppeteer.networkConditions['Slow 3G'];
|
||||
const fast3G = puppeteer.networkConditions['Fast 3G'];
|
||||
|
||||
expect(
|
||||
await page.evaluate('window.navigator.connection.effectiveType')
|
||||
).toBe('4g');
|
||||
await page.emulateNetworkConditions(fast3G);
|
||||
expect(
|
||||
await page.evaluate('window.navigator.connection.effectiveType')
|
||||
).toBe('3g');
|
||||
await page.emulateNetworkConditions(slow3G);
|
||||
expect(
|
||||
await page.evaluate('window.navigator.connection.effectiveType')
|
||||
).toBe('2g');
|
||||
await page.emulateNetworkConditions(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe('ExecutionContext.queryObjects', function () {
|
||||
it('should work', async () => {
|
||||
const { page } = getTestState();
|
||||
@ -708,6 +745,22 @@ describe('Page', function () {
|
||||
.catch((error_) => (error = error_));
|
||||
expect(error).toBeInstanceOf(puppeteer.errors.TimeoutError);
|
||||
});
|
||||
it('should work with async predicate', async () => {
|
||||
const { page, server } = getTestState();
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
const [response] = await Promise.all([
|
||||
page.waitForResponse(async (response) => {
|
||||
console.log(response.url());
|
||||
return response.url() === server.PREFIX + '/digits/2.png';
|
||||
}),
|
||||
page.evaluate(() => {
|
||||
fetch('/digits/1.png');
|
||||
fetch('/digits/2.png');
|
||||
fetch('/digits/3.png');
|
||||
}),
|
||||
]);
|
||||
expect(response.url()).toBe(server.PREFIX + '/digits/2.png');
|
||||
});
|
||||
it('should work with no timeout', async () => {
|
||||
const { page, server } = getTestState();
|
||||
|
||||
|
@ -49,21 +49,23 @@ describe('Screenshots', function () {
|
||||
});
|
||||
expect(screenshot).toBeGolden('screenshot-clip-rect.png');
|
||||
});
|
||||
it('should clip elements to the viewport', async () => {
|
||||
const { page, server } = getTestState();
|
||||
|
||||
await page.setViewport({ width: 500, height: 500 });
|
||||
await page.goto(server.PREFIX + '/grid.html');
|
||||
const screenshot = await page.screenshot({
|
||||
clip: {
|
||||
x: 50,
|
||||
y: 600,
|
||||
width: 100,
|
||||
height: 100,
|
||||
},
|
||||
});
|
||||
expect(screenshot).toBeGolden('screenshot-offscreen-clip.png');
|
||||
});
|
||||
it(
|
||||
'should get screenshot bigger than the viewport',
|
||||
async () => {
|
||||
const { page, server } = getTestState();
|
||||
await page.setViewport({ width: 50, height: 50 });
|
||||
await page.goto(server.PREFIX + '/grid.html');
|
||||
const screenshot = await page.screenshot({
|
||||
clip: {
|
||||
x: 25,
|
||||
y: 25,
|
||||
width: 100,
|
||||
height: 100,
|
||||
},
|
||||
});
|
||||
expect(screenshot).toBeGolden('screenshot-offscreen-clip.png');
|
||||
}
|
||||
);
|
||||
it('should run in parallel', async () => {
|
||||
const { page, server } = getTestState();
|
||||
|
||||
|
@ -79,7 +79,7 @@ describeFailsFirefox('Workers', function () {
|
||||
]);
|
||||
expect(message.text()).toBe('1');
|
||||
expect(message.location()).toEqual({
|
||||
url: 'data:text/javascript,console.log(1)',
|
||||
url: '',
|
||||
lineNumber: 0,
|
||||
columnNumber: 8,
|
||||
});
|
||||
|
@ -1,7 +0,0 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./lib/esm",
|
||||
"module": "ES2015",
|
||||
},
|
||||
}
|
@ -8,6 +8,7 @@
|
||||
"module": "ESNext",
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"resolveJsonModule": true
|
||||
"resolveJsonModule": true,
|
||||
"sourceMap": true
|
||||
}
|
||||
}
|
||||
|
@ -576,6 +576,13 @@ function compareDocumentations(actual, expected) {
|
||||
expectedName: 'Viewport',
|
||||
},
|
||||
],
|
||||
[
|
||||
'Method Page.emulateNetworkConditions() networkConditions',
|
||||
{
|
||||
actualName: 'Object',
|
||||
expectedName: 'NetworkConditions',
|
||||
},
|
||||
],
|
||||
[
|
||||
'Method Page.setViewport() options.viewport',
|
||||
{
|
||||
@ -835,6 +842,28 @@ function compareDocumentations(actual, expected) {
|
||||
expectedName: 'ConnectOptions',
|
||||
},
|
||||
],
|
||||
[
|
||||
'Method Page.deleteCookie() ...cookies',
|
||||
{
|
||||
actualName: '...Object',
|
||||
expectedName: '...DeleteCookiesRequest',
|
||||
},
|
||||
],
|
||||
[
|
||||
'Method Page.emulateVisionDeficiency() type',
|
||||
{
|
||||
actualName: 'string',
|
||||
expectedName:
|
||||
'"none"|"achromatopsia"|"blurredVision"|"deuteranopia"|"protanopia"|"tritanopia"',
|
||||
},
|
||||
],
|
||||
[
|
||||
'Method BrowserContext.overridePermissions() permissions',
|
||||
{
|
||||
actualName: 'Array<string>',
|
||||
expectedName: 'Array<Permission>',
|
||||
},
|
||||
],
|
||||
]);
|
||||
|
||||
const expectedForSource = expectedNamingMismatches.get(source);
|
||||
|
@ -26,6 +26,8 @@ const RED_COLOR = '\x1b[31m';
|
||||
const YELLOW_COLOR = '\x1b[33m';
|
||||
const RESET_COLOR = '\x1b[0m';
|
||||
|
||||
const IS_RELEASE = Boolean(process.env.IS_RELEASE);
|
||||
|
||||
run();
|
||||
|
||||
async function run() {
|
||||
@ -35,11 +37,13 @@ async function run() {
|
||||
const messages = [];
|
||||
let changedFiles = false;
|
||||
|
||||
if (!VERSION.endsWith('-post')) {
|
||||
if (IS_RELEASE) {
|
||||
const versions = await Source.readFile(
|
||||
path.join(PROJECT_DIR, 'versions.js')
|
||||
);
|
||||
versions.setText(versions.text().replace(`, 'NEXT'],`, `, '${VERSION}'],`));
|
||||
versions.setText(
|
||||
versions.text().replace(`, 'NEXT'],`, `, 'v${VERSION}'],`)
|
||||
);
|
||||
await versions.save();
|
||||
}
|
||||
|
||||
@ -125,12 +129,12 @@ async function run() {
|
||||
}
|
||||
console.log(`${errors.length} failures, ${warnings.length} warnings.`);
|
||||
|
||||
if (!clearExit && !process.env.TRAVIS)
|
||||
if (!clearExit && !process.env.GITHUB_ACTIONS)
|
||||
console.log(
|
||||
'\nIs your lib/ directory up to date? You might need to `npm run tsc`.\n'
|
||||
);
|
||||
|
||||
const runningTime = Date.now() - startTime;
|
||||
console.log(`DocLint Finished in ${runningTime / 1000} seconds`);
|
||||
process.exit(clearExit ? 0 : 1);
|
||||
process.exit(clearExit || IS_RELEASE ? 0 : 1);
|
||||
}
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
const Message = require('../Message');
|
||||
|
||||
const IS_RELEASE = Boolean(process.env.IS_RELEASE);
|
||||
|
||||
module.exports.ensureReleasedAPILinks = function (sources, version) {
|
||||
// Release version is everything that doesn't include "-".
|
||||
const apiLinkRegex = /https:\/\/github.com\/puppeteer\/puppeteer\/blob\/v[^/]*\/docs\/api.md/gi;
|
||||
@ -35,7 +37,7 @@ module.exports.ensureReleasedAPILinks = function (sources, version) {
|
||||
|
||||
module.exports.runCommands = function (sources, version) {
|
||||
// Release version is everything that doesn't include "-".
|
||||
const isReleaseVersion = !version.includes('-');
|
||||
const isReleaseVersion = IS_RELEASE || !version.includes('-');
|
||||
|
||||
const messages = [];
|
||||
const commands = [];
|
||||
@ -70,7 +72,7 @@ module.exports.runCommands = function (sources, version) {
|
||||
for (const command of commands) {
|
||||
let newText = null;
|
||||
if (command.name === 'version')
|
||||
newText = isReleaseVersion ? 'v' + version : 'Tip-Of-Tree';
|
||||
newText = isReleaseVersion ? `v${version}` : 'Tip-Of-Tree';
|
||||
else if (command.name === 'empty-if-release')
|
||||
newText = isReleaseVersion ? '' : command.originalText;
|
||||
else if (command.name === 'toc')
|
||||
|
26
remote/test/puppeteer/utils/remove_version_suffix.js
Normal file
26
remote/test/puppeteer/utils/remove_version_suffix.js
Normal file
@ -0,0 +1,26 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const json = fs.readFileSync('./package.json', 'utf8').toString();
|
||||
const pkg = JSON.parse(json);
|
||||
const oldVersion = pkg.version;
|
||||
const version = oldVersion.replace(/-post$/, '');
|
||||
const updated = json.replace(
|
||||
`"version": "${oldVersion}"`,
|
||||
`"version": "${version}"`
|
||||
);
|
||||
fs.writeFileSync('./package.json', updated);
|
@ -17,7 +17,9 @@
|
||||
const versionsPerRelease = new Map([
|
||||
// This is a mapping from Chromium version => Puppeteer version.
|
||||
// In Chromium roll patches, use 'NEXT' for the Puppeteer version.
|
||||
['88.0.4298.0', '5.5.0'],
|
||||
['90.0.4403.0', 'v7.0.0'],
|
||||
['89.0.4389.0', 'v6.0.0'],
|
||||
['88.0.4298.0', 'v5.5.0'],
|
||||
['87.0.4272.0', 'v5.4.0'],
|
||||
['86.0.4240.0', 'v5.3.0'],
|
||||
['85.0.4182.0', 'v5.2.1'],
|
||||
|
@ -17,6 +17,7 @@ const { chromeLauncher } = require('@web/test-runner-chrome');
|
||||
|
||||
module.exports = {
|
||||
files: ['test-browser/**/*.spec.js'],
|
||||
browserStartTimeout: 60 * 1000,
|
||||
browsers: [
|
||||
chromeLauncher({
|
||||
async createPage({ browser }) {
|
||||
|
Loading…
Reference in New Issue
Block a user