Page.ts (99372B)
1 /** 2 * @license 3 * Copyright 2017 Google Inc. 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 import type {Protocol} from 'devtools-protocol'; 8 9 import { 10 concat, 11 EMPTY, 12 filter, 13 first, 14 firstValueFrom, 15 from, 16 map, 17 merge, 18 mergeMap, 19 mergeScan, 20 of, 21 raceWith, 22 ReplaySubject, 23 startWith, 24 switchMap, 25 take, 26 takeUntil, 27 timer, 28 type Observable, 29 } from '../../third_party/rxjs/rxjs.js'; 30 import type {HTTPRequest} from '../api/HTTPRequest.js'; 31 import type {HTTPResponse} from '../api/HTTPResponse.js'; 32 import type {Accessibility} from '../cdp/Accessibility.js'; 33 import type {Coverage} from '../cdp/Coverage.js'; 34 import type {DeviceRequestPrompt} from '../cdp/DeviceRequestPrompt.js'; 35 import type {NetworkConditions} from '../cdp/NetworkManager.js'; 36 import type {Tracing} from '../cdp/Tracing.js'; 37 import type {ConsoleMessage} from '../common/ConsoleMessage.js'; 38 import type { 39 Cookie, 40 CookieParam, 41 DeleteCookiesRequest, 42 } from '../common/Cookie.js'; 43 import type {Device} from '../common/Device.js'; 44 import {TargetCloseError} from '../common/Errors.js'; 45 import { 46 EventEmitter, 47 type EventsWithWildcard, 48 type EventType, 49 type Handler, 50 } from '../common/EventEmitter.js'; 51 import type {FileChooser} from '../common/FileChooser.js'; 52 import type {PDFOptions} from '../common/PDFOptions.js'; 53 import {TimeoutSettings} from '../common/TimeoutSettings.js'; 54 import type { 55 Awaitable, 56 AwaitablePredicate, 57 EvaluateFunc, 58 EvaluateFuncWith, 59 HandleFor, 60 NodeFor, 61 } from '../common/types.js'; 62 import { 63 debugError, 64 fromEmitterEvent, 65 filterAsync, 66 isString, 67 NETWORK_IDLE_TIME, 68 timeout, 69 withSourcePuppeteerURLIfNone, 70 fromAbortSignal, 71 } from '../common/util.js'; 72 import type {Viewport} from '../common/Viewport.js'; 73 import {environment} from '../environment.js'; 74 import type {ScreenRecorder} from '../node/ScreenRecorder.js'; 75 import {guarded} from '../util/decorators.js'; 76 import { 77 AsyncDisposableStack, 78 asyncDisposeSymbol, 79 DisposableStack, 80 disposeSymbol, 81 } from '../util/disposable.js'; 82 import {stringToTypedArray} from '../util/encoding.js'; 83 84 import type {Browser} from './Browser.js'; 85 import type {BrowserContext} from './BrowserContext.js'; 86 import type {CDPSession} from './CDPSession.js'; 87 import type {Dialog} from './Dialog.js'; 88 import type { 89 BoundingBox, 90 ClickOptions, 91 ElementHandle, 92 } from './ElementHandle.js'; 93 import type { 94 Frame, 95 FrameAddScriptTagOptions, 96 FrameAddStyleTagOptions, 97 FrameWaitForFunctionOptions, 98 GoToOptions, 99 WaitForOptions, 100 } from './Frame.js'; 101 import type { 102 Keyboard, 103 KeyboardTypeOptions, 104 Mouse, 105 Touchscreen, 106 } from './Input.js'; 107 import type {JSHandle} from './JSHandle.js'; 108 import { 109 FunctionLocator, 110 Locator, 111 NodeLocator, 112 type AwaitedLocator, 113 } from './locators/locators.js'; 114 import type {Target} from './Target.js'; 115 import type {WebWorker} from './WebWorker.js'; 116 117 /** 118 * @public 119 */ 120 export interface Metrics { 121 Timestamp?: number; 122 Documents?: number; 123 Frames?: number; 124 JSEventListeners?: number; 125 Nodes?: number; 126 LayoutCount?: number; 127 RecalcStyleCount?: number; 128 LayoutDuration?: number; 129 RecalcStyleDuration?: number; 130 ScriptDuration?: number; 131 TaskDuration?: number; 132 JSHeapUsedSize?: number; 133 JSHeapTotalSize?: number; 134 } 135 136 /** 137 * @public 138 */ 139 export interface Credentials { 140 username: string; 141 password: string; 142 } 143 144 /** 145 * @public 146 */ 147 export interface WaitForNetworkIdleOptions extends WaitTimeoutOptions { 148 /** 149 * Time (in milliseconds) the network should be idle. 150 * 151 * @defaultValue `500` 152 */ 153 idleTime?: number; 154 /** 155 * Maximum number concurrent of network connections to be considered inactive. 156 * 157 * @defaultValue `0` 158 */ 159 concurrency?: number; 160 } 161 162 /** 163 * @public 164 */ 165 export interface WaitTimeoutOptions { 166 /** 167 * Maximum wait time in milliseconds. Pass 0 to disable the timeout. 168 * 169 * The default value can be changed by using the 170 * {@link Page.setDefaultTimeout} method. 171 * 172 * @defaultValue `30_000` 173 */ 174 timeout?: number; 175 /** 176 * A signal object that allows you to cancel a waitFor call. 177 */ 178 signal?: AbortSignal; 179 } 180 181 /** 182 * @public 183 */ 184 export interface WaitForSelectorOptions { 185 /** 186 * Wait for the selected element to be present in DOM and to be visible. See 187 * {@link ElementHandle.isVisible} for the definition of element visibility. 188 * 189 * @defaultValue `false` 190 */ 191 visible?: boolean; 192 /** 193 * Wait for the selected element to not be found in the DOM or to be hidden. 194 * See {@link ElementHandle.isHidden} for the definition of element 195 * invisibility. 196 * 197 * @defaultValue `false` 198 */ 199 hidden?: boolean; 200 /** 201 * Maximum time to wait in milliseconds. Pass `0` to disable timeout. 202 * 203 * The default value can be changed by using {@link Page.setDefaultTimeout} 204 * 205 * @defaultValue `30_000` (30 seconds) 206 */ 207 timeout?: number; 208 /** 209 * A signal object that allows you to cancel a waitForSelector call. 210 */ 211 signal?: AbortSignal; 212 } 213 214 /** 215 * @public 216 */ 217 export interface GeolocationOptions { 218 /** 219 * Latitude between `-90` and `90`. 220 */ 221 longitude: number; 222 /** 223 * Longitude between `-180` and `180`. 224 */ 225 latitude: number; 226 /** 227 * Optional non-negative accuracy value. 228 */ 229 accuracy?: number; 230 } 231 232 /** 233 * A media feature to emulate. 234 * 235 * @public 236 */ 237 export interface MediaFeature { 238 /** 239 * A name of the feature, for example, 'prefers-reduced-motion'. 240 */ 241 name: string; 242 /** 243 * A value for the feature, for example, 'reduce'. 244 */ 245 value: string; 246 } 247 248 /** 249 * @public 250 */ 251 export interface ScreenshotClip extends BoundingBox { 252 /** 253 * @defaultValue `1` 254 */ 255 scale?: number; 256 } 257 258 /** 259 * @public 260 */ 261 export type ImageFormat = 'png' | 'jpeg' | 'webp'; 262 263 /** 264 * @public 265 */ 266 export type VideoFormat = 'webm' | 'gif' | 'mp4'; 267 268 /** 269 * @public 270 */ 271 export interface ScreenshotOptions { 272 /** 273 * @defaultValue `false` 274 */ 275 optimizeForSpeed?: boolean; 276 /** 277 * @defaultValue `'png'` 278 */ 279 type?: ImageFormat; 280 /** 281 * Quality of the image, between 0-100. Not applicable to `png` images. 282 */ 283 quality?: number; 284 /** 285 * Capture the screenshot from the surface, rather than the view. 286 * 287 * @defaultValue `true` 288 */ 289 fromSurface?: boolean; 290 /** 291 * When `true`, takes a screenshot of the full page. 292 * 293 * @defaultValue `false` 294 */ 295 fullPage?: boolean; 296 /** 297 * Hides default white background and allows capturing screenshots with transparency. 298 * 299 * @defaultValue `false` 300 */ 301 omitBackground?: boolean; 302 /** 303 * The file path to save the image to. The screenshot type will be inferred 304 * from file extension. If path is a relative path, then it is resolved 305 * relative to current working directory. If no path is provided, the image 306 * won't be saved to the disk. 307 */ 308 path?: `${string}.${ImageFormat}`; 309 /** 310 * Specifies the region of the page/element to clip. 311 */ 312 clip?: ScreenshotClip; 313 /** 314 * Encoding of the image. 315 * 316 * @defaultValue `'binary'` 317 */ 318 encoding?: 'base64' | 'binary'; 319 /** 320 * Capture the screenshot beyond the viewport. 321 * 322 * @defaultValue `false` if there is no `clip`. `true` otherwise. 323 */ 324 captureBeyondViewport?: boolean; 325 } 326 327 /** 328 * @public 329 * @experimental 330 */ 331 export interface ScreencastOptions { 332 /** 333 * File path to save the screencast to. 334 */ 335 path?: `${string}.${VideoFormat}`; 336 /** 337 * Specifies whether to overwrite output file, 338 * or exit immediately if it already exists. 339 * 340 * @defaultValue `true` 341 */ 342 overwrite?: boolean; 343 /** 344 * Specifies the output file format. 345 * 346 * @defaultValue `'webm'` 347 */ 348 format?: VideoFormat; 349 /** 350 * Specifies the region of the viewport to crop. 351 */ 352 crop?: BoundingBox; 353 /** 354 * Scales the output video. 355 * 356 * For example, `0.5` will shrink the width and height of the output video by 357 * half. `2` will double the width and height of the output video. 358 * 359 * @defaultValue `1` 360 */ 361 scale?: number; 362 /** 363 * Specifies the speed to record at. 364 * 365 * For example, `0.5` will slowdown the output video by 50%. `2` will double the 366 * speed of the output video. 367 * 368 * @defaultValue `1` 369 */ 370 speed?: number; 371 /** 372 * Specifies the frame rate in frames per second. 373 * 374 * @defaultValue `30` (`20` for GIF) 375 */ 376 fps?: number; 377 /** 378 * Specifies the number of times to loop playback, from `0` to `Infinity`. 379 * A value of `0` or `undefined` will disable looping. 380 * 381 * @defaultValue `undefined` 382 */ 383 loop?: number; 384 /** 385 * Specifies the delay between iterations of a loop, in ms. 386 * `-1` is a special value to re-use the previous delay. 387 * 388 * @defaultValue `-1` 389 */ 390 delay?: number; 391 /** 392 * Specifies the recording 393 * {@link https://trac.ffmpeg.org/wiki/Encode/VP9#constantq | quality} 394 * Constant Rate Factor between `0`–`63`. Lower values mean better quality. 395 * 396 * @defaultValue `30` 397 */ 398 quality?: number; 399 /** 400 * Specifies the maximum number of 401 * {@link https://ffmpeg.org/ffmpeg-filters.html#palettegen | palette} 402 * colors to quantize, with GIF limited to `256`. 403 * Restrict the palette to only necessary colors to reduce output file size. 404 * 405 * @defaultValue `256` 406 */ 407 colors?: number; 408 /** 409 * Path to the {@link https://ffmpeg.org/ | ffmpeg}. 410 * 411 * Required if `ffmpeg` is not in your PATH. 412 * 413 * @defaultValue `'ffmpeg'` 414 */ 415 ffmpegPath?: string; 416 } 417 418 /** 419 * @public 420 */ 421 export interface QueryOptions { 422 /** 423 * Whether to run the query in isolation. When returning many elements 424 * from {@link Page.$$} or similar methods, it might be useful to turn 425 * off the isolation to improve performance. By default, the querying 426 * code will be executed in a separate sandbox realm. 427 * 428 * @defaultValue `true` 429 */ 430 isolate: boolean; 431 } 432 433 /** 434 * All the events that a page instance may emit. 435 * 436 * @public 437 */ 438 export const enum PageEvent { 439 /** 440 * Emitted when the page closes. 441 */ 442 Close = 'close', 443 /** 444 * Emitted when JavaScript within the page calls one of console API methods, 445 * e.g. `console.log` or `console.dir`. Also emitted if the page throws an 446 * error or a warning. 447 * 448 * @remarks 449 * A `console` event provides a {@link ConsoleMessage} representing the 450 * console message that was logged. 451 * 452 * @example 453 * An example of handling `console` event: 454 * 455 * ```ts 456 * page.on('console', msg => { 457 * for (let i = 0; i < msg.args().length; ++i) 458 * console.log(`${i}: ${msg.args()[i]}`); 459 * }); 460 * page.evaluate(() => console.log('hello', 5, {foo: 'bar'})); 461 * ``` 462 */ 463 Console = 'console', 464 /** 465 * Emitted when a JavaScript dialog appears, such as `alert`, `prompt`, 466 * `confirm` or `beforeunload`. Puppeteer can respond to the dialog via 467 * {@link Dialog.accept} or {@link Dialog.dismiss}. 468 */ 469 Dialog = 'dialog', 470 /** 471 * Emitted when the JavaScript 472 * {@link https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded | DOMContentLoaded } 473 * event is dispatched. 474 */ 475 DOMContentLoaded = 'domcontentloaded', 476 /** 477 * Emitted when the page crashes. Will contain an `Error`. 478 */ 479 Error = 'error', 480 /** Emitted when a frame is attached. Will contain a {@link Frame}. */ 481 FrameAttached = 'frameattached', 482 /** Emitted when a frame is detached. Will contain a {@link Frame}. */ 483 FrameDetached = 'framedetached', 484 /** 485 * Emitted when a frame is navigated to a new URL. Will contain a 486 * {@link Frame}. 487 */ 488 FrameNavigated = 'framenavigated', 489 /** 490 * Emitted when the JavaScript 491 * {@link https://developer.mozilla.org/en-US/docs/Web/Events/load | load} 492 * event is dispatched. 493 */ 494 Load = 'load', 495 /** 496 * Emitted when the JavaScript code makes a call to `console.timeStamp`. For 497 * the list of metrics see {@link Page.metrics | page.metrics}. 498 * 499 * @remarks 500 * Contains an object with two properties: 501 * 502 * - `title`: the title passed to `console.timeStamp` 503 * - `metrics`: object containing metrics as key/value pairs. The values will 504 * be `number`s. 505 */ 506 Metrics = 'metrics', 507 /** 508 * Emitted when an uncaught exception happens within the page. Contains an 509 * `Error`. 510 */ 511 PageError = 'pageerror', 512 /** 513 * Emitted when the page opens a new tab or window. 514 * 515 * Contains a {@link Page} corresponding to the popup window. 516 * 517 * @example 518 * 519 * ```ts 520 * const [popup] = await Promise.all([ 521 * new Promise(resolve => page.once('popup', resolve)), 522 * page.click('a[target=_blank]'), 523 * ]); 524 * ``` 525 * 526 * ```ts 527 * const [popup] = await Promise.all([ 528 * new Promise(resolve => page.once('popup', resolve)), 529 * page.evaluate(() => window.open('https://example.com')), 530 * ]); 531 * ``` 532 */ 533 Popup = 'popup', 534 /** 535 * Emitted when a page issues a request and contains a {@link HTTPRequest}. 536 * 537 * @remarks 538 * The object is readonly. See {@link Page.setRequestInterception} for 539 * intercepting and mutating requests. 540 */ 541 Request = 'request', 542 /** 543 * Emitted when a request ended up loading from cache. Contains a 544 * {@link HTTPRequest}. 545 * 546 * @remarks 547 * For certain requests, might contain undefined. 548 * {@link https://crbug.com/750469} 549 */ 550 RequestServedFromCache = 'requestservedfromcache', 551 /** 552 * Emitted when a request fails, for example by timing out. 553 * 554 * Contains a {@link HTTPRequest}. 555 * 556 * @remarks 557 * HTTP Error responses, such as 404 or 503, are still successful responses 558 * from HTTP standpoint, so request will complete with `requestfinished` event 559 * and not with `requestfailed`. 560 */ 561 RequestFailed = 'requestfailed', 562 /** 563 * Emitted when a request finishes successfully. Contains a 564 * {@link HTTPRequest}. 565 */ 566 RequestFinished = 'requestfinished', 567 /** 568 * Emitted when a response is received. Contains a {@link HTTPResponse}. 569 */ 570 Response = 'response', 571 /** 572 * Emitted when a dedicated 573 * {@link https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API | WebWorker} 574 * is spawned by the page. 575 */ 576 WorkerCreated = 'workercreated', 577 /** 578 * Emitted when a dedicated 579 * {@link https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API | WebWorker} 580 * is destroyed by the page. 581 */ 582 WorkerDestroyed = 'workerdestroyed', 583 } 584 585 /** 586 * Denotes the objects received by callback functions for page events. 587 * 588 * See {@link PageEvent} for more detail on the events and when they are 589 * emitted. 590 * 591 * @public 592 */ 593 export interface PageEvents extends Record<EventType, unknown> { 594 [PageEvent.Close]: undefined; 595 [PageEvent.Console]: ConsoleMessage; 596 [PageEvent.Dialog]: Dialog; 597 [PageEvent.DOMContentLoaded]: undefined; 598 [PageEvent.Error]: Error; 599 [PageEvent.FrameAttached]: Frame; 600 [PageEvent.FrameDetached]: Frame; 601 [PageEvent.FrameNavigated]: Frame; 602 [PageEvent.Load]: undefined; 603 [PageEvent.Metrics]: {title: string; metrics: Metrics}; 604 [PageEvent.PageError]: Error; 605 [PageEvent.Popup]: Page | null; 606 [PageEvent.Request]: HTTPRequest; 607 [PageEvent.Response]: HTTPResponse; 608 [PageEvent.RequestFailed]: HTTPRequest; 609 [PageEvent.RequestFinished]: HTTPRequest; 610 [PageEvent.RequestServedFromCache]: HTTPRequest; 611 [PageEvent.WorkerCreated]: WebWorker; 612 [PageEvent.WorkerDestroyed]: WebWorker; 613 } 614 615 /** 616 * @public 617 */ 618 export interface NewDocumentScriptEvaluation { 619 identifier: string; 620 } 621 622 /** 623 * @internal 624 */ 625 export function setDefaultScreenshotOptions(options: ScreenshotOptions): void { 626 options.optimizeForSpeed ??= false; 627 options.type ??= 'png'; 628 options.fromSurface ??= true; 629 options.fullPage ??= false; 630 options.omitBackground ??= false; 631 options.encoding ??= 'binary'; 632 options.captureBeyondViewport ??= true; 633 } 634 635 /** 636 * Page provides methods to interact with a single tab or 637 * {@link https://developer.chrome.com/extensions/background_pages | extension background page} 638 * in the browser. 639 * 640 * :::note 641 * 642 * One Browser instance might have multiple Page instances. 643 * 644 * ::: 645 * 646 * @example 647 * This example creates a page, navigates it to a URL, and then saves a screenshot: 648 * 649 * ```ts 650 * import puppeteer from 'puppeteer'; 651 * 652 * (async () => { 653 * const browser = await puppeteer.launch(); 654 * const page = await browser.newPage(); 655 * await page.goto('https://example.com'); 656 * await page.screenshot({path: 'screenshot.png'}); 657 * await browser.close(); 658 * })(); 659 * ``` 660 * 661 * The Page class extends from Puppeteer's {@link EventEmitter} class and will 662 * emit various events which are documented in the {@link PageEvent} enum. 663 * 664 * @example 665 * This example logs a message for a single page `load` event: 666 * 667 * ```ts 668 * page.once('load', () => console.log('Page loaded!')); 669 * ``` 670 * 671 * To unsubscribe from events use the {@link EventEmitter.off} method: 672 * 673 * ```ts 674 * function logRequest(interceptedRequest) { 675 * console.log('A request was made:', interceptedRequest.url()); 676 * } 677 * page.on('request', logRequest); 678 * // Sometime later... 679 * page.off('request', logRequest); 680 * ``` 681 * 682 * @public 683 */ 684 export abstract class Page extends EventEmitter<PageEvents> { 685 /** 686 * @internal 687 */ 688 _isDragging = false; 689 /** 690 * @internal 691 */ 692 _timeoutSettings = new TimeoutSettings(); 693 694 #requestHandlers = new WeakMap<Handler<HTTPRequest>, Handler<HTTPRequest>>(); 695 696 #inflight$ = new ReplaySubject<number>(1); 697 698 /** 699 * @internal 700 */ 701 constructor() { 702 super(); 703 704 fromEmitterEvent(this, PageEvent.Request) 705 .pipe( 706 mergeMap(originalRequest => { 707 return concat( 708 of(1), 709 merge( 710 fromEmitterEvent(this, PageEvent.RequestFailed), 711 fromEmitterEvent(this, PageEvent.RequestFinished), 712 fromEmitterEvent(this, PageEvent.Response).pipe( 713 map(response => { 714 return response.request(); 715 }), 716 ), 717 ).pipe( 718 filter(request => { 719 return request.id === originalRequest.id; 720 }), 721 take(1), 722 map(() => { 723 return -1; 724 }), 725 ), 726 ); 727 }), 728 mergeScan((acc, addend) => { 729 return of(acc + addend); 730 }, 0), 731 takeUntil(fromEmitterEvent(this, PageEvent.Close)), 732 startWith(0), 733 ) 734 .subscribe(this.#inflight$); 735 } 736 737 /** 738 * `true` if the service worker are being bypassed, `false` otherwise. 739 */ 740 abstract isServiceWorkerBypassed(): boolean; 741 742 /** 743 * `true` if drag events are being intercepted, `false` otherwise. 744 * 745 * @deprecated We no longer support intercepting drag payloads. Use the new 746 * drag APIs found on {@link ElementHandle} to drag (or just use the 747 * {@link Page.mouse}). 748 */ 749 abstract isDragInterceptionEnabled(): boolean; 750 751 /** 752 * `true` if the page has JavaScript enabled, `false` otherwise. 753 */ 754 abstract isJavaScriptEnabled(): boolean; 755 756 /** 757 * Listen to page events. 758 * 759 * @remarks 760 * This method exists to define event typings and handle proper wireup of 761 * cooperative request interception. Actual event listening and dispatching is 762 * delegated to {@link EventEmitter}. 763 * 764 * @internal 765 */ 766 override on<K extends keyof EventsWithWildcard<PageEvents>>( 767 type: K, 768 handler: (event: EventsWithWildcard<PageEvents>[K]) => void, 769 ): this { 770 if (type !== PageEvent.Request) { 771 return super.on(type, handler); 772 } 773 let wrapper = this.#requestHandlers.get( 774 handler as (event: PageEvents[PageEvent.Request]) => void, 775 ); 776 if (wrapper === undefined) { 777 wrapper = (event: HTTPRequest) => { 778 event.enqueueInterceptAction(() => { 779 return handler(event as EventsWithWildcard<PageEvents>[K]); 780 }); 781 }; 782 this.#requestHandlers.set( 783 handler as (event: PageEvents[PageEvent.Request]) => void, 784 wrapper, 785 ); 786 } 787 return super.on( 788 type, 789 wrapper as (event: EventsWithWildcard<PageEvents>[K]) => void, 790 ); 791 } 792 793 /** 794 * @internal 795 */ 796 override off<K extends keyof EventsWithWildcard<PageEvents>>( 797 type: K, 798 handler: (event: EventsWithWildcard<PageEvents>[K]) => void, 799 ): this { 800 if (type === PageEvent.Request) { 801 handler = 802 (this.#requestHandlers.get( 803 handler as ( 804 event: EventsWithWildcard<PageEvents>[PageEvent.Request], 805 ) => void, 806 ) as (event: EventsWithWildcard<PageEvents>[K]) => void) || handler; 807 } 808 return super.off(type, handler); 809 } 810 811 /** 812 * This method is typically coupled with an action that triggers file 813 * choosing. 814 * 815 * :::caution 816 * 817 * This must be called before the file chooser is launched. It will not return 818 * a currently active file chooser. 819 * 820 * ::: 821 * 822 * :::caution 823 * 824 * Interception of file dialogs triggered via DOM APIs such as 825 * window.showOpenFilePicker is currently not supported. 826 * 827 * ::: 828 * 829 * @remarks 830 * In the "headful" browser, this method results in the native file picker 831 * dialog `not showing up` for the user. 832 * 833 * @example 834 * The following example clicks a button that issues a file chooser 835 * and then responds with `/tmp/myfile.pdf` as if a user has selected this file. 836 * 837 * ```ts 838 * const [fileChooser] = await Promise.all([ 839 * page.waitForFileChooser(), 840 * page.click('#upload-file-button'), 841 * // some button that triggers file selection 842 * ]); 843 * await fileChooser.accept(['/tmp/myfile.pdf']); 844 * ``` 845 */ 846 abstract waitForFileChooser( 847 options?: WaitTimeoutOptions, 848 ): Promise<FileChooser>; 849 850 /** 851 * Sets the page's geolocation. 852 * 853 * @remarks 854 * Consider using {@link BrowserContext.overridePermissions} to grant 855 * permissions for the page to read its geolocation. 856 * 857 * @example 858 * 859 * ```ts 860 * await page.setGeolocation({latitude: 59.95, longitude: 30.31667}); 861 * ``` 862 */ 863 abstract setGeolocation(options: GeolocationOptions): Promise<void>; 864 865 /** 866 * A target this page was created from. 867 * 868 * @deprecated Use {@link Page.createCDPSession} directly. 869 */ 870 abstract target(): Target; 871 872 /** 873 * Get the browser the page belongs to. 874 */ 875 abstract browser(): Browser; 876 877 /** 878 * Get the browser context that the page belongs to. 879 */ 880 abstract browserContext(): BrowserContext; 881 882 /** 883 * The page's main frame. 884 */ 885 abstract mainFrame(): Frame; 886 887 /** 888 * Creates a Chrome Devtools Protocol session attached to the page. 889 */ 890 abstract createCDPSession(): Promise<CDPSession>; 891 892 /** 893 * {@inheritDoc Keyboard} 894 */ 895 abstract get keyboard(): Keyboard; 896 897 /** 898 * {@inheritDoc Touchscreen} 899 */ 900 abstract get touchscreen(): Touchscreen; 901 902 /** 903 * {@inheritDoc Coverage} 904 */ 905 abstract get coverage(): Coverage; 906 907 /** 908 * {@inheritDoc Tracing} 909 */ 910 abstract get tracing(): Tracing; 911 912 /** 913 * {@inheritDoc Accessibility} 914 */ 915 get accessibility(): Accessibility { 916 return this.mainFrame().accessibility; 917 } 918 919 /** 920 * An array of all frames attached to the page. 921 */ 922 abstract frames(): Frame[]; 923 924 /** 925 * All of the dedicated {@link 926 * https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API | 927 * WebWorkers} associated with the page. 928 * 929 * @remarks 930 * This does not contain ServiceWorkers 931 */ 932 abstract workers(): WebWorker[]; 933 934 /** 935 * Activating request interception enables {@link HTTPRequest.abort}, 936 * {@link HTTPRequest.continue} and {@link HTTPRequest.respond} methods. This 937 * provides the capability to modify network requests that are made by a page. 938 * 939 * Once request interception is enabled, every request will stall unless it's 940 * continued, responded or aborted; or completed using the browser cache. 941 * 942 * See the 943 * {@link https://pptr.dev/guides/network-interception|Request interception guide} 944 * for more details. 945 * 946 * @example 947 * An example of a naïve request interceptor that aborts all image requests: 948 * 949 * ```ts 950 * import puppeteer from 'puppeteer'; 951 * (async () => { 952 * const browser = await puppeteer.launch(); 953 * const page = await browser.newPage(); 954 * await page.setRequestInterception(true); 955 * page.on('request', interceptedRequest => { 956 * if ( 957 * interceptedRequest.url().endsWith('.png') || 958 * interceptedRequest.url().endsWith('.jpg') 959 * ) 960 * interceptedRequest.abort(); 961 * else interceptedRequest.continue(); 962 * }); 963 * await page.goto('https://example.com'); 964 * await browser.close(); 965 * })(); 966 * ``` 967 * 968 * @param value - Whether to enable request interception. 969 */ 970 abstract setRequestInterception(value: boolean): Promise<void>; 971 972 /** 973 * Toggles ignoring of service worker for each request. 974 * 975 * @param bypass - Whether to bypass service worker and load from network. 976 */ 977 abstract setBypassServiceWorker(bypass: boolean): Promise<void>; 978 979 /** 980 * @param enabled - Whether to enable drag interception. 981 * 982 * @deprecated We no longer support intercepting drag payloads. Use the new 983 * drag APIs found on {@link ElementHandle} to drag (or just use the 984 * {@link Page.mouse}). 985 */ 986 abstract setDragInterception(enabled: boolean): Promise<void>; 987 988 /** 989 * Sets the network connection to offline. 990 * 991 * It does not change the parameters used in {@link Page.emulateNetworkConditions} 992 * 993 * @param enabled - When `true`, enables offline mode for the page. 994 */ 995 abstract setOfflineMode(enabled: boolean): Promise<void>; 996 997 /** 998 * This does not affect WebSockets and WebRTC PeerConnections (see 999 * https://crbug.com/563644). To set the page offline, you can use 1000 * {@link Page.setOfflineMode}. 1001 * 1002 * A list of predefined network conditions can be used by importing 1003 * {@link PredefinedNetworkConditions}. 1004 * 1005 * @example 1006 * 1007 * ```ts 1008 * import {PredefinedNetworkConditions} from 'puppeteer'; 1009 * const slow3G = PredefinedNetworkConditions['Slow 3G']; 1010 * 1011 * (async () => { 1012 * const browser = await puppeteer.launch(); 1013 * const page = await browser.newPage(); 1014 * await page.emulateNetworkConditions(slow3G); 1015 * await page.goto('https://www.google.com'); 1016 * // other actions... 1017 * await browser.close(); 1018 * })(); 1019 * ``` 1020 * 1021 * @param networkConditions - Passing `null` disables network condition 1022 * emulation. 1023 */ 1024 abstract emulateNetworkConditions( 1025 networkConditions: NetworkConditions | null, 1026 ): Promise<void>; 1027 1028 /** 1029 * This setting will change the default maximum navigation time for the 1030 * following methods and related shortcuts: 1031 * 1032 * - {@link Page.goBack | page.goBack(options)} 1033 * 1034 * - {@link Page.goForward | page.goForward(options)} 1035 * 1036 * - {@link Page.goto | page.goto(url,options)} 1037 * 1038 * - {@link Page.reload | page.reload(options)} 1039 * 1040 * - {@link Page.setContent | page.setContent(html,options)} 1041 * 1042 * - {@link Page.waitForNavigation | page.waitForNavigation(options)} 1043 * @param timeout - Maximum navigation time in milliseconds. 1044 */ 1045 abstract setDefaultNavigationTimeout(timeout: number): void; 1046 1047 /** 1048 * @param timeout - Maximum time in milliseconds. 1049 */ 1050 abstract setDefaultTimeout(timeout: number): void; 1051 1052 /** 1053 * Maximum time in milliseconds. 1054 */ 1055 abstract getDefaultTimeout(): number; 1056 1057 /** 1058 * Maximum navigation time in milliseconds. 1059 */ 1060 abstract getDefaultNavigationTimeout(): number; 1061 1062 /** 1063 * Creates a locator for the provided selector. See {@link Locator} for 1064 * details and supported actions. 1065 * 1066 * @param selector - 1067 * {@link https://pptr.dev/guides/page-interactions#selectors | selector} 1068 * to query the page for. 1069 * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors} 1070 * can be passed as-is and a 1071 * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax} 1072 * allows querying by 1073 * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text}, 1074 * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name}, 1075 * and 1076 * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath} 1077 * and 1078 * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}. 1079 * Alternatively, you can specify the selector type using a 1080 * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}. 1081 */ 1082 locator<Selector extends string>( 1083 selector: Selector, 1084 ): Locator<NodeFor<Selector>>; 1085 1086 /** 1087 * Creates a locator for the provided function. See {@link Locator} for 1088 * details and supported actions. 1089 * 1090 * @param selector - 1091 * {@link https://pptr.dev/guides/page-interactions#selectors | selector} 1092 * to query the page for. 1093 * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors} 1094 * can be passed as-is and a 1095 * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax} 1096 * allows querying by 1097 * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text}, 1098 * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name}, 1099 * and 1100 * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath} 1101 * and 1102 * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}. 1103 * Alternatively, you can specify the selector type using a 1104 * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}. 1105 */ 1106 locator<Ret>(func: () => Awaitable<Ret>): Locator<Ret>; 1107 locator<Selector extends string, Ret>( 1108 selectorOrFunc: Selector | (() => Awaitable<Ret>), 1109 ): Locator<NodeFor<Selector>> | Locator<Ret> { 1110 if (typeof selectorOrFunc === 'string') { 1111 return NodeLocator.create(this, selectorOrFunc); 1112 } else { 1113 return FunctionLocator.create(this, selectorOrFunc); 1114 } 1115 } 1116 1117 /** 1118 * A shortcut for {@link Locator.race} that does not require static imports. 1119 * 1120 * @internal 1121 */ 1122 locatorRace<Locators extends readonly unknown[] | []>( 1123 locators: Locators, 1124 ): Locator<AwaitedLocator<Locators[number]>> { 1125 return Locator.race(locators); 1126 } 1127 1128 /** 1129 * Finds the first element that matches the selector. If no element matches 1130 * the selector, the return value resolves to `null`. 1131 * 1132 * @param selector - 1133 * {@link https://pptr.dev/guides/page-interactions#selectors | selector} 1134 * to query the page for. 1135 * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors} 1136 * can be passed as-is and a 1137 * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax} 1138 * allows querying by 1139 * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text}, 1140 * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name}, 1141 * and 1142 * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath} 1143 * and 1144 * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}. 1145 * Alternatively, you can specify the selector type using a 1146 * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}. 1147 * 1148 * @remarks 1149 * 1150 * Shortcut for {@link Frame.$ | Page.mainFrame().$(selector) }. 1151 */ 1152 async $<Selector extends string>( 1153 selector: Selector, 1154 ): Promise<ElementHandle<NodeFor<Selector>> | null> { 1155 return await this.mainFrame().$(selector); 1156 } 1157 1158 /** 1159 * Finds elements on the page that match the selector. If no elements 1160 * match the selector, the return value resolves to `[]`. 1161 * 1162 * @param selector - 1163 * {@link https://pptr.dev/guides/page-interactions#selectors | selector} 1164 * to query the page for. 1165 * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors} 1166 * can be passed as-is and a 1167 * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax} 1168 * allows querying by 1169 * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text}, 1170 * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name}, 1171 * and 1172 * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath} 1173 * and 1174 * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}. 1175 * Alternatively, you can specify the selector type using a 1176 * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}. 1177 * 1178 * @remarks 1179 * 1180 * Shortcut for {@link Frame.$$ | Page.mainFrame().$$(selector) }. 1181 */ 1182 async $$<Selector extends string>( 1183 selector: Selector, 1184 options?: QueryOptions, 1185 ): Promise<Array<ElementHandle<NodeFor<Selector>>>> { 1186 return await this.mainFrame().$$(selector, options); 1187 } 1188 1189 /** 1190 * @remarks 1191 * 1192 * The only difference between {@link Page.evaluate | page.evaluate} and 1193 * `page.evaluateHandle` is that `evaluateHandle` will return the value 1194 * wrapped in an in-page object. 1195 * 1196 * If the function passed to `page.evaluateHandle` returns a Promise, the 1197 * function will wait for the promise to resolve and return its value. 1198 * 1199 * You can pass a string instead of a function (although functions are 1200 * recommended as they are easier to debug and use with TypeScript): 1201 * 1202 * @example 1203 * 1204 * ```ts 1205 * const aHandle = await page.evaluateHandle('document'); 1206 * ``` 1207 * 1208 * @example 1209 * {@link JSHandle} instances can be passed as arguments to the `pageFunction`: 1210 * 1211 * ```ts 1212 * const aHandle = await page.evaluateHandle(() => document.body); 1213 * const resultHandle = await page.evaluateHandle( 1214 * body => body.innerHTML, 1215 * aHandle, 1216 * ); 1217 * console.log(await resultHandle.jsonValue()); 1218 * await resultHandle.dispose(); 1219 * ``` 1220 * 1221 * Most of the time this function returns a {@link JSHandle}, 1222 * but if `pageFunction` returns a reference to an element, 1223 * you instead get an {@link ElementHandle} back: 1224 * 1225 * @example 1226 * 1227 * ```ts 1228 * const button = await page.evaluateHandle(() => 1229 * document.querySelector('button'), 1230 * ); 1231 * // can call `click` because `button` is an `ElementHandle` 1232 * await button.click(); 1233 * ``` 1234 * 1235 * The TypeScript definitions assume that `evaluateHandle` returns 1236 * a `JSHandle`, but if you know it's going to return an 1237 * `ElementHandle`, pass it as the generic argument: 1238 * 1239 * ```ts 1240 * const button = await page.evaluateHandle<ElementHandle>(...); 1241 * ``` 1242 * 1243 * @param pageFunction - a function that is run within the page 1244 * @param args - arguments to be passed to the pageFunction 1245 */ 1246 async evaluateHandle< 1247 Params extends unknown[], 1248 Func extends EvaluateFunc<Params> = EvaluateFunc<Params>, 1249 >( 1250 pageFunction: Func | string, 1251 ...args: Params 1252 ): Promise<HandleFor<Awaited<ReturnType<Func>>>> { 1253 pageFunction = withSourcePuppeteerURLIfNone( 1254 this.evaluateHandle.name, 1255 pageFunction, 1256 ); 1257 return await this.mainFrame().evaluateHandle(pageFunction, ...args); 1258 } 1259 1260 /** 1261 * This method iterates the JavaScript heap and finds all objects with the 1262 * given prototype. 1263 * 1264 * @example 1265 * 1266 * ```ts 1267 * // Create a Map object 1268 * await page.evaluate(() => (window.map = new Map())); 1269 * // Get a handle to the Map object prototype 1270 * const mapPrototype = await page.evaluateHandle(() => Map.prototype); 1271 * // Query all map instances into an array 1272 * const mapInstances = await page.queryObjects(mapPrototype); 1273 * // Count amount of map objects in heap 1274 * const count = await page.evaluate(maps => maps.length, mapInstances); 1275 * await mapInstances.dispose(); 1276 * await mapPrototype.dispose(); 1277 * ``` 1278 * 1279 * @param prototypeHandle - a handle to the object prototype. 1280 * @returns Promise which resolves to a handle to an array of objects with 1281 * this prototype. 1282 */ 1283 abstract queryObjects<Prototype>( 1284 prototypeHandle: JSHandle<Prototype>, 1285 ): Promise<JSHandle<Prototype[]>>; 1286 1287 /** 1288 * This method finds the first element within the page that matches the selector 1289 * and passes the result as the first argument to the `pageFunction`. 1290 * 1291 * @remarks 1292 * 1293 * If no element is found matching `selector`, the method will throw an error. 1294 * 1295 * If `pageFunction` returns a promise `$eval` will wait for the promise to 1296 * resolve and then return its value. 1297 * 1298 * @example 1299 * 1300 * ```ts 1301 * const searchValue = await page.$eval('#search', el => el.value); 1302 * const preloadHref = await page.$eval('link[rel=preload]', el => el.href); 1303 * const html = await page.$eval('.main-container', el => el.outerHTML); 1304 * ``` 1305 * 1306 * If you are using TypeScript, you may have to provide an explicit type to the 1307 * first argument of the `pageFunction`. 1308 * By default it is typed as `Element`, but you may need to provide a more 1309 * specific sub-type: 1310 * 1311 * @example 1312 * 1313 * ```ts 1314 * // if you don't provide HTMLInputElement here, TS will error 1315 * // as `value` is not on `Element` 1316 * const searchValue = await page.$eval( 1317 * '#search', 1318 * (el: HTMLInputElement) => el.value, 1319 * ); 1320 * ``` 1321 * 1322 * The compiler should be able to infer the return type 1323 * from the `pageFunction` you provide. If it is unable to, you can use the generic 1324 * type to tell the compiler what return type you expect from `$eval`: 1325 * 1326 * @example 1327 * 1328 * ```ts 1329 * // The compiler can infer the return type in this case, but if it can't 1330 * // or if you want to be more explicit, provide it as the generic type. 1331 * const searchValue = await page.$eval<string>( 1332 * '#search', 1333 * (el: HTMLInputElement) => el.value, 1334 * ); 1335 * ``` 1336 * 1337 * @param selector - 1338 * {@link https://pptr.dev/guides/page-interactions#selectors | selector} 1339 * to query the page for. 1340 * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors} 1341 * can be passed as-is and a 1342 * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax} 1343 * allows querying by 1344 * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text}, 1345 * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name}, 1346 * and 1347 * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath} 1348 * and 1349 * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}. 1350 * Alternatively, you can specify the selector type using a 1351 * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}. 1352 * @param pageFunction - the function to be evaluated in the page context. 1353 * Will be passed the result of the element matching the selector as its 1354 * first argument. 1355 * @param args - any additional arguments to pass through to `pageFunction`. 1356 * 1357 * @returns The result of calling `pageFunction`. If it returns an element it 1358 * is wrapped in an {@link ElementHandle}, else the raw value itself is 1359 * returned. 1360 */ 1361 async $eval< 1362 Selector extends string, 1363 Params extends unknown[], 1364 Func extends EvaluateFuncWith<NodeFor<Selector>, Params> = EvaluateFuncWith< 1365 NodeFor<Selector>, 1366 Params 1367 >, 1368 >( 1369 selector: Selector, 1370 pageFunction: Func | string, 1371 ...args: Params 1372 ): Promise<Awaited<ReturnType<Func>>> { 1373 pageFunction = withSourcePuppeteerURLIfNone(this.$eval.name, pageFunction); 1374 return await this.mainFrame().$eval(selector, pageFunction, ...args); 1375 } 1376 1377 /** 1378 * This method returns all elements matching the selector and passes the 1379 * resulting array as the first argument to the `pageFunction`. 1380 * 1381 * @remarks 1382 * If `pageFunction` returns a promise `$$eval` will wait for the promise to 1383 * resolve and then return its value. 1384 * 1385 * @example 1386 * 1387 * ```ts 1388 * // get the amount of divs on the page 1389 * const divCount = await page.$$eval('div', divs => divs.length); 1390 * 1391 * // get the text content of all the `.options` elements: 1392 * const options = await page.$$eval('div > span.options', options => { 1393 * return options.map(option => option.textContent); 1394 * }); 1395 * ``` 1396 * 1397 * If you are using TypeScript, you may have to provide an explicit type to the 1398 * first argument of the `pageFunction`. 1399 * By default it is typed as `Element[]`, but you may need to provide a more 1400 * specific sub-type: 1401 * 1402 * @example 1403 * 1404 * ```ts 1405 * await page.$$eval('input', elements => { 1406 * return elements.map(e => e.value); 1407 * }); 1408 * ``` 1409 * 1410 * The compiler should be able to infer the return type 1411 * from the `pageFunction` you provide. If it is unable to, you can use the generic 1412 * type to tell the compiler what return type you expect from `$$eval`: 1413 * 1414 * @example 1415 * 1416 * ```ts 1417 * const allInputValues = await page.$$eval('input', elements => 1418 * elements.map(e => e.textContent), 1419 * ); 1420 * ``` 1421 * 1422 * @param selector - 1423 * {@link https://pptr.dev/guides/page-interactions#selectors | selector} 1424 * to query the page for. 1425 * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors} 1426 * can be passed as-is and a 1427 * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax} 1428 * allows querying by 1429 * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text}, 1430 * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name}, 1431 * and 1432 * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath} 1433 * and 1434 * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}. 1435 * Alternatively, you can specify the selector type using a 1436 * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}. 1437 * @param pageFunction - the function to be evaluated in the page context. 1438 * Will be passed an array of matching elements as its first argument. 1439 * @param args - any additional arguments to pass through to `pageFunction`. 1440 * 1441 * @returns The result of calling `pageFunction`. If it returns an element it 1442 * is wrapped in an {@link ElementHandle}, else the raw value itself is 1443 * returned. 1444 */ 1445 async $$eval< 1446 Selector extends string, 1447 Params extends unknown[], 1448 Func extends EvaluateFuncWith< 1449 Array<NodeFor<Selector>>, 1450 Params 1451 > = EvaluateFuncWith<Array<NodeFor<Selector>>, Params>, 1452 >( 1453 selector: Selector, 1454 pageFunction: Func | string, 1455 ...args: Params 1456 ): Promise<Awaited<ReturnType<Func>>> { 1457 pageFunction = withSourcePuppeteerURLIfNone(this.$$eval.name, pageFunction); 1458 return await this.mainFrame().$$eval(selector, pageFunction, ...args); 1459 } 1460 1461 /** 1462 * If no URLs are specified, this method returns cookies for the 1463 * current page URL. If URLs are specified, only cookies for those 1464 * URLs are returned. 1465 * 1466 * @deprecated Page-level cookie API is deprecated. Use 1467 * {@link Browser.cookies} or {@link BrowserContext.cookies} instead. 1468 */ 1469 abstract cookies(...urls: string[]): Promise<Cookie[]>; 1470 1471 /** 1472 * @deprecated Page-level cookie API is deprecated. Use 1473 * {@link Browser.deleteCookie} or {@link BrowserContext.deleteCookie} 1474 * instead. 1475 */ 1476 abstract deleteCookie(...cookies: DeleteCookiesRequest[]): Promise<void>; 1477 1478 /** 1479 * @example 1480 * 1481 *```ts 1482 * await page.setCookie(cookieObject1, cookieObject2); 1483 *``` 1484 * 1485 * @deprecated Page-level cookie API is deprecated. Use 1486 * {@link Browser.setCookie} or {@link BrowserContext.setCookie} 1487 * instead. 1488 */ 1489 abstract setCookie(...cookies: CookieParam[]): Promise<void>; 1490 1491 /** 1492 * Adds a `<script>` tag into the page with the desired URL or content. 1493 * 1494 * @remarks 1495 * Shortcut for 1496 * {@link Frame.addScriptTag | page.mainFrame().addScriptTag(options)}. 1497 * 1498 * @param options - Options for the script. 1499 * @returns An {@link ElementHandle | element handle} to the injected 1500 * `<script>` element. 1501 */ 1502 async addScriptTag( 1503 options: FrameAddScriptTagOptions, 1504 ): Promise<ElementHandle<HTMLScriptElement>> { 1505 return await this.mainFrame().addScriptTag(options); 1506 } 1507 1508 /** 1509 * Adds a `<link rel="stylesheet">` tag into the page with the desired URL or 1510 * a `<style type="text/css">` tag with the content. 1511 * 1512 * Shortcut for 1513 * {@link Frame.(addStyleTag:2) | page.mainFrame().addStyleTag(options)}. 1514 * 1515 * @returns An {@link ElementHandle | element handle} to the injected `<link>` 1516 * or `<style>` element. 1517 */ 1518 async addStyleTag( 1519 options: Omit<FrameAddStyleTagOptions, 'url'>, 1520 ): Promise<ElementHandle<HTMLStyleElement>>; 1521 async addStyleTag( 1522 options: FrameAddStyleTagOptions, 1523 ): Promise<ElementHandle<HTMLLinkElement>>; 1524 async addStyleTag( 1525 options: FrameAddStyleTagOptions, 1526 ): Promise<ElementHandle<HTMLStyleElement | HTMLLinkElement>> { 1527 return await this.mainFrame().addStyleTag(options); 1528 } 1529 1530 /** 1531 * The method adds a function called `name` on the page's `window` object. 1532 * When called, the function executes `puppeteerFunction` in node.js and 1533 * returns a `Promise` which resolves to the return value of 1534 * `puppeteerFunction`. 1535 * 1536 * If the puppeteerFunction returns a `Promise`, it will be awaited. 1537 * 1538 * :::note 1539 * 1540 * Functions installed via `page.exposeFunction` survive navigations. 1541 * 1542 * ::: 1543 * 1544 * @example 1545 * An example of adding an `md5` function into the page: 1546 * 1547 * ```ts 1548 * import puppeteer from 'puppeteer'; 1549 * import crypto from 'crypto'; 1550 * 1551 * (async () => { 1552 * const browser = await puppeteer.launch(); 1553 * const page = await browser.newPage(); 1554 * page.on('console', msg => console.log(msg.text())); 1555 * await page.exposeFunction('md5', text => 1556 * crypto.createHash('md5').update(text).digest('hex'), 1557 * ); 1558 * await page.evaluate(async () => { 1559 * // use window.md5 to compute hashes 1560 * const myString = 'PUPPETEER'; 1561 * const myHash = await window.md5(myString); 1562 * console.log(`md5 of ${myString} is ${myHash}`); 1563 * }); 1564 * await browser.close(); 1565 * })(); 1566 * ``` 1567 * 1568 * @example 1569 * An example of adding a `window.readfile` function into the page: 1570 * 1571 * ```ts 1572 * import puppeteer from 'puppeteer'; 1573 * import fs from 'node:fs'; 1574 * 1575 * (async () => { 1576 * const browser = await puppeteer.launch(); 1577 * const page = await browser.newPage(); 1578 * page.on('console', msg => console.log(msg.text())); 1579 * await page.exposeFunction('readfile', async filePath => { 1580 * return new Promise((resolve, reject) => { 1581 * fs.readFile(filePath, 'utf8', (err, text) => { 1582 * if (err) reject(err); 1583 * else resolve(text); 1584 * }); 1585 * }); 1586 * }); 1587 * await page.evaluate(async () => { 1588 * // use window.readfile to read contents of a file 1589 * const content = await window.readfile('/etc/hosts'); 1590 * console.log(content); 1591 * }); 1592 * await browser.close(); 1593 * })(); 1594 * ``` 1595 * 1596 * @param name - Name of the function on the window object 1597 * @param pptrFunction - Callback function which will be called in Puppeteer's 1598 * context. 1599 */ 1600 abstract exposeFunction( 1601 name: string, 1602 // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type 1603 pptrFunction: Function | {default: Function}, 1604 ): Promise<void>; 1605 1606 /** 1607 * The method removes a previously added function via ${@link Page.exposeFunction} 1608 * called `name` from the page's `window` object. 1609 */ 1610 abstract removeExposedFunction(name: string): Promise<void>; 1611 1612 /** 1613 * Provide credentials for `HTTP authentication`. 1614 * 1615 * :::note 1616 * 1617 * Request interception will be turned on behind the scenes to 1618 * implement authentication. This might affect performance. 1619 * 1620 * ::: 1621 * 1622 * @remarks 1623 * To disable authentication, pass `null`. 1624 */ 1625 abstract authenticate(credentials: Credentials | null): Promise<void>; 1626 1627 /** 1628 * The extra HTTP headers will be sent with every request the page initiates. 1629 * 1630 * :::tip 1631 * 1632 * All HTTP header names are lowercased. (HTTP headers are 1633 * case-insensitive, so this shouldn’t impact your server code.) 1634 * 1635 * ::: 1636 * 1637 * :::note 1638 * 1639 * page.setExtraHTTPHeaders does not guarantee the order of headers in 1640 * the outgoing requests. 1641 * 1642 * ::: 1643 * 1644 * @param headers - An object containing additional HTTP headers to be sent 1645 * with every request. All header values must be strings. 1646 */ 1647 abstract setExtraHTTPHeaders(headers: Record<string, string>): Promise<void>; 1648 1649 /** 1650 * @param userAgent - Specific user agent to use in this page 1651 * @param userAgentData - Specific user agent client hint data to use in this 1652 * page 1653 * @returns Promise which resolves when the user agent is set. 1654 */ 1655 abstract setUserAgent( 1656 userAgent: string, 1657 userAgentMetadata?: Protocol.Emulation.UserAgentMetadata, 1658 ): Promise<void>; 1659 1660 /** 1661 * Object containing metrics as key/value pairs. 1662 * 1663 * @returns 1664 * 1665 * - `Timestamp` : The timestamp when the metrics sample was taken. 1666 * 1667 * - `Documents` : Number of documents in the page. 1668 * 1669 * - `Frames` : Number of frames in the page. 1670 * 1671 * - `JSEventListeners` : Number of events in the page. 1672 * 1673 * - `Nodes` : Number of DOM nodes in the page. 1674 * 1675 * - `LayoutCount` : Total number of full or partial page layout. 1676 * 1677 * - `RecalcStyleCount` : Total number of page style recalculations. 1678 * 1679 * - `LayoutDuration` : Combined durations of all page layouts. 1680 * 1681 * - `RecalcStyleDuration` : Combined duration of all page style 1682 * recalculations. 1683 * 1684 * - `ScriptDuration` : Combined duration of JavaScript execution. 1685 * 1686 * - `TaskDuration` : Combined duration of all tasks performed by the browser. 1687 * 1688 * - `JSHeapUsedSize` : Used JavaScript heap size. 1689 * 1690 * - `JSHeapTotalSize` : Total JavaScript heap size. 1691 * 1692 * @remarks 1693 * All timestamps are in monotonic time: monotonically increasing time 1694 * in seconds since an arbitrary point in the past. 1695 */ 1696 abstract metrics(): Promise<Metrics>; 1697 1698 /** 1699 * The page's URL. 1700 * 1701 * @remarks 1702 * 1703 * Shortcut for {@link Frame.url | page.mainFrame().url()}. 1704 */ 1705 url(): string { 1706 return this.mainFrame().url(); 1707 } 1708 1709 /** 1710 * The full HTML contents of the page, including the DOCTYPE. 1711 */ 1712 async content(): Promise<string> { 1713 return await this.mainFrame().content(); 1714 } 1715 1716 /** 1717 * Set the content of the page. 1718 * 1719 * @param html - HTML markup to assign to the page. 1720 * @param options - Parameters that has some properties. 1721 */ 1722 async setContent(html: string, options?: WaitForOptions): Promise<void> { 1723 await this.mainFrame().setContent(html, options); 1724 } 1725 1726 /** 1727 * {@inheritDoc Frame.goto} 1728 */ 1729 async goto(url: string, options?: GoToOptions): Promise<HTTPResponse | null> { 1730 return await this.mainFrame().goto(url, options); 1731 } 1732 1733 /** 1734 * Reloads the page. 1735 * 1736 * @param options - Options to configure waiting behavior. 1737 * @returns A promise which resolves to the main resource response. In case of 1738 * multiple redirects, the navigation will resolve with the response of the 1739 * last redirect. 1740 */ 1741 abstract reload(options?: WaitForOptions): Promise<HTTPResponse | null>; 1742 1743 /** 1744 * Waits for the page to navigate to a new URL or to reload. It is useful when 1745 * you run code that will indirectly cause the page to navigate. 1746 * 1747 * @example 1748 * 1749 * ```ts 1750 * const [response] = await Promise.all([ 1751 * page.waitForNavigation(), // The promise resolves after navigation has finished 1752 * page.click('a.my-link'), // Clicking the link will indirectly cause a navigation 1753 * ]); 1754 * ``` 1755 * 1756 * @remarks 1757 * 1758 * Usage of the 1759 * {@link https://developer.mozilla.org/en-US/docs/Web/API/History_API | History API} 1760 * to change the URL is considered a navigation. 1761 * 1762 * @param options - Navigation parameters which might have the following 1763 * properties: 1764 * @returns A `Promise` which resolves to the main resource response. 1765 * 1766 * - In case of multiple redirects, the navigation will resolve with the 1767 * response of the last redirect. 1768 * - In case of navigation to a different anchor or navigation due to History 1769 * API usage, the navigation will resolve with `null`. 1770 */ 1771 async waitForNavigation( 1772 options: WaitForOptions = {}, 1773 ): Promise<HTTPResponse | null> { 1774 return await this.mainFrame().waitForNavigation(options); 1775 } 1776 1777 /** 1778 * @param urlOrPredicate - A URL or predicate to wait for 1779 * @param options - Optional waiting parameters 1780 * @returns Promise which resolves to the matched request 1781 * @example 1782 * 1783 * ```ts 1784 * const firstRequest = await page.waitForRequest( 1785 * 'https://example.com/resource', 1786 * ); 1787 * const finalRequest = await page.waitForRequest( 1788 * request => request.url() === 'https://example.com', 1789 * ); 1790 * return finalRequest.response()?.ok(); 1791 * ``` 1792 * 1793 * @remarks 1794 * Optional Waiting Parameters have: 1795 * 1796 * - `timeout`: Maximum wait time in milliseconds, defaults to `30` seconds, pass 1797 * `0` to disable the timeout. The default value can be changed by using the 1798 * {@link Page.setDefaultTimeout} method. 1799 */ 1800 waitForRequest( 1801 urlOrPredicate: string | AwaitablePredicate<HTTPRequest>, 1802 options: WaitTimeoutOptions = {}, 1803 ): Promise<HTTPRequest> { 1804 const {timeout: ms = this._timeoutSettings.timeout(), signal} = options; 1805 if (typeof urlOrPredicate === 'string') { 1806 const url = urlOrPredicate; 1807 urlOrPredicate = (request: HTTPRequest) => { 1808 return request.url() === url; 1809 }; 1810 } 1811 const observable$ = fromEmitterEvent(this, PageEvent.Request).pipe( 1812 filterAsync(urlOrPredicate), 1813 raceWith( 1814 timeout(ms), 1815 fromAbortSignal(signal), 1816 fromEmitterEvent(this, PageEvent.Close).pipe( 1817 map(() => { 1818 throw new TargetCloseError('Page closed!'); 1819 }), 1820 ), 1821 ), 1822 ); 1823 return firstValueFrom(observable$); 1824 } 1825 1826 /** 1827 * @param urlOrPredicate - A URL or predicate to wait for. 1828 * @param options - Optional waiting parameters 1829 * @returns Promise which resolves to the matched response. 1830 * @example 1831 * 1832 * ```ts 1833 * const firstResponse = await page.waitForResponse( 1834 * 'https://example.com/resource', 1835 * ); 1836 * const finalResponse = await page.waitForResponse( 1837 * response => 1838 * response.url() === 'https://example.com' && response.status() === 200, 1839 * ); 1840 * const finalResponse = await page.waitForResponse(async response => { 1841 * return (await response.text()).includes('<html>'); 1842 * }); 1843 * return finalResponse.ok(); 1844 * ``` 1845 * 1846 * @remarks 1847 * Optional Parameter have: 1848 * 1849 * - `timeout`: Maximum wait time in milliseconds, defaults to `30` seconds, 1850 * pass `0` to disable the timeout. The default value can be changed by using 1851 * the {@link Page.setDefaultTimeout} method. 1852 */ 1853 waitForResponse( 1854 urlOrPredicate: string | AwaitablePredicate<HTTPResponse>, 1855 options: WaitTimeoutOptions = {}, 1856 ): Promise<HTTPResponse> { 1857 const {timeout: ms = this._timeoutSettings.timeout(), signal} = options; 1858 if (typeof urlOrPredicate === 'string') { 1859 const url = urlOrPredicate; 1860 urlOrPredicate = (response: HTTPResponse) => { 1861 return response.url() === url; 1862 }; 1863 } 1864 const observable$ = fromEmitterEvent(this, PageEvent.Response).pipe( 1865 filterAsync(urlOrPredicate), 1866 raceWith( 1867 timeout(ms), 1868 fromAbortSignal(signal), 1869 fromEmitterEvent(this, PageEvent.Close).pipe( 1870 map(() => { 1871 throw new TargetCloseError('Page closed!'); 1872 }), 1873 ), 1874 ), 1875 ); 1876 return firstValueFrom(observable$); 1877 } 1878 1879 /** 1880 * Waits for the network to be idle. 1881 * 1882 * @param options - Options to configure waiting behavior. 1883 * @returns A promise which resolves once the network is idle. 1884 */ 1885 waitForNetworkIdle(options: WaitForNetworkIdleOptions = {}): Promise<void> { 1886 return firstValueFrom(this.waitForNetworkIdle$(options)); 1887 } 1888 1889 /** 1890 * @internal 1891 */ 1892 waitForNetworkIdle$( 1893 options: WaitForNetworkIdleOptions = {}, 1894 ): Observable<void> { 1895 const { 1896 timeout: ms = this._timeoutSettings.timeout(), 1897 idleTime = NETWORK_IDLE_TIME, 1898 concurrency = 0, 1899 signal, 1900 } = options; 1901 1902 return this.#inflight$.pipe( 1903 switchMap(inflight => { 1904 if (inflight > concurrency) { 1905 return EMPTY; 1906 } 1907 return timer(idleTime); 1908 }), 1909 map(() => {}), 1910 raceWith( 1911 timeout(ms), 1912 fromAbortSignal(signal), 1913 fromEmitterEvent(this, PageEvent.Close).pipe( 1914 map(() => { 1915 throw new TargetCloseError('Page closed!'); 1916 }), 1917 ), 1918 ), 1919 ); 1920 } 1921 1922 /** 1923 * Waits for a frame matching the given conditions to appear. 1924 * 1925 * @example 1926 * 1927 * ```ts 1928 * const frame = await page.waitForFrame(async frame => { 1929 * const frameElement = await frame.frameElement(); 1930 * if (!frameElement) { 1931 * return false; 1932 * } 1933 * const name = await frameElement.evaluate(el => el.getAttribute('name')); 1934 * return name === 'test'; 1935 * }); 1936 * ``` 1937 */ 1938 async waitForFrame( 1939 urlOrPredicate: string | ((frame: Frame) => Awaitable<boolean>), 1940 options: WaitTimeoutOptions = {}, 1941 ): Promise<Frame> { 1942 const {timeout: ms = this.getDefaultTimeout(), signal} = options; 1943 1944 const predicate = isString(urlOrPredicate) 1945 ? (frame: Frame) => { 1946 return urlOrPredicate === frame.url(); 1947 } 1948 : urlOrPredicate; 1949 1950 return await firstValueFrom( 1951 merge( 1952 fromEmitterEvent(this, PageEvent.FrameAttached), 1953 fromEmitterEvent(this, PageEvent.FrameNavigated), 1954 from(this.frames()), 1955 ).pipe( 1956 filterAsync(predicate), 1957 first(), 1958 raceWith( 1959 timeout(ms), 1960 fromAbortSignal(signal), 1961 fromEmitterEvent(this, PageEvent.Close).pipe( 1962 map(() => { 1963 throw new TargetCloseError('Page closed.'); 1964 }), 1965 ), 1966 ), 1967 ), 1968 ); 1969 } 1970 1971 /** 1972 * This method navigate to the previous page in history. 1973 * @param options - Navigation parameters 1974 * @returns Promise which resolves to the main resource response. In case of 1975 * multiple redirects, the navigation will resolve with the response of the 1976 * last redirect. If can not go back, resolves to `null`. 1977 */ 1978 abstract goBack(options?: WaitForOptions): Promise<HTTPResponse | null>; 1979 1980 /** 1981 * This method navigate to the next page in history. 1982 * @param options - Navigation Parameter 1983 * @returns Promise which resolves to the main resource response. In case of 1984 * multiple redirects, the navigation will resolve with the response of the 1985 * last redirect. If can not go forward, resolves to `null`. 1986 */ 1987 abstract goForward(options?: WaitForOptions): Promise<HTTPResponse | null>; 1988 1989 /** 1990 * Brings page to front (activates tab). 1991 */ 1992 abstract bringToFront(): Promise<void>; 1993 1994 /** 1995 * Emulates a given device's metrics and user agent. 1996 * 1997 * To aid emulation, Puppeteer provides a list of known devices that can be 1998 * via {@link KnownDevices}. 1999 * 2000 * @remarks 2001 * This method is a shortcut for calling two methods: 2002 * {@link Page.setUserAgent} and {@link Page.setViewport}. 2003 * 2004 * This method will resize the page. A lot of websites don't expect phones to 2005 * change size, so you should emulate before navigating to the page. 2006 * 2007 * @example 2008 * 2009 * ```ts 2010 * import {KnownDevices} from 'puppeteer'; 2011 * const iPhone = KnownDevices['iPhone 15 Pro']; 2012 * 2013 * (async () => { 2014 * const browser = await puppeteer.launch(); 2015 * const page = await browser.newPage(); 2016 * await page.emulate(iPhone); 2017 * await page.goto('https://www.google.com'); 2018 * // other actions... 2019 * await browser.close(); 2020 * })(); 2021 * ``` 2022 */ 2023 async emulate(device: Device): Promise<void> { 2024 await Promise.all([ 2025 this.setUserAgent(device.userAgent), 2026 this.setViewport(device.viewport), 2027 ]); 2028 } 2029 2030 /** 2031 * @param enabled - Whether or not to enable JavaScript on the page. 2032 * @remarks 2033 * NOTE: changing this value won't affect scripts that have already been run. 2034 * It will take full effect on the next navigation. 2035 */ 2036 abstract setJavaScriptEnabled(enabled: boolean): Promise<void>; 2037 2038 /** 2039 * Toggles bypassing page's Content-Security-Policy. 2040 * @param enabled - sets bypassing of page's Content-Security-Policy. 2041 * @remarks 2042 * NOTE: CSP bypassing happens at the moment of CSP initialization rather than 2043 * evaluation. Usually, this means that `page.setBypassCSP` should be called 2044 * before navigating to the domain. 2045 */ 2046 abstract setBypassCSP(enabled: boolean): Promise<void>; 2047 2048 /** 2049 * @param type - Changes the CSS media type of the page. The only allowed 2050 * values are `screen`, `print` and `null`. Passing `null` disables CSS media 2051 * emulation. 2052 * @example 2053 * 2054 * ```ts 2055 * await page.evaluate(() => matchMedia('screen').matches); 2056 * // → true 2057 * await page.evaluate(() => matchMedia('print').matches); 2058 * // → false 2059 * 2060 * await page.emulateMediaType('print'); 2061 * await page.evaluate(() => matchMedia('screen').matches); 2062 * // → false 2063 * await page.evaluate(() => matchMedia('print').matches); 2064 * // → true 2065 * 2066 * await page.emulateMediaType(null); 2067 * await page.evaluate(() => matchMedia('screen').matches); 2068 * // → true 2069 * await page.evaluate(() => matchMedia('print').matches); 2070 * // → false 2071 * ``` 2072 */ 2073 abstract emulateMediaType(type?: string): Promise<void>; 2074 2075 /** 2076 * Enables CPU throttling to emulate slow CPUs. 2077 * @param factor - slowdown factor (1 is no throttle, 2 is 2x slowdown, etc). 2078 */ 2079 abstract emulateCPUThrottling(factor: number | null): Promise<void>; 2080 2081 /** 2082 * @param features - `<?Array<Object>>` Given an array of media feature 2083 * objects, emulates CSS media features on the page. Each media feature object 2084 * must have the following properties: 2085 * @example 2086 * 2087 * ```ts 2088 * await page.emulateMediaFeatures([ 2089 * {name: 'prefers-color-scheme', value: 'dark'}, 2090 * ]); 2091 * await page.evaluate( 2092 * () => matchMedia('(prefers-color-scheme: dark)').matches, 2093 * ); 2094 * // → true 2095 * await page.evaluate( 2096 * () => matchMedia('(prefers-color-scheme: light)').matches, 2097 * ); 2098 * // → false 2099 * 2100 * await page.emulateMediaFeatures([ 2101 * {name: 'prefers-reduced-motion', value: 'reduce'}, 2102 * ]); 2103 * await page.evaluate( 2104 * () => matchMedia('(prefers-reduced-motion: reduce)').matches, 2105 * ); 2106 * // → true 2107 * await page.evaluate( 2108 * () => matchMedia('(prefers-reduced-motion: no-preference)').matches, 2109 * ); 2110 * // → false 2111 * 2112 * await page.emulateMediaFeatures([ 2113 * {name: 'prefers-color-scheme', value: 'dark'}, 2114 * {name: 'prefers-reduced-motion', value: 'reduce'}, 2115 * ]); 2116 * await page.evaluate( 2117 * () => matchMedia('(prefers-color-scheme: dark)').matches, 2118 * ); 2119 * // → true 2120 * await page.evaluate( 2121 * () => matchMedia('(prefers-color-scheme: light)').matches, 2122 * ); 2123 * // → false 2124 * await page.evaluate( 2125 * () => matchMedia('(prefers-reduced-motion: reduce)').matches, 2126 * ); 2127 * // → true 2128 * await page.evaluate( 2129 * () => matchMedia('(prefers-reduced-motion: no-preference)').matches, 2130 * ); 2131 * // → false 2132 * 2133 * await page.emulateMediaFeatures([{name: 'color-gamut', value: 'p3'}]); 2134 * await page.evaluate(() => matchMedia('(color-gamut: srgb)').matches); 2135 * // → true 2136 * await page.evaluate(() => matchMedia('(color-gamut: p3)').matches); 2137 * // → true 2138 * await page.evaluate(() => matchMedia('(color-gamut: rec2020)').matches); 2139 * // → false 2140 * ``` 2141 */ 2142 abstract emulateMediaFeatures(features?: MediaFeature[]): Promise<void>; 2143 2144 /** 2145 * @param timezoneId - Changes the timezone of the page. See 2146 * {@link https://source.chromium.org/chromium/chromium/deps/icu.git/+/faee8bc70570192d82d2978a71e2a615788597d1:source/data/misc/metaZones.txt | ICU’s metaZones.txt} 2147 * for a list of supported timezone IDs. Passing 2148 * `null` disables timezone emulation. 2149 */ 2150 abstract emulateTimezone(timezoneId?: string): Promise<void>; 2151 2152 /** 2153 * Emulates the idle state. 2154 * If no arguments set, clears idle state emulation. 2155 * 2156 * @example 2157 * 2158 * ```ts 2159 * // set idle emulation 2160 * await page.emulateIdleState({isUserActive: true, isScreenUnlocked: false}); 2161 * 2162 * // do some checks here 2163 * ... 2164 * 2165 * // clear idle emulation 2166 * await page.emulateIdleState(); 2167 * ``` 2168 * 2169 * @param overrides - Mock idle state. If not set, clears idle overrides 2170 */ 2171 abstract emulateIdleState(overrides?: { 2172 isUserActive: boolean; 2173 isScreenUnlocked: boolean; 2174 }): Promise<void>; 2175 2176 /** 2177 * Simulates the given vision deficiency on the page. 2178 * 2179 * @example 2180 * 2181 * ```ts 2182 * import puppeteer from 'puppeteer'; 2183 * 2184 * (async () => { 2185 * const browser = await puppeteer.launch(); 2186 * const page = await browser.newPage(); 2187 * await page.goto('https://v8.dev/blog/10-years'); 2188 * 2189 * await page.emulateVisionDeficiency('achromatopsia'); 2190 * await page.screenshot({path: 'achromatopsia.png'}); 2191 * 2192 * await page.emulateVisionDeficiency('deuteranopia'); 2193 * await page.screenshot({path: 'deuteranopia.png'}); 2194 * 2195 * await page.emulateVisionDeficiency('blurredVision'); 2196 * await page.screenshot({path: 'blurred-vision.png'}); 2197 * 2198 * await page.emulateVisionDeficiency('reducedContrast'); 2199 * await page.screenshot({path: 'reduced-contrast.png'}); 2200 * 2201 * await browser.close(); 2202 * })(); 2203 * ``` 2204 * 2205 * @param type - the type of deficiency to simulate, or `'none'` to reset. 2206 */ 2207 abstract emulateVisionDeficiency( 2208 type?: Protocol.Emulation.SetEmulatedVisionDeficiencyRequest['type'], 2209 ): Promise<void>; 2210 2211 /** 2212 * `page.setViewport` will resize the page. A lot of websites don't expect 2213 * phones to change size, so you should set the viewport before navigating to 2214 * the page. 2215 * 2216 * In the case of multiple pages in a single browser, each page can have its 2217 * own viewport size. Setting the viewport to `null` resets the viewport to 2218 * its default value. 2219 * 2220 * @example 2221 * 2222 * ```ts 2223 * const page = await browser.newPage(); 2224 * await page.setViewport({ 2225 * width: 640, 2226 * height: 480, 2227 * deviceScaleFactor: 1, 2228 * }); 2229 * await page.goto('https://example.com'); 2230 * ``` 2231 * 2232 * @param viewport - 2233 * @remarks 2234 * NOTE: in certain cases, setting viewport will reload the page in order to 2235 * set the isMobile or hasTouch properties. 2236 */ 2237 abstract setViewport(viewport: Viewport | null): Promise<void>; 2238 2239 /** 2240 * Returns the current page viewport settings without checking the actual page 2241 * viewport. 2242 * 2243 * This is either the viewport set with the previous {@link Page.setViewport} 2244 * call or the default viewport set via 2245 * {@link ConnectOptions.defaultViewport | 2246 * ConnectOptions.defaultViewport}. 2247 */ 2248 abstract viewport(): Viewport | null; 2249 2250 /** 2251 * Evaluates a function in the page's context and returns the result. 2252 * 2253 * If the function passed to `page.evaluate` returns a Promise, the 2254 * function will wait for the promise to resolve and return its value. 2255 * 2256 * @example 2257 * 2258 * ```ts 2259 * const result = await frame.evaluate(() => { 2260 * return Promise.resolve(8 * 7); 2261 * }); 2262 * console.log(result); // prints "56" 2263 * ``` 2264 * 2265 * You can pass a string instead of a function (although functions are 2266 * recommended as they are easier to debug and use with TypeScript): 2267 * 2268 * @example 2269 * 2270 * ```ts 2271 * const aHandle = await page.evaluate('1 + 2'); 2272 * ``` 2273 * 2274 * To get the best TypeScript experience, you should pass in as the 2275 * generic the type of `pageFunction`: 2276 * 2277 * ```ts 2278 * const aHandle = await page.evaluate(() => 2); 2279 * ``` 2280 * 2281 * @example 2282 * 2283 * {@link ElementHandle} instances (including {@link JSHandle}s) can be passed 2284 * as arguments to the `pageFunction`: 2285 * 2286 * ```ts 2287 * const bodyHandle = await page.$('body'); 2288 * const html = await page.evaluate(body => body.innerHTML, bodyHandle); 2289 * await bodyHandle.dispose(); 2290 * ``` 2291 * 2292 * @param pageFunction - a function that is run within the page 2293 * @param args - arguments to be passed to the pageFunction 2294 * 2295 * @returns the return value of `pageFunction`. 2296 */ 2297 async evaluate< 2298 Params extends unknown[], 2299 Func extends EvaluateFunc<Params> = EvaluateFunc<Params>, 2300 >( 2301 pageFunction: Func | string, 2302 ...args: Params 2303 ): Promise<Awaited<ReturnType<Func>>> { 2304 pageFunction = withSourcePuppeteerURLIfNone( 2305 this.evaluate.name, 2306 pageFunction, 2307 ); 2308 return await this.mainFrame().evaluate(pageFunction, ...args); 2309 } 2310 2311 /** 2312 * Adds a function which would be invoked in one of the following scenarios: 2313 * 2314 * - whenever the page is navigated 2315 * 2316 * - whenever the child frame is attached or navigated. In this case, the 2317 * function is invoked in the context of the newly attached frame. 2318 * 2319 * The function is invoked after the document was created but before any of 2320 * its scripts were run. This is useful to amend the JavaScript environment, 2321 * e.g. to seed `Math.random`. 2322 * @param pageFunction - Function to be evaluated in browser context 2323 * @param args - Arguments to pass to `pageFunction` 2324 * @example 2325 * An example of overriding the navigator.languages property before the page loads: 2326 * 2327 * ```ts 2328 * // preload.js 2329 * 2330 * // overwrite the `languages` property to use a custom getter 2331 * Object.defineProperty(navigator, 'languages', { 2332 * get: function () { 2333 * return ['en-US', 'en', 'bn']; 2334 * }, 2335 * }); 2336 * 2337 * // In your puppeteer script, assuming the preload.js file is 2338 * // in same folder of our script. 2339 * const preloadFile = fs.readFileSync('./preload.js', 'utf8'); 2340 * await page.evaluateOnNewDocument(preloadFile); 2341 * ``` 2342 */ 2343 abstract evaluateOnNewDocument< 2344 Params extends unknown[], 2345 Func extends (...args: Params) => unknown = (...args: Params) => unknown, 2346 >( 2347 pageFunction: Func | string, 2348 ...args: Params 2349 ): Promise<NewDocumentScriptEvaluation>; 2350 2351 /** 2352 * Removes script that injected into page by Page.evaluateOnNewDocument. 2353 * 2354 * @param identifier - script identifier 2355 */ 2356 abstract removeScriptToEvaluateOnNewDocument( 2357 identifier: string, 2358 ): Promise<void>; 2359 2360 /** 2361 * Toggles ignoring cache for each request based on the enabled state. By 2362 * default, caching is enabled. 2363 * @param enabled - sets the `enabled` state of cache 2364 * @defaultValue `true` 2365 */ 2366 abstract setCacheEnabled(enabled?: boolean): Promise<void>; 2367 2368 /** 2369 * @internal 2370 */ 2371 async _maybeWriteTypedArrayToFile( 2372 path: string | undefined, 2373 typedArray: Uint8Array, 2374 ): Promise<void> { 2375 if (!path) { 2376 return; 2377 } 2378 2379 await environment.value.fs.promises.writeFile(path, typedArray); 2380 } 2381 2382 /** 2383 * Captures a screencast of this {@link Page | page}. 2384 * 2385 * @example 2386 * Recording a {@link Page | page}: 2387 * 2388 * ``` 2389 * import puppeteer from 'puppeteer'; 2390 * 2391 * // Launch a browser 2392 * const browser = await puppeteer.launch(); 2393 * 2394 * // Create a new page 2395 * const page = await browser.newPage(); 2396 * 2397 * // Go to your site. 2398 * await page.goto("https://www.example.com"); 2399 * 2400 * // Start recording. 2401 * const recorder = await page.screencast({path: 'recording.webm'}); 2402 * 2403 * // Do something. 2404 * 2405 * // Stop recording. 2406 * await recorder.stop(); 2407 * 2408 * browser.close(); 2409 * ``` 2410 * 2411 * @param options - Configures screencast behavior. 2412 * 2413 * @experimental 2414 * 2415 * @remarks 2416 * 2417 * By default, all recordings will be {@link https://www.webmproject.org/ | WebM} format using 2418 * the {@link https://www.webmproject.org/vp9/ | VP9} video codec, with a frame rate of 30 FPS. 2419 * 2420 * You must have {@link https://ffmpeg.org/ | ffmpeg} installed on your system. 2421 */ 2422 async screencast( 2423 options: Readonly<ScreencastOptions> = {}, 2424 ): Promise<ScreenRecorder> { 2425 const ScreenRecorder = environment.value.ScreenRecorder; 2426 const [width, height, devicePixelRatio] = 2427 await this.#getNativePixelDimensions(); 2428 let crop: BoundingBox | undefined; 2429 if (options.crop) { 2430 const { 2431 x, 2432 y, 2433 width: cropWidth, 2434 height: cropHeight, 2435 } = roundRectangle(normalizeRectangle(options.crop)); 2436 if (x < 0 || y < 0) { 2437 throw new Error( 2438 `\`crop.x\` and \`crop.y\` must be greater than or equal to 0.`, 2439 ); 2440 } 2441 if (cropWidth <= 0 || cropHeight <= 0) { 2442 throw new Error( 2443 `\`crop.height\` and \`crop.width\` must be greater than or equal to 0.`, 2444 ); 2445 } 2446 2447 const viewportWidth = width / devicePixelRatio; 2448 const viewportHeight = height / devicePixelRatio; 2449 if (x + cropWidth > viewportWidth) { 2450 throw new Error( 2451 `\`crop.width\` cannot be larger than the viewport width (${viewportWidth}).`, 2452 ); 2453 } 2454 if (y + cropHeight > viewportHeight) { 2455 throw new Error( 2456 `\`crop.height\` cannot be larger than the viewport height (${viewportHeight}).`, 2457 ); 2458 } 2459 2460 crop = { 2461 x: x * devicePixelRatio, 2462 y: y * devicePixelRatio, 2463 width: cropWidth * devicePixelRatio, 2464 height: cropHeight * devicePixelRatio, 2465 }; 2466 } 2467 if (options.speed !== undefined && options.speed <= 0) { 2468 throw new Error(`\`speed\` must be greater than 0.`); 2469 } 2470 if (options.scale !== undefined && options.scale <= 0) { 2471 throw new Error(`\`scale\` must be greater than 0.`); 2472 } 2473 2474 const recorder = new ScreenRecorder(this, width, height, { 2475 ...options, 2476 crop, 2477 }); 2478 try { 2479 await this._startScreencast(); 2480 } catch (error) { 2481 void recorder.stop(); 2482 throw error; 2483 } 2484 if (options.path) { 2485 const {createWriteStream} = environment.value.fs; 2486 const stream = createWriteStream(options.path, 'binary'); 2487 recorder.pipe(stream); 2488 } 2489 return recorder; 2490 } 2491 2492 #screencastSessionCount = 0; 2493 #startScreencastPromise: Promise<void> | undefined; 2494 2495 /** 2496 * @internal 2497 */ 2498 async _startScreencast(): Promise<void> { 2499 ++this.#screencastSessionCount; 2500 if (!this.#startScreencastPromise) { 2501 this.#startScreencastPromise = this.mainFrame() 2502 .client.send('Page.startScreencast', {format: 'png'}) 2503 .then(() => { 2504 // Wait for the first frame. 2505 return new Promise(resolve => { 2506 return this.mainFrame().client.once('Page.screencastFrame', () => { 2507 return resolve(); 2508 }); 2509 }); 2510 }); 2511 } 2512 await this.#startScreencastPromise; 2513 } 2514 2515 /** 2516 * @internal 2517 */ 2518 async _stopScreencast(): Promise<void> { 2519 --this.#screencastSessionCount; 2520 if (!this.#startScreencastPromise) { 2521 return; 2522 } 2523 this.#startScreencastPromise = undefined; 2524 if (this.#screencastSessionCount === 0) { 2525 await this.mainFrame().client.send('Page.stopScreencast'); 2526 } 2527 } 2528 2529 /** 2530 * Gets the native, non-emulated dimensions of the viewport. 2531 */ 2532 async #getNativePixelDimensions(): Promise< 2533 readonly [width: number, height: number, devicePixelRatio: number] 2534 > { 2535 const viewport = this.viewport(); 2536 using stack = new DisposableStack(); 2537 if (viewport && viewport.deviceScaleFactor !== 0) { 2538 await this.setViewport({...viewport, deviceScaleFactor: 0}); 2539 stack.defer(() => { 2540 void this.setViewport(viewport).catch(debugError); 2541 }); 2542 } 2543 return await this.mainFrame() 2544 .isolatedRealm() 2545 .evaluate(() => { 2546 return [ 2547 window.visualViewport!.width * window.devicePixelRatio, 2548 window.visualViewport!.height * window.devicePixelRatio, 2549 window.devicePixelRatio, 2550 ] as const; 2551 }); 2552 } 2553 2554 /** 2555 * Captures a screenshot of this {@link Page | page}. 2556 * 2557 * @param options - Configures screenshot behavior. 2558 * 2559 * @remarks 2560 * 2561 * While a screenshot is being taken in a {@link BrowserContext}, the 2562 * following methods will automatically wait for the screenshot to 2563 * finish to prevent interference with the screenshot process: 2564 * {@link BrowserContext.newPage}, {@link Browser.newPage}, 2565 * {@link Page.close}. 2566 * 2567 * Calling {@link Page.bringToFront} will not wait for existing 2568 * screenshot operations. 2569 * 2570 */ 2571 async screenshot( 2572 options: Readonly<ScreenshotOptions> & {encoding: 'base64'}, 2573 ): Promise<string>; 2574 async screenshot(options?: Readonly<ScreenshotOptions>): Promise<Uint8Array>; 2575 @guarded(function () { 2576 return this.browser(); 2577 }) 2578 async screenshot( 2579 userOptions: Readonly<ScreenshotOptions> = {}, 2580 ): Promise<Uint8Array | string> { 2581 using _guard = await this.browserContext().startScreenshot(); 2582 2583 const options = { 2584 ...userOptions, 2585 clip: userOptions.clip 2586 ? { 2587 ...userOptions.clip, 2588 } 2589 : undefined, 2590 }; 2591 if (options.type === undefined && options.path !== undefined) { 2592 const filePath = options.path; 2593 // Note we cannot use Node.js here due to browser compatibility. 2594 const extension = filePath 2595 .slice(filePath.lastIndexOf('.') + 1) 2596 .toLowerCase(); 2597 switch (extension) { 2598 case 'png': 2599 options.type = 'png'; 2600 break; 2601 case 'jpeg': 2602 case 'jpg': 2603 options.type = 'jpeg'; 2604 break; 2605 case 'webp': 2606 options.type = 'webp'; 2607 break; 2608 } 2609 } 2610 if (options.quality !== undefined) { 2611 if (options.quality < 0 || options.quality > 100) { 2612 throw new Error( 2613 `Expected 'quality' (${options.quality}) to be between 0 and 100, inclusive.`, 2614 ); 2615 } 2616 if ( 2617 options.type === undefined || 2618 !['jpeg', 'webp'].includes(options.type) 2619 ) { 2620 throw new Error( 2621 `${options.type ?? 'png'} screenshots do not support 'quality'.`, 2622 ); 2623 } 2624 } 2625 if (options.clip) { 2626 if (options.clip.width <= 0) { 2627 throw new Error("'width' in 'clip' must be positive."); 2628 } 2629 if (options.clip.height <= 0) { 2630 throw new Error("'height' in 'clip' must be positive."); 2631 } 2632 } 2633 2634 setDefaultScreenshotOptions(options); 2635 2636 await using stack = new AsyncDisposableStack(); 2637 if (options.clip) { 2638 if (options.fullPage) { 2639 throw new Error("'clip' and 'fullPage' are mutually exclusive"); 2640 } 2641 2642 options.clip = roundRectangle(normalizeRectangle(options.clip)); 2643 } else { 2644 if (options.fullPage) { 2645 // If `captureBeyondViewport` is `false`, then we set the viewport to 2646 // capture the full page. Note this may be affected by on-page CSS and 2647 // JavaScript. 2648 if (!options.captureBeyondViewport) { 2649 const scrollDimensions = await this.mainFrame() 2650 .isolatedRealm() 2651 .evaluate(() => { 2652 const element = document.documentElement; 2653 return { 2654 width: element.scrollWidth, 2655 height: element.scrollHeight, 2656 }; 2657 }); 2658 const viewport = this.viewport(); 2659 await this.setViewport({ 2660 ...viewport, 2661 ...scrollDimensions, 2662 }); 2663 stack.defer(async () => { 2664 await this.setViewport(viewport).catch(debugError); 2665 }); 2666 } 2667 } else { 2668 options.captureBeyondViewport = false; 2669 } 2670 } 2671 2672 const data = await this._screenshot(options); 2673 if (options.encoding === 'base64') { 2674 return data; 2675 } 2676 2677 const typedArray = stringToTypedArray(data, true); 2678 await this._maybeWriteTypedArrayToFile(options.path, typedArray); 2679 return typedArray; 2680 } 2681 2682 /** 2683 * @internal 2684 */ 2685 abstract _screenshot(options: Readonly<ScreenshotOptions>): Promise<string>; 2686 2687 /** 2688 * Generates a PDF of the page with the `print` CSS media type. 2689 * 2690 * @param options - options for generating the PDF. 2691 * 2692 * @remarks 2693 * 2694 * To generate a PDF with the `screen` media type, call 2695 * {@link Page.emulateMediaType | `page.emulateMediaType('screen')`} before 2696 * calling `page.pdf()`. 2697 * 2698 * By default, `page.pdf()` generates a pdf with modified colors for printing. 2699 * Use the 2700 * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-print-color-adjust | `-webkit-print-color-adjust`} 2701 * property to force rendering of exact colors. 2702 */ 2703 abstract createPDFStream( 2704 options?: PDFOptions, 2705 ): Promise<ReadableStream<Uint8Array>>; 2706 2707 /** 2708 * {@inheritDoc Page.createPDFStream} 2709 */ 2710 abstract pdf(options?: PDFOptions): Promise<Uint8Array>; 2711 2712 /** 2713 * The page's title 2714 * 2715 * @remarks 2716 * 2717 * Shortcut for {@link Frame.title | page.mainFrame().title()}. 2718 */ 2719 async title(): Promise<string> { 2720 return await this.mainFrame().title(); 2721 } 2722 2723 abstract close(options?: {runBeforeUnload?: boolean}): Promise<void>; 2724 2725 /** 2726 * Indicates that the page has been closed. 2727 * @returns 2728 */ 2729 abstract isClosed(): boolean; 2730 2731 /** 2732 * {@inheritDoc Mouse} 2733 */ 2734 abstract get mouse(): Mouse; 2735 2736 /** 2737 * This method fetches an element with `selector`, scrolls it into view if 2738 * needed, and then uses {@link Page.mouse} to click in the center of the 2739 * element. If there's no element matching `selector`, the method throws an 2740 * error. 2741 * 2742 * @remarks 2743 * 2744 * Bear in mind that if `click()` triggers a navigation event and 2745 * there's a separate `page.waitForNavigation()` promise to be resolved, you 2746 * may end up with a race condition that yields unexpected results. The 2747 * correct pattern for click and wait for navigation is the following: 2748 * 2749 * ```ts 2750 * const [response] = await Promise.all([ 2751 * page.waitForNavigation(waitOptions), 2752 * page.click(selector, clickOptions), 2753 * ]); 2754 * ``` 2755 * 2756 * Shortcut for {@link Frame.click | page.mainFrame().click(selector[, options]) }. 2757 * @param selector - 2758 * {@link https://pptr.dev/guides/page-interactions#selectors | selector} 2759 * to query the page for. 2760 * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors} 2761 * can be passed as-is and a 2762 * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax} 2763 * allows querying by 2764 * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text}, 2765 * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name}, 2766 * and 2767 * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath} 2768 * and 2769 * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}. 2770 * Alternatively, you can specify the selector type using a 2771 * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}. If there are 2772 * multiple elements satisfying the `selector`, the first will be clicked 2773 * @param options - `Object` 2774 * @returns Promise which resolves when the element matching `selector` is 2775 * successfully clicked. The Promise will be rejected if there is no element 2776 * matching `selector`. 2777 */ 2778 click(selector: string, options?: Readonly<ClickOptions>): Promise<void> { 2779 return this.mainFrame().click(selector, options); 2780 } 2781 2782 /** 2783 * This method fetches an element with `selector` and focuses it. If 2784 * there's no element matching `selector`, the method throws an error. 2785 * @param selector - 2786 * {@link https://pptr.dev/guides/page-interactions#selectors | selector} 2787 * to query the page for. 2788 * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors} 2789 * can be passed as-is and a 2790 * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax} 2791 * allows querying by 2792 * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text}, 2793 * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name}, 2794 * and 2795 * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath} 2796 * and 2797 * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}. 2798 * Alternatively, you can specify the selector type using a 2799 * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}. 2800 * If there are multiple elements satisfying the selector, the first 2801 * will be focused. 2802 * @returns Promise which resolves when the element matching selector 2803 * is successfully focused. The promise will be rejected if there is 2804 * no element matching selector. 2805 * 2806 * @remarks 2807 * 2808 * Shortcut for 2809 * {@link Frame.focus | page.mainFrame().focus(selector)}. 2810 */ 2811 focus(selector: string): Promise<void> { 2812 return this.mainFrame().focus(selector); 2813 } 2814 2815 /** 2816 * This method fetches an element with `selector`, scrolls it into view if 2817 * needed, and then uses {@link Page.mouse} 2818 * to hover over the center of the element. 2819 * If there's no element matching `selector`, the method throws an error. 2820 * @param selector - 2821 * {@link https://pptr.dev/guides/page-interactions#selectors | selector} 2822 * to query the page for. 2823 * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors} 2824 * can be passed as-is and a 2825 * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax} 2826 * allows querying by 2827 * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text}, 2828 * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name}, 2829 * and 2830 * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath} 2831 * and 2832 * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}. 2833 * Alternatively, you can specify the selector type using a 2834 * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}. If there are 2835 * multiple elements satisfying the `selector`, the first will be hovered. 2836 * @returns Promise which resolves when the element matching `selector` is 2837 * successfully hovered. Promise gets rejected if there's no element matching 2838 * `selector`. 2839 * 2840 * @remarks 2841 * 2842 * Shortcut for {@link Page.hover | page.mainFrame().hover(selector)}. 2843 */ 2844 hover(selector: string): Promise<void> { 2845 return this.mainFrame().hover(selector); 2846 } 2847 2848 /** 2849 * Triggers a `change` and `input` event once all the provided options have been 2850 * selected. If there's no `<select>` element matching `selector`, the method 2851 * throws an error. 2852 * 2853 * @example 2854 * 2855 * ```ts 2856 * page.select('select#colors', 'blue'); // single selection 2857 * page.select('select#colors', 'red', 'green', 'blue'); // multiple selections 2858 * ``` 2859 * 2860 * @param selector - 2861 * {@link https://pptr.dev/guides/page-interactions#selectors | selector} 2862 * to query the page for. 2863 * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors} 2864 * can be passed as-is and a 2865 * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax} 2866 * allows querying by 2867 * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text}, 2868 * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name}, 2869 * and 2870 * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath} 2871 * and 2872 * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}. 2873 * Alternatively, you can specify the selector type using a 2874 * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}. 2875 * @param values - Values of options to select. If the `<select>` has the 2876 * `multiple` attribute, all values are considered, otherwise only the first one 2877 * is taken into account. 2878 * @returns 2879 * 2880 * @remarks 2881 * 2882 * Shortcut for {@link Frame.select | page.mainFrame().select()} 2883 */ 2884 select(selector: string, ...values: string[]): Promise<string[]> { 2885 return this.mainFrame().select(selector, ...values); 2886 } 2887 2888 /** 2889 * This method fetches an element with `selector`, scrolls it into view if 2890 * needed, and then uses {@link Page.touchscreen} 2891 * to tap in the center of the element. 2892 * If there's no element matching `selector`, the method throws an error. 2893 * @param selector - 2894 * {@link https://pptr.dev/guides/page-interactions#selectors | selector} 2895 * to query the page for. 2896 * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors} 2897 * can be passed as-is and a 2898 * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax} 2899 * allows querying by 2900 * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text}, 2901 * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name}, 2902 * and 2903 * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath} 2904 * and 2905 * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}. 2906 * Alternatively, you can specify the selector type using a 2907 * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}. If there are multiple elements satisfying the 2908 * selector, the first will be tapped. 2909 * 2910 * @remarks 2911 * 2912 * Shortcut for {@link Frame.tap | page.mainFrame().tap(selector)}. 2913 */ 2914 tap(selector: string): Promise<void> { 2915 return this.mainFrame().tap(selector); 2916 } 2917 2918 /** 2919 * Sends a `keydown`, `keypress/input`, and `keyup` event for each character 2920 * in the text. 2921 * 2922 * To press a special key, like `Control` or `ArrowDown`, use {@link Keyboard.press}. 2923 * @example 2924 * 2925 * ```ts 2926 * await page.type('#mytextarea', 'Hello'); 2927 * // Types instantly 2928 * await page.type('#mytextarea', 'World', {delay: 100}); 2929 * // Types slower, like a user 2930 * ``` 2931 * 2932 * @param selector - 2933 * {@link https://pptr.dev/guides/page-interactions#selectors | selector} 2934 * to query the page for. 2935 * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors} 2936 * can be passed as-is and a 2937 * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax} 2938 * allows querying by 2939 * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text}, 2940 * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name}, 2941 * and 2942 * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath} 2943 * and 2944 * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}. 2945 * Alternatively, you can specify the selector type using a 2946 * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}. 2947 * @param text - A text to type into a focused element. 2948 * @param options - have property `delay` which is the Time to wait between 2949 * key presses in milliseconds. Defaults to `0`. 2950 * @returns 2951 */ 2952 type( 2953 selector: string, 2954 text: string, 2955 options?: Readonly<KeyboardTypeOptions>, 2956 ): Promise<void> { 2957 return this.mainFrame().type(selector, text, options); 2958 } 2959 2960 /** 2961 * Wait for the `selector` to appear in page. If at the moment of calling the 2962 * method the `selector` already exists, the method will return immediately. If 2963 * the `selector` doesn't appear after the `timeout` milliseconds of waiting, the 2964 * function will throw. 2965 * 2966 * @example 2967 * This method works across navigations: 2968 * 2969 * ```ts 2970 * import puppeteer from 'puppeteer'; 2971 * (async () => { 2972 * const browser = await puppeteer.launch(); 2973 * const page = await browser.newPage(); 2974 * let currentURL; 2975 * page 2976 * .waitForSelector('img') 2977 * .then(() => console.log('First URL with image: ' + currentURL)); 2978 * for (currentURL of [ 2979 * 'https://example.com', 2980 * 'https://google.com', 2981 * 'https://bbc.com', 2982 * ]) { 2983 * await page.goto(currentURL); 2984 * } 2985 * await browser.close(); 2986 * })(); 2987 * ``` 2988 * 2989 * @param selector - 2990 * {@link https://pptr.dev/guides/page-interactions#selectors | selector} 2991 * to query the page for. 2992 * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors} 2993 * can be passed as-is and a 2994 * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax} 2995 * allows querying by 2996 * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text}, 2997 * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name}, 2998 * and 2999 * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath} 3000 * and 3001 * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}. 3002 * Alternatively, you can specify the selector type using a 3003 * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}. 3004 * @param options - Optional waiting parameters 3005 * @returns Promise which resolves when element specified by selector string 3006 * is added to DOM. Resolves to `null` if waiting for hidden: `true` and 3007 * selector is not found in DOM. 3008 * 3009 * @remarks 3010 * The optional Parameter in Arguments `options` are: 3011 * 3012 * - `visible`: A boolean wait for element to be present in DOM and to be 3013 * visible, i.e. to not have `display: none` or `visibility: hidden` CSS 3014 * properties. Defaults to `false`. 3015 * 3016 * - `hidden`: Wait for element to not be found in the DOM or to be hidden, 3017 * i.e. have `display: none` or `visibility: hidden` CSS properties. Defaults to 3018 * `false`. 3019 * 3020 * - `timeout`: maximum time to wait for in milliseconds. Defaults to `30000` 3021 * (30 seconds). Pass `0` to disable timeout. The default value can be changed 3022 * by using the {@link Page.setDefaultTimeout} method. 3023 */ 3024 async waitForSelector<Selector extends string>( 3025 selector: Selector, 3026 options: WaitForSelectorOptions = {}, 3027 ): Promise<ElementHandle<NodeFor<Selector>> | null> { 3028 return await this.mainFrame().waitForSelector(selector, options); 3029 } 3030 3031 /** 3032 * Waits for the provided function, `pageFunction`, to return a truthy value when 3033 * evaluated in the page's context. 3034 * 3035 * @example 3036 * {@link Page.waitForFunction} can be used to observe a viewport size change: 3037 * 3038 * ```ts 3039 * import puppeteer from 'puppeteer'; 3040 * (async () => { 3041 * const browser = await puppeteer.launch(); 3042 * const page = await browser.newPage(); 3043 * const watchDog = page.waitForFunction('window.innerWidth < 100'); 3044 * await page.setViewport({width: 50, height: 50}); 3045 * await watchDog; 3046 * await browser.close(); 3047 * })(); 3048 * ``` 3049 * 3050 * @example 3051 * Arguments can be passed from Node.js to `pageFunction`: 3052 * 3053 * ```ts 3054 * const selector = '.foo'; 3055 * await page.waitForFunction( 3056 * selector => !!document.querySelector(selector), 3057 * {}, 3058 * selector, 3059 * ); 3060 * ``` 3061 * 3062 * @example 3063 * The provided `pageFunction` can be asynchronous: 3064 * 3065 * ```ts 3066 * const username = 'github-username'; 3067 * await page.waitForFunction( 3068 * async username => { 3069 * const githubResponse = await fetch( 3070 * `https://api.github.com/users/${username}`, 3071 * ); 3072 * const githubUser = await githubResponse.json(); 3073 * // show the avatar 3074 * const img = document.createElement('img'); 3075 * img.src = githubUser.avatar_url; 3076 * // wait 3 seconds 3077 * await new Promise((resolve, reject) => setTimeout(resolve, 3000)); 3078 * img.remove(); 3079 * }, 3080 * {}, 3081 * username, 3082 * ); 3083 * ``` 3084 * 3085 * @param pageFunction - Function to be evaluated in browser context until it returns a 3086 * truthy value. 3087 * @param options - Options for configuring waiting behavior. 3088 */ 3089 waitForFunction< 3090 Params extends unknown[], 3091 Func extends EvaluateFunc<Params> = EvaluateFunc<Params>, 3092 >( 3093 pageFunction: Func | string, 3094 options?: FrameWaitForFunctionOptions, 3095 ...args: Params 3096 ): Promise<HandleFor<Awaited<ReturnType<Func>>>> { 3097 return this.mainFrame().waitForFunction(pageFunction, options, ...args); 3098 } 3099 3100 /** 3101 * This method is typically coupled with an action that triggers a device 3102 * request from an api such as WebBluetooth. 3103 * 3104 * :::caution 3105 * 3106 * This must be called before the device request is made. It will not return a 3107 * currently active device prompt. 3108 * 3109 * ::: 3110 * 3111 * @example 3112 * 3113 * ```ts 3114 * const [devicePrompt] = Promise.all([ 3115 * page.waitForDevicePrompt(), 3116 * page.click('#connect-bluetooth'), 3117 * ]); 3118 * await devicePrompt.select( 3119 * await devicePrompt.waitForDevice(({name}) => name.includes('My Device')), 3120 * ); 3121 * ``` 3122 */ 3123 abstract waitForDevicePrompt( 3124 options?: WaitTimeoutOptions, 3125 ): Promise<DeviceRequestPrompt>; 3126 3127 /** @internal */ 3128 override [disposeSymbol](): void { 3129 return void this.close().catch(debugError); 3130 } 3131 3132 /** @internal */ 3133 [asyncDisposeSymbol](): Promise<void> { 3134 return this.close(); 3135 } 3136 } 3137 3138 /** 3139 * @internal 3140 */ 3141 export const supportedMetrics = new Set<string>([ 3142 'Timestamp', 3143 'Documents', 3144 'Frames', 3145 'JSEventListeners', 3146 'Nodes', 3147 'LayoutCount', 3148 'RecalcStyleCount', 3149 'LayoutDuration', 3150 'RecalcStyleDuration', 3151 'ScriptDuration', 3152 'TaskDuration', 3153 'JSHeapUsedSize', 3154 'JSHeapTotalSize', 3155 ]); 3156 3157 /** @see https://w3c.github.io/webdriver-bidi/#normalize-rect */ 3158 function normalizeRectangle<BoundingBoxType extends BoundingBox>( 3159 clip: Readonly<BoundingBoxType>, 3160 ): BoundingBoxType { 3161 return { 3162 ...clip, 3163 ...(clip.width < 0 3164 ? { 3165 x: clip.x + clip.width, 3166 width: -clip.width, 3167 } 3168 : { 3169 x: clip.x, 3170 width: clip.width, 3171 }), 3172 ...(clip.height < 0 3173 ? { 3174 y: clip.y + clip.height, 3175 height: -clip.height, 3176 } 3177 : { 3178 y: clip.y, 3179 height: clip.height, 3180 }), 3181 }; 3182 } 3183 3184 function roundRectangle<BoundingBoxType extends BoundingBox>( 3185 clip: Readonly<BoundingBoxType>, 3186 ): BoundingBoxType { 3187 const x = Math.round(clip.x); 3188 const y = Math.round(clip.y); 3189 const width = Math.round(clip.width + clip.x - x); 3190 const height = Math.round(clip.height + clip.y - y); 3191 return {...clip, x, y, width, height}; 3192 }