chore: drop wrapApiCall (1) (#10428)

This commit is contained in:
Pavel Feldman 2021-11-19 10:12:48 -08:00 committed by GitHub
parent e87b56a2e5
commit 2a98800ac0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 154 additions and 272 deletions

View file

@ -88,14 +88,12 @@ export class Frame extends ChannelOwner<channels.FrameChannel> implements api.Fr
} }
async goto(url: string, options: channels.FrameGotoOptions = {}): Promise<network.Response | null> { async goto(url: string, options: channels.FrameGotoOptions = {}): Promise<network.Response | null> {
return this._wrapApiCall(async (channel: channels.FrameChannel) => { const waitUntil = verifyLoadState('waitUntil', options.waitUntil === undefined ? 'load' : options.waitUntil);
const waitUntil = verifyLoadState('waitUntil', options.waitUntil === undefined ? 'load' : options.waitUntil); return network.Response.fromNullable((await this._channel.goto({ url, ...options, waitUntil })).response);
return network.Response.fromNullable((await channel.goto({ url, ...options, waitUntil })).response);
});
} }
private _setupNavigationWaiter(channel: channels.EventTargetChannel, options: { timeout?: number }): Waiter { private _setupNavigationWaiter(options: { timeout?: number }): Waiter {
const waiter = new Waiter(channel, ''); const waiter = new Waiter(this._page!._channel, '');
if (this._page!.isClosed()) if (this._page!.isClosed())
waiter.rejectImmediately(new Error('Navigation failed because page was closed!')); waiter.rejectImmediately(new Error('Navigation failed because page was closed!'));
waiter.rejectOnEvent(this._page!, Events.Page.Close, new Error('Navigation failed because page was closed!')); waiter.rejectOnEvent(this._page!, Events.Page.Close, new Error('Navigation failed because page was closed!'));
@ -109,7 +107,7 @@ export class Frame extends ChannelOwner<channels.FrameChannel> implements api.Fr
async waitForNavigation(options: WaitForNavigationOptions = {}): Promise<network.Response | null> { async waitForNavigation(options: WaitForNavigationOptions = {}): Promise<network.Response | null> {
return this._page!._wrapApiCall(async (channel: channels.PageChannel) => { return this._page!._wrapApiCall(async (channel: channels.PageChannel) => {
const waitUntil = verifyLoadState('waitUntil', options.waitUntil === undefined ? 'load' : options.waitUntil); const waitUntil = verifyLoadState('waitUntil', options.waitUntil === undefined ? 'load' : options.waitUntil);
const waiter = this._setupNavigationWaiter(channel, options); const waiter = this._setupNavigationWaiter(options);
const toUrl = typeof options.url === 'string' ? ` to "${options.url}"` : ''; const toUrl = typeof options.url === 'string' ? ` to "${options.url}"` : '';
waiter.log(`waiting for navigation${toUrl} until "${waitUntil}"`); waiter.log(`waiting for navigation${toUrl} until "${waitUntil}"`);
@ -146,7 +144,7 @@ export class Frame extends ChannelOwner<channels.FrameChannel> implements api.Fr
if (this._loadStates.has(state)) if (this._loadStates.has(state))
return; return;
return this._page!._wrapApiCall(async (channel: channels.PageChannel) => { return this._page!._wrapApiCall(async (channel: channels.PageChannel) => {
const waiter = this._setupNavigationWaiter(channel, options); const waiter = this._setupNavigationWaiter(options);
await waiter.waitForEvent<LifecycleEvent>(this._eventEmitter, 'loadstate', s => { await waiter.waitForEvent<LifecycleEvent>(this._eventEmitter, 'loadstate', s => {
waiter.log(` "${s}" event fired`); waiter.log(` "${s}" event fired`);
return s === state; return s === state;
@ -163,87 +161,65 @@ export class Frame extends ChannelOwner<channels.FrameChannel> implements api.Fr
} }
async frameElement(): Promise<ElementHandle> { async frameElement(): Promise<ElementHandle> {
return this._wrapApiCall(async (channel: channels.FrameChannel) => { return ElementHandle.from((await this._channel.frameElement()).element);
return ElementHandle.from((await channel.frameElement()).element);
});
} }
async evaluateHandle<R, Arg>(pageFunction: structs.PageFunction<Arg, R>, arg?: Arg): Promise<structs.SmartHandle<R>> { async evaluateHandle<R, Arg>(pageFunction: structs.PageFunction<Arg, R>, arg?: Arg): Promise<structs.SmartHandle<R>> {
assertMaxArguments(arguments.length, 2); assertMaxArguments(arguments.length, 2);
return this._wrapApiCall(async (channel: channels.FrameChannel) => { const result = await this._channel.evaluateExpressionHandle({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) });
const result = await channel.evaluateExpressionHandle({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) }); return JSHandle.from(result.handle) as any as structs.SmartHandle<R>;
return JSHandle.from(result.handle) as any as structs.SmartHandle<R>;
});
} }
async evaluate<R, Arg>(pageFunction: structs.PageFunction<Arg, R>, arg?: Arg): Promise<R> { async evaluate<R, Arg>(pageFunction: structs.PageFunction<Arg, R>, arg?: Arg): Promise<R> {
assertMaxArguments(arguments.length, 2); assertMaxArguments(arguments.length, 2);
return this._wrapApiCall(async (channel: channels.FrameChannel) => { const result = await this._channel.evaluateExpression({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) });
const result = await channel.evaluateExpression({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) }); return parseResult(result.value);
return parseResult(result.value);
});
} }
async $(selector: string, options?: { strict?: boolean }): Promise<ElementHandle<SVGElement | HTMLElement> | null> { async $(selector: string, options?: { strict?: boolean }): Promise<ElementHandle<SVGElement | HTMLElement> | null> {
return this._wrapApiCall(async (channel: channels.FrameChannel) => { const result = await this._channel.querySelector({ selector, ...options });
const result = await channel.querySelector({ selector, ...options }); return ElementHandle.fromNullable(result.element) as ElementHandle<SVGElement | HTMLElement> | null;
return ElementHandle.fromNullable(result.element) as ElementHandle<SVGElement | HTMLElement> | null;
});
} }
waitForSelector(selector: string, options: channels.FrameWaitForSelectorOptions & { state: 'attached' | 'visible' }): Promise<ElementHandle<SVGElement | HTMLElement>>; waitForSelector(selector: string, options: channels.FrameWaitForSelectorOptions & { state: 'attached' | 'visible' }): Promise<ElementHandle<SVGElement | HTMLElement>>;
waitForSelector(selector: string, options?: channels.FrameWaitForSelectorOptions): Promise<ElementHandle<SVGElement | HTMLElement> | null>; waitForSelector(selector: string, options?: channels.FrameWaitForSelectorOptions): Promise<ElementHandle<SVGElement | HTMLElement> | null>;
async 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(async (channel: channels.FrameChannel) => { if ((options as any).visibility)
if ((options as any).visibility) throw new Error('options.visibility is not supported, did you mean options.state?');
throw new Error('options.visibility is not supported, did you mean options.state?'); if ((options as any).waitFor && (options as any).waitFor !== 'visible')
if ((options as any).waitFor && (options as any).waitFor !== 'visible') throw new Error('options.waitFor is not supported, did you mean options.state?');
throw new Error('options.waitFor is not supported, did you mean options.state?'); const result = await this._channel.waitForSelector({ selector, ...options });
const result = await channel.waitForSelector({ selector, ...options }); return ElementHandle.fromNullable(result.element) as ElementHandle<SVGElement | HTMLElement> | null;
return ElementHandle.fromNullable(result.element) as ElementHandle<SVGElement | HTMLElement> | null;
});
} }
async dispatchEvent(selector: string, type: string, eventInit?: any, options: channels.FrameDispatchEventOptions = {}): Promise<void> { async dispatchEvent(selector: string, type: string, eventInit?: any, options: channels.FrameDispatchEventOptions = {}): Promise<void> {
return this._wrapApiCall(async (channel: channels.FrameChannel) => { await this._channel.dispatchEvent({ selector, type, eventInit: serializeArgument(eventInit), ...options });
await channel.dispatchEvent({ selector, type, eventInit: serializeArgument(eventInit), ...options });
});
} }
async $eval<R, Arg>(selector: string, pageFunction: structs.PageFunctionOn<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); assertMaxArguments(arguments.length, 3);
return this._wrapApiCall(async (channel: channels.FrameChannel) => { const result = await this._channel.evalOnSelector({ selector, expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) });
const result = await channel.evalOnSelector({ selector, expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) }); return parseResult(result.value);
return parseResult(result.value);
});
} }
async $$eval<R, Arg>(selector: string, pageFunction: structs.PageFunctionOn<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); assertMaxArguments(arguments.length, 3);
return this._wrapApiCall(async (channel: channels.FrameChannel) => { const result = await this._channel.evalOnSelectorAll({ selector, expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) });
const result = await channel.evalOnSelectorAll({ selector, expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) }); return parseResult(result.value);
return parseResult(result.value);
});
} }
async $$(selector: string): Promise<ElementHandle<SVGElement | HTMLElement>[]> { async $$(selector: string): Promise<ElementHandle<SVGElement | HTMLElement>[]> {
return this._wrapApiCall(async (channel: channels.FrameChannel) => { const result = await this._channel.querySelectorAll({ selector });
const result = await channel.querySelectorAll({ selector }); return result.elements.map(e => ElementHandle.from(e) as ElementHandle<SVGElement | HTMLElement>);
return result.elements.map(e => ElementHandle.from(e) as ElementHandle<SVGElement | HTMLElement>);
});
} }
async content(): Promise<string> { async content(): Promise<string> {
return this._wrapApiCall(async (channel: channels.FrameChannel) => { return (await this._channel.content()).value;
return (await channel.content()).value;
});
} }
async setContent(html: string, options: channels.FrameSetContentOptions = {}): Promise<void> { async setContent(html: string, options: channels.FrameSetContentOptions = {}): Promise<void> {
return this._wrapApiCall(async (channel: channels.FrameChannel) => { const waitUntil = verifyLoadState('waitUntil', options.waitUntil === undefined ? 'load' : options.waitUntil);
const waitUntil = verifyLoadState('waitUntil', options.waitUntil === undefined ? 'load' : options.waitUntil); await this._channel.setContent({ html, ...options, waitUntil });
await channel.setContent({ html, ...options, waitUntil });
});
} }
name(): string { name(): string {
@ -267,55 +243,41 @@ export class Frame extends ChannelOwner<channels.FrameChannel> implements api.Fr
} }
async addScriptTag(options: { url?: string, path?: string, content?: string, type?: string } = {}): Promise<ElementHandle> { async addScriptTag(options: { url?: string, path?: string, content?: string, type?: string } = {}): Promise<ElementHandle> {
return this._wrapApiCall(async (channel: channels.FrameChannel) => { const copy = { ...options };
const copy = { ...options }; if (copy.path) {
if (copy.path) { copy.content = (await fs.promises.readFile(copy.path)).toString();
copy.content = (await fs.promises.readFile(copy.path)).toString(); copy.content += '//# sourceURL=' + copy.path.replace(/\n/g, '');
copy.content += '//# sourceURL=' + copy.path.replace(/\n/g, ''); }
} return ElementHandle.from((await this._channel.addScriptTag({ ...copy })).element);
return ElementHandle.from((await channel.addScriptTag({ ...copy })).element);
});
} }
async addStyleTag(options: { url?: string; path?: string; content?: string; } = {}): Promise<ElementHandle> { async addStyleTag(options: { url?: string; path?: string; content?: string; } = {}): Promise<ElementHandle> {
return this._wrapApiCall(async (channel: channels.FrameChannel) => { const copy = { ...options };
const copy = { ...options }; if (copy.path) {
if (copy.path) { copy.content = (await fs.promises.readFile(copy.path)).toString();
copy.content = (await fs.promises.readFile(copy.path)).toString(); copy.content += '/*# sourceURL=' + copy.path.replace(/\n/g, '') + '*/';
copy.content += '/*# sourceURL=' + copy.path.replace(/\n/g, '') + '*/'; }
} return ElementHandle.from((await this._channel.addStyleTag({ ...copy })).element);
return ElementHandle.from((await channel.addStyleTag({ ...copy })).element);
});
} }
async click(selector: string, options: channels.FrameClickOptions = {}) { async click(selector: string, options: channels.FrameClickOptions = {}) {
return this._wrapApiCall(async (channel: channels.FrameChannel) => { return await this._channel.click({ selector, ...options });
return await channel.click({ selector, ...options });
});
} }
async dblclick(selector: string, options: channels.FrameDblclickOptions = {}) { async dblclick(selector: string, options: channels.FrameDblclickOptions = {}) {
return this._wrapApiCall(async (channel: channels.FrameChannel) => { return await this._channel.dblclick({ selector, ...options });
return await channel.dblclick({ selector, ...options });
});
} }
async dragAndDrop(source: string, target: string, options: channels.FrameDragAndDropOptions = {}) { async dragAndDrop(source: string, target: string, options: channels.FrameDragAndDropOptions = {}) {
return this._wrapApiCall(async (channel: channels.FrameChannel) => { return await this._channel.dragAndDrop({ source, target, ...options });
return await channel.dragAndDrop({ source, target, ...options });
});
} }
async tap(selector: string, options: channels.FrameTapOptions = {}) { async tap(selector: string, options: channels.FrameTapOptions = {}) {
return this._wrapApiCall(async (channel: channels.FrameChannel) => { return await this._channel.tap({ selector, ...options });
return await channel.tap({ selector, ...options });
});
} }
async fill(selector: string, value: string, options: channels.FrameFillOptions = {}) { async fill(selector: string, value: string, options: channels.FrameFillOptions = {}) {
return this._wrapApiCall(async (channel: channels.FrameChannel) => { return await this._channel.fill({ selector, value, ...options });
return await channel.fill({ selector, value, ...options });
});
} }
locator(selector: string): Locator { locator(selector: string): Locator {
@ -327,119 +289,81 @@ export class Frame extends ChannelOwner<channels.FrameChannel> implements api.Fr
} }
async focus(selector: string, options: channels.FrameFocusOptions = {}) { async focus(selector: string, options: channels.FrameFocusOptions = {}) {
return this._wrapApiCall(async (channel: channels.FrameChannel) => { await this._channel.focus({ selector, ...options });
await channel.focus({ selector, ...options });
});
} }
async textContent(selector: string, options: channels.FrameTextContentOptions = {}): Promise<null|string> { async textContent(selector: string, options: channels.FrameTextContentOptions = {}): Promise<null|string> {
return this._wrapApiCall(async (channel: channels.FrameChannel) => { const value = (await this._channel.textContent({ selector, ...options })).value;
const value = (await channel.textContent({ selector, ...options })).value; return value === undefined ? null : value;
return value === undefined ? null : value;
});
} }
async innerText(selector: string, options: channels.FrameInnerTextOptions = {}): Promise<string> { async innerText(selector: string, options: channels.FrameInnerTextOptions = {}): Promise<string> {
return this._wrapApiCall(async (channel: channels.FrameChannel) => { return (await this._channel.innerText({ selector, ...options })).value;
return (await channel.innerText({ selector, ...options })).value;
});
} }
async innerHTML(selector: string, options: channels.FrameInnerHTMLOptions = {}): Promise<string> { async innerHTML(selector: string, options: channels.FrameInnerHTMLOptions = {}): Promise<string> {
return this._wrapApiCall(async (channel: channels.FrameChannel) => { return (await this._channel.innerHTML({ selector, ...options })).value;
return (await channel.innerHTML({ selector, ...options })).value;
});
} }
async getAttribute(selector: string, name: string, options: channels.FrameGetAttributeOptions = {}): Promise<string | null> { async getAttribute(selector: string, name: string, options: channels.FrameGetAttributeOptions = {}): Promise<string | null> {
return this._wrapApiCall(async (channel: channels.FrameChannel) => { const value = (await this._channel.getAttribute({ selector, name, ...options })).value;
const value = (await channel.getAttribute({ selector, name, ...options })).value; return value === undefined ? null : value;
return value === undefined ? null : value;
});
} }
async inputValue(selector: string, options: channels.FrameInputValueOptions = {}): Promise<string> { async inputValue(selector: string, options: channels.FrameInputValueOptions = {}): Promise<string> {
return this._wrapApiCall(async (channel: channels.FrameChannel) => { return (await this._channel.inputValue({ selector, ...options })).value;
return (await channel.inputValue({ selector, ...options })).value;
});
} }
async isChecked(selector: string, options: channels.FrameIsCheckedOptions = {}): Promise<boolean> { async isChecked(selector: string, options: channels.FrameIsCheckedOptions = {}): Promise<boolean> {
return this._wrapApiCall(async (channel: channels.FrameChannel) => { return (await this._channel.isChecked({ selector, ...options })).value;
return (await channel.isChecked({ selector, ...options })).value;
});
} }
async isDisabled(selector: string, options: channels.FrameIsDisabledOptions = {}): Promise<boolean> { async isDisabled(selector: string, options: channels.FrameIsDisabledOptions = {}): Promise<boolean> {
return this._wrapApiCall(async (channel: channels.FrameChannel) => { return (await this._channel.isDisabled({ selector, ...options })).value;
return (await channel.isDisabled({ selector, ...options })).value;
});
} }
async isEditable(selector: string, options: channels.FrameIsEditableOptions = {}): Promise<boolean> { async isEditable(selector: string, options: channels.FrameIsEditableOptions = {}): Promise<boolean> {
return this._wrapApiCall(async (channel: channels.FrameChannel) => { return (await this._channel.isEditable({ selector, ...options })).value;
return (await channel.isEditable({ selector, ...options })).value;
});
} }
async isEnabled(selector: string, options: channels.FrameIsEnabledOptions = {}): Promise<boolean> { async isEnabled(selector: string, options: channels.FrameIsEnabledOptions = {}): Promise<boolean> {
return this._wrapApiCall(async (channel: channels.FrameChannel) => { return (await this._channel.isEnabled({ selector, ...options })).value;
return (await channel.isEnabled({ selector, ...options })).value;
});
} }
async isHidden(selector: string, options: channels.FrameIsHiddenOptions = {}): Promise<boolean> { async isHidden(selector: string, options: channels.FrameIsHiddenOptions = {}): Promise<boolean> {
return this._wrapApiCall(async (channel: channels.FrameChannel) => { return (await this._channel.isHidden({ selector, ...options })).value;
return (await channel.isHidden({ selector, ...options })).value;
});
} }
async isVisible(selector: string, options: channels.FrameIsVisibleOptions = {}): Promise<boolean> { async isVisible(selector: string, options: channels.FrameIsVisibleOptions = {}): Promise<boolean> {
return this._wrapApiCall(async (channel: channels.FrameChannel) => { return (await this._channel.isVisible({ selector, ...options })).value;
return (await channel.isVisible({ selector, ...options })).value;
});
} }
async hover(selector: string, options: channels.FrameHoverOptions = {}) { async hover(selector: string, options: channels.FrameHoverOptions = {}) {
return this._wrapApiCall(async (channel: channels.FrameChannel) => { await this._channel.hover({ selector, ...options });
await channel.hover({ selector, ...options });
});
} }
async selectOption(selector: string, values: string | api.ElementHandle | SelectOption | string[] | api.ElementHandle[] | SelectOption[] | null, options: SelectOptionOptions & StrictOptions = {}): Promise<string[]> { async selectOption(selector: string, values: string | api.ElementHandle | SelectOption | string[] | api.ElementHandle[] | SelectOption[] | null, options: SelectOptionOptions & StrictOptions = {}): Promise<string[]> {
return this._wrapApiCall(async (channel: channels.FrameChannel) => { return (await this._channel.selectOption({ selector, ...convertSelectOptionValues(values), ...options })).values;
return (await channel.selectOption({ selector, ...convertSelectOptionValues(values), ...options })).values;
});
} }
async setInputFiles(selector: string, files: string | FilePayload | string[] | FilePayload[], options: channels.FrameSetInputFilesOptions = {}): Promise<void> { async setInputFiles(selector: string, files: string | FilePayload | string[] | FilePayload[], options: channels.FrameSetInputFilesOptions = {}): Promise<void> {
return this._wrapApiCall(async (channel: channels.FrameChannel) => { await this._channel.setInputFiles({ selector, files: await convertInputFiles(files), ...options });
await channel.setInputFiles({ selector, files: await convertInputFiles(files), ...options });
});
} }
async type(selector: string, text: string, options: channels.FrameTypeOptions = {}) { async type(selector: string, text: string, options: channels.FrameTypeOptions = {}) {
return this._wrapApiCall(async (channel: channels.FrameChannel) => { await this._channel.type({ selector, text, ...options });
await channel.type({ selector, text, ...options });
});
} }
async press(selector: string, key: string, options: channels.FramePressOptions = {}) { async press(selector: string, key: string, options: channels.FramePressOptions = {}) {
return this._wrapApiCall(async (channel: channels.FrameChannel) => { await this._channel.press({ selector, key, ...options });
await channel.press({ selector, key, ...options });
});
} }
async check(selector: string, options: channels.FrameCheckOptions = {}) { async check(selector: string, options: channels.FrameCheckOptions = {}) {
return this._wrapApiCall(async (channel: channels.FrameChannel) => { await this._channel.check({ selector, ...options });
await channel.check({ selector, ...options });
});
} }
async uncheck(selector: string, options: channels.FrameUncheckOptions = {}) { async uncheck(selector: string, options: channels.FrameUncheckOptions = {}) {
return this._wrapApiCall(async (channel: channels.FrameChannel) => { await this._channel.uncheck({ selector, ...options });
await channel.uncheck({ selector, ...options });
});
} }
async setChecked(selector: string, checked: boolean, options?: channels.FrameCheckOptions) { async setChecked(selector: string, checked: boolean, options?: channels.FrameCheckOptions) {
@ -450,30 +374,24 @@ export class Frame extends ChannelOwner<channels.FrameChannel> implements api.Fr
} }
async waitForTimeout(timeout: number) { async waitForTimeout(timeout: number) {
return this._wrapApiCall(async (channel: channels.FrameChannel) => { await this._channel.waitForTimeout({ timeout });
await channel.waitForTimeout({ timeout });
});
} }
async waitForFunction<R, Arg>(pageFunction: structs.PageFunction<Arg, R>, arg?: Arg, options: WaitForFunctionOptions = {}): Promise<structs.SmartHandle<R>> { async waitForFunction<R, Arg>(pageFunction: structs.PageFunction<Arg, R>, arg?: Arg, options: WaitForFunctionOptions = {}): Promise<structs.SmartHandle<R>> {
return this._wrapApiCall(async (channel: channels.FrameChannel) => { if (typeof options.polling === 'string')
if (typeof options.polling === 'string') assert(options.polling === 'raf', 'Unknown polling option: ' + options.polling);
assert(options.polling === 'raf', 'Unknown polling option: ' + options.polling); const result = await this._channel.waitForFunction({
const result = await channel.waitForFunction({ ...options,
...options, pollingInterval: options.polling === 'raf' ? undefined : options.polling,
pollingInterval: options.polling === 'raf' ? undefined : options.polling, expression: String(pageFunction),
expression: String(pageFunction), isFunction: typeof pageFunction === 'function',
isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg),
arg: serializeArgument(arg),
});
return JSHandle.from(result.handle) as any as structs.SmartHandle<R>;
}); });
return JSHandle.from(result.handle) as any as structs.SmartHandle<R>;
} }
async title(): Promise<string> { async title(): Promise<string> {
return this._wrapApiCall(async (channel: channels.FrameChannel) => { return (await this._channel.title()).value;
return (await channel.title()).value;
});
} }
} }

