2020-06-25 16:05:36 -07:00
|
|
|
/**
|
|
|
|
* Copyright 2017 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 { assertMaxArguments } from '../../helper';
|
|
|
|
import * as types from '../../types';
|
2020-06-26 12:28:27 -07:00
|
|
|
import { FrameChannel, FrameInitializer } from '../channels';
|
2020-06-25 16:05:36 -07:00
|
|
|
import { BrowserContext } from './browserContext';
|
|
|
|
import { ChannelOwner } from './channelOwner';
|
2020-06-26 11:51:47 -07:00
|
|
|
import { ElementHandle, convertSelectOptionValues } from './elementHandle';
|
2020-06-27 11:10:07 -07:00
|
|
|
import { JSHandle, Func1, FuncOn, SmartHandle, serializeArgument, parseResult } from './jsHandle';
|
2020-06-25 16:05:36 -07:00
|
|
|
import * as network from './network';
|
|
|
|
import { Response } from './network';
|
|
|
|
import { Page } from './page';
|
2020-07-01 13:55:29 -07:00
|
|
|
import { ConnectionScope } from './connection';
|
2020-06-27 11:10:07 -07:00
|
|
|
import { normalizeFilePayloads } from '../serializers';
|
2020-06-25 16:05:36 -07:00
|
|
|
|
|
|
|
export type GotoOptions = types.NavigateOptions & {
|
|
|
|
referer?: string,
|
|
|
|
};
|
|
|
|
|
|
|
|
export type FunctionWithSource = (source: { context: BrowserContext, page: Page, frame: Frame }, ...args: any) => any;
|
|
|
|
|
2020-06-26 12:28:27 -07:00
|
|
|
export class Frame extends ChannelOwner<FrameChannel, FrameInitializer> {
|
2020-06-25 16:05:36 -07:00
|
|
|
_parentFrame: Frame | null = null;
|
|
|
|
_url = '';
|
2020-06-26 11:51:47 -07:00
|
|
|
_name = '';
|
2020-06-26 17:24:21 -07:00
|
|
|
_detached = false;
|
2020-06-25 16:05:36 -07:00
|
|
|
_childFrames = new Set<Frame>();
|
2020-06-26 12:28:27 -07:00
|
|
|
_page: Page | undefined;
|
2020-06-25 16:05:36 -07:00
|
|
|
|
|
|
|
static from(frame: FrameChannel): Frame {
|
2020-07-01 18:36:09 -07:00
|
|
|
return (frame as any)._object;
|
2020-06-25 16:05:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static fromNullable(frame: FrameChannel | null): Frame | null {
|
|
|
|
return frame ? Frame.from(frame) : null;
|
|
|
|
}
|
|
|
|
|
2020-07-01 13:55:29 -07:00
|
|
|
constructor(scope: ConnectionScope, guid: string, initializer: FrameInitializer) {
|
|
|
|
super(scope, guid, initializer);
|
2020-06-26 12:28:27 -07:00
|
|
|
this._parentFrame = Frame.fromNullable(initializer.parentFrame);
|
2020-06-25 16:05:36 -07:00
|
|
|
if (this._parentFrame)
|
|
|
|
this._parentFrame._childFrames.add(this);
|
2020-06-26 12:28:27 -07:00
|
|
|
this._name = initializer.name;
|
|
|
|
this._url = initializer.url;
|
2020-06-25 16:05:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
async goto(url: string, options: GotoOptions = {}): Promise<network.Response | null> {
|
2020-07-06 10:04:09 -07:00
|
|
|
return Response.fromNullable(await this._channel.goto({ url, ...options, isPage: this._page!._isPageCall }));
|
2020-06-25 16:05:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
async waitForNavigation(options: types.WaitForNavigationOptions = {}): Promise<network.Response | null> {
|
2020-07-06 10:04:09 -07:00
|
|
|
return Response.fromNullable(await this._channel.waitForNavigation({ ...options, isPage: this._page!._isPageCall }));
|
2020-06-25 16:05:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
async waitForLoadState(state: types.LifecycleEvent = 'load', options: types.TimeoutOptions = {}): Promise<void> {
|
2020-07-06 10:04:09 -07:00
|
|
|
await this._channel.waitForLoadState({ state, ...options, isPage: this._page!._isPageCall });
|
2020-06-25 16:05:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
async frameElement(): Promise<ElementHandle> {
|
|
|
|
return ElementHandle.from(await this._channel.frameElement());
|
|
|
|
}
|
|
|
|
|
|
|
|
async evaluateHandle<R, Arg>(pageFunction: Func1<Arg, R>, arg: Arg): Promise<SmartHandle<R>>;
|
|
|
|
async evaluateHandle<R>(pageFunction: Func1<void, R>, arg?: any): Promise<SmartHandle<R>>;
|
|
|
|
async evaluateHandle<R, Arg>(pageFunction: Func1<Arg, R>, arg: Arg): Promise<SmartHandle<R>> {
|
|
|
|
assertMaxArguments(arguments.length, 2);
|
2020-06-29 18:58:09 -07:00
|
|
|
return JSHandle.from(await this._channel.evaluateExpressionHandle({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg), isPage: this._page!._isPageCall })) as SmartHandle<R>;
|
2020-06-25 16:05:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
async evaluate<R, Arg>(pageFunction: Func1<Arg, R>, arg: Arg): Promise<R>;
|
|
|
|
async evaluate<R>(pageFunction: Func1<void, R>, arg?: any): Promise<R>;
|
|
|
|
async evaluate<R, Arg>(pageFunction: Func1<Arg, R>, arg: Arg): Promise<R> {
|
|
|
|
assertMaxArguments(arguments.length, 2);
|
2020-06-29 18:58:09 -07:00
|
|
|
return parseResult(await this._channel.evaluateExpression({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg), isPage: this._page!._isPageCall }));
|
2020-06-25 16:05:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
async $(selector: string): Promise<ElementHandle<Element> | null> {
|
2020-06-29 18:58:09 -07:00
|
|
|
return ElementHandle.fromNullable(await this._channel.querySelector({ selector, isPage: this._page!._isPageCall })) as ElementHandle<Element> | null;
|
2020-06-25 16:05:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
async waitForSelector(selector: string, options: types.WaitForElementOptions = {}): Promise<ElementHandle<Element> | null> {
|
2020-07-06 10:04:09 -07:00
|
|
|
return ElementHandle.fromNullable(await this._channel.waitForSelector({ selector, ...options, isPage: this._page!._isPageCall })) as ElementHandle<Element> | null;
|
2020-06-25 16:05:36 -07:00
|
|
|
}
|
|
|
|
|
2020-06-30 10:55:11 -07:00
|
|
|
async dispatchEvent(selector: string, type: string, eventInit?: any, options: types.TimeoutOptions = {}): Promise<void> {
|
2020-07-06 10:04:09 -07:00
|
|
|
await this._channel.dispatchEvent({ selector, type, eventInit: serializeArgument(eventInit), ...options, isPage: this._page!._isPageCall });
|
2020-06-25 16:05:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
async $eval<R, Arg>(selector: string, pageFunction: FuncOn<Element, Arg, R>, arg: Arg): Promise<R>;
|
|
|
|
async $eval<R>(selector: string, pageFunction: FuncOn<Element, void, R>, arg?: any): Promise<R>;
|
|
|
|
async $eval<R, Arg>(selector: string, pageFunction: FuncOn<Element, Arg, R>, arg: Arg): Promise<R> {
|
|
|
|
assertMaxArguments(arguments.length, 3);
|
2020-07-03 18:04:08 -07:00
|
|
|
return await this._channel.evalOnSelector({ selector, expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg), isPage: this._page!._isPageCall });
|
2020-06-25 16:05:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
async $$eval<R, Arg>(selector: string, pageFunction: FuncOn<Element[], Arg, R>, arg: Arg): Promise<R>;
|
|
|
|
async $$eval<R>(selector: string, pageFunction: FuncOn<Element[], void, R>, arg?: any): Promise<R>;
|
|
|
|
async $$eval<R, Arg>(selector: string, pageFunction: FuncOn<Element[], Arg, R>, arg: Arg): Promise<R> {
|
|
|
|
assertMaxArguments(arguments.length, 3);
|
2020-07-03 18:04:08 -07:00
|
|
|
return await this._channel.evalOnSelectorAll({ selector, expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg), isPage: this._page!._isPageCall });
|
2020-06-25 16:05:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
async $$(selector: string): Promise<ElementHandle<Element>[]> {
|
2020-06-29 18:58:09 -07:00
|
|
|
const result = await this._channel.querySelectorAll({ selector, isPage: this._page!._isPageCall });
|
2020-06-25 16:05:36 -07:00
|
|
|
return result.map(c => ElementHandle.from(c) as ElementHandle<Element>);
|
|
|
|
}
|
|
|
|
|
|
|
|
async content(): Promise<string> {
|
|
|
|
return await this._channel.content();
|
|
|
|
}
|
|
|
|
|
|
|
|
async setContent(html: string, options: types.NavigateOptions = {}): Promise<void> {
|
2020-07-06 10:04:09 -07:00
|
|
|
await this._channel.setContent({ html, ...options, isPage: this._page!._isPageCall });
|
2020-06-25 16:05:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
name(): string {
|
|
|
|
return this._name || '';
|
|
|
|
}
|
|
|
|
|
|
|
|
url(): string {
|
|
|
|
return this._url;
|
|
|
|
}
|
|
|
|
|
|
|
|
parentFrame(): Frame | null {
|
|
|
|
return this._parentFrame;
|
|
|
|
}
|
|
|
|
|
|
|
|
childFrames(): Frame[] {
|
|
|
|
return Array.from(this._childFrames);
|
|
|
|
}
|
|
|
|
|
|
|
|
isDetached(): boolean {
|
|
|
|
return this._detached;
|
|
|
|
}
|
|
|
|
|
|
|
|
async addScriptTag(options: { url?: string, path?: string, content?: string, type?: string }): Promise<ElementHandle> {
|
2020-07-06 10:04:09 -07:00
|
|
|
return ElementHandle.from(await this._channel.addScriptTag({ ...options, isPage: this._page!._isPageCall }));
|
2020-06-25 16:05:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
async addStyleTag(options: { url?: string; path?: string; content?: string; }): Promise<ElementHandle> {
|
2020-07-06 10:04:09 -07:00
|
|
|
return ElementHandle.from(await this._channel.addStyleTag({ ...options, isPage: this._page!._isPageCall }));
|
2020-06-25 16:05:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
async click(selector: string, options: types.MouseClickOptions & types.PointerActionWaitOptions & types.NavigatingActionWaitOptions = {}) {
|
2020-07-06 10:04:09 -07:00
|
|
|
return await this._channel.click({ selector, ...options, isPage: this._page!._isPageCall });
|
2020-06-25 16:05:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
async dblclick(selector: string, options: types.MouseMultiClickOptions & types.PointerActionWaitOptions & types.NavigatingActionWaitOptions = {}) {
|
2020-07-06 10:04:09 -07:00
|
|
|
return await this._channel.dblclick({ selector, ...options, isPage: this._page!._isPageCall });
|
2020-06-25 16:05:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
async fill(selector: string, value: string, options: types.NavigatingActionWaitOptions = {}) {
|
2020-07-06 10:04:09 -07:00
|
|
|
return await this._channel.fill({ selector, value, ...options, isPage: this._page!._isPageCall });
|
2020-06-25 16:05:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
async focus(selector: string, options: types.TimeoutOptions = {}) {
|
2020-07-06 10:04:09 -07:00
|
|
|
await this._channel.focus({ selector, ...options, isPage: this._page!._isPageCall });
|
2020-06-25 16:05:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
async textContent(selector: string, options: types.TimeoutOptions = {}): Promise<null|string> {
|
2020-07-06 10:04:09 -07:00
|
|
|
return await this._channel.textContent({ selector, ...options, isPage: this._page!._isPageCall });
|
2020-06-25 16:05:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
async innerText(selector: string, options: types.TimeoutOptions = {}): Promise<string> {
|
2020-07-06 10:04:09 -07:00
|
|
|
return await this._channel.innerText({ selector, ...options, isPage: this._page!._isPageCall });
|
2020-06-25 16:05:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
async innerHTML(selector: string, options: types.TimeoutOptions = {}): Promise<string> {
|
2020-07-06 10:04:09 -07:00
|
|
|
return await this._channel.innerHTML({ selector, ...options, isPage: this._page!._isPageCall });
|
2020-06-25 16:05:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
async getAttribute(selector: string, name: string, options: types.TimeoutOptions = {}): Promise<string | null> {
|
2020-07-06 10:04:09 -07:00
|
|
|
return await this._channel.getAttribute({ selector, name, ...options, isPage: this._page!._isPageCall });
|
2020-06-25 16:05:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
async hover(selector: string, options: types.PointerActionOptions & types.PointerActionWaitOptions = {}) {
|
2020-07-06 10:04:09 -07:00
|
|
|
await this._channel.hover({ selector, ...options, isPage: this._page!._isPageCall });
|
2020-06-25 16:05:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
async selectOption(selector: string, values: string | ElementHandle | types.SelectOption | string[] | ElementHandle[] | types.SelectOption[] | null, options: types.NavigatingActionWaitOptions = {}): Promise<string[]> {
|
2020-07-06 10:04:09 -07:00
|
|
|
return await this._channel.selectOption({ selector, values: convertSelectOptionValues(values), ...options, isPage: this._page!._isPageCall });
|
2020-06-25 16:05:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
async setInputFiles(selector: string, files: string | types.FilePayload | string[] | types.FilePayload[], options: types.NavigatingActionWaitOptions = {}): Promise<void> {
|
2020-06-27 11:10:07 -07:00
|
|
|
const filePayloads = await normalizeFilePayloads(files);
|
2020-07-06 10:04:09 -07:00
|
|
|
await this._channel.setInputFiles({ selector, files: filePayloads.map(f => ({ name: f.name, mimeType: f.mimeType, buffer: f.buffer.toString('base64') })), ...options, isPage: this._page!._isPageCall });
|
2020-06-25 16:05:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
async type(selector: string, text: string, options: { delay?: number } & types.NavigatingActionWaitOptions = {}) {
|
2020-07-06 10:04:09 -07:00
|
|
|
await this._channel.type({ selector, text, ...options, isPage: this._page!._isPageCall });
|
2020-06-25 16:05:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
async press(selector: string, key: string, options: { delay?: number } & types.NavigatingActionWaitOptions = {}) {
|
2020-07-06 10:04:09 -07:00
|
|
|
await this._channel.press({ selector, key, ...options, isPage: this._page!._isPageCall });
|
2020-06-25 16:05:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
async check(selector: string, options: types.PointerActionWaitOptions & types.NavigatingActionWaitOptions = {}) {
|
2020-07-06 10:04:09 -07:00
|
|
|
await this._channel.check({ selector, ...options, isPage: this._page!._isPageCall });
|
2020-06-25 16:05:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
async uncheck(selector: string, options: types.PointerActionWaitOptions & types.NavigatingActionWaitOptions = {}) {
|
2020-07-06 10:04:09 -07:00
|
|
|
await this._channel.uncheck({ selector, ...options, isPage: this._page!._isPageCall });
|
2020-06-25 16:05:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
async waitForTimeout(timeout: number) {
|
|
|
|
await new Promise(fulfill => setTimeout(fulfill, timeout));
|
|
|
|
}
|
|
|
|
|
|
|
|
async waitForFunction<R, Arg>(pageFunction: Func1<Arg, R>, arg: Arg, options?: types.WaitForFunctionOptions): Promise<SmartHandle<R>>;
|
|
|
|
async waitForFunction<R>(pageFunction: Func1<void, R>, arg?: any, options?: types.WaitForFunctionOptions): Promise<SmartHandle<R>>;
|
|
|
|
async waitForFunction<R, Arg>(pageFunction: Func1<Arg, R>, arg: Arg, options: types.WaitForFunctionOptions = {}): Promise<SmartHandle<R>> {
|
2020-07-06 10:04:09 -07:00
|
|
|
return JSHandle.from(await this._channel.waitForFunction({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg), ...options, isPage: this._page!._isPageCall })) as SmartHandle<R>;
|
2020-06-25 16:05:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
async title(): Promise<string> {
|
|
|
|
return await this._channel.title();
|
|
|
|
}
|
|
|
|
}
|