feat(types): make our client classes implement public types (#4817)
This patch: - introduces non-exported but used in api/impl struct types (e.g. Point); - makes all client classes implement respective public api interface. Pros: - Typescript is now responsible for type checking. We can remove our doclint checker (not removed yet). - Electron and Android types can be defined in the same way (this is not implemented yet). - We can move most of the type structs like Point to the public api and make some of them available. Cons: - Any cons?
This commit is contained in:
parent
dc25173ae3
commit
34c1b338be
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
import * as channels from '../protocol/channels';
|
||||
import { ElementHandle } from './elementHandle';
|
||||
import * as api from '../../types/types';
|
||||
|
||||
type SerializedAXNode = Omit<channels.AXNode, 'valueString' | 'valueNumber' | 'children' | 'checked' | 'pressed'> & {
|
||||
value?: string|number,
|
||||
|
|
@ -38,7 +39,7 @@ function axNodeFromProtocol(axNode: channels.AXNode): SerializedAXNode {
|
|||
return result;
|
||||
}
|
||||
|
||||
export class Accessibility {
|
||||
export class Accessibility implements api.Accessibility {
|
||||
private _channel: channels.PageChannel;
|
||||
|
||||
constructor(channel: channels.PageChannel) {
|
||||
|
|
|
|||
|
|
@ -21,8 +21,9 @@ import { ChannelOwner } from './channelOwner';
|
|||
import { Events } from './events';
|
||||
import { BrowserContextOptions } from './types';
|
||||
import { isSafeCloseError } from '../utils/errors';
|
||||
import * as api from '../../types/types';
|
||||
|
||||
export class Browser extends ChannelOwner<channels.BrowserChannel, channels.BrowserInitializer> {
|
||||
export class Browser extends ChannelOwner<channels.BrowserChannel, channels.BrowserInitializer> implements api.Browser {
|
||||
readonly _contexts = new Set<BrowserContext>();
|
||||
private _isConnected = true;
|
||||
private _closedPromise: Promise<void>;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Page, BindingCall, FunctionWithSource } from './page';
|
||||
import { Page, BindingCall } from './page';
|
||||
import * as network from './network';
|
||||
import * as channels from '../protocol/channels';
|
||||
import * as util from 'util';
|
||||
|
|
@ -30,16 +30,18 @@ import { URLMatch, Headers, WaitForEventOptions, BrowserContextOptions, StorageS
|
|||
import { isUnderTest, headersObjectToArray, mkdirIfNeeded } from '../utils/utils';
|
||||
import { isSafeCloseError } from '../utils/errors';
|
||||
import { serializeArgument } from './jsHandle';
|
||||
import * as api from '../../types/types';
|
||||
import * as structs from '../../types/structs';
|
||||
|
||||
const fsWriteFileAsync = util.promisify(fs.writeFile.bind(fs));
|
||||
const fsReadFileAsync = util.promisify(fs.readFile.bind(fs));
|
||||
|
||||
export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel, channels.BrowserContextInitializer> {
|
||||
export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel, channels.BrowserContextInitializer> implements api.BrowserContext {
|
||||
_pages = new Set<Page>();
|
||||
private _routes: { url: URLMatch, handler: network.RouteHandler }[] = [];
|
||||
readonly _browser: Browser | null = null;
|
||||
readonly _browserName: string;
|
||||
readonly _bindings = new Map<string, FunctionWithSource>();
|
||||
readonly _bindings = new Map<string, (source: structs.BindingSource, ...args: any[]) => any>();
|
||||
_timeoutSettings = new TimeoutSettings();
|
||||
_ownerPage: Page | undefined;
|
||||
private _closedPromise: Promise<void>;
|
||||
|
|
@ -182,7 +184,7 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel,
|
|||
});
|
||||
}
|
||||
|
||||
async exposeBinding(name: string, playwrightBinding: FunctionWithSource, options: { handle?: boolean } = {}): Promise<void> {
|
||||
async exposeBinding(name: string, playwrightBinding: (source: structs.BindingSource, ...args: any[]) => any, options: { handle?: boolean } = {}): Promise<void> {
|
||||
return this._wrapApiCall('browserContext.exposeBinding', async () => {
|
||||
await this._channel.exposeBinding({ name, needsHandle: options.handle });
|
||||
this._bindings.set(name, playwrightBinding);
|
||||
|
|
@ -192,7 +194,7 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel,
|
|||
async exposeFunction(name: string, playwrightFunction: Function): Promise<void> {
|
||||
return this._wrapApiCall('browserContext.exposeFunction', async () => {
|
||||
await this._channel.exposeBinding({ name });
|
||||
const binding: FunctionWithSource = (source, ...args) => playwrightFunction(...args);
|
||||
const binding = (source: structs.BindingSource, ...args: any[]) => playwrightFunction(...args);
|
||||
this._bindings.set(name, binding);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,19 +32,21 @@ import { assert, makeWaitForNextTask, mkdirIfNeeded } from '../utils/utils';
|
|||
import { SelectorsOwner, sharedSelectors } from './selectors';
|
||||
import { kBrowserClosedError } from '../utils/errors';
|
||||
import { Stream } from './stream';
|
||||
import * as api from '../../types/types';
|
||||
|
||||
export interface BrowserServerLauncher {
|
||||
launchServer(options?: LaunchServerOptions): Promise<BrowserServer>;
|
||||
launchServer(options?: LaunchServerOptions): Promise<api.BrowserServer>;
|
||||
}
|
||||
|
||||
export interface BrowserServer {
|
||||
// This is here just for api generation and checking.
|
||||
export interface BrowserServer extends api.BrowserServer {
|
||||
process(): ChildProcess;
|
||||
wsEndpoint(): string;
|
||||
close(): Promise<void>;
|
||||
kill(): Promise<void>;
|
||||
}
|
||||
|
||||
export class BrowserType extends ChannelOwner<channels.BrowserTypeChannel, channels.BrowserTypeInitializer> {
|
||||
export class BrowserType extends ChannelOwner<channels.BrowserTypeChannel, channels.BrowserTypeInitializer> implements api.BrowserType<api.Browser> {
|
||||
private _timeoutSettings = new TimeoutSettings();
|
||||
_serverLauncher?: BrowserServerLauncher;
|
||||
|
||||
|
|
@ -83,7 +85,7 @@ export class BrowserType extends ChannelOwner<channels.BrowserTypeChannel, chann
|
|||
}, logger);
|
||||
}
|
||||
|
||||
async launchServer(options: LaunchServerOptions = {}): Promise<BrowserServer> {
|
||||
async launchServer(options: LaunchServerOptions = {}): Promise<api.BrowserServer> {
|
||||
if (!this._serverLauncher)
|
||||
throw new Error('Launching server is not supported');
|
||||
return this._serverLauncher.launchServer(options);
|
||||
|
|
|
|||
|
|
@ -17,8 +17,9 @@
|
|||
import * as channels from '../protocol/channels';
|
||||
import { ChannelOwner } from './channelOwner';
|
||||
import { Protocol } from '../server/chromium/protocol';
|
||||
import * as api from '../../types/types';
|
||||
|
||||
export class CDPSession extends ChannelOwner<channels.CDPSessionChannel, channels.CDPSessionInitializer> {
|
||||
export class CDPSession extends ChannelOwner<channels.CDPSessionChannel, channels.CDPSessionInitializer> implements api.CDPSession {
|
||||
static from(cdpSession: channels.CDPSessionChannel): CDPSession {
|
||||
return (cdpSession as any)._object;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,8 +17,19 @@
|
|||
import { Page } from './page';
|
||||
import { CDPSession } from './cdpSession';
|
||||
import { Browser } from './browser';
|
||||
import * as api from '../../types/types';
|
||||
import { ChromiumBrowserContext } from './chromiumBrowserContext';
|
||||
import { BrowserContextOptions } from './types';
|
||||
|
||||
export class ChromiumBrowser extends Browser implements api.ChromiumBrowser {
|
||||
contexts(): ChromiumBrowserContext[] {
|
||||
return super.contexts() as ChromiumBrowserContext[];
|
||||
}
|
||||
|
||||
newContext(options?: BrowserContextOptions): Promise<ChromiumBrowserContext> {
|
||||
return super.newContext(options) as Promise<ChromiumBrowserContext>;
|
||||
}
|
||||
|
||||
export class ChromiumBrowser extends Browser {
|
||||
async newBrowserCDPSession(): Promise<CDPSession> {
|
||||
return this._wrapApiCall('chromiumBrowser.newBrowserCDPSession', async () => {
|
||||
return CDPSession.from((await this._channel.crNewBrowserCDPSession()).session);
|
||||
|
|
|
|||
|
|
@ -22,8 +22,9 @@ import { CDPSession } from './cdpSession';
|
|||
import { Events } from './events';
|
||||
import { Worker } from './worker';
|
||||
import { BrowserContext } from './browserContext';
|
||||
import * as api from '../../types/types';
|
||||
|
||||
export class ChromiumBrowserContext extends BrowserContext {
|
||||
export class ChromiumBrowserContext extends BrowserContext implements api.ChromiumBrowserContext {
|
||||
_backgroundPages = new Set<Page>();
|
||||
_serviceWorkers = new Set<Worker>();
|
||||
|
||||
|
|
|
|||
|
|
@ -15,8 +15,9 @@
|
|||
*/
|
||||
|
||||
import * as channels from '../protocol/channels';
|
||||
import * as api from '../../types/types';
|
||||
|
||||
export class ChromiumCoverage {
|
||||
export class ChromiumCoverage implements api.ChromiumCoverage {
|
||||
private _channel: channels.PageChannel;
|
||||
|
||||
constructor(channel: channels.PageChannel) {
|
||||
|
|
|
|||
|
|
@ -18,10 +18,11 @@ import * as util from 'util';
|
|||
import { JSHandle } from './jsHandle';
|
||||
import * as channels from '../protocol/channels';
|
||||
import { ChannelOwner } from './channelOwner';
|
||||
import * as api from '../../types/types';
|
||||
|
||||
type ConsoleMessageLocation = channels.ConsoleMessageInitializer['location'];
|
||||
|
||||
export class ConsoleMessage extends ChannelOwner<channels.ConsoleMessageChannel, channels.ConsoleMessageInitializer> {
|
||||
export class ConsoleMessage extends ChannelOwner<channels.ConsoleMessageChannel, channels.ConsoleMessageInitializer> implements api.ConsoleMessage {
|
||||
static from(message: channels.ConsoleMessageChannel): ConsoleMessage {
|
||||
return (message as any)._object;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,8 +16,9 @@
|
|||
|
||||
import * as channels from '../protocol/channels';
|
||||
import { ChannelOwner } from './channelOwner';
|
||||
import * as api from '../../types/types';
|
||||
|
||||
export class Dialog extends ChannelOwner<channels.DialogChannel, channels.DialogInitializer> {
|
||||
export class Dialog extends ChannelOwner<channels.DialogChannel, channels.DialogInitializer> implements api.Dialog {
|
||||
static from(dialog: channels.DialogChannel): Dialog {
|
||||
return (dialog as any)._object;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,8 +22,9 @@ import { Browser } from './browser';
|
|||
import { BrowserContext } from './browserContext';
|
||||
import * as fs from 'fs';
|
||||
import { mkdirIfNeeded } from '../utils/utils';
|
||||
import * as api from '../../types/types';
|
||||
|
||||
export class Download extends ChannelOwner<channels.DownloadChannel, channels.DownloadInitializer> {
|
||||
export class Download extends ChannelOwner<channels.DownloadChannel, channels.DownloadInitializer> implements api.Download {
|
||||
private _browser: Browser | null;
|
||||
|
||||
static from(download: channels.DownloadChannel): Download {
|
||||
|
|
|
|||
|
|
@ -18,12 +18,13 @@ import * as channels from '../protocol/channels';
|
|||
import { BrowserContext } from './browserContext';
|
||||
import { ChannelOwner } from './channelOwner';
|
||||
import { Page } from './page';
|
||||
import { serializeArgument, FuncOn, parseResult, SmartHandle, JSHandle } from './jsHandle';
|
||||
import { serializeArgument, parseResult, JSHandle } from './jsHandle';
|
||||
import { TimeoutSettings } from '../utils/timeoutSettings';
|
||||
import { Waiter } from './waiter';
|
||||
import { Events } from './events';
|
||||
import { WaitForEventOptions, Env, Logger } from './types';
|
||||
import { envObjectToArray } from './clientHelper';
|
||||
import * as structs from '../../types/structs';
|
||||
|
||||
type ElectronOptions = Omit<channels.ElectronLaunchOptions, 'env'> & {
|
||||
env?: Env,
|
||||
|
|
@ -110,17 +111,13 @@ export class ElectronApplication extends ChannelOwner<channels.ElectronApplicati
|
|||
return result;
|
||||
}
|
||||
|
||||
async evaluate<R, Arg>(pageFunction: FuncOn<any, Arg, R>, arg: Arg): Promise<R>;
|
||||
async evaluate<R>(pageFunction: FuncOn<any, void, R>, arg?: any): Promise<R>;
|
||||
async evaluate<R, Arg>(pageFunction: FuncOn<any, Arg, R>, arg: Arg): Promise<R> {
|
||||
async evaluate<R, Arg>(pageFunction: structs.PageFunctionOn<any, Arg, R>, arg: Arg): Promise<R> {
|
||||
const result = await this._channel.evaluateExpression({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) });
|
||||
return parseResult(result.value);
|
||||
}
|
||||
|
||||
async evaluateHandle<R, Arg>(pageFunction: FuncOn<any, Arg, R>, arg: Arg): Promise<SmartHandle<R>>;
|
||||
async evaluateHandle<R>(pageFunction: FuncOn<any, void, R>, arg?: any): Promise<SmartHandle<R>>;
|
||||
async evaluateHandle<R, Arg>(pageFunction: FuncOn<any, Arg, R>, arg: Arg): Promise<SmartHandle<R>> {
|
||||
async evaluateHandle<R, Arg>(pageFunction: structs.PageFunctionOn<any, Arg, R>, arg: Arg): Promise<structs.SmartHandle<R>> {
|
||||
const result = await this._channel.evaluateExpressionHandle({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) });
|
||||
return JSHandle.from(result.handle) as SmartHandle<R>;
|
||||
return JSHandle.from(result.handle) as any as structs.SmartHandle<R>;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
import * as channels from '../protocol/channels';
|
||||
import { Frame } from './frame';
|
||||
import { FuncOn, JSHandle, serializeArgument, parseResult } from './jsHandle';
|
||||
import { JSHandle, serializeArgument, parseResult } from './jsHandle';
|
||||
import { ChannelOwner } from './channelOwner';
|
||||
import { SelectOption, FilePayload, Rect, SelectOptionOptions } from './types';
|
||||
import * as fs from 'fs';
|
||||
|
|
@ -24,10 +24,12 @@ import * as mime from 'mime';
|
|||
import * as path from 'path';
|
||||
import * as util from 'util';
|
||||
import { assert, isString, mkdirIfNeeded } from '../utils/utils';
|
||||
import * as api from '../../types/types';
|
||||
import * as structs from '../../types/structs';
|
||||
|
||||
const fsWriteFileAsync = util.promisify(fs.writeFile.bind(fs));
|
||||
|
||||
export class ElementHandle<T extends Node = Node> extends JSHandle<T> {
|
||||
export class ElementHandle<T extends Node = Node> extends JSHandle<T> implements api.ElementHandle {
|
||||
readonly _elementChannel: channels.ElementHandleChannel;
|
||||
|
||||
static from(handle: channels.ElementHandleChannel): ElementHandle {
|
||||
|
|
@ -43,8 +45,8 @@ export class ElementHandle<T extends Node = Node> extends JSHandle<T> {
|
|||
this._elementChannel = this._channel as channels.ElementHandleChannel;
|
||||
}
|
||||
|
||||
asElement(): ElementHandle<T> | null {
|
||||
return this;
|
||||
asElement(): T extends Node ? ElementHandle<T> : null {
|
||||
return this as any;
|
||||
}
|
||||
|
||||
async ownerFrame(): Promise<Frame | null> {
|
||||
|
|
@ -121,7 +123,7 @@ export class ElementHandle<T extends Node = Node> extends JSHandle<T> {
|
|||
});
|
||||
}
|
||||
|
||||
async selectOption(values: string | ElementHandle | SelectOption | string[] | ElementHandle[] | SelectOption[] | null, options: SelectOptionOptions = {}): Promise<string[]> {
|
||||
async selectOption(values: string | api.ElementHandle | SelectOption | string[] | api.ElementHandle[] | SelectOption[] | null, options: SelectOptionOptions = {}): Promise<string[]> {
|
||||
return this._wrapApiCall('elementHandle.selectOption', async () => {
|
||||
const result = await this._elementChannel.selectOption({ ...convertSelectOptionValues(values), ...options });
|
||||
return result.values;
|
||||
|
|
@ -198,31 +200,27 @@ export class ElementHandle<T extends Node = Node> extends JSHandle<T> {
|
|||
});
|
||||
}
|
||||
|
||||
async $(selector: string): Promise<ElementHandle<Element> | null> {
|
||||
async $(selector: string): Promise<ElementHandle<SVGElement | HTMLElement> | null> {
|
||||
return this._wrapApiCall('elementHandle.$', async () => {
|
||||
return ElementHandle.fromNullable((await this._elementChannel.querySelector({ selector })).element) as ElementHandle<Element> | null;
|
||||
return ElementHandle.fromNullable((await this._elementChannel.querySelector({ selector })).element) as ElementHandle<SVGElement | HTMLElement> | null;
|
||||
});
|
||||
}
|
||||
|
||||
async $$(selector: string): Promise<ElementHandle<Element>[]> {
|
||||
async $$(selector: string): Promise<ElementHandle<SVGElement | HTMLElement>[]> {
|
||||
return this._wrapApiCall('elementHandle.$$', async () => {
|
||||
const result = await this._elementChannel.querySelectorAll({ selector });
|
||||
return result.elements.map(h => ElementHandle.from(h) as ElementHandle<Element>);
|
||||
return result.elements.map(h => ElementHandle.from(h) as ElementHandle<SVGElement | HTMLElement>);
|
||||
});
|
||||
}
|
||||
|
||||
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> {
|
||||
async $eval<R, Arg>(selector: string, pageFunction: structs.PageFunctionOn<Element, Arg, R>, arg?: Arg): Promise<R> {
|
||||
return this._wrapApiCall('elementHandle.$eval', async () => {
|
||||
const result = await this._elementChannel.evalOnSelector({ selector, expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) });
|
||||
return parseResult(result.value);
|
||||
});
|
||||
}
|
||||
|
||||
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> {
|
||||
async $$eval<R, Arg>(selector: string, pageFunction: structs.PageFunctionOn<Element[], Arg, R>, arg?: Arg): Promise<R> {
|
||||
return this._wrapApiCall('elementHandle.$$eval', async () => {
|
||||
const result = await this._elementChannel.evalOnSelectorAll({ selector, expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) });
|
||||
return parseResult(result.value);
|
||||
|
|
@ -235,15 +233,17 @@ export class ElementHandle<T extends Node = Node> extends JSHandle<T> {
|
|||
});
|
||||
}
|
||||
|
||||
async waitForSelector(selector: string, options: channels.ElementHandleWaitForSelectorOptions = {}): Promise<ElementHandle<Element> | null> {
|
||||
waitForSelector(selector: string, options: channels.ElementHandleWaitForSelectorOptions & { state: 'attached' | 'visible' }): Promise<ElementHandle<SVGElement | HTMLElement>>;
|
||||
waitForSelector(selector: string, options?: channels.ElementHandleWaitForSelectorOptions): Promise<ElementHandle<SVGElement | HTMLElement> | null>;
|
||||
async waitForSelector(selector: string, options: channels.ElementHandleWaitForSelectorOptions = {}): Promise<ElementHandle<SVGElement | HTMLElement> | null> {
|
||||
return this._wrapApiCall('elementHandle.waitForSelector', async () => {
|
||||
const result = await this._elementChannel.waitForSelector({ selector, ...options });
|
||||
return ElementHandle.fromNullable(result.element) as ElementHandle<Element> | null;
|
||||
return ElementHandle.fromNullable(result.element) as ElementHandle<SVGElement | HTMLElement> | null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function convertSelectOptionValues(values: string | ElementHandle | SelectOption | string[] | ElementHandle[] | SelectOption[] | null): { elements?: channels.ElementHandleChannel[], options?: SelectOption[] } {
|
||||
export function convertSelectOptionValues(values: string | api.ElementHandle | SelectOption | string[] | api.ElementHandle[] | SelectOption[] | null): { elements?: channels.ElementHandleChannel[], options?: SelectOption[] } {
|
||||
if (values === null)
|
||||
return {};
|
||||
if (!Array.isArray(values))
|
||||
|
|
|
|||
|
|
@ -18,8 +18,9 @@ import { ElementHandle } from './elementHandle';
|
|||
import { Page } from './page';
|
||||
import { FilePayload } from './types';
|
||||
import * as channels from '../protocol/channels';
|
||||
import * as api from '../../types/types';
|
||||
|
||||
export class FileChooser {
|
||||
export class FileChooser implements api.FileChooser {
|
||||
private _page: Page;
|
||||
private _elementHandle: ElementHandle<Node>;
|
||||
private _isMultiple: boolean;
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
|
||||
import { Browser } from './browser';
|
||||
import * as api from '../../types/types';
|
||||
|
||||
export class FirefoxBrowser extends Browser {
|
||||
export class FirefoxBrowser extends Browser implements api.FirefoxBrowser {
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import { assert } from '../utils/utils';
|
|||
import * as channels from '../protocol/channels';
|
||||
import { ChannelOwner } from './channelOwner';
|
||||
import { ElementHandle, convertSelectOptionValues, convertInputFiles } from './elementHandle';
|
||||
import { assertMaxArguments, JSHandle, Func1, FuncOn, SmartHandle, serializeArgument, parseResult } from './jsHandle';
|
||||
import { assertMaxArguments, JSHandle, serializeArgument, parseResult } from './jsHandle';
|
||||
import * as fs from 'fs';
|
||||
import * as network from './network';
|
||||
import * as util from 'util';
|
||||
|
|
@ -29,6 +29,8 @@ import { Waiter } from './waiter';
|
|||
import { Events } from './events';
|
||||
import { LifecycleEvent, URLMatch, SelectOption, SelectOptionOptions, FilePayload, WaitForFunctionOptions, kLifecycleEvents } from './types';
|
||||
import { urlMatches } from './clientHelper';
|
||||
import * as api from '../../types/types';
|
||||
import * as structs from '../../types/structs';
|
||||
|
||||
const fsReadFileAsync = util.promisify(fs.readFile.bind(fs));
|
||||
|
||||
|
|
@ -38,7 +40,7 @@ export type WaitForNavigationOptions = {
|
|||
url?: URLMatch,
|
||||
};
|
||||
|
||||
export class Frame extends ChannelOwner<channels.FrameChannel, channels.FrameInitializer> {
|
||||
export class Frame extends ChannelOwner<channels.FrameChannel, channels.FrameInitializer> implements api.Frame {
|
||||
_eventEmitter: EventEmitter;
|
||||
_loadStates: Set<LifecycleEvent>;
|
||||
_parentFrame: Frame | null = null;
|
||||
|
|
@ -164,29 +166,25 @@ export class Frame extends ChannelOwner<channels.FrameChannel, channels.FrameIni
|
|||
});
|
||||
}
|
||||
|
||||
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>> {
|
||||
async evaluateHandle<R, Arg>(pageFunction: structs.PageFunction<Arg, R>, arg?: Arg): Promise<structs.SmartHandle<R>> {
|
||||
assertMaxArguments(arguments.length, 2);
|
||||
return this._wrapApiCall(this._apiName('evaluateHandle'), async () => {
|
||||
const result = await this._channel.evaluateExpressionHandle({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) });
|
||||
return JSHandle.from(result.handle) as SmartHandle<R>;
|
||||
return JSHandle.from(result.handle) as any as structs.SmartHandle<R>;
|
||||
});
|
||||
}
|
||||
|
||||
async _evaluateHandleInUtility<R, Arg>(pageFunction: Func1<Arg, R>, arg: Arg): Promise<SmartHandle<R>>;
|
||||
async _evaluateHandleInUtility<R>(pageFunction: Func1<void, R>, arg?: any): Promise<SmartHandle<R>>;
|
||||
async _evaluateHandleInUtility<R, Arg>(pageFunction: Func1<Arg, R>, arg: Arg): Promise<SmartHandle<R>> {
|
||||
async _evaluateHandleInUtility<R, Arg>(pageFunction: structs.PageFunction<Arg, R>, arg: Arg): Promise<structs.SmartHandle<R>>;
|
||||
async _evaluateHandleInUtility<R>(pageFunction: structs.PageFunction<void, R>, arg?: any): Promise<structs.SmartHandle<R>>;
|
||||
async _evaluateHandleInUtility<R, Arg>(pageFunction: structs.PageFunction<Arg, R>, arg?: Arg): Promise<structs.SmartHandle<R>> {
|
||||
assertMaxArguments(arguments.length, 2);
|
||||
return this._wrapApiCall(this._apiName('_evaluateHandleInUtility'), async () => {
|
||||
const result = await this._channel.evaluateExpressionHandle({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg), world: 'utility' });
|
||||
return JSHandle.from(result.handle) as SmartHandle<R>;
|
||||
return JSHandle.from(result.handle) as any as structs.SmartHandle<R>;
|
||||
});
|
||||
}
|
||||
|
||||
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> {
|
||||
async evaluate<R, Arg>(pageFunction: structs.PageFunction<Arg, R>, arg?: Arg): Promise<R> {
|
||||
assertMaxArguments(arguments.length, 2);
|
||||
return this._wrapApiCall(this._apiName('evaluate'), async () => {
|
||||
const result = await this._channel.evaluateExpression({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) });
|
||||
|
|
@ -194,9 +192,9 @@ export class Frame extends ChannelOwner<channels.FrameChannel, channels.FrameIni
|
|||
});
|
||||
}
|
||||
|
||||
async _evaluateInUtility<R, Arg>(pageFunction: Func1<Arg, R>, arg: Arg): Promise<R>;
|
||||
async _evaluateInUtility<R>(pageFunction: Func1<void, R>, arg?: any): Promise<R>;
|
||||
async _evaluateInUtility<R, Arg>(pageFunction: Func1<Arg, R>, arg: Arg): Promise<R> {
|
||||
async _evaluateInUtility<R, Arg>(pageFunction: structs.PageFunction<Arg, R>, arg: Arg): Promise<R>;
|
||||
async _evaluateInUtility<R>(pageFunction: structs.PageFunction<void, R>, arg?: any): Promise<R>;
|
||||
async _evaluateInUtility<R, Arg>(pageFunction: structs.PageFunction<Arg, R>, arg?: Arg): Promise<R> {
|
||||
assertMaxArguments(arguments.length, 2);
|
||||
return this._wrapApiCall(this._apiName('evaluate'), async () => {
|
||||
const result = await this._channel.evaluateExpression({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg), world: 'utility' });
|
||||
|
|
@ -204,21 +202,23 @@ export class Frame extends ChannelOwner<channels.FrameChannel, channels.FrameIni
|
|||
});
|
||||
}
|
||||
|
||||
async $(selector: string): Promise<ElementHandle<Element> | null> {
|
||||
async $(selector: string): Promise<ElementHandle<SVGElement | HTMLElement> | null> {
|
||||
return this._wrapApiCall(this._apiName('$'), async () => {
|
||||
const result = await this._channel.querySelector({ selector });
|
||||
return ElementHandle.fromNullable(result.element) as ElementHandle<Element> | null;
|
||||
return ElementHandle.fromNullable(result.element) as ElementHandle<SVGElement | HTMLElement> | null;
|
||||
});
|
||||
}
|
||||
|
||||
async waitForSelector(selector: string, options: channels.FrameWaitForSelectorOptions = {}): Promise<ElementHandle<Element> | null> {
|
||||
waitForSelector(selector: string, options: channels.FrameWaitForSelectorOptions & { state: 'attached' | 'visible' }): Promise<ElementHandle<SVGElement | HTMLElement>>;
|
||||
waitForSelector(selector: string, options?: channels.FrameWaitForSelectorOptions): Promise<ElementHandle<SVGElement | HTMLElement> | null>;
|
||||
async waitForSelector(selector: string, options: channels.FrameWaitForSelectorOptions = {}): Promise<ElementHandle<SVGElement | HTMLElement> | 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?');
|
||||
if ((options as any).waitFor && (options as any).waitFor !== 'visible')
|
||||
throw new Error('options.waitFor is not supported, did you mean options.state?');
|
||||
const result = await this._channel.waitForSelector({ selector, ...options });
|
||||
return ElementHandle.fromNullable(result.element) as ElementHandle<Element> | null;
|
||||
return ElementHandle.fromNullable(result.element) as ElementHandle<SVGElement | HTMLElement> | null;
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -228,9 +228,7 @@ export class Frame extends ChannelOwner<channels.FrameChannel, channels.FrameIni
|
|||
});
|
||||
}
|
||||
|
||||
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> {
|
||||
async $eval<R, Arg>(selector: string, pageFunction: structs.PageFunctionOn<Element, Arg, R>, arg?: Arg): Promise<R> {
|
||||
assertMaxArguments(arguments.length, 3);
|
||||
return this._wrapApiCall(this._apiName('$eval'), async () => {
|
||||
const result = await this._channel.evalOnSelector({ selector, expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) });
|
||||
|
|
@ -238,9 +236,7 @@ export class Frame extends ChannelOwner<channels.FrameChannel, channels.FrameIni
|
|||
});
|
||||
}
|
||||
|
||||
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> {
|
||||
async $$eval<R, Arg>(selector: string, pageFunction: structs.PageFunctionOn<Element[], Arg, R>, arg?: Arg): Promise<R> {
|
||||
assertMaxArguments(arguments.length, 3);
|
||||
return this._wrapApiCall(this._apiName('$$eval'), async () => {
|
||||
const result = await this._channel.evalOnSelectorAll({ selector, expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) });
|
||||
|
|
@ -248,10 +244,10 @@ export class Frame extends ChannelOwner<channels.FrameChannel, channels.FrameIni
|
|||
});
|
||||
}
|
||||
|
||||
async $$(selector: string): Promise<ElementHandle<Element>[]> {
|
||||
async $$(selector: string): Promise<ElementHandle<SVGElement | HTMLElement>[]> {
|
||||
return this._wrapApiCall(this._apiName('$$'), async () => {
|
||||
const result = await this._channel.querySelectorAll({ selector });
|
||||
return result.elements.map(e => ElementHandle.from(e) as ElementHandle<Element>);
|
||||
return result.elements.map(e => ElementHandle.from(e) as ElementHandle<SVGElement | HTMLElement>);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -372,7 +368,7 @@ export class Frame extends ChannelOwner<channels.FrameChannel, channels.FrameIni
|
|||
});
|
||||
}
|
||||
|
||||
async selectOption(selector: string, values: string | ElementHandle | SelectOption | string[] | ElementHandle[] | SelectOption[] | null, options: SelectOptionOptions = {}): Promise<string[]> {
|
||||
async selectOption(selector: string, values: string | api.ElementHandle | SelectOption | string[] | api.ElementHandle[] | SelectOption[] | null, options: SelectOptionOptions = {}): Promise<string[]> {
|
||||
return this._wrapApiCall(this._apiName('selectOption'), async () => {
|
||||
return (await this._channel.selectOption({ selector, ...convertSelectOptionValues(values), ...options })).values;
|
||||
});
|
||||
|
|
@ -412,9 +408,7 @@ export class Frame extends ChannelOwner<channels.FrameChannel, channels.FrameIni
|
|||
await new Promise(fulfill => setTimeout(fulfill, timeout));
|
||||
}
|
||||
|
||||
async waitForFunction<R, Arg>(pageFunction: Func1<Arg, R>, arg: Arg, options?: WaitForFunctionOptions): Promise<SmartHandle<R>>;
|
||||
async waitForFunction<R>(pageFunction: Func1<void, R>, arg?: any, options?: WaitForFunctionOptions): Promise<SmartHandle<R>>;
|
||||
async waitForFunction<R, Arg>(pageFunction: Func1<Arg, R>, arg: Arg, options: WaitForFunctionOptions = {}): Promise<SmartHandle<R>> {
|
||||
async waitForFunction<R, Arg>(pageFunction: structs.PageFunction<Arg, R>, arg?: Arg, options: WaitForFunctionOptions = {}): Promise<structs.SmartHandle<R>> {
|
||||
return this._wrapApiCall(this._apiName('waitForFunction'), async () => {
|
||||
if (typeof options.polling === 'string')
|
||||
assert(options.polling === 'raf', 'Unknown polling option: ' + options.polling);
|
||||
|
|
@ -425,7 +419,7 @@ export class Frame extends ChannelOwner<channels.FrameChannel, channels.FrameIni
|
|||
isFunction: typeof pageFunction === 'function',
|
||||
arg: serializeArgument(arg),
|
||||
});
|
||||
return JSHandle.from(result.handle) as SmartHandle<R>;
|
||||
return JSHandle.from(result.handle) as any as structs.SmartHandle<R>;
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,8 +16,9 @@
|
|||
*/
|
||||
|
||||
import * as channels from '../protocol/channels';
|
||||
import * as api from '../../types/types';
|
||||
|
||||
export class Keyboard {
|
||||
export class Keyboard implements api.Keyboard {
|
||||
private _channel: channels.PageChannel;
|
||||
|
||||
constructor(channel: channels.PageChannel) {
|
||||
|
|
@ -45,7 +46,7 @@ export class Keyboard {
|
|||
}
|
||||
}
|
||||
|
||||
export class Mouse {
|
||||
export class Mouse implements api.Mouse {
|
||||
private _channel: channels.PageChannel;
|
||||
|
||||
constructor(channel: channels.PageChannel) {
|
||||
|
|
@ -73,7 +74,7 @@ export class Mouse {
|
|||
}
|
||||
}
|
||||
|
||||
export class Touchscreen {
|
||||
export class Touchscreen implements api.Touchscreen {
|
||||
private _channel: channels.PageChannel;
|
||||
|
||||
constructor(channel: channels.PageChannel) {
|
||||
|
|
|
|||
|
|
@ -15,27 +15,12 @@
|
|||
*/
|
||||
|
||||
import * as channels from '../protocol/channels';
|
||||
import { ElementHandle } from './elementHandle';
|
||||
import { ChannelOwner } from './channelOwner';
|
||||
import { parseSerializedValue, serializeValue } from '../protocol/serializers';
|
||||
import * as api from '../../types/types';
|
||||
import * as structs from '../../types/structs';
|
||||
|
||||
type NoHandles<Arg> = Arg extends JSHandle ? never : (Arg extends object ? { [Key in keyof Arg]: NoHandles<Arg[Key]> } : Arg);
|
||||
type Unboxed<Arg> =
|
||||
Arg extends ElementHandle<infer T> ? T :
|
||||
Arg extends JSHandle<infer T> ? T :
|
||||
Arg extends NoHandles<Arg> ? Arg :
|
||||
Arg extends [infer A0] ? [Unboxed<A0>] :
|
||||
Arg extends [infer A0, infer A1] ? [Unboxed<A0>, Unboxed<A1>] :
|
||||
Arg extends [infer A0, infer A1, infer A2] ? [Unboxed<A0>, Unboxed<A1>, Unboxed<A2>] :
|
||||
Arg extends Array<infer T> ? Array<Unboxed<T>> :
|
||||
Arg extends object ? { [Key in keyof Arg]: Unboxed<Arg[Key]> } :
|
||||
Arg;
|
||||
export type Func0<R> = string | (() => R | Promise<R>);
|
||||
export type Func1<Arg, R> = string | ((arg: Unboxed<Arg>) => R | Promise<R>);
|
||||
export type FuncOn<On, Arg2, R> = string | ((on: On, arg2: Unboxed<Arg2>) => R | Promise<R>);
|
||||
export type SmartHandle<T> = T extends Node ? ElementHandle<T> : JSHandle<T>;
|
||||
|
||||
export class JSHandle<T = any> extends ChannelOwner<channels.JSHandleChannel, channels.JSHandleInitializer> {
|
||||
export class JSHandle<T = any> extends ChannelOwner<channels.JSHandleChannel, channels.JSHandleInitializer> implements api.JSHandle {
|
||||
private _preview: string;
|
||||
|
||||
static from(handle: channels.JSHandleChannel): JSHandle {
|
||||
|
|
@ -48,18 +33,14 @@ export class JSHandle<T = any> extends ChannelOwner<channels.JSHandleChannel, ch
|
|||
this._channel.on('previewUpdated', ({preview}) => this._preview = preview);
|
||||
}
|
||||
|
||||
async evaluate<R, Arg>(pageFunction: FuncOn<T, Arg, R>, arg: Arg): Promise<R>;
|
||||
async evaluate<R>(pageFunction: FuncOn<T, void, R>, arg?: any): Promise<R>;
|
||||
async evaluate<R, Arg>(pageFunction: FuncOn<T, Arg, R>, arg: Arg): Promise<R> {
|
||||
async evaluate<R, Arg>(pageFunction: structs.PageFunctionOn<T, Arg, R>, arg?: Arg): Promise<R> {
|
||||
const result = await this._channel.evaluateExpression({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) });
|
||||
return parseResult(result.value);
|
||||
}
|
||||
|
||||
async evaluateHandle<R, Arg>(pageFunction: FuncOn<T, Arg, R>, arg: Arg): Promise<SmartHandle<R>>;
|
||||
async evaluateHandle<R>(pageFunction: FuncOn<T, void, R>, arg?: any): Promise<SmartHandle<R>>;
|
||||
async evaluateHandle<R, Arg>(pageFunction: FuncOn<T, Arg, R>, arg: Arg): Promise<SmartHandle<R>> {
|
||||
async evaluateHandle<R, Arg>(pageFunction: structs.PageFunctionOn<T, Arg, R>, arg?: Arg): Promise<structs.SmartHandle<R>> {
|
||||
const result = await this._channel.evaluateExpressionHandle({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) });
|
||||
return JSHandle.from(result.handle) as SmartHandle<R>;
|
||||
return JSHandle.from(result.handle) as any as structs.SmartHandle<R>;
|
||||
}
|
||||
|
||||
async getProperty(propertyName: string): Promise<JSHandle> {
|
||||
|
|
@ -78,8 +59,8 @@ export class JSHandle<T = any> extends ChannelOwner<channels.JSHandleChannel, ch
|
|||
return parseResult((await this._channel.jsonValue()).value);
|
||||
}
|
||||
|
||||
asElement(): ElementHandle | null {
|
||||
return null;
|
||||
asElement(): T extends Node ? api.ElementHandle<T> : null {
|
||||
return null as any;
|
||||
}
|
||||
|
||||
async dispose() {
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import { isString, headersObjectToArray, headersArrayToObject } from '../utils/u
|
|||
import { Events } from './events';
|
||||
import { Page } from './page';
|
||||
import { Waiter } from './waiter';
|
||||
import * as api from '../../types/types';
|
||||
|
||||
export type NetworkCookie = {
|
||||
name: string,
|
||||
|
|
@ -50,7 +51,7 @@ export type SetNetworkCookieParam = {
|
|||
sameSite?: 'Strict' | 'Lax' | 'None'
|
||||
};
|
||||
|
||||
export class Request extends ChannelOwner<channels.RequestChannel, channels.RequestInitializer> {
|
||||
export class Request extends ChannelOwner<channels.RequestChannel, channels.RequestInitializer> implements api.Request {
|
||||
private _redirectedFrom: Request | null = null;
|
||||
private _redirectedTo: Request | null = null;
|
||||
_failureText: string | null = null;
|
||||
|
|
@ -167,7 +168,7 @@ export class Request extends ChannelOwner<channels.RequestChannel, channels.Requ
|
|||
}
|
||||
}
|
||||
|
||||
export class Route extends ChannelOwner<channels.RouteChannel, channels.RouteInitializer> {
|
||||
export class Route extends ChannelOwner<channels.RouteChannel, channels.RouteInitializer> implements api.Route {
|
||||
static from(route: channels.RouteChannel): Route {
|
||||
return (route as any)._object;
|
||||
}
|
||||
|
|
@ -246,7 +247,7 @@ export type ResourceTiming = {
|
|||
responseEnd: number;
|
||||
};
|
||||
|
||||
export class Response extends ChannelOwner<channels.ResponseChannel, channels.ResponseInitializer> {
|
||||
export class Response extends ChannelOwner<channels.ResponseChannel, channels.ResponseInitializer> implements api.Response {
|
||||
private _headers: Headers;
|
||||
private _request: Request;
|
||||
|
||||
|
|
@ -316,7 +317,7 @@ export class Response extends ChannelOwner<channels.ResponseChannel, channels.Re
|
|||
}
|
||||
}
|
||||
|
||||
export class WebSocket extends ChannelOwner<channels.WebSocketChannel, channels.WebSocketInitializer> {
|
||||
export class WebSocket extends ChannelOwner<channels.WebSocketChannel, channels.WebSocketInitializer> implements api.WebSocket {
|
||||
private _page: Page;
|
||||
private _isClosed: boolean;
|
||||
|
||||
|
|
|
|||
|
|
@ -30,13 +30,14 @@ import { ElementHandle, determineScreenshotType } from './elementHandle';
|
|||
import { Worker } from './worker';
|
||||
import { Frame, verifyLoadState, WaitForNavigationOptions } from './frame';
|
||||
import { Keyboard, Mouse, Touchscreen } from './input';
|
||||
import { assertMaxArguments, Func1, FuncOn, SmartHandle, serializeArgument, parseResult, JSHandle } from './jsHandle';
|
||||
import { assertMaxArguments, serializeArgument, parseResult, JSHandle } from './jsHandle';
|
||||
import { Request, Response, Route, RouteHandler, WebSocket, validateHeaders } from './network';
|
||||
import { FileChooser } from './fileChooser';
|
||||
import { Buffer } from 'buffer';
|
||||
import { ChromiumCoverage } from './chromiumCoverage';
|
||||
import { Waiter } from './waiter';
|
||||
|
||||
import * as api from '../../types/types';
|
||||
import * as structs from '../../types/structs';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as util from 'util';
|
||||
|
|
@ -61,9 +62,8 @@ type PDFOptions = Omit<channels.PagePdfParams, 'width' | 'height' | 'margin'> &
|
|||
path?: string,
|
||||
};
|
||||
type Listener = (...args: any[]) => void;
|
||||
export type FunctionWithSource = (source: { context: BrowserContext, page: Page, frame: Frame }, ...args: any) => any;
|
||||
|
||||
export class Page extends ChannelOwner<channels.PageChannel, channels.PageInitializer> {
|
||||
export class Page extends ChannelOwner<channels.PageChannel, channels.PageInitializer> implements api.Page {
|
||||
private _browserContext: BrowserContext;
|
||||
_ownedContext: BrowserContext | undefined;
|
||||
|
||||
|
|
@ -79,9 +79,9 @@ export class Page extends ChannelOwner<channels.PageChannel, channels.PageInitia
|
|||
readonly mouse: Mouse;
|
||||
readonly touchscreen: Touchscreen;
|
||||
coverage: ChromiumCoverage | null = null;
|
||||
pdf?: (options?: PDFOptions) => Promise<Buffer>;
|
||||
pdf: (options?: PDFOptions) => Promise<Buffer>;
|
||||
|
||||
readonly _bindings = new Map<string, FunctionWithSource>();
|
||||
readonly _bindings = new Map<string, (source: structs.BindingSource, ...args: any[]) => any>();
|
||||
readonly _timeoutSettings: TimeoutSettings;
|
||||
_isPageCall = false;
|
||||
private _video: Video | null = null;
|
||||
|
|
@ -136,6 +136,8 @@ export class Page extends ChannelOwner<channels.PageChannel, channels.PageInitia
|
|||
if (this._browserContext._browserName === 'chromium') {
|
||||
this.coverage = new ChromiumCoverage(this._channel);
|
||||
this.pdf = options => this._pdf(options);
|
||||
} else {
|
||||
this.pdf = undefined as any;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -261,11 +263,13 @@ export class Page extends ChannelOwner<channels.PageChannel, channels.PageInitia
|
|||
}
|
||||
}
|
||||
|
||||
async $(selector: string): Promise<ElementHandle<Element> | null> {
|
||||
async $(selector: string): Promise<ElementHandle<SVGElement | HTMLElement> | null> {
|
||||
return this._attributeToPage(() => this._mainFrame.$(selector));
|
||||
}
|
||||
|
||||
async waitForSelector(selector: string, options?: channels.FrameWaitForSelectorOptions): Promise<ElementHandle<Element> | null> {
|
||||
waitForSelector(selector: string, options: channels.FrameWaitForSelectorOptions & { state: 'attached' | 'visible' }): Promise<ElementHandle<SVGElement | HTMLElement>>;
|
||||
waitForSelector(selector: string, options?: channels.FrameWaitForSelectorOptions): Promise<ElementHandle<SVGElement | HTMLElement> | null>;
|
||||
async waitForSelector(selector: string, options?: channels.FrameWaitForSelectorOptions): Promise<ElementHandle<SVGElement | HTMLElement> | null> {
|
||||
return this._attributeToPage(() => this._mainFrame.waitForSelector(selector, options));
|
||||
}
|
||||
|
||||
|
|
@ -273,28 +277,22 @@ export class Page extends ChannelOwner<channels.PageChannel, channels.PageInitia
|
|||
return this._attributeToPage(() => this._mainFrame.dispatchEvent(selector, type, eventInit, options));
|
||||
}
|
||||
|
||||
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>> {
|
||||
async evaluateHandle<R, Arg>(pageFunction: structs.PageFunction<Arg, R>, arg?: Arg): Promise<structs.SmartHandle<R>> {
|
||||
assertMaxArguments(arguments.length, 2);
|
||||
return this._attributeToPage(() => this._mainFrame.evaluateHandle(pageFunction, arg));
|
||||
}
|
||||
|
||||
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> {
|
||||
async $eval<R, Arg>(selector: string, pageFunction: structs.PageFunctionOn<Element, Arg, R>, arg?: Arg): Promise<R> {
|
||||
assertMaxArguments(arguments.length, 3);
|
||||
return this._attributeToPage(() => this._mainFrame.$eval(selector, pageFunction, arg));
|
||||
}
|
||||
|
||||
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> {
|
||||
async $$eval<R, Arg>(selector: string, pageFunction: structs.PageFunctionOn<Element[], Arg, R>, arg?: Arg): Promise<R> {
|
||||
assertMaxArguments(arguments.length, 3);
|
||||
return this._attributeToPage(() => this._mainFrame.$$eval(selector, pageFunction, arg));
|
||||
}
|
||||
|
||||
async $$(selector: string): Promise<ElementHandle<Element>[]> {
|
||||
async $$(selector: string): Promise<ElementHandle<SVGElement | HTMLElement>[]> {
|
||||
return this._attributeToPage(() => this._mainFrame.$$(selector));
|
||||
}
|
||||
|
||||
|
|
@ -309,12 +307,12 @@ export class Page extends ChannelOwner<channels.PageChannel, channels.PageInitia
|
|||
async exposeFunction(name: string, playwrightFunction: Function) {
|
||||
return this._wrapApiCall('page.exposeFunction', async () => {
|
||||
await this._channel.exposeBinding({ name });
|
||||
const binding: FunctionWithSource = (source, ...args) => playwrightFunction(...args);
|
||||
const binding = (source: structs.BindingSource, ...args: any[]) => playwrightFunction(...args);
|
||||
this._bindings.set(name, binding);
|
||||
});
|
||||
}
|
||||
|
||||
async exposeBinding(name: string, playwrightBinding: FunctionWithSource, options: { handle?: boolean } = {}) {
|
||||
async exposeBinding(name: string, playwrightBinding: (source: structs.BindingSource, ...args: any[]) => any, options: { handle?: boolean } = {}) {
|
||||
return this._wrapApiCall('page.exposeBinding', async () => {
|
||||
await this._channel.exposeBinding({ name, needsHandle: options.handle });
|
||||
this._bindings.set(name, playwrightBinding);
|
||||
|
|
@ -425,9 +423,7 @@ export class Page extends ChannelOwner<channels.PageChannel, channels.PageInitia
|
|||
return this._viewportSize;
|
||||
}
|
||||
|
||||
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> {
|
||||
async evaluate<R, Arg>(pageFunction: structs.PageFunction<Arg, R>, arg?: Arg): Promise<R> {
|
||||
assertMaxArguments(arguments.length, 2);
|
||||
return this._attributeToPage(() => this._mainFrame.evaluate(pageFunction, arg));
|
||||
}
|
||||
|
|
@ -538,7 +534,7 @@ export class Page extends ChannelOwner<channels.PageChannel, channels.PageInitia
|
|||
return this._attributeToPage(() => this._mainFrame.hover(selector, options));
|
||||
}
|
||||
|
||||
async selectOption(selector: string, values: string | ElementHandle | SelectOption | string[] | ElementHandle[] | SelectOption[] | null, options?: SelectOptionOptions): Promise<string[]> {
|
||||
async selectOption(selector: string, values: string | api.ElementHandle | SelectOption | string[] | api.ElementHandle[] | SelectOption[] | null, options?: SelectOptionOptions): Promise<string[]> {
|
||||
return this._attributeToPage(() => this._mainFrame.selectOption(selector, values, options));
|
||||
}
|
||||
|
||||
|
|
@ -566,9 +562,7 @@ export class Page extends ChannelOwner<channels.PageChannel, channels.PageInitia
|
|||
await this._mainFrame.waitForTimeout(timeout);
|
||||
}
|
||||
|
||||
async waitForFunction<R, Arg>(pageFunction: Func1<Arg, R>, arg: Arg, options?: WaitForFunctionOptions): Promise<SmartHandle<R>>;
|
||||
async waitForFunction<R>(pageFunction: Func1<void, R>, arg?: any, options?: WaitForFunctionOptions): Promise<SmartHandle<R>>;
|
||||
async waitForFunction<R, Arg>(pageFunction: Func1<Arg, R>, arg: Arg, options?: WaitForFunctionOptions): Promise<SmartHandle<R>> {
|
||||
async waitForFunction<R, Arg>(pageFunction: structs.PageFunction<Arg, R>, arg?: Arg, options?: WaitForFunctionOptions): Promise<structs.SmartHandle<R>> {
|
||||
return this._attributeToPage(() => this._mainFrame.waitForFunction(pageFunction, arg, options));
|
||||
}
|
||||
|
||||
|
|
@ -636,7 +630,7 @@ export class BindingCall extends ChannelOwner<channels.BindingCallChannel, chann
|
|||
super(parent, type, guid, initializer);
|
||||
}
|
||||
|
||||
async call(func: FunctionWithSource) {
|
||||
async call(func: (source: structs.BindingSource, ...args: any[]) => any) {
|
||||
try {
|
||||
const frame = Frame.from(this._initializer.frame);
|
||||
const source = {
|
||||
|
|
|
|||
|
|
@ -18,8 +18,9 @@ import { evaluationScript } from './clientHelper';
|
|||
import * as channels from '../protocol/channels';
|
||||
import { ChannelOwner } from './channelOwner';
|
||||
import { SelectorEngine } from './types';
|
||||
import * as api from '../../types/types';
|
||||
|
||||
export class Selectors {
|
||||
export class Selectors implements api.Selectors {
|
||||
private _channels = new Set<SelectorsOwner>();
|
||||
private _registrations: channels.SelectorsRegisterParams[] = [];
|
||||
|
||||
|
|
|
|||
|
|
@ -16,8 +16,9 @@
|
|||
|
||||
import * as path from 'path';
|
||||
import { Page } from './page';
|
||||
import * as api from '../../types/types';
|
||||
|
||||
export class Video {
|
||||
export class Video implements api.Video {
|
||||
private _page: Page;
|
||||
private _pathCallback: ((path: string) => void) | undefined;
|
||||
private _pathPromise: Promise<string>;
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
|
||||
import { Browser } from './browser';
|
||||
import * as api from '../../types/types';
|
||||
|
||||
export class WebKitBrowser extends Browser {
|
||||
export class WebKitBrowser extends Browser implements api.WebKitBrowser {
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,12 +17,14 @@
|
|||
import { Events } from './events';
|
||||
import * as channels from '../protocol/channels';
|
||||
import { ChannelOwner } from './channelOwner';
|
||||
import { assertMaxArguments, Func1, JSHandle, parseResult, serializeArgument, SmartHandle } from './jsHandle';
|
||||
import { assertMaxArguments, JSHandle, parseResult, serializeArgument } from './jsHandle';
|
||||
import { Page } from './page';
|
||||
import { BrowserContext } from './browserContext';
|
||||
import { ChromiumBrowserContext } from './chromiumBrowserContext';
|
||||
import * as api from '../../types/types';
|
||||
import * as structs from '../../types/structs';
|
||||
|
||||
export class Worker extends ChannelOwner<channels.WorkerChannel, channels.WorkerInitializer> {
|
||||
export class Worker extends ChannelOwner<channels.WorkerChannel, channels.WorkerInitializer> implements api.Worker {
|
||||
_page: Page | undefined; // Set for web workers.
|
||||
_context: BrowserContext | undefined; // Set for service workers.
|
||||
|
||||
|
|
@ -45,19 +47,15 @@ export class Worker extends ChannelOwner<channels.WorkerChannel, channels.Worker
|
|||
return this._initializer.url;
|
||||
}
|
||||
|
||||
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> {
|
||||
async evaluate<R, Arg>(pageFunction: structs.PageFunction<Arg, R>, arg?: Arg): Promise<R> {
|
||||
assertMaxArguments(arguments.length, 2);
|
||||
const result = await this._channel.evaluateExpression({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) });
|
||||
return parseResult(result.value);
|
||||
}
|
||||
|
||||
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>> {
|
||||
async evaluateHandle<R, Arg>(pageFunction: structs.PageFunction<Arg, R>, arg?: Arg): Promise<structs.SmartHandle<R>> {
|
||||
assertMaxArguments(arguments.length, 2);
|
||||
const result = await this._channel.evaluateExpressionHandle({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) });
|
||||
return JSHandle.from(result.handle) as SmartHandle<R>;
|
||||
return JSHandle.from(result.handle) as any as structs.SmartHandle<R>;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
45
types/structs.d.ts
vendored
Normal file
45
types/structs.d.ts
vendored
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
* 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 { JSHandle, ElementHandle, Frame, Page, BrowserContext } from './types';
|
||||
|
||||
/**
|
||||
* Can be converted to JSON
|
||||
*/
|
||||
export type Serializable = {};
|
||||
/**
|
||||
* Can be converted to JSON, but may also contain JSHandles.
|
||||
*/
|
||||
export type EvaluationArgument = {};
|
||||
|
||||
export type NoHandles<Arg> = Arg extends JSHandle ? never : (Arg extends object ? { [Key in keyof Arg]: NoHandles<Arg[Key]> } : Arg);
|
||||
export type Unboxed<Arg> =
|
||||
Arg extends ElementHandle<infer T> ? T :
|
||||
Arg extends JSHandle<infer T> ? T :
|
||||
Arg extends NoHandles<Arg> ? Arg :
|
||||
Arg extends [infer A0] ? [Unboxed<A0>] :
|
||||
Arg extends [infer A0, infer A1] ? [Unboxed<A0>, Unboxed<A1>] :
|
||||
Arg extends [infer A0, infer A1, infer A2] ? [Unboxed<A0>, Unboxed<A1>, Unboxed<A2>] :
|
||||
Arg extends [infer A0, infer A1, infer A2, infer A3] ? [Unboxed<A0>, Unboxed<A1>, Unboxed<A2>, Unboxed<A3>] :
|
||||
Arg extends Array<infer T> ? Array<Unboxed<T>> :
|
||||
Arg extends object ? { [Key in keyof Arg]: Unboxed<Arg[Key]> } :
|
||||
Arg;
|
||||
export type PageFunction0<R> = string | (() => R | Promise<R>);
|
||||
export type PageFunction<Arg, R> = string | ((arg: Unboxed<Arg>) => R | Promise<R>);
|
||||
export type PageFunctionOn<On, Arg2, R> = string | ((on: On, arg2: Unboxed<Arg2>) => R | Promise<R>);
|
||||
export type SmartHandle<T> = T extends Node ? ElementHandle<T> : JSHandle<T>;
|
||||
export type ElementHandleForTag<K extends keyof HTMLElementTagNameMap> = ElementHandle<HTMLElementTagNameMap[K]>;
|
||||
export type BindingSource = { context: BrowserContext, page: Page, frame: Frame };
|
||||
29
types/types.d.ts
vendored
29
types/types.d.ts
vendored
|
|
@ -18,32 +18,7 @@ import { Protocol } from './protocol';
|
|||
import { ChildProcess } from 'child_process';
|
||||
import { EventEmitter } from 'events';
|
||||
import { Readable } from 'stream';
|
||||
|
||||
/**
|
||||
* Can be converted to JSON
|
||||
*/
|
||||
type Serializable = {};
|
||||
/**
|
||||
* Can be converted to JSON, but may also contain JSHandles.
|
||||
*/
|
||||
type EvaluationArgument = {};
|
||||
|
||||
type NoHandles<Arg> = Arg extends JSHandle ? never : (Arg extends object ? { [Key in keyof Arg]: NoHandles<Arg[Key]> } : Arg);
|
||||
type Unboxed<Arg> =
|
||||
Arg extends ElementHandle<infer T> ? T :
|
||||
Arg extends JSHandle<infer T> ? T :
|
||||
Arg extends NoHandles<Arg> ? Arg :
|
||||
Arg extends [infer A0] ? [Unboxed<A0>] :
|
||||
Arg extends [infer A0, infer A1] ? [Unboxed<A0>, Unboxed<A1>] :
|
||||
Arg extends [infer A0, infer A1, infer A2] ? [Unboxed<A0>, Unboxed<A1>, Unboxed<A2>] :
|
||||
Arg extends [infer A0, infer A1, infer A2, infer A3] ? [Unboxed<A0>, Unboxed<A1>, Unboxed<A2>, Unboxed<A3>] :
|
||||
Arg extends Array<infer T> ? Array<Unboxed<T>> :
|
||||
Arg extends object ? { [Key in keyof Arg]: Unboxed<Arg[Key]> } :
|
||||
Arg;
|
||||
type PageFunction<Arg, R> = string | ((arg: Unboxed<Arg>) => R | Promise<R>);
|
||||
type PageFunctionOn<On, Arg2, R> = string | ((on: On, arg2: Unboxed<Arg2>) => R | Promise<R>);
|
||||
type SmartHandle<T> = T extends Node ? ElementHandle<T> : JSHandle<T>;
|
||||
type ElementHandleForTag<K extends keyof HTMLElementTagNameMap> = ElementHandle<HTMLElementTagNameMap[K]>;
|
||||
import { Serializable, EvaluationArgument, PageFunction, PageFunctionOn, SmartHandle, ElementHandleForTag, BindingSource } from './structs';
|
||||
|
||||
type PageWaitForSelectorOptionsNotHidden = PageWaitForSelectorOptions & {
|
||||
state: 'visible'|'attached';
|
||||
|
|
@ -52,8 +27,6 @@ type ElementHandleWaitForSelectorOptionsNotHidden = ElementHandleWaitForSelector
|
|||
state: 'visible'|'attached';
|
||||
};
|
||||
|
||||
type BindingSource = { context: BrowserContext, page: Page, frame: Frame };
|
||||
|
||||
/**
|
||||
* Page provides methods to interact with a single tab in a Browser, or an extension background page in Chromium. One Browser instance might have multiple Page instances.
|
||||
* This example creates a page, navigates it to a URL, and then saves a screenshot:
|
||||
|
|
|
|||
|
|
@ -200,7 +200,8 @@ function compareDocumentations(actual, expected) {
|
|||
[/Handle\<R\>/g, 'JSHandle'],
|
||||
[/JSHandle\<Object\>/g, 'JSHandle'],
|
||||
[/object/g, 'Object'],
|
||||
[/Promise\<T\>/, 'Promise<Object>']
|
||||
[/Promise\<T\>/, 'Promise<Object>'],
|
||||
[/TextendsNode\?ElementHandle:null/, 'null|ElementHandle']
|
||||
]
|
||||
let actualName = actual.name;
|
||||
for (const replacer of mdReplacers)
|
||||
|
|
|
|||
29
utils/generate_types/overrides.d.ts
vendored
29
utils/generate_types/overrides.d.ts
vendored
|
|
@ -17,32 +17,7 @@ import { Protocol } from './protocol';
|
|||
import { ChildProcess } from 'child_process';
|
||||
import { EventEmitter } from 'events';
|
||||
import { Readable } from 'stream';
|
||||
|
||||
/**
|
||||
* Can be converted to JSON
|
||||
*/
|
||||
type Serializable = {};
|
||||
/**
|
||||
* Can be converted to JSON, but may also contain JSHandles.
|
||||
*/
|
||||
type EvaluationArgument = {};
|
||||
|
||||
type NoHandles<Arg> = Arg extends JSHandle ? never : (Arg extends object ? { [Key in keyof Arg]: NoHandles<Arg[Key]> } : Arg);
|
||||
type Unboxed<Arg> =
|
||||
Arg extends ElementHandle<infer T> ? T :
|
||||
Arg extends JSHandle<infer T> ? T :
|
||||
Arg extends NoHandles<Arg> ? Arg :
|
||||
Arg extends [infer A0] ? [Unboxed<A0>] :
|
||||
Arg extends [infer A0, infer A1] ? [Unboxed<A0>, Unboxed<A1>] :
|
||||
Arg extends [infer A0, infer A1, infer A2] ? [Unboxed<A0>, Unboxed<A1>, Unboxed<A2>] :
|
||||
Arg extends [infer A0, infer A1, infer A2, infer A3] ? [Unboxed<A0>, Unboxed<A1>, Unboxed<A2>, Unboxed<A3>] :
|
||||
Arg extends Array<infer T> ? Array<Unboxed<T>> :
|
||||
Arg extends object ? { [Key in keyof Arg]: Unboxed<Arg[Key]> } :
|
||||
Arg;
|
||||
type PageFunction<Arg, R> = string | ((arg: Unboxed<Arg>) => R | Promise<R>);
|
||||
type PageFunctionOn<On, Arg2, R> = string | ((on: On, arg2: Unboxed<Arg2>) => R | Promise<R>);
|
||||
type SmartHandle<T> = T extends Node ? ElementHandle<T> : JSHandle<T>;
|
||||
type ElementHandleForTag<K extends keyof HTMLElementTagNameMap> = ElementHandle<HTMLElementTagNameMap[K]>;
|
||||
import { Serializable, EvaluationArgument, PageFunction, PageFunctionOn, SmartHandle, ElementHandleForTag, BindingSource } from './structs';
|
||||
|
||||
type PageWaitForSelectorOptionsNotHidden = PageWaitForSelectorOptions & {
|
||||
state: 'visible'|'attached';
|
||||
|
|
@ -51,8 +26,6 @@ type ElementHandleWaitForSelectorOptionsNotHidden = ElementHandleWaitForSelector
|
|||
state: 'visible'|'attached';
|
||||
};
|
||||
|
||||
type BindingSource = { context: BrowserContext, page: Page, frame: Frame };
|
||||
|
||||
export interface Page {
|
||||
evaluate<R, Arg>(pageFunction: PageFunction<Arg, R>, arg: Arg): Promise<R>;
|
||||
evaluate<R>(pageFunction: PageFunction<void, R>, arg?: any): Promise<R>;
|
||||
|
|
|
|||
Loading…
Reference in a new issue