View file

@ -303,25 +303,19 @@ export class Page extends ChannelOwner<channels.PageChannel> implements api.Page
} }
async exposeFunction(name: string, callback: Function) { async exposeFunction(name: string, callback: Function) {
return this._wrapApiCall(async (channel: channels.PageChannel) => { await this._channel.exposeBinding({ name });
await channel.exposeBinding({ name }); const binding = (source: structs.BindingSource, ...args: any[]) => callback(...args);
const binding = (source: structs.BindingSource, ...args: any[]) => callback(...args); this._bindings.set(name, binding);
this._bindings.set(name, binding);
});
} }
async exposeBinding(name: string, callback: (source: structs.BindingSource, ...args: any[]) => any, options: { handle?: boolean } = {}) { async exposeBinding(name: string, callback: (source: structs.BindingSource, ...args: any[]) => any, options: { handle?: boolean } = {}) {
return this._wrapApiCall(async (channel: channels.PageChannel) => { await this._channel.exposeBinding({ name, needsHandle: options.handle });
await channel.exposeBinding({ name, needsHandle: options.handle }); this._bindings.set(name, callback);
this._bindings.set(name, callback);
});
} }
async setExtraHTTPHeaders(headers: Headers) { async setExtraHTTPHeaders(headers: Headers) {
return this._wrapApiCall(async (channel: channels.PageChannel) => { validateHeaders(headers);
validateHeaders(headers); await this._channel.setExtraHTTPHeaders({ headers: headersObjectToArray(headers) });
await channel.setExtraHTTPHeaders({ headers: headersObjectToArray(headers) });
});
} }
url(): string { url(): string {
@ -341,10 +335,8 @@ export class Page extends ChannelOwner<channels.PageChannel> implements api.Page
} }
async reload(options: channels.PageReloadOptions = {}): Promise<Response | null> { async reload(options: channels.PageReloadOptions = {}): Promise<Response | null> {
return this._wrapApiCall(async (channel: channels.PageChannel) => { const waitUntil = verifyLoadState('waitUntil', options.waitUntil === undefined ? 'load' : options.waitUntil);
const waitUntil = verifyLoadState('waitUntil', options.waitUntil === undefined ? 'load' : options.waitUntil); return Response.fromNullable((await this._channel.reload({ ...options, waitUntil })).response);
return Response.fromNullable((await channel.reload({ ...options, waitUntil })).response);
});
} }
async waitForLoadState(state?: LifecycleEvent, options?: { timeout?: number }): Promise<void> { async waitForLoadState(state?: LifecycleEvent, options?: { timeout?: number }): Promise<void> {
@ -360,35 +352,29 @@ export class Page extends ChannelOwner<channels.PageChannel> implements api.Page
} }
async waitForRequest(urlOrPredicate: string | RegExp | ((r: Request) => boolean | Promise<boolean>), options: { timeout?: number } = {}): Promise<Request> { async waitForRequest(urlOrPredicate: string | RegExp | ((r: Request) => boolean | Promise<boolean>), options: { timeout?: number } = {}): Promise<Request> {
return this._wrapApiCall(async (channel: channels.PageChannel) => { const predicate = (request: Request) => {
const predicate = (request: Request) => { if (isString(urlOrPredicate) || isRegExp(urlOrPredicate))
if (isString(urlOrPredicate) || isRegExp(urlOrPredicate)) return urlMatches(this._browserContext._options.baseURL, request.url(), urlOrPredicate);
return urlMatches(this._browserContext._options.baseURL, request.url(), urlOrPredicate); return urlOrPredicate(request);
return urlOrPredicate(request); };
}; const trimmedUrl = trimUrl(urlOrPredicate);
const trimmedUrl = trimUrl(urlOrPredicate); const logLine = trimmedUrl ? `waiting for request ${trimmedUrl}` : undefined;
const logLine = trimmedUrl ? `waiting for request ${trimmedUrl}` : undefined; return this._waitForEvent(this._channel, Events.Page.Request, { predicate, timeout: options.timeout }, logLine);
return this._waitForEvent(channel, Events.Page.Request, { predicate, timeout: options.timeout }, logLine);
});
} }
async waitForResponse(urlOrPredicate: string | RegExp | ((r: Response) => boolean | Promise<boolean>), options: { timeout?: number } = {}): Promise<Response> { async waitForResponse(urlOrPredicate: string | RegExp | ((r: Response) => boolean | Promise<boolean>), options: { timeout?: number } = {}): Promise<Response> {
return this._wrapApiCall(async (channel: channels.PageChannel) => { const predicate = (response: Response) => {
const predicate = (response: Response) => { if (isString(urlOrPredicate) || isRegExp(urlOrPredicate))
if (isString(urlOrPredicate) || isRegExp(urlOrPredicate)) return urlMatches(this._browserContext._options.baseURL, response.url(), urlOrPredicate);
return urlMatches(this._browserContext._options.baseURL, response.url(), urlOrPredicate); return urlOrPredicate(response);
return urlOrPredicate(response); };
}; const trimmedUrl = trimUrl(urlOrPredicate);
const trimmedUrl = trimUrl(urlOrPredicate); const logLine = trimmedUrl ? `waiting for response ${trimmedUrl}` : undefined;
const logLine = trimmedUrl ? `waiting for response ${trimmedUrl}` : undefined; return this._waitForEvent(this._channel, Events.Page.Response, { predicate, timeout: options.timeout }, logLine);
return this._waitForEvent(channel, Events.Page.Response, { predicate, timeout: options.timeout }, logLine);
});
} }
async waitForEvent(event: string, optionsOrPredicate: WaitForEventOptions = {}): Promise<any> { async waitForEvent(event: string, optionsOrPredicate: WaitForEventOptions = {}): Promise<any> {
return this._wrapApiCall(async channel => { return this._waitForEvent(this._channel, event, optionsOrPredicate, `waiting for event "${event}"`);
return this._waitForEvent(channel, event, optionsOrPredicate, `waiting for event "${event}"`);
});
} }
private async _waitForEvent(channel: channels.EventTargetChannel, event: string, optionsOrPredicate: WaitForEventOptions, logLine?: string): Promise<any> { private async _waitForEvent(channel: channels.EventTargetChannel, event: string, optionsOrPredicate: WaitForEventOptions, logLine?: string): Promise<any> {
@ -408,35 +394,27 @@ export class Page extends ChannelOwner<channels.PageChannel> implements api.Page
} }
async goBack(options: channels.PageGoBackOptions = {}): Promise<Response | null> { async goBack(options: channels.PageGoBackOptions = {}): Promise<Response | null> {
return this._wrapApiCall(async (channel: channels.PageChannel) => { const waitUntil = verifyLoadState('waitUntil', options.waitUntil === undefined ? 'load' : options.waitUntil);
const waitUntil = verifyLoadState('waitUntil', options.waitUntil === undefined ? 'load' : options.waitUntil); return Response.fromNullable((await this._channel.goBack({ ...options, waitUntil })).response);
return Response.fromNullable((await channel.goBack({ ...options, waitUntil })).response);
});
} }
async goForward(options: channels.PageGoForwardOptions = {}): Promise<Response | null> { async goForward(options: channels.PageGoForwardOptions = {}): Promise<Response | null> {
return this._wrapApiCall(async (channel: channels.PageChannel) => { const waitUntil = verifyLoadState('waitUntil', options.waitUntil === undefined ? 'load' : options.waitUntil);
const waitUntil = verifyLoadState('waitUntil', options.waitUntil === undefined ? 'load' : options.waitUntil); return Response.fromNullable((await this._channel.goForward({ ...options, waitUntil })).response);
return Response.fromNullable((await channel.goForward({ ...options, waitUntil })).response);
});
} }
async emulateMedia(options: { media?: 'screen' | 'print' | null, colorScheme?: 'dark' | 'light' | 'no-preference' | null, reducedMotion?: 'reduce' | 'no-preference' | null, forcedColors?: 'active' | 'none' | null } = {}) { async emulateMedia(options: { media?: 'screen' | 'print' | null, colorScheme?: 'dark' | 'light' | 'no-preference' | null, reducedMotion?: 'reduce' | 'no-preference' | null, forcedColors?: 'active' | 'none' | null } = {}) {
return this._wrapApiCall(async (channel: channels.PageChannel) => { await this._channel.emulateMedia({
await channel.emulateMedia({ media: options.media === null ? 'null' : options.media,
media: options.media === null ? 'null' : options.media, colorScheme: options.colorScheme === null ? 'null' : options.colorScheme,
colorScheme: options.colorScheme === null ? 'null' : options.colorScheme, reducedMotion: options.reducedMotion === null ? 'null' : options.reducedMotion,
reducedMotion: options.reducedMotion === null ? 'null' : options.reducedMotion, forcedColors: options.forcedColors === null ? 'null' : options.forcedColors,
forcedColors: options.forcedColors === null ? 'null' : options.forcedColors,
});
}); });
} }
async setViewportSize(viewportSize: Size) { async setViewportSize(viewportSize: Size) {
return this._wrapApiCall(async (channel: channels.PageChannel) => { this._viewportSize = viewportSize;
this._viewportSize = viewportSize; await this._channel.setViewportSize({ viewportSize });
await channel.setViewportSize({ viewportSize });
});
} }
viewportSize(): Size | null { viewportSize(): Size | null {
@ -449,26 +427,20 @@ export class Page extends ChannelOwner<channels.PageChannel> implements api.Page
} }
async addInitScript(script: Function | string | { path?: string, content?: string }, arg?: any) { async addInitScript(script: Function | string | { path?: string, content?: string }, arg?: any) {
return this._wrapApiCall(async (channel: channels.PageChannel) => { const source = await evaluationScript(script, arg);
const source = await evaluationScript(script, arg); await this._channel.addInitScript({ source });
await channel.addInitScript({ source });
});
} }
async route(url: URLMatch, handler: RouteHandlerCallback, options: { times?: number } = {}): Promise<void> { async route(url: URLMatch, handler: RouteHandlerCallback, options: { times?: number } = {}): Promise<void> {
return this._wrapApiCall(async (channel: channels.PageChannel) => { this._routes.unshift(new RouteHandler(this._browserContext._options.baseURL, url, handler, options.times));
this._routes.unshift(new RouteHandler(this._browserContext._options.baseURL, url, handler, options.times)); if (this._routes.length === 1)
if (this._routes.length === 1) await this._channel.setNetworkInterceptionEnabled({ enabled: true });
await channel.setNetworkInterceptionEnabled({ enabled: true });
});
} }
async unroute(url: URLMatch, handler?: RouteHandlerCallback): Promise<void> { async unroute(url: URLMatch, handler?: RouteHandlerCallback): Promise<void> {
return this._wrapApiCall(async (channel: channels.PageChannel) => { this._routes = this._routes.filter(route => route.url !== url || (handler && route.handler !== handler));
this._routes = this._routes.filter(route => route.url !== url || (handler && route.handler !== handler)); if (!this._routes.length)
if (!this._routes.length) await this._disableInterception(this._channel);
await this._disableInterception(channel);
});
} }
private async _disableInterception(channel: channels.PageChannel) { private async _disableInterception(channel: channels.PageChannel) {
@ -476,18 +448,16 @@ export class Page extends ChannelOwner<channels.PageChannel> implements api.Page
} }
async screenshot(options: channels.PageScreenshotOptions & { path?: string } = {}): Promise<Buffer> { async screenshot(options: channels.PageScreenshotOptions & { path?: string } = {}): Promise<Buffer> {
return this._wrapApiCall(async (channel: channels.PageChannel) => { const copy = { ...options };
const copy = { ...options }; if (!copy.type)
if (!copy.type) copy.type = determineScreenshotType(options);
copy.type = determineScreenshotType(options); const result = await this._channel.screenshot(copy);
const result = await channel.screenshot(copy); const buffer = Buffer.from(result.binary, 'base64');
const buffer = Buffer.from(result.binary, 'base64'); if (options.path) {
if (options.path) { await mkdirIfNeeded(options.path);
await mkdirIfNeeded(options.path); await fs.promises.writeFile(options.path, buffer);
await fs.promises.writeFile(options.path, buffer); }
} return buffer;
return buffer;
});
} }
async title(): Promise<string> { async title(): Promise<string> {
@ -495,9 +465,7 @@ export class Page extends ChannelOwner<channels.PageChannel> implements api.Page
} }
async bringToFront(): Promise<void> { async bringToFront(): Promise<void> {
return this._wrapApiCall(async (channel: channels.PageChannel) => { await this._channel.bringToFront();
await channel.bringToFront();
});
} }
async close(options: { runBeforeUnload?: boolean } = { runBeforeUnload: undefined }) { async close(options: { runBeforeUnload?: boolean } = { runBeforeUnload: undefined }) {
@ -668,33 +636,29 @@ export class Page extends ChannelOwner<channels.PageChannel> implements api.Page
} }
async pause() { async pause() {
return this.context()._wrapApiCall(async (channel: channels.BrowserContextChannel) => { await this.context()._channel.pause();
await channel.pause();
});
} }
async pdf(options: PDFOptions = {}): Promise<Buffer> { async pdf(options: PDFOptions = {}): Promise<Buffer> {
return this._wrapApiCall(async (channel: channels.PageChannel) => { const transportOptions: channels.PagePdfParams = { ...options } as channels.PagePdfParams;
const transportOptions: channels.PagePdfParams = { ...options } as channels.PagePdfParams; if (transportOptions.margin)
if (transportOptions.margin) transportOptions.margin = { ...transportOptions.margin };
transportOptions.margin = { ...transportOptions.margin }; if (typeof options.width === 'number')
if (typeof options.width === 'number') transportOptions.width = options.width + 'px';
transportOptions.width = options.width + 'px'; if (typeof options.height === 'number')
if (typeof options.height === 'number') transportOptions.height = options.height + 'px';
transportOptions.height = options.height + 'px'; for (const margin of ['top', 'right', 'bottom', 'left']) {
for (const margin of ['top', 'right', 'bottom', 'left']) { const index = margin as 'top' | 'right' | 'bottom' | 'left';
const index = margin as 'top' | 'right' | 'bottom' | 'left'; if (options.margin && typeof options.margin[index] === 'number')
if (options.margin && typeof options.margin[index] === 'number') transportOptions.margin![index] = transportOptions.margin![index] + 'px';
transportOptions.margin![index] = transportOptions.margin![index] + 'px'; }
} const result = await this._channel.pdf(transportOptions);
const result = await channel.pdf(transportOptions); const buffer = Buffer.from(result.pdf, 'base64');
const buffer = Buffer.from(result.pdf, 'base64'); if (options.path) {
if (options.path) { await fs.promises.mkdir(path.dirname(options.path), { recursive: true });
await fs.promises.mkdir(path.dirname(options.path), { recursive: true }); await fs.promises.writeFile(options.path, buffer);
await fs.promises.writeFile(options.path, buffer); }
} return buffer;
return buffer;
});
} }
} }