diff --git a/src/rpc/channels.ts b/src/rpc/channels.ts index ecadff6c04d72..ecb2ac4713ffc 100644 --- a/src/rpc/channels.ts +++ b/src/rpc/channels.ts @@ -120,10 +120,16 @@ export type SelectorsRegisterParams = { source: string, contentScript?: boolean, }; +export type SelectorsRegisterOptions = { + contentScript?: boolean, +}; export type SelectorsRegisterResult = void; export type SelectorsCreateSelectorParams = { name: string, handle: ElementHandleChannel, +}; +export type SelectorsCreateSelectorOptions = { + }; export type SelectorsCreateSelectorResult = { value?: string, @@ -145,6 +151,10 @@ export type BrowserTypeConnectParams = { slowMo?: number, timeout?: number, }; +export type BrowserTypeConnectOptions = { + slowMo?: number, + timeout?: number, +}; export type BrowserTypeConnectResult = { browser: BrowserChannel, }; @@ -173,6 +183,31 @@ export type BrowserTypeLaunchParams = { firefoxUserPrefs?: SerializedValue, slowMo?: number, }; +export type BrowserTypeLaunchOptions = { + executablePath?: string, + args?: string[], + ignoreAllDefaultArgs?: boolean, + ignoreDefaultArgs?: string[], + handleSIGINT?: boolean, + handleSIGTERM?: boolean, + handleSIGHUP?: boolean, + timeout?: number, + env?: { + name: string, + value: string, + }[], + headless?: boolean, + devtools?: boolean, + proxy?: { + server: string, + bypass?: string, + username?: string, + password?: string, + }, + downloadsPath?: string, + firefoxUserPrefs?: SerializedValue, + slowMo?: number, +}; export type BrowserTypeLaunchResult = { browser: BrowserChannel, }; @@ -201,6 +236,31 @@ export type BrowserTypeLaunchServerParams = { firefoxUserPrefs?: SerializedValue, port?: number, }; +export type BrowserTypeLaunchServerOptions = { + executablePath?: string, + args?: string[], + ignoreAllDefaultArgs?: boolean, + ignoreDefaultArgs?: string[], + handleSIGINT?: boolean, + handleSIGTERM?: boolean, + handleSIGHUP?: boolean, + timeout?: number, + env?: { + name: string, + value: string, + }[], + headless?: boolean, + devtools?: boolean, + proxy?: { + server: string, + bypass?: string, + username?: string, + password?: string, + }, + downloadsPath?: string, + firefoxUserPrefs?: SerializedValue, + port?: number, +}; export type BrowserTypeLaunchServerResult = { server: BrowserServerChannel, }; @@ -260,6 +320,61 @@ export type BrowserTypeLaunchPersistentContextParams = { colorScheme?: 'dark' | 'light' | 'no-preference', acceptDownloads?: boolean, }; +export type BrowserTypeLaunchPersistentContextOptions = { + executablePath?: string, + args?: string[], + ignoreAllDefaultArgs?: boolean, + ignoreDefaultArgs?: string[], + handleSIGINT?: boolean, + handleSIGTERM?: boolean, + handleSIGHUP?: boolean, + timeout?: number, + env?: { + name: string, + value: string, + }[], + headless?: boolean, + devtools?: boolean, + proxy?: { + server: string, + bypass?: string, + username?: string, + password?: string, + }, + downloadsPath?: string, + slowMo?: number, + noDefaultViewport?: boolean, + viewport?: { + width: number, + height: number, + }, + ignoreHTTPSErrors?: boolean, + javaScriptEnabled?: boolean, + bypassCSP?: boolean, + userAgent?: string, + locale?: string, + timezoneId?: string, + geolocation?: { + longitude: number, + latitude: number, + accuracy?: number, + }, + permissions?: string[], + extraHTTPHeaders?: { + name: string, + value: string, + }[], + offline?: boolean, + httpCredentials?: { + username: string, + password: string, + }, + deviceScaleFactor?: number, + isMobile?: boolean, + hasTouch?: boolean, + colorScheme?: 'dark' | 'light' | 'no-preference', + acceptDownloads?: boolean, +}; export type BrowserTypeLaunchPersistentContextResult = { context: BrowserContextChannel, }; @@ -279,8 +394,10 @@ export type BrowserServerCloseEvent = { signal?: string, }; export type BrowserServerCloseParams = {}; +export type BrowserServerCloseOptions = {}; export type BrowserServerCloseResult = void; export type BrowserServerKillParams = {}; +export type BrowserServerKillOptions = {}; export type BrowserServerKillResult = void; // ----------- Browser ----------- @@ -297,6 +414,7 @@ export interface BrowserChannel extends Channel { } export type BrowserCloseEvent = {}; export type BrowserCloseParams = {}; +export type BrowserCloseOptions = {}; export type BrowserCloseResult = void; export type BrowserNewContextParams = { noDefaultViewport?: boolean, @@ -331,10 +449,44 @@ export type BrowserNewContextParams = { colorScheme?: 'dark' | 'light' | 'no-preference', acceptDownloads?: boolean, }; +export type BrowserNewContextOptions = { + noDefaultViewport?: boolean, + viewport?: { + width: number, + height: number, + }, + ignoreHTTPSErrors?: boolean, + javaScriptEnabled?: boolean, + bypassCSP?: boolean, + userAgent?: string, + locale?: string, + timezoneId?: string, + geolocation?: { + longitude: number, + latitude: number, + accuracy?: number, + }, + permissions?: string[], + extraHTTPHeaders?: { + name: string, + value: string, + }[], + offline?: boolean, + httpCredentials?: { + username: string, + password: string, + }, + deviceScaleFactor?: number, + isMobile?: boolean, + hasTouch?: boolean, + colorScheme?: 'dark' | 'light' | 'no-preference', + acceptDownloads?: boolean, +}; export type BrowserNewContextResult = { context: BrowserContextChannel, }; export type BrowserCrNewBrowserCDPSessionParams = {}; +export type BrowserCrNewBrowserCDPSessionOptions = {}; export type BrowserCrNewBrowserCDPSessionResult = { session: CDPSessionChannel, }; @@ -344,8 +496,15 @@ export type BrowserCrStartTracingParams = { screenshots?: boolean, categories?: string[], }; +export type BrowserCrStartTracingOptions = { + page?: PageChannel, + path?: string, + screenshots?: boolean, + categories?: string[], +}; export type BrowserCrStartTracingResult = void; export type BrowserCrStopTracingParams = {}; +export type BrowserCrStopTracingOptions = {}; export type BrowserCrStopTracingResult = { binary: Binary, }; @@ -406,20 +565,32 @@ export type BrowserContextAddCookiesParams = { secure?: boolean, sameSite?: 'Strict' | 'Lax' | 'None', }[], +}; +export type BrowserContextAddCookiesOptions = { + }; export type BrowserContextAddCookiesResult = void; export type BrowserContextAddInitScriptParams = { source: string, +}; +export type BrowserContextAddInitScriptOptions = { + }; export type BrowserContextAddInitScriptResult = void; export type BrowserContextClearCookiesParams = {}; +export type BrowserContextClearCookiesOptions = {}; export type BrowserContextClearCookiesResult = void; export type BrowserContextClearPermissionsParams = {}; +export type BrowserContextClearPermissionsOptions = {}; export type BrowserContextClearPermissionsResult = void; export type BrowserContextCloseParams = {}; +export type BrowserContextCloseOptions = {}; export type BrowserContextCloseResult = void; export type BrowserContextCookiesParams = { urls: string[], +}; +export type BrowserContextCookiesOptions = { + }; export type BrowserContextCookiesResult = { cookies: { @@ -435,23 +606,36 @@ export type BrowserContextCookiesResult = { }; export type BrowserContextExposeBindingParams = { name: string, +}; +export type BrowserContextExposeBindingOptions = { + }; export type BrowserContextExposeBindingResult = void; export type BrowserContextGrantPermissionsParams = { permissions: string[], origin?: string, }; +export type BrowserContextGrantPermissionsOptions = { + origin?: string, +}; export type BrowserContextGrantPermissionsResult = void; export type BrowserContextNewPageParams = {}; +export type BrowserContextNewPageOptions = {}; export type BrowserContextNewPageResult = { page: PageChannel, }; export type BrowserContextSetDefaultNavigationTimeoutNoReplyParams = { timeout: number, +}; +export type BrowserContextSetDefaultNavigationTimeoutNoReplyOptions = { + }; export type BrowserContextSetDefaultNavigationTimeoutNoReplyResult = void; export type BrowserContextSetDefaultTimeoutNoReplyParams = { timeout: number, +}; +export type BrowserContextSetDefaultTimeoutNoReplyOptions = { + }; export type BrowserContextSetDefaultTimeoutNoReplyResult = void; export type BrowserContextSetExtraHTTPHeadersParams = { @@ -459,6 +643,9 @@ export type BrowserContextSetExtraHTTPHeadersParams = { name: string, value: string, }[], +}; +export type BrowserContextSetExtraHTTPHeadersOptions = { + }; export type BrowserContextSetExtraHTTPHeadersResult = void; export type BrowserContextSetGeolocationParams = { @@ -468,6 +655,13 @@ export type BrowserContextSetGeolocationParams = { accuracy?: number, }, }; +export type BrowserContextSetGeolocationOptions = { + geolocation?: { + longitude: number, + latitude: number, + accuracy?: number, + }, +}; export type BrowserContextSetGeolocationResult = void; export type BrowserContextSetHTTPCredentialsParams = { httpCredentials?: { @@ -475,17 +669,32 @@ export type BrowserContextSetHTTPCredentialsParams = { password: string, }, }; +export type BrowserContextSetHTTPCredentialsOptions = { + httpCredentials?: { + username: string, + password: string, + }, +}; export type BrowserContextSetHTTPCredentialsResult = void; export type BrowserContextSetNetworkInterceptionEnabledParams = { enabled: boolean, +}; +export type BrowserContextSetNetworkInterceptionEnabledOptions = { + }; export type BrowserContextSetNetworkInterceptionEnabledResult = void; export type BrowserContextSetOfflineParams = { offline: boolean, +}; +export type BrowserContextSetOfflineOptions = { + }; export type BrowserContextSetOfflineResult = void; export type BrowserContextCrNewCDPSessionParams = { page: PageChannel, +}; +export type BrowserContextCrNewCDPSessionOptions = { + }; export type BrowserContextCrNewCDPSessionResult = { session: CDPSessionChannel, @@ -606,37 +815,63 @@ export type PageWorkerEvent = { }; export type PageSetDefaultNavigationTimeoutNoReplyParams = { timeout: number, +}; +export type PageSetDefaultNavigationTimeoutNoReplyOptions = { + }; export type PageSetDefaultNavigationTimeoutNoReplyResult = void; export type PageSetDefaultTimeoutNoReplyParams = { timeout: number, +}; +export type PageSetDefaultTimeoutNoReplyOptions = { + }; export type PageSetDefaultTimeoutNoReplyResult = void; export type PageSetFileChooserInterceptedNoReplyParams = { intercepted: boolean, +}; +export type PageSetFileChooserInterceptedNoReplyOptions = { + }; export type PageSetFileChooserInterceptedNoReplyResult = void; export type PageAddInitScriptParams = { source: string, +}; +export type PageAddInitScriptOptions = { + }; export type PageAddInitScriptResult = void; export type PageCloseParams = { runBeforeUnload?: boolean, }; +export type PageCloseOptions = { + runBeforeUnload?: boolean, +}; export type PageCloseResult = void; export type PageEmulateMediaParams = { media?: 'screen' | 'print' | 'null', colorScheme?: 'dark' | 'light' | 'no-preference' | 'null', }; +export type PageEmulateMediaOptions = { + media?: 'screen' | 'print' | 'null', + colorScheme?: 'dark' | 'light' | 'no-preference' | 'null', +}; export type PageEmulateMediaResult = void; export type PageExposeBindingParams = { name: string, +}; +export type PageExposeBindingOptions = { + }; export type PageExposeBindingResult = void; export type PageGoBackParams = { timeout?: number, waitUntil?: 'load' | 'domcontentloaded' | 'networkidle', }; +export type PageGoBackOptions = { + timeout?: number, + waitUntil?: 'load' | 'domcontentloaded' | 'networkidle', +}; export type PageGoBackResult = { response?: ResponseChannel, }; @@ -644,10 +879,15 @@ export type PageGoForwardParams = { timeout?: number, waitUntil?: 'load' | 'domcontentloaded' | 'networkidle', }; +export type PageGoForwardOptions = { + timeout?: number, + waitUntil?: 'load' | 'domcontentloaded' | 'networkidle', +}; export type PageGoForwardResult = { response?: ResponseChannel, }; export type PageOpenerParams = {}; +export type PageOpenerOptions = {}; export type PageOpenerResult = { page?: PageChannel, }; @@ -655,6 +895,10 @@ export type PageReloadParams = { timeout?: number, waitUntil?: 'load' | 'domcontentloaded' | 'networkidle', }; +export type PageReloadOptions = { + timeout?: number, + waitUntil?: 'load' | 'domcontentloaded' | 'networkidle', +}; export type PageReloadResult = { response?: ResponseChannel, }; @@ -672,6 +916,20 @@ export type PageScreenshotParams = { y: number, }, }; +export type PageScreenshotOptions = { + timeout?: number, + type?: 'png' | 'jpeg', + path?: string, + quality?: number, + omitBackground?: boolean, + fullPage?: boolean, + clip?: { + width: number, + height: number, + x: number, + y: number, + }, +}; export type PageScreenshotResult = { binary: Binary, }; @@ -680,10 +938,16 @@ export type PageSetExtraHTTPHeadersParams = { name: string, value: string, }[], +}; +export type PageSetExtraHTTPHeadersOptions = { + }; export type PageSetExtraHTTPHeadersResult = void; export type PageSetNetworkInterceptionEnabledParams = { enabled: boolean, +}; +export type PageSetNetworkInterceptionEnabledOptions = { + }; export type PageSetNetworkInterceptionEnabledResult = void; export type PageSetViewportSizeParams = { @@ -691,45 +955,74 @@ export type PageSetViewportSizeParams = { width: number, height: number, }, +}; +export type PageSetViewportSizeOptions = { + }; export type PageSetViewportSizeResult = void; export type PageKeyboardDownParams = { key: string, +}; +export type PageKeyboardDownOptions = { + }; export type PageKeyboardDownResult = void; export type PageKeyboardUpParams = { key: string, +}; +export type PageKeyboardUpOptions = { + }; export type PageKeyboardUpResult = void; export type PageKeyboardInsertTextParams = { text: string, +}; +export type PageKeyboardInsertTextOptions = { + }; export type PageKeyboardInsertTextResult = void; export type PageKeyboardTypeParams = { text: string, delay?: number, }; +export type PageKeyboardTypeOptions = { + delay?: number, +}; export type PageKeyboardTypeResult = void; export type PageKeyboardPressParams = { key: string, delay?: number, }; +export type PageKeyboardPressOptions = { + delay?: number, +}; export type PageKeyboardPressResult = void; export type PageMouseMoveParams = { x: number, y: number, steps?: number, }; +export type PageMouseMoveOptions = { + steps?: number, +}; export type PageMouseMoveResult = void; export type PageMouseDownParams = { button?: 'left' | 'right' | 'middle', clickCount?: number, }; +export type PageMouseDownOptions = { + button?: 'left' | 'right' | 'middle', + clickCount?: number, +}; export type PageMouseDownResult = void; export type PageMouseUpParams = { button?: 'left' | 'right' | 'middle', clickCount?: number, }; +export type PageMouseUpOptions = { + button?: 'left' | 'right' | 'middle', + clickCount?: number, +}; export type PageMouseUpResult = void; export type PageMouseClickParams = { x: number, @@ -738,11 +1031,20 @@ export type PageMouseClickParams = { button?: 'left' | 'right' | 'middle', clickCount?: number, }; +export type PageMouseClickOptions = { + delay?: number, + button?: 'left' | 'right' | 'middle', + clickCount?: number, +}; export type PageMouseClickResult = void; export type PageAccessibilitySnapshotParams = { interestingOnly?: boolean, root?: ElementHandleChannel, }; +export type PageAccessibilitySnapshotOptions = { + interestingOnly?: boolean, + root?: ElementHandleChannel, +}; export type PageAccessibilitySnapshotResult = { rootAXNode?: AXNode, }; @@ -765,6 +1067,25 @@ export type PagePdfParams = { right?: string, }, }; +export type PagePdfOptions = { + scale?: number, + displayHeaderFooter?: boolean, + headerTemplate?: string, + footerTemplate?: string, + printBackground?: boolean, + landscape?: boolean, + pageRanges?: string, + format?: string, + width?: string, + height?: string, + preferCSSPageSize?: boolean, + margin?: { + top?: string, + bottom?: string, + left?: string, + right?: string, + }, +}; export type PagePdfResult = { pdf: Binary, }; @@ -772,8 +1093,13 @@ export type PageCrStartJSCoverageParams = { resetOnNavigation?: boolean, reportAnonymousScripts?: boolean, }; +export type PageCrStartJSCoverageOptions = { + resetOnNavigation?: boolean, + reportAnonymousScripts?: boolean, +}; export type PageCrStartJSCoverageResult = void; export type PageCrStopJSCoverageParams = {}; +export type PageCrStopJSCoverageOptions = {}; export type PageCrStopJSCoverageResult = { entries: { url: string, @@ -793,8 +1119,12 @@ export type PageCrStopJSCoverageResult = { export type PageCrStartCSSCoverageParams = { resetOnNavigation?: boolean, }; +export type PageCrStartCSSCoverageOptions = { + resetOnNavigation?: boolean, +}; export type PageCrStartCSSCoverageResult = void; export type PageCrStopCSSCoverageParams = {}; +export type PageCrStopCSSCoverageOptions = {}; export type PageCrStopCSSCoverageResult = { entries: { url: string, @@ -806,6 +1136,7 @@ export type PageCrStopCSSCoverageResult = { }[], }; export type PageBringToFrontParams = {}; +export type PageBringToFrontOptions = {}; export type PageBringToFrontResult = void; // ----------- Frame ----------- @@ -867,6 +1198,9 @@ export type FrameEvalOnSelectorParams = { expression: string, isFunction: boolean, arg: SerializedArgument, +}; +export type FrameEvalOnSelectorOptions = { + }; export type FrameEvalOnSelectorResult = { value: SerializedValue, @@ -876,6 +1210,9 @@ export type FrameEvalOnSelectorAllParams = { expression: string, isFunction: boolean, arg: SerializedArgument, +}; +export type FrameEvalOnSelectorAllOptions = { + }; export type FrameEvalOnSelectorAllResult = { value: SerializedValue, @@ -885,6 +1222,11 @@ export type FrameAddScriptTagParams = { content?: string, type?: string, }; +export type FrameAddScriptTagOptions = { + url?: string, + content?: string, + type?: string, +}; export type FrameAddScriptTagResult = { element: ElementHandleChannel, }; @@ -892,6 +1234,10 @@ export type FrameAddStyleTagParams = { url?: string, content?: string, }; +export type FrameAddStyleTagOptions = { + url?: string, + content?: string, +}; export type FrameAddStyleTagResult = { element: ElementHandleChannel, }; @@ -901,6 +1247,11 @@ export type FrameCheckParams = { noWaitAfter?: boolean, timeout?: number, }; +export type FrameCheckOptions = { + force?: boolean, + noWaitAfter?: boolean, + timeout?: number, +}; export type FrameCheckResult = void; export type FrameClickParams = { selector: string, @@ -916,8 +1267,22 @@ export type FrameClickParams = { clickCount?: number, timeout?: number, }; +export type FrameClickOptions = { + force?: boolean, + noWaitAfter?: boolean, + modifiers?: ('Alt' | 'Control' | 'Meta' | 'Shift')[], + position?: { + x: number, + y: number, + }, + delay?: number, + button?: 'left' | 'right' | 'middle', + clickCount?: number, + timeout?: number, +}; export type FrameClickResult = void; export type FrameContentParams = {}; +export type FrameContentOptions = {}; export type FrameContentResult = { value: string, }; @@ -934,6 +1299,18 @@ export type FrameDblclickParams = { button?: 'left' | 'right' | 'middle', timeout?: number, }; +export type FrameDblclickOptions = { + force?: boolean, + noWaitAfter?: boolean, + modifiers?: ('Alt' | 'Control' | 'Meta' | 'Shift')[], + position?: { + x: number, + y: number, + }, + delay?: number, + button?: 'left' | 'right' | 'middle', + timeout?: number, +}; export type FrameDblclickResult = void; export type FrameDispatchEventParams = { selector: string, @@ -941,11 +1318,17 @@ export type FrameDispatchEventParams = { eventInit: SerializedArgument, timeout?: number, }; +export type FrameDispatchEventOptions = { + timeout?: number, +}; export type FrameDispatchEventResult = void; export type FrameEvaluateExpressionParams = { expression: string, isFunction: boolean, arg: SerializedArgument, +}; +export type FrameEvaluateExpressionOptions = { + }; export type FrameEvaluateExpressionResult = { value: SerializedValue, @@ -954,6 +1337,9 @@ export type FrameEvaluateExpressionHandleParams = { expression: string, isFunction: boolean, arg: SerializedArgument, +}; +export type FrameEvaluateExpressionHandleOptions = { + }; export type FrameEvaluateExpressionHandleResult = { handle: JSHandleChannel, @@ -964,13 +1350,21 @@ export type FrameFillParams = { timeout?: number, noWaitAfter?: boolean, }; +export type FrameFillOptions = { + timeout?: number, + noWaitAfter?: boolean, +}; export type FrameFillResult = void; export type FrameFocusParams = { selector: string, timeout?: number, }; +export type FrameFocusOptions = { + timeout?: number, +}; export type FrameFocusResult = void; export type FrameFrameElementParams = {}; +export type FrameFrameElementOptions = {}; export type FrameFrameElementResult = { element: ElementHandleChannel, }; @@ -979,6 +1373,9 @@ export type FrameGetAttributeParams = { name: string, timeout?: number, }; +export type FrameGetAttributeOptions = { + timeout?: number, +}; export type FrameGetAttributeResult = { value?: string, }; @@ -988,6 +1385,11 @@ export type FrameGotoParams = { waitUntil?: 'load' | 'domcontentloaded' | 'networkidle', referer?: string, }; +export type FrameGotoOptions = { + timeout?: number, + waitUntil?: 'load' | 'domcontentloaded' | 'networkidle', + referer?: string, +}; export type FrameGotoResult = { response?: ResponseChannel, }; @@ -1001,11 +1403,23 @@ export type FrameHoverParams = { }, timeout?: number, }; +export type FrameHoverOptions = { + force?: boolean, + modifiers?: ('Alt' | 'Control' | 'Meta' | 'Shift')[], + position?: { + x: number, + y: number, + }, + timeout?: number, +}; export type FrameHoverResult = void; export type FrameInnerHTMLParams = { selector: string, timeout?: number, }; +export type FrameInnerHTMLOptions = { + timeout?: number, +}; export type FrameInnerHTMLResult = { value: string, }; @@ -1013,6 +1427,9 @@ export type FrameInnerTextParams = { selector: string, timeout?: number, }; +export type FrameInnerTextOptions = { + timeout?: number, +}; export type FrameInnerTextResult = { value: string, }; @@ -1023,15 +1440,26 @@ export type FramePressParams = { noWaitAfter?: boolean, timeout?: number, }; +export type FramePressOptions = { + delay?: number, + noWaitAfter?: boolean, + timeout?: number, +}; export type FramePressResult = void; export type FrameQuerySelectorParams = { selector: string, +}; +export type FrameQuerySelectorOptions = { + }; export type FrameQuerySelectorResult = { element?: ElementHandleChannel, }; export type FrameQuerySelectorAllParams = { selector: string, +}; +export type FrameQuerySelectorAllOptions = { + }; export type FrameQuerySelectorAllResult = { elements: ElementHandleChannel[], @@ -1047,6 +1475,16 @@ export type FrameSelectOptionParams = { timeout?: number, noWaitAfter?: boolean, }; +export type FrameSelectOptionOptions = { + elements?: ElementHandleChannel[], + options?: { + value?: string, + label?: string, + index?: number, + }[], + timeout?: number, + noWaitAfter?: boolean, +}; export type FrameSelectOptionResult = { values: string[], }; @@ -1055,6 +1493,10 @@ export type FrameSetContentParams = { timeout?: number, waitUntil?: 'load' | 'domcontentloaded' | 'networkidle', }; +export type FrameSetContentOptions = { + timeout?: number, + waitUntil?: 'load' | 'domcontentloaded' | 'networkidle', +}; export type FrameSetContentResult = void; export type FrameSetInputFilesParams = { selector: string, @@ -1066,15 +1508,23 @@ export type FrameSetInputFilesParams = { timeout?: number, noWaitAfter?: boolean, }; +export type FrameSetInputFilesOptions = { + timeout?: number, + noWaitAfter?: boolean, +}; export type FrameSetInputFilesResult = void; export type FrameTextContentParams = { selector: string, timeout?: number, }; +export type FrameTextContentOptions = { + timeout?: number, +}; export type FrameTextContentResult = { value?: string, }; export type FrameTitleParams = {}; +export type FrameTitleOptions = {}; export type FrameTitleResult = { value: string, }; @@ -1085,6 +1535,11 @@ export type FrameTypeParams = { noWaitAfter?: boolean, timeout?: number, }; +export type FrameTypeOptions = { + delay?: number, + noWaitAfter?: boolean, + timeout?: number, +}; export type FrameTypeResult = void; export type FrameUncheckParams = { selector: string, @@ -1092,6 +1547,11 @@ export type FrameUncheckParams = { noWaitAfter?: boolean, timeout?: number, }; +export type FrameUncheckOptions = { + force?: boolean, + noWaitAfter?: boolean, + timeout?: number, +}; export type FrameUncheckResult = void; export type FrameWaitForFunctionParams = { expression: string, @@ -1100,6 +1560,10 @@ export type FrameWaitForFunctionParams = { timeout?: number, pollingInterval?: number, }; +export type FrameWaitForFunctionOptions = { + timeout?: number, + pollingInterval?: number, +}; export type FrameWaitForFunctionResult = { handle: JSHandleChannel, }; @@ -1108,6 +1572,10 @@ export type FrameWaitForSelectorParams = { timeout?: number, state?: 'attached' | 'detached' | 'visible' | 'hidden', }; +export type FrameWaitForSelectorOptions = { + timeout?: number, + state?: 'attached' | 'detached' | 'visible' | 'hidden', +}; export type FrameWaitForSelectorResult = { element?: ElementHandleChannel, }; @@ -1124,6 +1592,9 @@ export type WorkerEvaluateExpressionParams = { expression: string, isFunction: boolean, arg: SerializedArgument, +}; +export type WorkerEvaluateExpressionOptions = { + }; export type WorkerEvaluateExpressionResult = { value: SerializedValue, @@ -1132,6 +1603,9 @@ export type WorkerEvaluateExpressionHandleParams = { expression: string, isFunction: boolean, arg: SerializedArgument, +}; +export type WorkerEvaluateExpressionHandleOptions = { + }; export type WorkerEvaluateExpressionHandleResult = { handle: JSHandleChannel, @@ -1154,11 +1628,15 @@ export type JSHandlePreviewUpdatedEvent = { preview: string, }; export type JSHandleDisposeParams = {}; +export type JSHandleDisposeOptions = {}; export type JSHandleDisposeResult = void; export type JSHandleEvaluateExpressionParams = { expression: string, isFunction: boolean, arg: SerializedArgument, +}; +export type JSHandleEvaluateExpressionOptions = { + }; export type JSHandleEvaluateExpressionResult = { value: SerializedValue, @@ -1167,11 +1645,15 @@ export type JSHandleEvaluateExpressionHandleParams = { expression: string, isFunction: boolean, arg: SerializedArgument, +}; +export type JSHandleEvaluateExpressionHandleOptions = { + }; export type JSHandleEvaluateExpressionHandleResult = { handle: JSHandleChannel, }; export type JSHandleGetPropertyListParams = {}; +export type JSHandleGetPropertyListOptions = {}; export type JSHandleGetPropertyListResult = { properties: { name: string, @@ -1180,11 +1662,15 @@ export type JSHandleGetPropertyListResult = { }; export type JSHandleGetPropertyParams = { name: string, +}; +export type JSHandleGetPropertyOptions = { + }; export type JSHandleGetPropertyResult = { handle: JSHandleChannel, }; export type JSHandleJsonValueParams = {}; +export type JSHandleJsonValueOptions = {}; export type JSHandleJsonValueResult = { value: SerializedValue, }; @@ -1224,6 +1710,9 @@ export type ElementHandleEvalOnSelectorParams = { expression: string, isFunction: boolean, arg: SerializedArgument, +}; +export type ElementHandleEvalOnSelectorOptions = { + }; export type ElementHandleEvalOnSelectorResult = { value: SerializedValue, @@ -1233,11 +1722,15 @@ export type ElementHandleEvalOnSelectorAllParams = { expression: string, isFunction: boolean, arg: SerializedArgument, +}; +export type ElementHandleEvalOnSelectorAllOptions = { + }; export type ElementHandleEvalOnSelectorAllResult = { value: SerializedValue, }; export type ElementHandleBoundingBoxParams = {}; +export type ElementHandleBoundingBoxOptions = {}; export type ElementHandleBoundingBoxResult = { value?: { width: number, @@ -1251,6 +1744,11 @@ export type ElementHandleCheckParams = { noWaitAfter?: boolean, timeout?: number, }; +export type ElementHandleCheckOptions = { + force?: boolean, + noWaitAfter?: boolean, + timeout?: number, +}; export type ElementHandleCheckResult = void; export type ElementHandleClickParams = { force?: boolean, @@ -1265,8 +1763,22 @@ export type ElementHandleClickParams = { clickCount?: number, timeout?: number, }; +export type ElementHandleClickOptions = { + force?: boolean, + noWaitAfter?: boolean, + modifiers?: ('Alt' | 'Control' | 'Meta' | 'Shift')[], + position?: { + x: number, + y: number, + }, + delay?: number, + button?: 'left' | 'right' | 'middle', + clickCount?: number, + timeout?: number, +}; export type ElementHandleClickResult = void; export type ElementHandleContentFrameParams = {}; +export type ElementHandleContentFrameOptions = {}; export type ElementHandleContentFrameResult = { frame?: FrameChannel, }; @@ -1282,10 +1794,25 @@ export type ElementHandleDblclickParams = { button?: 'left' | 'right' | 'middle', timeout?: number, }; +export type ElementHandleDblclickOptions = { + force?: boolean, + noWaitAfter?: boolean, + modifiers?: ('Alt' | 'Control' | 'Meta' | 'Shift')[], + position?: { + x: number, + y: number, + }, + delay?: number, + button?: 'left' | 'right' | 'middle', + timeout?: number, +}; export type ElementHandleDblclickResult = void; export type ElementHandleDispatchEventParams = { type: string, eventInit: SerializedArgument, +}; +export type ElementHandleDispatchEventOptions = { + }; export type ElementHandleDispatchEventResult = void; export type ElementHandleFillParams = { @@ -1293,11 +1820,19 @@ export type ElementHandleFillParams = { timeout?: number, noWaitAfter?: boolean, }; +export type ElementHandleFillOptions = { + timeout?: number, + noWaitAfter?: boolean, +}; export type ElementHandleFillResult = void; export type ElementHandleFocusParams = {}; +export type ElementHandleFocusOptions = {}; export type ElementHandleFocusResult = void; export type ElementHandleGetAttributeParams = { name: string, +}; +export type ElementHandleGetAttributeOptions = { + }; export type ElementHandleGetAttributeResult = { value?: string, @@ -1311,16 +1846,28 @@ export type ElementHandleHoverParams = { }, timeout?: number, }; +export type ElementHandleHoverOptions = { + force?: boolean, + modifiers?: ('Alt' | 'Control' | 'Meta' | 'Shift')[], + position?: { + x: number, + y: number, + }, + timeout?: number, +}; export type ElementHandleHoverResult = void; export type ElementHandleInnerHTMLParams = {}; +export type ElementHandleInnerHTMLOptions = {}; export type ElementHandleInnerHTMLResult = { value: string, }; export type ElementHandleInnerTextParams = {}; +export type ElementHandleInnerTextOptions = {}; export type ElementHandleInnerTextResult = { value: string, }; export type ElementHandleOwnerFrameParams = {}; +export type ElementHandleOwnerFrameOptions = {}; export type ElementHandleOwnerFrameResult = { frame?: FrameChannel, }; @@ -1330,15 +1877,26 @@ export type ElementHandlePressParams = { timeout?: number, noWaitAfter?: boolean, }; +export type ElementHandlePressOptions = { + delay?: number, + timeout?: number, + noWaitAfter?: boolean, +}; export type ElementHandlePressResult = void; export type ElementHandleQuerySelectorParams = { selector: string, +}; +export type ElementHandleQuerySelectorOptions = { + }; export type ElementHandleQuerySelectorResult = { element?: ElementHandleChannel, }; export type ElementHandleQuerySelectorAllParams = { selector: string, +}; +export type ElementHandleQuerySelectorAllOptions = { + }; export type ElementHandleQuerySelectorAllResult = { elements: ElementHandleChannel[], @@ -1350,12 +1908,22 @@ export type ElementHandleScreenshotParams = { quality?: number, omitBackground?: boolean, }; +export type ElementHandleScreenshotOptions = { + timeout?: number, + type?: 'png' | 'jpeg', + path?: string, + quality?: number, + omitBackground?: boolean, +}; export type ElementHandleScreenshotResult = { binary: Binary, }; export type ElementHandleScrollIntoViewIfNeededParams = { timeout?: number, }; +export type ElementHandleScrollIntoViewIfNeededOptions = { + timeout?: number, +}; export type ElementHandleScrollIntoViewIfNeededResult = void; export type ElementHandleSelectOptionParams = { elements?: ElementHandleChannel[], @@ -1367,12 +1935,25 @@ export type ElementHandleSelectOptionParams = { timeout?: number, noWaitAfter?: boolean, }; +export type ElementHandleSelectOptionOptions = { + elements?: ElementHandleChannel[], + options?: { + value?: string, + label?: string, + index?: number, + }[], + timeout?: number, + noWaitAfter?: boolean, +}; export type ElementHandleSelectOptionResult = { values: string[], }; export type ElementHandleSelectTextParams = { timeout?: number, }; +export type ElementHandleSelectTextOptions = { + timeout?: number, +}; export type ElementHandleSelectTextResult = void; export type ElementHandleSetInputFilesParams = { files: { @@ -1383,8 +1964,13 @@ export type ElementHandleSetInputFilesParams = { timeout?: number, noWaitAfter?: boolean, }; +export type ElementHandleSetInputFilesOptions = { + timeout?: number, + noWaitAfter?: boolean, +}; export type ElementHandleSetInputFilesResult = void; export type ElementHandleTextContentParams = {}; +export type ElementHandleTextContentOptions = {}; export type ElementHandleTextContentResult = { value?: string, }; @@ -1394,12 +1980,22 @@ export type ElementHandleTypeParams = { noWaitAfter?: boolean, timeout?: number, }; +export type ElementHandleTypeOptions = { + delay?: number, + noWaitAfter?: boolean, + timeout?: number, +}; export type ElementHandleTypeResult = void; export type ElementHandleUncheckParams = { force?: boolean, noWaitAfter?: boolean, timeout?: number, }; +export type ElementHandleUncheckOptions = { + force?: boolean, + noWaitAfter?: boolean, + timeout?: number, +}; export type ElementHandleUncheckResult = void; // ----------- Request ----------- @@ -1420,6 +2016,7 @@ export interface RequestChannel extends Channel { response(params?: RequestResponseParams): Promise; } export type RequestResponseParams = {}; +export type RequestResponseOptions = {}; export type RequestResponseResult = { response?: ResponseChannel, }; @@ -1435,6 +2032,9 @@ export interface RouteChannel extends Channel { } export type RouteAbortParams = { errorCode: string, +}; +export type RouteAbortOptions = { + }; export type RouteAbortResult = void; export type RouteContinueParams = { @@ -1445,6 +2045,14 @@ export type RouteContinueParams = { }[], postData?: Binary, }; +export type RouteContinueOptions = { + method?: string, + headers?: { + name: string, + value: string, + }[], + postData?: Binary, +}; export type RouteContinueResult = void; export type RouteFulfillParams = { status: number, @@ -1454,6 +2062,9 @@ export type RouteFulfillParams = { }[], body: string, isBase64: boolean, +}; +export type RouteFulfillOptions = { + }; export type RouteFulfillResult = void; @@ -1473,10 +2084,12 @@ export interface ResponseChannel extends Channel { finished(params?: ResponseFinishedParams): Promise; } export type ResponseBodyParams = {}; +export type ResponseBodyOptions = {}; export type ResponseBodyResult = { binary: Binary, }; export type ResponseFinishedParams = {}; +export type ResponseFinishedOptions = {}; export type ResponseFinishedResult = { error?: string, }; @@ -1507,10 +2120,16 @@ export interface BindingCallChannel extends Channel { } export type BindingCallRejectParams = { error: SerializedError, +}; +export type BindingCallRejectOptions = { + }; export type BindingCallRejectResult = void; export type BindingCallResolveParams = { result: SerializedArgument, +}; +export type BindingCallResolveOptions = { + }; export type BindingCallResolveResult = void; @@ -1527,8 +2146,12 @@ export interface DialogChannel extends Channel { export type DialogAcceptParams = { promptText?: string, }; +export type DialogAcceptOptions = { + promptText?: string, +}; export type DialogAcceptResult = void; export type DialogDismissParams = {}; +export type DialogDismissOptions = {}; export type DialogDismissResult = void; // ----------- Download ----------- @@ -1544,22 +2167,29 @@ export interface DownloadChannel extends Channel { delete(params?: DownloadDeleteParams): Promise; } export type DownloadPathParams = {}; +export type DownloadPathOptions = {}; export type DownloadPathResult = { value?: string, }; export type DownloadSaveAsParams = { path: string, +}; +export type DownloadSaveAsOptions = { + }; export type DownloadSaveAsResult = void; export type DownloadFailureParams = {}; +export type DownloadFailureOptions = {}; export type DownloadFailureResult = { error?: string, }; export type DownloadStreamParams = {}; +export type DownloadStreamOptions = {}; export type DownloadStreamResult = { stream?: StreamChannel, }; export type DownloadDeleteParams = {}; +export type DownloadDeleteOptions = {}; export type DownloadDeleteResult = void; // ----------- Stream ----------- @@ -1570,6 +2200,9 @@ export interface StreamChannel extends Channel { export type StreamReadParams = { size?: number, }; +export type StreamReadOptions = { + size?: number, +}; export type StreamReadResult = { binary: Binary, }; @@ -1589,10 +2222,14 @@ export type CDPSessionSendParams = { method: string, params?: SerializedValue, }; +export type CDPSessionSendOptions = { + params?: SerializedValue, +}; export type CDPSessionSendResult = { result: SerializedValue, }; export type CDPSessionDetachParams = {}; +export type CDPSessionDetachOptions = {}; export type CDPSessionDetachResult = void; // ----------- Electron ----------- @@ -1613,6 +2250,18 @@ export type ElectronLaunchParams = { handleSIGHUP?: boolean, timeout?: number, }; +export type ElectronLaunchOptions = { + args?: string[], + cwd?: string, + env?: { + name: string, + value: string, + }[], + handleSIGINT?: boolean, + handleSIGTERM?: boolean, + handleSIGHUP?: boolean, + timeout?: number, +}; export type ElectronLaunchResult = { electronApplication: ElectronApplicationChannel, }; @@ -1638,6 +2287,9 @@ export type ElectronApplicationWindowEvent = { }; export type ElectronApplicationNewBrowserWindowParams = { arg: SerializedArgument, +}; +export type ElectronApplicationNewBrowserWindowOptions = { + }; export type ElectronApplicationNewBrowserWindowResult = { page: PageChannel, @@ -1646,6 +2298,9 @@ export type ElectronApplicationEvaluateExpressionParams = { expression: string, isFunction: boolean, arg: SerializedArgument, +}; +export type ElectronApplicationEvaluateExpressionOptions = { + }; export type ElectronApplicationEvaluateExpressionResult = { value: SerializedValue, @@ -1654,9 +2309,13 @@ export type ElectronApplicationEvaluateExpressionHandleParams = { expression: string, isFunction: boolean, arg: SerializedArgument, +}; +export type ElectronApplicationEvaluateExpressionHandleOptions = { + }; export type ElectronApplicationEvaluateExpressionHandleResult = { handle: JSHandleChannel, }; export type ElectronApplicationCloseParams = {}; +export type ElectronApplicationCloseOptions = {}; export type ElectronApplicationCloseResult = void; diff --git a/src/rpc/client/accessibility.ts b/src/rpc/client/accessibility.ts index 773ab4e1d3109..170870ef9f598 100644 --- a/src/rpc/client/accessibility.ts +++ b/src/rpc/client/accessibility.ts @@ -15,10 +15,28 @@ * limitations under the License. */ -import { PageChannel } from '../channels'; +import { PageChannel, AXNode } from '../channels'; import { ElementHandle } from './elementHandle'; -import * as types from '../../types'; -import { axNodeFromProtocol } from '../serializers'; + +type SerializedAXNode = Omit & { + value?: string|number, + checked?: boolean | 'mixed', + pressed?: boolean | 'mixed', + children?: SerializedAXNode[] +}; + +function axNodeFromProtocol(axNode: AXNode): SerializedAXNode { + const result: SerializedAXNode = { + ...axNode, + value: axNode.valueNumber !== undefined ? axNode.valueNumber : axNode.valueString, + checked: axNode.checked === 'checked' ? true : axNode.checked === 'unchecked' ? false : axNode.checked, + pressed: axNode.pressed === 'pressed' ? true : axNode.pressed === 'released' ? false : axNode.pressed, + children: axNode.children ? axNode.children.map(axNodeFromProtocol) : undefined, + }; + delete (result as any).valueNumber; + delete (result as any).valueString; + return result; +} export class Accessibility { private _channel: PageChannel; @@ -27,7 +45,7 @@ export class Accessibility { this._channel = channel; } - async snapshot(options: { interestingOnly?: boolean; root?: ElementHandle } = {}): Promise { + async snapshot(options: { interestingOnly?: boolean; root?: ElementHandle } = {}): Promise { const root = options.root ? options.root._elementChannel : undefined; const result = await this._channel.accessibilitySnapshot({ interestingOnly: options.interestingOnly, root }); return result.rootAXNode ? axNodeFromProtocol(result.rootAXNode) : null; diff --git a/src/rpc/client/browser.ts b/src/rpc/client/browser.ts index 1844c75d11847..acba1f42546eb 100644 --- a/src/rpc/client/browser.ts +++ b/src/rpc/client/browser.ts @@ -14,15 +14,14 @@ * limitations under the License. */ -import * as types from '../../types'; import { BrowserChannel, BrowserInitializer, BrowserNewContextParams } from '../channels'; import { BrowserContext } from './browserContext'; import { Page } from './page'; import { ChannelOwner } from './channelOwner'; -import { Events } from '../../events'; -import { LoggerSink } from '../../loggerSink'; +import { Events } from './events'; import { BrowserType } from './browserType'; import { headersObjectToArray } from '../../converters'; +import { BrowserContextOptions } from './types'; export class Browser extends ChannelOwner { readonly _contexts = new Set(); @@ -50,7 +49,7 @@ export class Browser extends ChannelOwner { this._closedPromise = new Promise(f => this.once(Events.Browser.Disconnected, f)); } - async newContext(options: types.BrowserContextOptions & { logger?: LoggerSink } = {}): Promise { + async newContext(options: BrowserContextOptions = {}): Promise { const logger = options.logger; options = { ...options, logger: undefined }; return this._wrapApiCall('browser.newContext', async () => { @@ -75,7 +74,7 @@ export class Browser extends ChannelOwner { return this._initializer.version; } - async newPage(options: types.BrowserContextOptions & { logger?: LoggerSink } = {}): Promise { + async newPage(options: BrowserContextOptions = {}): Promise { const context = await this.newContext(options); const page = await context.newPage(); page._ownedContext = context; diff --git a/src/rpc/client/browserContext.ts b/src/rpc/client/browserContext.ts index e87e6d729ee75..ede729133aff3 100644 --- a/src/rpc/client/browserContext.ts +++ b/src/rpc/client/browserContext.ts @@ -17,20 +17,20 @@ import * as frames from './frame'; import { Page, BindingCall } from './page'; -import * as types from '../../types'; import * as network from './network'; import { BrowserContextChannel, BrowserContextInitializer } from '../channels'; import { ChannelOwner } from './channelOwner'; import { helper } from '../../helper'; import { Browser } from './browser'; -import { Events } from '../../events'; +import { Events } from './events'; import { TimeoutSettings } from '../../timeoutSettings'; import { Waiter } from './waiter'; import { headersObjectToArray } from '../../converters'; +import { URLMatch, Headers, WaitForEventOptions } from './types'; export class BrowserContext extends ChannelOwner { _pages = new Set(); - private _routes: { url: types.URLMatch, handler: network.RouteHandler }[] = []; + private _routes: { url: URLMatch, handler: network.RouteHandler }[] = []; readonly _browser: Browser | undefined; readonly _browserName: string; readonly _bindings = new Map(); @@ -138,13 +138,13 @@ export class BrowserContext extends ChannelOwner { + async setGeolocation(geolocation: { longitude: number, latitude: number, accuracy?: number } | null): Promise { return this._wrapApiCall('browserContext.setGeolocation', async () => { await this._channel.setGeolocation({ geolocation: geolocation || undefined }); }); } - async setExtraHTTPHeaders(headers: types.Headers): Promise { + async setExtraHTTPHeaders(headers: Headers): Promise { return this._wrapApiCall('browserContext.setExtraHTTPHeaders', async () => { await this._channel.setExtraHTTPHeaders({ headers: headersObjectToArray(headers) }); }); @@ -156,7 +156,7 @@ export class BrowserContext extends ChannelOwner { + async setHTTPCredentials(httpCredentials: { username: string, password: string } | null): Promise { return this._wrapApiCall('browserContext.setHTTPCredentials', async () => { await this._channel.setHTTPCredentials({ httpCredentials: httpCredentials || undefined }); }); @@ -186,7 +186,7 @@ export class BrowserContext extends ChannelOwner playwrightFunction(...args)); } - async route(url: types.URLMatch, handler: network.RouteHandler): Promise { + async route(url: URLMatch, handler: network.RouteHandler): Promise { return this._wrapApiCall('browserContext.route', async () => { this._routes.push({ url, handler }); if (this._routes.length === 1) @@ -194,7 +194,7 @@ export class BrowserContext extends ChannelOwner { + async unroute(url: URLMatch, handler?: network.RouteHandler): Promise { return this._wrapApiCall('browserContext.unroute', async () => { this._routes = this._routes.filter(route => route.url !== url || (handler && route.handler !== handler)); if (this._routes.length === 0) @@ -202,7 +202,7 @@ export class BrowserContext extends ChannelOwner { + async waitForEvent(event: string, optionsOrPredicate: WaitForEventOptions = {}): Promise { const timeout = this._timeoutSettings.timeout(typeof optionsOrPredicate === 'function' ? {} : optionsOrPredicate); const predicate = typeof optionsOrPredicate === 'function' ? optionsOrPredicate : optionsOrPredicate.predicate; const waiter = new Waiter(); diff --git a/src/rpc/client/browserServer.ts b/src/rpc/client/browserServer.ts index 76e672bb26df4..79b730ec55b79 100644 --- a/src/rpc/client/browserServer.ts +++ b/src/rpc/client/browserServer.ts @@ -17,7 +17,7 @@ import { ChildProcess } from 'child_process'; import { BrowserServerChannel, BrowserServerInitializer } from '../channels'; import { ChannelOwner } from './channelOwner'; -import { Events } from '../../events'; +import { Events } from './events'; export class BrowserServer extends ChannelOwner { static from(server: BrowserServerChannel): BrowserServer { diff --git a/src/rpc/client/browserType.ts b/src/rpc/client/browserType.ts index 1b886d5f0c244..5b93894b823fd 100644 --- a/src/rpc/client/browserType.ts +++ b/src/rpc/client/browserType.ts @@ -14,18 +14,15 @@ * limitations under the License. */ -import * as types from '../../types'; import { BrowserTypeChannel, BrowserTypeInitializer, BrowserTypeLaunchParams, BrowserTypeLaunchServerParams, BrowserTypeLaunchPersistentContextParams } from '../channels'; import { Browser } from './browser'; import { BrowserContext } from './browserContext'; import { ChannelOwner } from './channelOwner'; import { BrowserServer } from './browserServer'; -import { LoggerSink } from '../../loggerSink'; import { headersObjectToArray, envObjectToArray } from '../../converters'; import { serializeArgument } from './jsHandle'; import { assert } from '../../helper'; - -type FirefoxPrefsOptions = { firefoxUserPrefs?: { [key: string]: string | number | boolean } }; +import { LaunchOptions, LaunchServerOptions, BrowserContextOptions, ConnectOptions } from './types'; export class BrowserType extends ChannelOwner { @@ -45,7 +42,7 @@ export class BrowserType extends ChannelOwner { + async launch(options: LaunchOptions = {}): Promise { const logger = options.logger; options = { ...options, logger: undefined }; return this._wrapApiCall('browserType.launch', async () => { @@ -64,7 +61,7 @@ export class BrowserType extends ChannelOwner { + async launchServer(options: LaunchServerOptions = {}): Promise { const logger = options.logger; options = { ...options, logger: undefined }; return this._wrapApiCall('browserType.launchServer', async () => { @@ -79,7 +76,7 @@ export class BrowserType extends ChannelOwner { + async launchPersistentContext(userDataDir: string, options: LaunchOptions & BrowserContextOptions = {}): Promise { const logger = options.logger; options = { ...options, logger: undefined }; return this._wrapApiCall('browserType.launchPersistentContext', async () => { @@ -100,7 +97,7 @@ export class BrowserType extends ChannelOwner { + async connect(options: ConnectOptions): Promise { const logger = options.logger; options = { ...options, logger: undefined }; return this._wrapApiCall('browserType.connect', async () => { diff --git a/src/rpc/client/channelOwner.ts b/src/rpc/client/channelOwner.ts index b5a9041befc86..0ea022574d91e 100644 --- a/src/rpc/client/channelOwner.ts +++ b/src/rpc/client/channelOwner.ts @@ -17,7 +17,7 @@ import { EventEmitter } from 'events'; import type { Channel } from '../channels'; import type { Connection } from './connection'; -import type { LoggerSink } from '../../loggerSink'; +import type { LoggerSink } from './types'; import { DebugLoggerSink } from '../../logger'; export abstract class ChannelOwner extends EventEmitter { diff --git a/src/rpc/client/chromiumBrowserContext.ts b/src/rpc/client/chromiumBrowserContext.ts index a8acbc27ad457..675eae70247b8 100644 --- a/src/rpc/client/chromiumBrowserContext.ts +++ b/src/rpc/client/chromiumBrowserContext.ts @@ -19,7 +19,7 @@ import { Page } from './page'; import { BrowserContextInitializer } from '../channels'; import { ChannelOwner } from './channelOwner'; import { CDPSession } from './cdpSession'; -import { Events as ChromiumEvents } from '../../chromium/events'; +import { Events } from './events'; import { Worker } from './worker'; import { BrowserContext } from './browserContext'; @@ -32,13 +32,13 @@ export class ChromiumBrowserContext extends BrowserContext { this._channel.on('crBackgroundPage', ({ page }) => { const backgroundPage = Page.from(page); this._backgroundPages.add(backgroundPage); - this.emit(ChromiumEvents.ChromiumBrowserContext.BackgroundPage, backgroundPage); + this.emit(Events.ChromiumBrowserContext.BackgroundPage, backgroundPage); }); this._channel.on('crServiceWorker', ({worker}) => { const serviceWorker = Worker.from(worker); serviceWorker._context = this; this._serviceWorkers.add(serviceWorker); - this.emit(ChromiumEvents.ChromiumBrowserContext.ServiceWorker, serviceWorker); + this.emit(Events.ChromiumBrowserContext.ServiceWorker, serviceWorker); }); } diff --git a/src/rpc/client/chromiumCoverage.ts b/src/rpc/client/chromiumCoverage.ts index 9bcdde38eb70e..25c196f19e6ed 100644 --- a/src/rpc/client/chromiumCoverage.ts +++ b/src/rpc/client/chromiumCoverage.ts @@ -14,8 +14,12 @@ * limitations under the License. */ -import * as types from '../../types'; -import { PageChannel } from '../channels'; +import { PageChannel, PageCrStartJSCoverageOptions, PageCrStopJSCoverageResult, PageCrStartCSSCoverageOptions, PageCrStopCSSCoverageResult } from '../channels'; + +let __dummyJSResult: PageCrStopJSCoverageResult; +type PageCrStopJSCoverageResultEntries = typeof __dummyJSResult.entries; +let __dummyCSSResult: PageCrStopCSSCoverageResult; +type PageCrStopCSSCoverageResultEntries = typeof __dummyCSSResult.entries; export class ChromiumCoverage { private _channel: PageChannel; @@ -24,19 +28,19 @@ export class ChromiumCoverage { this._channel = channel; } - async startJSCoverage(options: types.JSCoverageOptions = {}) { + async startJSCoverage(options: PageCrStartJSCoverageOptions = {}) { await this._channel.crStartJSCoverage(options); } - async stopJSCoverage(): Promise { + async stopJSCoverage(): Promise { return (await this._channel.crStopJSCoverage()).entries; } - async startCSSCoverage(options: types.CSSCoverageOptions = {}) { + async startCSSCoverage(options: PageCrStartCSSCoverageOptions = {}) { await this._channel.crStartCSSCoverage(options); } - async stopCSSCoverage(): Promise { + async stopCSSCoverage(): Promise { return (await this._channel.crStopCSSCoverage()).entries; } } diff --git a/src/rpc/client/consoleMessage.ts b/src/rpc/client/consoleMessage.ts index 4a8c98dba4265..31071b9af2f6d 100644 --- a/src/rpc/client/consoleMessage.ts +++ b/src/rpc/client/consoleMessage.ts @@ -15,11 +15,13 @@ */ import * as util from 'util'; -import { ConsoleMessageLocation } from '../../types'; import { JSHandle } from './jsHandle'; import { ConsoleMessageChannel, ConsoleMessageInitializer } from '../channels'; import { ChannelOwner } from './channelOwner'; +let __dummyInitializer: ConsoleMessageInitializer; +type ConsoleMessageLocation = typeof __dummyInitializer.location; + export class ConsoleMessage extends ChannelOwner { static from(message: ConsoleMessageChannel): ConsoleMessage { return (message as any)._object; diff --git a/src/rpc/client/electron.ts b/src/rpc/client/electron.ts index 2c06873b563af..acdd203eae21e 100644 --- a/src/rpc/client/electron.ts +++ b/src/rpc/client/electron.ts @@ -14,18 +14,16 @@ * limitations under the License. */ -import * as types from '../../types'; -import { ElectronChannel, ElectronInitializer, ElectronApplicationChannel, ElectronApplicationInitializer, ElectronLaunchParams } from '../channels'; +import { ElectronChannel, ElectronInitializer, ElectronApplicationChannel, ElectronApplicationInitializer, ElectronLaunchParams, ElectronLaunchOptions } from '../channels'; import { BrowserContext } from './browserContext'; import { ChannelOwner } from './channelOwner'; import { Page } from './page'; import { serializeArgument, FuncOn, parseResult, SmartHandle, JSHandle } from './jsHandle'; -import { ElectronEvents, ElectronLaunchOptionsBase } from '../../server/electron'; import { TimeoutSettings } from '../../timeoutSettings'; import { Waiter } from './waiter'; -import { Events } from '../../events'; -import { LoggerSink } from '../../loggerSink'; +import { Events } from './events'; import { envObjectToArray } from '../../converters'; +import { WaitForEventOptions, Env, LoggerSink } from './types'; export class Electron extends ChannelOwner { static from(electron: ElectronChannel): Electron { @@ -36,7 +34,7 @@ export class Electron extends ChannelOwner super(parent, type, guid, initializer); } - async launch(executablePath: string, options: ElectronLaunchOptionsBase & { logger?: LoggerSink } = {}): Promise { + async launch(executablePath: string, options: ElectronLaunchOptions & { env?: Env, logger?: LoggerSink } = {}): Promise { const logger = options.logger; options = { ...options, logger: undefined }; return this._wrapApiCall('electron.launch', async () => { @@ -66,10 +64,10 @@ export class ElectronApplication extends ChannelOwner this._windows.delete(window)); }); - this._channel.on('close', () => this.emit(ElectronEvents.ElectronApplication.Close)); + this._channel.on('close', () => this.emit(Events.ElectronApplication.Close)); } windows(): Page[] { @@ -95,13 +93,13 @@ export class ElectronApplication extends ChannelOwner { + async waitForEvent(event: string, optionsOrPredicate: WaitForEventOptions = {}): Promise { const timeout = this._timeoutSettings.timeout(typeof optionsOrPredicate === 'function' ? {} : optionsOrPredicate); const predicate = typeof optionsOrPredicate === 'function' ? optionsOrPredicate : optionsOrPredicate.predicate; const waiter = new Waiter(); waiter.rejectOnTimeout(timeout, `Timeout while waiting for event "${event}"`); - if (event !== ElectronEvents.ElectronApplication.Close) - waiter.rejectOnEvent(this, ElectronEvents.ElectronApplication.Close, new Error('Electron application closed')); + if (event !== Events.ElectronApplication.Close) + waiter.rejectOnEvent(this, Events.ElectronApplication.Close, new Error('Electron application closed')); const result = await waiter.waitForEvent(this, event, predicate as any); waiter.dispose(); return result; diff --git a/src/rpc/client/elementHandle.ts b/src/rpc/client/elementHandle.ts index 1bc13d8cca3a6..975f538d763d8 100644 --- a/src/rpc/client/elementHandle.ts +++ b/src/rpc/client/elementHandle.ts @@ -14,13 +14,13 @@ * limitations under the License. */ -import * as types from '../../types'; -import { ElementHandleChannel, JSHandleInitializer } from '../channels'; +import { ElementHandleChannel, JSHandleInitializer, ElementHandleScrollIntoViewIfNeededOptions, ElementHandleHoverOptions, ElementHandleClickOptions, ElementHandleDblclickOptions, ElementHandleSelectOptionOptions, ElementHandleFillOptions, ElementHandleSetInputFilesOptions, ElementHandlePressOptions, ElementHandleCheckOptions, ElementHandleUncheckOptions, ElementHandleScreenshotOptions, ElementHandleTypeOptions } from '../channels'; import { Frame } from './frame'; import { FuncOn, JSHandle, serializeArgument, parseResult } from './jsHandle'; import { ChannelOwner } from './channelOwner'; import { helper, assert } from '../../helper'; import { normalizeFilePayloads } from '../../converters'; +import { SelectOption, FilePayload, Rect, SelectOptionOptions } from './types'; export class ElementHandle extends JSHandle { readonly _elementChannel: ElementHandleChannel; @@ -86,50 +86,50 @@ export class ElementHandle extends JSHandle { }); } - async scrollIntoViewIfNeeded(options: types.TimeoutOptions = {}) { + async scrollIntoViewIfNeeded(options: ElementHandleScrollIntoViewIfNeededOptions = {}) { return this._wrapApiCall('elementHandle.scrollIntoViewIfNeeded', async () => { await this._elementChannel.scrollIntoViewIfNeeded(options); }); } - async hover(options: types.PointerActionOptions & types.PointerActionWaitOptions = {}): Promise { + async hover(options: ElementHandleHoverOptions = {}): Promise { return this._wrapApiCall('elementHandle.hover', async () => { await this._elementChannel.hover(options); }); } - async click(options: types.MouseClickOptions & types.PointerActionWaitOptions & types.NavigatingActionWaitOptions = {}): Promise { + async click(options: ElementHandleClickOptions = {}): Promise { return this._wrapApiCall('elementHandle.click', async () => { return await this._elementChannel.click(options); }); } - async dblclick(options: types.MouseMultiClickOptions & types.PointerActionWaitOptions & types.NavigatingActionWaitOptions = {}): Promise { + async dblclick(options: ElementHandleDblclickOptions = {}): Promise { return this._wrapApiCall('elementHandle.dblclick', async () => { return await this._elementChannel.dblclick(options); }); } - async selectOption(values: string | ElementHandle | types.SelectOption | string[] | ElementHandle[] | types.SelectOption[] | null, options: types.NavigatingActionWaitOptions = {}): Promise { + async selectOption(values: string | ElementHandle | SelectOption | string[] | ElementHandle[] | SelectOption[] | null, options: SelectOptionOptions = {}): Promise { return this._wrapApiCall('elementHandle.selectOption', async () => { const result = await this._elementChannel.selectOption({ ...convertSelectOptionValues(values), ...options }); return result.values; }); } - async fill(value: string, options: types.NavigatingActionWaitOptions = {}): Promise { + async fill(value: string, options: ElementHandleFillOptions = {}): Promise { return this._wrapApiCall('elementHandle.fill', async () => { return await this._elementChannel.fill({ value, ...options }); }); } - async selectText(options: types.TimeoutOptions = {}): Promise { + async selectText(options: ElementHandleSelectOptionOptions = {}): Promise { return this._wrapApiCall('elementHandle.selectText', async () => { await this._elementChannel.selectText(options); }); } - async setInputFiles(files: string | types.FilePayload | string[] | types.FilePayload[], options: types.NavigatingActionWaitOptions = {}) { + async setInputFiles(files: string | FilePayload | string[] | FilePayload[], options: ElementHandleSetInputFilesOptions = {}) { return this._wrapApiCall('elementHandle.setInputFiles', async () => { await this._elementChannel.setInputFiles({ files: await convertInputFiles(files), ...options }); }); @@ -141,38 +141,38 @@ export class ElementHandle extends JSHandle { }); } - async type(text: string, options: { delay?: number } & types.NavigatingActionWaitOptions = {}): Promise { + async type(text: string, options: ElementHandleTypeOptions = {}): Promise { return this._wrapApiCall('elementHandle.type', async () => { await this._elementChannel.type({ text, ...options }); }); } - async press(key: string, options: { delay?: number } & types.NavigatingActionWaitOptions = {}): Promise { + async press(key: string, options: ElementHandlePressOptions = {}): Promise { return this._wrapApiCall('elementHandle.press', async () => { await this._elementChannel.press({ key, ...options }); }); } - async check(options: types.PointerActionWaitOptions & types.NavigatingActionWaitOptions = {}) { + async check(options: ElementHandleCheckOptions = {}) { return this._wrapApiCall('elementHandle.check', async () => { return await this._elementChannel.check(options); }); } - async uncheck(options: types.PointerActionWaitOptions & types.NavigatingActionWaitOptions = {}) { + async uncheck(options: ElementHandleUncheckOptions = {}) { return this._wrapApiCall('elementHandle.uncheck', async () => { return await this._elementChannel.uncheck(options); }); } - async boundingBox(): Promise { + async boundingBox(): Promise { return this._wrapApiCall('elementHandle.boundingBox', async () => { const value = (await this._elementChannel.boundingBox()).value; return value === undefined ? null : value; }); } - async screenshot(options: types.ElementScreenshotOptions = {}): Promise { + async screenshot(options: ElementHandleScreenshotOptions = {}): Promise { return this._wrapApiCall('elementHandle.screenshot', async () => { return Buffer.from((await this._elementChannel.screenshot(options)).binary, 'base64'); }); @@ -210,7 +210,7 @@ export class ElementHandle extends JSHandle { } } -export function convertSelectOptionValues(values: string | ElementHandle | types.SelectOption | string[] | ElementHandle[] | types.SelectOption[] | null): { elements?: ElementHandleChannel[], options?: types.SelectOption[] } { +export function convertSelectOptionValues(values: string | ElementHandle | SelectOption | string[] | ElementHandle[] | SelectOption[] | null): { elements?: ElementHandleChannel[], options?: SelectOption[] } { if (!values) return {}; if (!Array.isArray(values)) @@ -224,10 +224,10 @@ export function convertSelectOptionValues(values: string | ElementHandle | types return { elements: (values as ElementHandle[]).map((v: ElementHandle) => v._elementChannel) }; if (helper.isString(values[0])) return { options: (values as string[]).map(value => ({ value })) }; - return { options: values as types.SelectOption[] }; + return { options: values as SelectOption[] }; } -export async function convertInputFiles(files: string | types.FilePayload | string[] | types.FilePayload[]): Promise<{ name: string, mimeType: string, buffer: string }[]> { +export async function convertInputFiles(files: string | FilePayload | string[] | FilePayload[]): Promise<{ name: string, mimeType: string, buffer: string }[]> { const filePayloads = await normalizeFilePayloads(files); return filePayloads.map(f => ({ name: f.name, mimeType: f.mimeType, buffer: f.buffer.toString('base64') })); } diff --git a/src/rpc/client/events.ts b/src/rpc/client/events.ts new file mode 100644 index 0000000000000..2c02e19ef820b --- /dev/null +++ b/src/rpc/client/events.ts @@ -0,0 +1,68 @@ +/** + * Copyright 2019 Google Inc. All rights reserved. + * Modifications copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export const Events = { + Browser: { + Disconnected: 'disconnected' + }, + + BrowserContext: { + Close: 'close', + Page: 'page', + }, + + BrowserServer: { + Close: 'close', + }, + + Page: { + Close: 'close', + Crash: 'crash', + Console: 'console', + Dialog: 'dialog', + Download: 'download', + FileChooser: 'filechooser', + DOMContentLoaded: 'domcontentloaded', + // Can't use just 'error' due to node.js special treatment of error events. + // @see https://nodejs.org/api/events.html#events_error_events + PageError: 'pageerror', + Request: 'request', + Response: 'response', + RequestFailed: 'requestfailed', + RequestFinished: 'requestfinished', + FrameAttached: 'frameattached', + FrameDetached: 'framedetached', + FrameNavigated: 'framenavigated', + Load: 'load', + Popup: 'popup', + Worker: 'worker', + }, + + Worker: { + Close: 'close', + }, + + ChromiumBrowserContext: { + BackgroundPage: 'backgroundpage', + ServiceWorker: 'serviceworker', + }, + + ElectronApplication: { + Close: 'close', + Window: 'window', + }, +}; diff --git a/src/rpc/client/fileChooser.ts b/src/rpc/client/fileChooser.ts index 30d071bc72bc8..2b20bd30059c4 100644 --- a/src/rpc/client/fileChooser.ts +++ b/src/rpc/client/fileChooser.ts @@ -14,9 +14,10 @@ * limitations under the License. */ -import * as types from '../../types'; import { ElementHandle } from './elementHandle'; import { Page } from './page'; +import { FilePayload } from './types'; +import { ElementHandleSetInputFilesOptions } from '../channels'; export class FileChooser { private _page: Page; @@ -41,7 +42,7 @@ export class FileChooser { return this._page; } - async setFiles(files: string | types.FilePayload | string[] | types.FilePayload[], options?: types.NavigatingActionWaitOptions) { + async setFiles(files: string | FilePayload | string[] | FilePayload[], options?: ElementHandleSetInputFilesOptions) { return this._elementHandle.setInputFiles(files, options); } } diff --git a/src/rpc/client/frame.ts b/src/rpc/client/frame.ts index 3b2c9d5d3b2a8..756fb0b947462 100644 --- a/src/rpc/client/frame.ts +++ b/src/rpc/client/frame.ts @@ -16,8 +16,7 @@ */ import { assertMaxArguments, helper, assert } from '../../helper'; -import * as types from '../../types'; -import { FrameChannel, FrameInitializer, FrameNavigatedEvent } from '../channels'; +import { FrameChannel, FrameInitializer, FrameNavigatedEvent, FrameGotoOptions, FrameWaitForSelectorOptions, FrameDispatchEventOptions, FrameSetContentOptions, FrameClickOptions, FrameDblclickOptions, FrameFillOptions, FrameFocusOptions, FrameTextContentOptions, FrameInnerTextOptions, FrameInnerHTMLOptions, FrameGetAttributeOptions, FrameHoverOptions, FrameSetInputFilesOptions, FrameTypeOptions, FramePressOptions, FrameCheckOptions, FrameUncheckOptions } from '../channels'; import { BrowserContext } from './browserContext'; import { ChannelOwner } from './channelOwner'; import { ElementHandle, convertSelectOptionValues, convertInputFiles } from './elementHandle'; @@ -28,19 +27,21 @@ import * as util from 'util'; import { Page } from './page'; import { EventEmitter } from 'events'; import { Waiter } from './waiter'; -import { Events } from '../../events'; +import { Events } from './events'; +import { LifecycleEvent, URLMatch, SelectOption, SelectOptionOptions, FilePayload, WaitForFunctionOptions, kLifecycleEvents } from './types'; const fsReadFileAsync = util.promisify(fs.readFile.bind(fs)); -export type GotoOptions = types.NavigateOptions & { - referer?: string, -}; - export type FunctionWithSource = (source: { context: BrowserContext, page: Page, frame: Frame }, ...args: any) => any; +export type WaitForNavigationOptions = { + timeout?: number, + waitUntil?: LifecycleEvent, + url?: URLMatch, +}; export class Frame extends ChannelOwner { _eventEmitter: EventEmitter; - _loadStates: Set; + _loadStates: Set; _parentFrame: Frame | null = null; _url = ''; _name = ''; @@ -87,14 +88,14 @@ export class Frame extends ChannelOwner { return this._page!._isPageCall ? 'page.' + method : 'frame.' + method; } - async goto(url: string, options: GotoOptions = {}): Promise { + async goto(url: string, options: FrameGotoOptions = {}): Promise { return this._wrapApiCall(this._apiName('goto'), async () => { const waitUntil = verifyLoadState('waitUntil', options.waitUntil === undefined ? 'load' : options.waitUntil); return network.Response.fromNullable((await this._channel.goto({ url, ...options, waitUntil })).response); }); } - private _setupNavigationWaiter(options: types.TimeoutOptions): Waiter { + private _setupNavigationWaiter(options: { timeout?: number }): Waiter { const waiter = new Waiter(); waiter.rejectOnEvent(this._page!, Events.Page.Close, new Error('Navigation failed because page was closed!')); waiter.rejectOnEvent(this._page!, Events.Page.Crash, new Error('Navigation failed because page crashed!')); @@ -105,7 +106,7 @@ export class Frame extends ChannelOwner { return waiter; } - async waitForNavigation(options: types.WaitForNavigationOptions = {}): Promise { + async waitForNavigation(options: WaitForNavigationOptions = {}): Promise { return this._wrapApiCall(this._apiName('waitForNavigation'), async () => { const waitUntil = verifyLoadState('waitUntil', options.waitUntil === undefined ? 'load' : options.waitUntil); const waiter = this._setupNavigationWaiter(options); @@ -127,7 +128,7 @@ export class Frame extends ChannelOwner { } if (!this._loadStates.has(waitUntil)) { - await waiter.waitForEvent(this._eventEmitter, 'loadstate', s => { + await waiter.waitForEvent(this._eventEmitter, 'loadstate', s => { waiter.log(` "${s}" event fired`); return s === waitUntil; }); @@ -140,13 +141,13 @@ export class Frame extends ChannelOwner { }); } - async waitForLoadState(state: types.LifecycleEvent = 'load', options: types.TimeoutOptions = {}): Promise { + async waitForLoadState(state: LifecycleEvent = 'load', options: { timeout?: number } = {}): Promise { state = verifyLoadState('state', state); if (this._loadStates.has(state)) return; return this._wrapApiCall(this._apiName('waitForLoadState'), async () => { const waiter = this._setupNavigationWaiter(options); - await waiter.waitForEvent(this._eventEmitter, 'loadstate', s => { + await waiter.waitForEvent(this._eventEmitter, 'loadstate', s => { waiter.log(` "${s}" event fired`); return s === state; }); @@ -187,7 +188,7 @@ export class Frame extends ChannelOwner { }); } - async waitForSelector(selector: string, options: types.WaitForElementOptions = {}): Promise | null> { + async waitForSelector(selector: string, options: FrameWaitForSelectorOptions = {}): Promise | null> { return this._wrapApiCall(this._apiName('waitForSelector'), async () => { if ((options as any).visibility) throw new Error('options.visibility is not supported, did you mean options.state?'); @@ -198,7 +199,7 @@ export class Frame extends ChannelOwner { }); } - async dispatchEvent(selector: string, type: string, eventInit?: any, options: types.TimeoutOptions = {}): Promise { + async dispatchEvent(selector: string, type: string, eventInit?: any, options: FrameDispatchEventOptions = {}): Promise { return this._wrapApiCall(this._apiName('dispatchEvent'), async () => { await this._channel.dispatchEvent({ selector, type, eventInit: serializeArgument(eventInit), ...options }); }); @@ -237,7 +238,7 @@ export class Frame extends ChannelOwner { }); } - async setContent(html: string, options: types.NavigateOptions = {}): Promise { + async setContent(html: string, options: FrameSetContentOptions = {}): Promise { return this._wrapApiCall(this._apiName('setContent'), async () => { const waitUntil = verifyLoadState('waitUntil', options.waitUntil === undefined ? 'load' : options.waitUntil); await this._channel.setContent({ html, ...options, waitUntil }); @@ -286,93 +287,93 @@ export class Frame extends ChannelOwner { }); } - async click(selector: string, options: types.MouseClickOptions & types.PointerActionWaitOptions & types.NavigatingActionWaitOptions = {}) { + async click(selector: string, options: FrameClickOptions = {}) { return this._wrapApiCall(this._apiName('click'), async () => { return await this._channel.click({ selector, ...options }); }); } - async dblclick(selector: string, options: types.MouseMultiClickOptions & types.PointerActionWaitOptions & types.NavigatingActionWaitOptions = {}) { + async dblclick(selector: string, options: FrameDblclickOptions = {}) { return this._wrapApiCall(this._apiName('dblclick'), async () => { return await this._channel.dblclick({ selector, ...options }); }); } - async fill(selector: string, value: string, options: types.NavigatingActionWaitOptions = {}) { + async fill(selector: string, value: string, options: FrameFillOptions = {}) { return this._wrapApiCall(this._apiName('fill'), async () => { return await this._channel.fill({ selector, value, ...options }); }); } - async focus(selector: string, options: types.TimeoutOptions = {}) { + async focus(selector: string, options: FrameFocusOptions = {}) { return this._wrapApiCall(this._apiName('focus'), async () => { await this._channel.focus({ selector, ...options }); }); } - async textContent(selector: string, options: types.TimeoutOptions = {}): Promise { + async textContent(selector: string, options: FrameTextContentOptions = {}): Promise { return this._wrapApiCall(this._apiName('textContent'), async () => { const value = (await this._channel.textContent({ selector, ...options })).value; return value === undefined ? null : value; }); } - async innerText(selector: string, options: types.TimeoutOptions = {}): Promise { + async innerText(selector: string, options: FrameInnerTextOptions = {}): Promise { return this._wrapApiCall(this._apiName('innerText'), async () => { return (await this._channel.innerText({ selector, ...options })).value; }); } - async innerHTML(selector: string, options: types.TimeoutOptions = {}): Promise { + async innerHTML(selector: string, options: FrameInnerHTMLOptions = {}): Promise { return this._wrapApiCall(this._apiName('innerHTML'), async () => { return (await this._channel.innerHTML({ selector, ...options })).value; }); } - async getAttribute(selector: string, name: string, options: types.TimeoutOptions = {}): Promise { + async getAttribute(selector: string, name: string, options: FrameGetAttributeOptions = {}): Promise { return this._wrapApiCall(this._apiName('getAttribute'), async () => { const value = (await this._channel.getAttribute({ selector, name, ...options })).value; return value === undefined ? null : value; }); } - async hover(selector: string, options: types.PointerActionOptions & types.PointerActionWaitOptions = {}) { + async hover(selector: string, options: FrameHoverOptions = {}) { return this._wrapApiCall(this._apiName('hover'), async () => { await this._channel.hover({ selector, ...options }); }); } - async selectOption(selector: string, values: string | ElementHandle | types.SelectOption | string[] | ElementHandle[] | types.SelectOption[] | null, options: types.NavigatingActionWaitOptions = {}): Promise { + async selectOption(selector: string, values: string | ElementHandle | SelectOption | string[] | ElementHandle[] | SelectOption[] | null, options: SelectOptionOptions = {}): Promise { return this._wrapApiCall(this._apiName('selectOption'), async () => { return (await this._channel.selectOption({ selector, ...convertSelectOptionValues(values), ...options })).values; }); } - async setInputFiles(selector: string, files: string | types.FilePayload | string[] | types.FilePayload[], options: types.NavigatingActionWaitOptions = {}): Promise { + async setInputFiles(selector: string, files: string | FilePayload | string[] | FilePayload[], options: FrameSetInputFilesOptions = {}): Promise { return this._wrapApiCall(this._apiName('setInputFiles'), async () => { await this._channel.setInputFiles({ selector, files: await convertInputFiles(files), ...options }); }); } - async type(selector: string, text: string, options: { delay?: number } & types.NavigatingActionWaitOptions = {}) { + async type(selector: string, text: string, options: FrameTypeOptions = {}) { return this._wrapApiCall(this._apiName('type'), async () => { await this._channel.type({ selector, text, ...options }); }); } - async press(selector: string, key: string, options: { delay?: number } & types.NavigatingActionWaitOptions = {}) { + async press(selector: string, key: string, options: FramePressOptions = {}) { return this._wrapApiCall(this._apiName('press'), async () => { await this._channel.press({ selector, key, ...options }); }); } - async check(selector: string, options: types.PointerActionWaitOptions & types.NavigatingActionWaitOptions = {}) { + async check(selector: string, options: FrameCheckOptions = {}) { return this._wrapApiCall(this._apiName('check'), async () => { await this._channel.check({ selector, ...options }); }); } - async uncheck(selector: string, options: types.PointerActionWaitOptions & types.NavigatingActionWaitOptions = {}) { + async uncheck(selector: string, options: FrameUncheckOptions = {}) { return this._wrapApiCall(this._apiName('uncheck'), async () => { await this._channel.uncheck({ selector, ...options }); }); @@ -382,9 +383,9 @@ export class Frame extends ChannelOwner { await new Promise(fulfill => setTimeout(fulfill, timeout)); } - async waitForFunction(pageFunction: Func1, arg: Arg, options?: types.WaitForFunctionOptions): Promise>; - async waitForFunction(pageFunction: Func1, arg?: any, options?: types.WaitForFunctionOptions): Promise>; - async waitForFunction(pageFunction: Func1, arg: Arg, options: types.WaitForFunctionOptions = {}): Promise> { + async waitForFunction(pageFunction: Func1, arg: Arg, options?: WaitForFunctionOptions): Promise>; + async waitForFunction(pageFunction: Func1, arg?: any, options?: WaitForFunctionOptions): Promise>; + async waitForFunction(pageFunction: Func1, arg: Arg, options: WaitForFunctionOptions = {}): Promise> { return this._wrapApiCall(this._apiName('waitForFunction'), async () => { if (typeof options.polling === 'string') assert(options.polling === 'raf', 'Unknown polling option: ' + options.polling); @@ -406,10 +407,10 @@ export class Frame extends ChannelOwner { } } -export function verifyLoadState(name: string, waitUntil: types.LifecycleEvent): types.LifecycleEvent { +export function verifyLoadState(name: string, waitUntil: LifecycleEvent): LifecycleEvent { if (waitUntil as unknown === 'networkidle0') waitUntil = 'networkidle'; - if (!types.kLifecycleEvents.has(waitUntil)) + if (!kLifecycleEvents.has(waitUntil)) throw new Error(`${name}: expected one of (load|domcontentloaded|networkidle)`); return waitUntil; } diff --git a/src/rpc/client/input.ts b/src/rpc/client/input.ts index f3b2b35bcec7b..7184b9e12786c 100644 --- a/src/rpc/client/input.ts +++ b/src/rpc/client/input.ts @@ -15,8 +15,7 @@ * limitations under the License. */ -import * as types from '../../types'; -import { PageChannel } from '../channels'; +import { PageChannel, PageKeyboardTypeOptions, PageKeyboardPressOptions, PageMouseDownOptions, PageMouseUpOptions, PageMouseClickOptions } from '../channels'; export class Keyboard { private _channel: PageChannel; @@ -37,11 +36,11 @@ export class Keyboard { await this._channel.keyboardInsertText({ text }); } - async type(text: string, options: { delay?: number } = {}) { + async type(text: string, options: PageKeyboardTypeOptions = {}) { await this._channel.keyboardType({ text, ...options }); } - async press(key: string, options: { delay?: number } = {}) { + async press(key: string, options: PageKeyboardPressOptions = {}) { await this._channel.keyboardPress({ key, ...options }); } } @@ -57,19 +56,19 @@ export class Mouse { await this._channel.mouseMove({ x, y, ...options }); } - async down(options: { button?: types.MouseButton, clickCount?: number } = {}) { + async down(options: PageMouseDownOptions = {}) { await this._channel.mouseDown({ ...options }); } - async up(options: { button?: types.MouseButton, clickCount?: number } = {}) { + async up(options: PageMouseUpOptions = {}) { await this._channel.mouseUp(options); } - async click(x: number, y: number, options: { delay?: number, button?: types.MouseButton, clickCount?: number } = {}) { + async click(x: number, y: number, options: PageMouseClickOptions = {}) { await this._channel.mouseClick({ x, y, ...options }); } - async dblclick(x: number, y: number, options: { delay?: number, button?: types.MouseButton } = {}) { + async dblclick(x: number, y: number, options: Omit = {}) { await this.click(x, y, { ...options, clickCount: 2 }); } } diff --git a/src/rpc/client/network.ts b/src/rpc/client/network.ts index aa144d40daf51..62492d638e726 100644 --- a/src/rpc/client/network.ts +++ b/src/rpc/client/network.ts @@ -15,11 +15,11 @@ */ import { URLSearchParams } from 'url'; -import * as types from '../../types'; import { RequestChannel, ResponseChannel, RouteChannel, RequestInitializer, ResponseInitializer, RouteInitializer } from '../channels'; import { ChannelOwner } from './channelOwner'; import { Frame } from './frame'; import { normalizeFulfillParameters, headersArrayToObject, normalizeContinueOverrides } from '../../converters'; +import { Headers } from './types'; export type NetworkCookie = { name: string, @@ -44,11 +44,24 @@ export type SetNetworkCookieParam = { sameSite?: 'Strict' | 'Lax' | 'None' }; +type FulfillResponse = { + status?: number, + headers?: Headers, + contentType?: string, + body?: string | Buffer, +}; + +type ContinueOverrides = { + method?: string, + headers?: Headers, + postData?: string | Buffer, +}; + export class Request extends ChannelOwner { private _redirectedFrom: Request | null = null; private _redirectedTo: Request | null = null; _failureText: string | null = null; - private _headers: types.Headers; + private _headers: Headers; private _postData: Buffer | null; static from(request: RequestChannel): Request { @@ -108,7 +121,7 @@ export class Request extends ChannelOwner { return JSON.parse(postData); } - headers(): types.Headers { + headers(): Headers { return { ...this._headers }; } @@ -162,12 +175,12 @@ export class Route extends ChannelOwner { await this._channel.abort({ errorCode }); } - async fulfill(response: types.FulfillResponse & { path?: string }) { + async fulfill(response: FulfillResponse & { path?: string }) { const normalized = await normalizeFulfillParameters(response); await this._channel.fulfill(normalized); } - async continue(overrides: types.ContinueOverrides = {}) { + async continue(overrides: ContinueOverrides = {}) { const normalized = normalizeContinueOverrides(overrides); await this._channel.continue({ method: normalized.method, @@ -180,7 +193,7 @@ export class Route extends ChannelOwner { export type RouteHandler = (route: Route, request: Request) => void; export class Response extends ChannelOwner { - private _headers: types.Headers; + private _headers: Headers; static from(response: ResponseChannel): Response { return (response as any)._object; @@ -211,7 +224,7 @@ export class Response extends ChannelOwner return this._initializer.statusText; } - headers(): types.Headers { + headers(): Headers { return { ...this._headers }; } diff --git a/src/rpc/client/page.ts b/src/rpc/client/page.ts index f09750486eccd..3f36619d98141 100644 --- a/src/rpc/client/page.ts +++ b/src/rpc/client/page.ts @@ -15,11 +15,10 @@ * limitations under the License. */ -import { Events } from '../../events'; +import { Events } from './events'; import { assert, assertMaxArguments, helper, Listener } from '../../helper'; import { TimeoutSettings } from '../../timeoutSettings'; -import * as types from '../../types'; -import { BindingCallChannel, BindingCallInitializer, PageChannel, PageInitializer, PagePdfParams } from '../channels'; +import { BindingCallChannel, BindingCallInitializer, PageChannel, PageInitializer, PagePdfParams, FrameWaitForSelectorOptions, FrameDispatchEventOptions, FrameSetContentOptions, FrameGotoOptions, PageReloadOptions, PageGoBackOptions, PageGoForwardOptions, PageScreenshotOptions, FrameClickOptions, FrameDblclickOptions, FrameFillOptions, FrameFocusOptions, FrameTextContentOptions, FrameInnerTextOptions, FrameInnerHTMLOptions, FrameGetAttributeOptions, FrameHoverOptions, FrameSetInputFilesOptions, FrameTypeOptions, FramePressOptions, FrameCheckOptions, FrameUncheckOptions } from '../channels'; import { parseError, serializeError } from '../serializers'; import { headersObjectToArray } from '../../converters'; import { Accessibility } from './accessibility'; @@ -30,7 +29,7 @@ import { Dialog } from './dialog'; import { Download } from './download'; import { ElementHandle } from './elementHandle'; import { Worker } from './worker'; -import { Frame, FunctionWithSource, GotoOptions, verifyLoadState } from './frame'; +import { Frame, FunctionWithSource, verifyLoadState, WaitForNavigationOptions } from './frame'; import { Keyboard, Mouse } from './input'; import { Func1, FuncOn, SmartHandle, serializeArgument, parseResult } from './jsHandle'; import { Request, Response, Route, RouteHandler } from './network'; @@ -41,6 +40,19 @@ import { Waiter } from './waiter'; import * as fs from 'fs'; import * as util from 'util'; +import { Size, URLMatch, Headers, LifecycleEvent, WaitForEventOptions, SelectOption, SelectOptionOptions, FilePayload, WaitForFunctionOptions } from './types'; + +type PDFOptions = Omit & { + width?: string | number, + height?: string | number, + margin?: { + top?: string | number, + bottom?: string | number, + left?: string | number, + right?: string | number + }, + path?: string, +}; const fsWriteFileAsync = util.promisify(fs.writeFile.bind(fs)); @@ -52,14 +64,14 @@ export class Page extends ChannelOwner { private _frames = new Set(); _workers = new Set(); private _closed = false; - private _viewportSize: types.Size | null; - private _routes: { url: types.URLMatch, handler: RouteHandler }[] = []; + private _viewportSize: Size | null; + private _routes: { url: URLMatch, handler: RouteHandler }[] = []; readonly accessibility: Accessibility; readonly keyboard: Keyboard; readonly mouse: Mouse; coverage: ChromiumCoverage | null = null; - pdf?: (options?: types.PDFOptions) => Promise; + pdf?: (options?: PDFOptions) => Promise; readonly _bindings = new Map(); readonly _timeoutSettings: TimeoutSettings; @@ -183,7 +195,7 @@ export class Page extends ChannelOwner { return this._mainFrame; } - frame(options: string | { name?: string, url?: types.URLMatch }): Frame | null { + frame(options: string | { name?: string, url?: URLMatch }): Frame | null { const name = helper.isString(options) ? options : options.name; const url = helper.isObject(options) ? options.url : undefined; assert(name || url, 'Either name or url matcher should be specified'); @@ -221,11 +233,11 @@ export class Page extends ChannelOwner { return this._attributeToPage(() => this._mainFrame.$(selector)); } - async waitForSelector(selector: string, options?: types.WaitForElementOptions): Promise | null> { + async waitForSelector(selector: string, options?: FrameWaitForSelectorOptions): Promise | null> { return this._attributeToPage(() => this._mainFrame.waitForSelector(selector, options)); } - async dispatchEvent(selector: string, type: string, eventInit?: any, options?: types.TimeoutOptions): Promise { + async dispatchEvent(selector: string, type: string, eventInit?: any, options?: FrameDispatchEventOptions): Promise { return this._attributeToPage(() => this._mainFrame.dispatchEvent(selector, type, eventInit, options)); } @@ -277,7 +289,7 @@ export class Page extends ChannelOwner { }); } - async setExtraHTTPHeaders(headers: types.Headers) { + async setExtraHTTPHeaders(headers: Headers) { return this._wrapApiCall('page.setExtraHTTPHeaders', async () => { await this._channel.setExtraHTTPHeaders({ headers: headersObjectToArray(headers) }); }); @@ -291,30 +303,30 @@ export class Page extends ChannelOwner { return this._attributeToPage(() => this._mainFrame.content()); } - async setContent(html: string, options?: types.NavigateOptions): Promise { + async setContent(html: string, options?: FrameSetContentOptions): Promise { return this._attributeToPage(() => this._mainFrame.setContent(html, options)); } - async goto(url: string, options?: GotoOptions): Promise { + async goto(url: string, options?: FrameGotoOptions): Promise { return this._attributeToPage(() => this._mainFrame.goto(url, options)); } - async reload(options: types.NavigateOptions = {}): Promise { + async reload(options: PageReloadOptions = {}): Promise { return this._wrapApiCall('page.reload', async () => { const waitUntil = verifyLoadState('waitUntil', options.waitUntil === undefined ? 'load' : options.waitUntil); return Response.fromNullable((await this._channel.reload({ ...options, waitUntil })).response); }); } - async waitForLoadState(state?: types.LifecycleEvent, options?: types.TimeoutOptions): Promise { + async waitForLoadState(state?: LifecycleEvent, options?: { timeout?: number }): Promise { return this._attributeToPage(() => this._mainFrame.waitForLoadState(state, options)); } - async waitForNavigation(options?: types.WaitForNavigationOptions): Promise { + async waitForNavigation(options?: WaitForNavigationOptions): Promise { return this._attributeToPage(() => this._mainFrame.waitForNavigation(options)); } - async waitForRequest(urlOrPredicate: string | RegExp | ((r: Request) => boolean), options: types.TimeoutOptions = {}): Promise { + async waitForRequest(urlOrPredicate: string | RegExp | ((r: Request) => boolean), options: { timeout?: number } = {}): Promise { const predicate = (request: Request) => { if (helper.isString(urlOrPredicate) || helper.isRegExp(urlOrPredicate)) return helper.urlMatches(request.url(), urlOrPredicate); @@ -323,7 +335,7 @@ export class Page extends ChannelOwner { return this.waitForEvent(Events.Page.Request, { predicate, timeout: options.timeout }); } - async waitForResponse(urlOrPredicate: string | RegExp | ((r: Response) => boolean), options: types.TimeoutOptions = {}): Promise { + async waitForResponse(urlOrPredicate: string | RegExp | ((r: Response) => boolean), options: { timeout?: number } = {}): Promise { const predicate = (response: Response) => { if (helper.isString(urlOrPredicate) || helper.isRegExp(urlOrPredicate)) return helper.urlMatches(response.url(), urlOrPredicate); @@ -332,7 +344,7 @@ export class Page extends ChannelOwner { return this.waitForEvent(Events.Page.Response, { predicate, timeout: options.timeout }); } - async waitForEvent(event: string, optionsOrPredicate: types.WaitForEventOptions = {}): Promise { + async waitForEvent(event: string, optionsOrPredicate: WaitForEventOptions = {}): Promise { const timeout = this._timeoutSettings.timeout(typeof optionsOrPredicate === 'function' ? {} : optionsOrPredicate); const predicate = typeof optionsOrPredicate === 'function' ? optionsOrPredicate : optionsOrPredicate.predicate; const waiter = new Waiter(); @@ -346,21 +358,21 @@ export class Page extends ChannelOwner { return result; } - async goBack(options: types.NavigateOptions = {}): Promise { + async goBack(options: PageGoBackOptions = {}): Promise { return this._wrapApiCall('page.goBack', async () => { const waitUntil = verifyLoadState('waitUntil', options.waitUntil === undefined ? 'load' : options.waitUntil); return Response.fromNullable((await this._channel.goBack({ ...options, waitUntil })).response); }); } - async goForward(options: types.NavigateOptions = {}): Promise { + async goForward(options: PageGoForwardOptions = {}): Promise { return this._wrapApiCall('page.goForward', async () => { const waitUntil = verifyLoadState('waitUntil', options.waitUntil === undefined ? 'load' : options.waitUntil); return Response.fromNullable((await this._channel.goForward({ ...options, waitUntil })).response); }); } - async emulateMedia(options: { media?: types.MediaType | null, colorScheme?: types.ColorScheme | null }) { + async emulateMedia(options: { media?: 'screen' | 'print' | null, colorScheme?: 'dark' | 'light' | 'no-preference' | null }) { return this._wrapApiCall('page.emulateMedia', async () => { await this._channel.emulateMedia({ media: options.media === null ? 'null' : options.media, @@ -369,14 +381,14 @@ export class Page extends ChannelOwner { }); } - async setViewportSize(viewportSize: types.Size) { + async setViewportSize(viewportSize: Size) { return this._wrapApiCall('page.setViewportSize', async () => { this._viewportSize = viewportSize; await this._channel.setViewportSize({ viewportSize }); }); } - viewportSize(): types.Size | null { + viewportSize(): Size | null { return this._viewportSize; } @@ -394,7 +406,7 @@ export class Page extends ChannelOwner { }); } - async route(url: types.URLMatch, handler: RouteHandler): Promise { + async route(url: URLMatch, handler: RouteHandler): Promise { return this._wrapApiCall('page.route', async () => { this._routes.push({ url, handler }); if (this._routes.length === 1) @@ -402,7 +414,7 @@ export class Page extends ChannelOwner { }); } - async unroute(url: types.URLMatch, handler?: RouteHandler): Promise { + async unroute(url: URLMatch, handler?: RouteHandler): Promise { return this._wrapApiCall('page.unroute', async () => { this._routes = this._routes.filter(route => route.url !== url || (handler && route.handler !== handler)); if (this._routes.length === 0) @@ -410,7 +422,7 @@ export class Page extends ChannelOwner { }); } - async screenshot(options: types.ScreenshotOptions = {}): Promise { + async screenshot(options: PageScreenshotOptions = {}): Promise { return this._wrapApiCall('page.screenshot', async () => { return Buffer.from((await this._channel.screenshot(options)).binary, 'base64'); }); @@ -438,63 +450,63 @@ export class Page extends ChannelOwner { return this._closed; } - async click(selector: string, options?: types.MouseClickOptions & types.PointerActionWaitOptions & types.NavigatingActionWaitOptions) { + async click(selector: string, options?: FrameClickOptions) { return this._attributeToPage(() => this._mainFrame.click(selector, options)); } - async dblclick(selector: string, options?: types.MouseMultiClickOptions & types.PointerActionWaitOptions & types.NavigatingActionWaitOptions) { + async dblclick(selector: string, options?: FrameDblclickOptions) { return this._attributeToPage(() => this._mainFrame.dblclick(selector, options)); } - async fill(selector: string, value: string, options?: types.NavigatingActionWaitOptions) { + async fill(selector: string, value: string, options?: FrameFillOptions) { return this._attributeToPage(() => this._mainFrame.fill(selector, value, options)); } - async focus(selector: string, options?: types.TimeoutOptions) { + async focus(selector: string, options?: FrameFocusOptions) { return this._attributeToPage(() => this._mainFrame.focus(selector, options)); } - async textContent(selector: string, options?: types.TimeoutOptions): Promise { + async textContent(selector: string, options?: FrameTextContentOptions): Promise { return this._attributeToPage(() => this._mainFrame.textContent(selector, options)); } - async innerText(selector: string, options?: types.TimeoutOptions): Promise { + async innerText(selector: string, options?: FrameInnerTextOptions): Promise { return this._attributeToPage(() => this._mainFrame.innerText(selector, options)); } - async innerHTML(selector: string, options?: types.TimeoutOptions): Promise { + async innerHTML(selector: string, options?: FrameInnerHTMLOptions): Promise { return this._attributeToPage(() => this._mainFrame.innerHTML(selector, options)); } - async getAttribute(selector: string, name: string, options?: types.TimeoutOptions): Promise { + async getAttribute(selector: string, name: string, options?: FrameGetAttributeOptions): Promise { return this._attributeToPage(() => this._mainFrame.getAttribute(selector, name, options)); } - async hover(selector: string, options?: types.PointerActionOptions & types.PointerActionWaitOptions) { + async hover(selector: string, options?: FrameHoverOptions) { return this._attributeToPage(() => this._mainFrame.hover(selector, options)); } - async selectOption(selector: string, values: string | ElementHandle | types.SelectOption | string[] | ElementHandle[] | types.SelectOption[] | null, options?: types.NavigatingActionWaitOptions): Promise { + async selectOption(selector: string, values: string | ElementHandle | SelectOption | string[] | ElementHandle[] | SelectOption[] | null, options?: SelectOptionOptions): Promise { return this._attributeToPage(() => this._mainFrame.selectOption(selector, values, options)); } - async setInputFiles(selector: string, files: string | types.FilePayload | string[] | types.FilePayload[], options?: types.NavigatingActionWaitOptions): Promise { + async setInputFiles(selector: string, files: string | FilePayload | string[] | FilePayload[], options?: FrameSetInputFilesOptions): Promise { return this._attributeToPage(() => this._mainFrame.setInputFiles(selector, files, options)); } - async type(selector: string, text: string, options?: { delay?: number } & types.NavigatingActionWaitOptions) { + async type(selector: string, text: string, options?: FrameTypeOptions) { return this._attributeToPage(() => this._mainFrame.type(selector, text, options)); } - async press(selector: string, key: string, options?: { delay?: number } & types.NavigatingActionWaitOptions) { + async press(selector: string, key: string, options?: FramePressOptions) { return this._attributeToPage(() => this._mainFrame.press(selector, key, options)); } - async check(selector: string, options?: types.PointerActionWaitOptions & types.NavigatingActionWaitOptions) { + async check(selector: string, options?: FrameCheckOptions) { return this._attributeToPage(() => this._mainFrame.check(selector, options)); } - async uncheck(selector: string, options?: types.PointerActionWaitOptions & types.NavigatingActionWaitOptions) { + async uncheck(selector: string, options?: FrameUncheckOptions) { return this._attributeToPage(() => this._mainFrame.uncheck(selector, options)); } @@ -502,9 +514,9 @@ export class Page extends ChannelOwner { await this._mainFrame.waitForTimeout(timeout); } - async waitForFunction(pageFunction: Func1, arg: Arg, options?: types.WaitForFunctionOptions): Promise>; - async waitForFunction(pageFunction: Func1, arg?: any, options?: types.WaitForFunctionOptions): Promise>; - async waitForFunction(pageFunction: Func1, arg: Arg, options?: types.WaitForFunctionOptions): Promise> { + async waitForFunction(pageFunction: Func1, arg: Arg, options?: WaitForFunctionOptions): Promise>; + async waitForFunction(pageFunction: Func1, arg?: any, options?: WaitForFunctionOptions): Promise>; + async waitForFunction(pageFunction: Func1, arg: Arg, options?: WaitForFunctionOptions): Promise> { return this._attributeToPage(() => this._mainFrame.waitForFunction(pageFunction, arg, options)); } @@ -528,7 +540,7 @@ export class Page extends ChannelOwner { return this; } - async _pdf(options: types.PDFOptions = {}): Promise { + async _pdf(options: PDFOptions = {}): Promise { const path = options.path; const transportOptions: PagePdfParams = { ...options } as PagePdfParams; if (path) diff --git a/src/rpc/client/playwright.ts b/src/rpc/client/playwright.ts index 98f5914b42cef..c6a6d70697acf 100644 --- a/src/rpc/client/playwright.ts +++ b/src/rpc/client/playwright.ts @@ -15,18 +15,27 @@ */ import { PlaywrightChannel, PlaywrightInitializer } from '../channels'; -import * as types from '../../types'; import { BrowserType } from './browserType'; import { ChannelOwner } from './channelOwner'; import { Selectors } from './selectors'; import { Electron } from './electron'; import { TimeoutError } from '../../errors'; +import { Size } from './types'; + +type DeviceDescriptor = { + userAgent: string, + viewport: Size, + deviceScaleFactor: number, + isMobile: boolean, + hasTouch: boolean +}; +type Devices = { [name: string]: DeviceDescriptor }; export class Playwright extends ChannelOwner { readonly chromium: BrowserType; readonly firefox: BrowserType; readonly webkit: BrowserType; - readonly devices: types.Devices; + readonly devices: Devices; readonly selectors: Selectors; readonly errors: { TimeoutError: typeof TimeoutError }; diff --git a/src/rpc/client/types.ts b/src/rpc/client/types.ts new file mode 100644 index 0000000000000..028d17df43b77 --- /dev/null +++ b/src/rpc/client/types.ts @@ -0,0 +1,57 @@ +/** + * Copyright 2018 Google Inc. All rights reserved. + * Modifications copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { BrowserNewContextOptions, BrowserTypeLaunchOptions, BrowserTypeLaunchServerOptions, BrowserTypeConnectParams } from '../channels'; + +type LoggerSeverity = 'verbose' | 'info' | 'warning' | 'error'; +export interface LoggerSink { + isEnabled(name: string, severity: LoggerSeverity): boolean; + log(name: string, severity: LoggerSeverity, message: string | Error, args: any[], hints: { color?: string }): void; +} + +export type Size = { width: number, height: number }; +export type Point = { x: number, y: number }; +export type Rect = Size & Point; +export type Headers = { [key: string]: string }; +export type Env = { [key: string]: string | number | boolean | undefined }; +export type URLMatch = string | RegExp | ((url: URL) => boolean); + +export type WaitForEventOptions = Function | { predicate?: Function, timeout?: number }; +export type WaitForFunctionOptions = { timeout?: number, polling?: 'raf' | number }; + +export type SelectOption = { value?: string, label?: string, index?: number }; +export type SelectOptionOptions = { timeout?: number, noWaitAfter?: boolean }; +export type FilePayload = { name: string, mimeType: string, buffer: Buffer }; + +export type LifecycleEvent = 'load' | 'domcontentloaded' | 'networkidle'; +export const kLifecycleEvents: Set = new Set(['load', 'domcontentloaded', 'networkidle']); + +export type BrowserContextOptions = Omit & { + viewport?: Size | null, + extraHTTPHeaders?: Headers, + logger?: LoggerSink, +}; + +type LaunchOverrides = { + ignoreDefaultArgs?: boolean | string[], + env?: Env, + firefoxUserPrefs?: { [key: string]: string | number | boolean }, + logger?: LoggerSink, +}; +export type LaunchOptions = Omit & LaunchOverrides; +export type LaunchServerOptions = Omit & LaunchOverrides; +export type ConnectOptions = BrowserTypeConnectParams & { logger?: LoggerSink }; diff --git a/src/rpc/client/worker.ts b/src/rpc/client/worker.ts index cf5dccd6eecfa..8b19441f0e39d 100644 --- a/src/rpc/client/worker.ts +++ b/src/rpc/client/worker.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { Events } from '../../events'; +import { Events } from './events'; import { assertMaxArguments } from '../../helper'; import { WorkerChannel, WorkerInitializer } from '../channels'; import { ChannelOwner } from './channelOwner'; diff --git a/src/rpc/serializers.ts b/src/rpc/serializers.ts index d5b3c6c7a110b..9c0c882f12d39 100644 --- a/src/rpc/serializers.ts +++ b/src/rpc/serializers.ts @@ -15,9 +15,8 @@ */ import { TimeoutError } from '../errors'; -import * as types from '../types'; import { helper } from '../helper'; -import { SerializedError, AXNode, SerializedValue } from './channels'; +import { SerializedError, SerializedValue } from './channels'; export function serializeError(e: any): SerializedError { if (helper.isError(e)) @@ -41,32 +40,6 @@ export function parseError(error: SerializedError): Error { return e; } -export function axNodeToProtocol(axNode: types.SerializedAXNode): AXNode { - const result: AXNode = { - ...axNode, - valueNumber: typeof axNode.value === 'number' ? axNode.value : undefined, - valueString: typeof axNode.value === 'string' ? axNode.value : undefined, - checked: axNode.checked === true ? 'checked' : axNode.checked === false ? 'unchecked' : axNode.checked, - pressed: axNode.pressed === true ? 'pressed' : axNode.pressed === false ? 'released' : axNode.pressed, - children: axNode.children ? axNode.children.map(axNodeToProtocol) : undefined, - }; - delete (result as any).value; - return result; -} - -export function axNodeFromProtocol(axNode: AXNode): types.SerializedAXNode { - const result: types.SerializedAXNode = { - ...axNode, - value: axNode.valueNumber !== undefined ? axNode.valueNumber : axNode.valueString, - checked: axNode.checked === 'checked' ? true : axNode.checked === 'unchecked' ? false : axNode.checked, - pressed: axNode.pressed === 'pressed' ? true : axNode.pressed === 'released' ? false : axNode.pressed, - children: axNode.children ? axNode.children.map(axNodeFromProtocol) : undefined, - }; - delete (result as any).valueNumber; - delete (result as any).valueString; - return result; -} - export function parseSerializedValue(value: SerializedValue, handles: any[] | undefined): any { if (value.n !== undefined) return value.n; diff --git a/src/rpc/server/pageDispatcher.ts b/src/rpc/server/pageDispatcher.ts index ac50374bdaf19..a488e6f91dac5 100644 --- a/src/rpc/server/pageDispatcher.ts +++ b/src/rpc/server/pageDispatcher.ts @@ -20,9 +20,9 @@ import { Frame } from '../../frames'; import { Request } from '../../network'; import { Page, Worker } from '../../page'; import * as types from '../../types'; -import { BindingCallChannel, BindingCallInitializer, ElementHandleChannel, PageChannel, PageInitializer, ResponseChannel, WorkerInitializer, WorkerChannel, JSHandleChannel, Binary, SerializedArgument, PagePdfParams, SerializedError, PageAccessibilitySnapshotResult, SerializedValue, PageEmulateMediaParams } from '../channels'; +import { BindingCallChannel, BindingCallInitializer, ElementHandleChannel, PageChannel, PageInitializer, ResponseChannel, WorkerInitializer, WorkerChannel, JSHandleChannel, Binary, SerializedArgument, PagePdfParams, SerializedError, PageAccessibilitySnapshotResult, SerializedValue, PageEmulateMediaParams, AXNode } from '../channels'; import { Dispatcher, DispatcherScope, lookupDispatcher, lookupNullableDispatcher } from './dispatcher'; -import { parseError, serializeError, axNodeToProtocol } from '../serializers'; +import { parseError, serializeError } from '../serializers'; import { headersArrayToObject } from '../../converters'; import { ConsoleMessageDispatcher } from './consoleMessageDispatcher'; import { DialogDispatcher } from './dialogDispatcher'; @@ -278,3 +278,16 @@ export class BindingCallDispatcher extends Dispatcher<{}, BindingCallInitializer this._reject!(parseError(params.error)); } } + +function axNodeToProtocol(axNode: types.SerializedAXNode): AXNode { + const result: AXNode = { + ...axNode, + valueNumber: typeof axNode.value === 'number' ? axNode.value : undefined, + valueString: typeof axNode.value === 'string' ? axNode.value : undefined, + checked: axNode.checked === true ? 'checked' : axNode.checked === false ? 'unchecked' : axNode.checked, + pressed: axNode.pressed === true ? 'pressed' : axNode.pressed === false ? 'released' : axNode.pressed, + children: axNode.children ? axNode.children.map(axNodeToProtocol) : undefined, + }; + delete (result as any).value; + return result; +} diff --git a/utils/generate_channels.js b/utils/generate_channels.js index b2d01216d3f24..aecf1b792fadf 100755 --- a/utils/generate_channels.js +++ b/utils/generate_channels.js @@ -70,11 +70,13 @@ function inlineType(type, indent, wrapEnums = false) { raise(type); } -function properties(props, indent) { +function properties(props, indent, onlyOptional) { const ts = []; const scheme = []; for (const [name, value] of Object.entries(props)) { const inner = inlineType(value, indent); + if (onlyOptional && !inner.optional) + continue; ts.push(`${indent}${name}${inner.optional ? '?' : ''}: ${inner.ts},`); const wrapped = inner.optional ? `tOptional(${inner.scheme})` : inner.scheme; scheme.push(`${indent}${name}: ${wrapped},`); @@ -82,10 +84,10 @@ function properties(props, indent) { return { ts: ts.join('\n'), scheme: scheme.join('\n') }; } -function objectType(props, indent) { +function objectType(props, indent, onlyOptional = false) { if (!Object.entries(props).length) return { ts: `{}`, scheme: `tObject({})` }; - const inner = properties(props, indent + ' '); + const inner = properties(props, indent + ' ', onlyOptional); return { ts: `{\n${inner.ts}\n${indent}}`, scheme: `tObject({\n${inner.scheme}\n${indent}})` }; } @@ -195,7 +197,9 @@ for (const [name, item] of Object.entries(protocol)) { method = {}; const parameters = objectType(method.parameters || {}, ''); const paramsName = `${channelName}${titleCase(methodName)}Params`; + const optionsName = `${channelName}${titleCase(methodName)}Options`; ts_types.set(paramsName, parameters.ts); + ts_types.set(optionsName, objectType(method.parameters || {}, '', true).ts); addScheme(paramsName, method.parameters ? parameters.scheme : `tOptional(tObject({}))`); for (const key of inherits.keys()) { if (inherits.get(key) === channelName)