diff --git a/src/page.ts b/src/page.ts index df1f87c556..8958c1290b 100644 --- a/src/page.ts +++ b/src/page.ts @@ -232,6 +232,10 @@ export class Page extends EventEmitter { return this._attributeToPage(() => this.mainFrame().evaluateHandle(pageFunction, arg)); } + async _evaluateExpressionHandle(expression: string, isFunction: boolean, arg: any): Promise { + return this._attributeToPage(() => this.mainFrame()._evaluateExpressionHandle(expression, isFunction, arg)); + } + async $eval(selector: string, pageFunction: js.FuncOn, arg: Arg): Promise; async $eval(selector: string, pageFunction: js.FuncOn, arg?: any): Promise; async $eval(selector: string, pageFunction: js.FuncOn, arg: Arg): Promise { @@ -239,6 +243,10 @@ export class Page extends EventEmitter { return this._attributeToPage(() => this.mainFrame().$eval(selector, pageFunction, arg)); } + async _$evalExpression(selector: string, expression: string, isFunction: boolean, arg: any): Promise { + return this._attributeToPage(() => this.mainFrame()._$evalExpression(selector, expression, isFunction, arg)); + } + async $$eval(selector: string, pageFunction: js.FuncOn, arg: Arg): Promise; async $$eval(selector: string, pageFunction: js.FuncOn, arg?: any): Promise; async $$eval(selector: string, pageFunction: js.FuncOn, arg: Arg): Promise { @@ -246,6 +254,10 @@ export class Page extends EventEmitter { return this._attributeToPage(() => this.mainFrame().$$eval(selector, pageFunction, arg)); } + async _$$evalExpression(selector: string, expression: string, isFunction: boolean, arg: any): Promise { + return this._attributeToPage(() => this.mainFrame()._$$evalExpression(selector, expression, isFunction, arg)); + } + async $$(selector: string): Promise[]> { return this._attributeToPage(() => this.mainFrame().$$(selector)); } @@ -393,6 +405,10 @@ export class Page extends EventEmitter { return this._attributeToPage(() => this.mainFrame().evaluate(pageFunction, arg)); } + async _evaluateExpression(expression: string, isFunction: boolean, arg: any): Promise { + return this._attributeToPage(() => this.mainFrame()._evaluateExpression(expression, isFunction, arg)); + } + async addInitScript(script: Function | string | { path?: string, content?: string }, arg?: any) { const source = await helper.evaluationScript(script, arg); await this._addInitScriptExpression(source); @@ -556,6 +572,10 @@ export class Page extends EventEmitter { return this._attributeToPage(() => this.mainFrame().waitForFunction(pageFunction, arg, options)); } + async _waitForFunctionExpression(expression: string, isFunction: boolean, arg: any, options: types.WaitForFunctionOptions = {}): Promise> { + return this._attributeToPage(() => this.mainFrame()._waitForFunctionExpression(expression, isFunction, arg, options)); + } + workers(): Worker[] { return [...this._workers.values()]; } diff --git a/src/rpc/channels.ts b/src/rpc/channels.ts index bccca4bb3f..fc8b9ccfb2 100644 --- a/src/rpc/channels.ts +++ b/src/rpc/channels.ts @@ -129,39 +129,39 @@ export type PageInitializer = { export interface FrameChannel extends Channel { - $$eval(params: { selector: string; expression: string, isFunction: boolean, arg: any }): Promise; - $eval(params: { selector: string; expression: string, isFunction: boolean, arg: any }): Promise; - addScriptTag(params: { options: { url?: string | undefined, path?: string | undefined, content?: string | undefined, type?: string | undefined } }): Promise; - addStyleTag(params: { options: { url?: string | undefined, path?: string | undefined, content?: string | undefined } }): Promise; - check(params: { selector: string, options: types.TimeoutOptions & { force?: boolean } & { noWaitAfter?: boolean } }): Promise; - click(params: { selector: string, options: types.PointerActionOptions & types.MouseClickOptions & types.TimeoutOptions & { force?: boolean } & { noWaitAfter?: boolean } }): Promise; + $$eval(params: { selector: string; expression: string, isFunction: boolean, arg: any, isPage?: boolean }): Promise; + $eval(params: { selector: string; expression: string, isFunction: boolean, arg: any, isPage?: boolean }): Promise; + addScriptTag(params: { options: { url?: string | undefined, path?: string | undefined, content?: string | undefined, type?: string | undefined }, isPage?: boolean }): Promise; + addStyleTag(params: { options: { url?: string | undefined, path?: string | undefined, content?: string | undefined }, isPage?: boolean }): Promise; + check(params: { selector: string, options: types.TimeoutOptions & { force?: boolean } & { noWaitAfter?: boolean }, isPage?: boolean }): Promise; + click(params: { selector: string, options: types.PointerActionOptions & types.MouseClickOptions & types.TimeoutOptions & { force?: boolean } & { noWaitAfter?: boolean }, isPage?: boolean }): Promise; content(): Promise; - dblclick(params: { selector: string, options: types.PointerActionOptions & types.MouseMultiClickOptions & types.TimeoutOptions & { force?: boolean }}): Promise; - dispatchEvent(params: { selector: string, type: string, eventInit: Object | undefined, options: types.TimeoutOptions }): Promise; - evaluateExpression(params: { expression: string, isFunction: boolean, arg: any }): Promise; - evaluateExpressionHandle(params: { expression: string, isFunction: boolean, arg: any}): Promise; - fill(params: { selector: string, value: string, options: types.NavigatingActionWaitOptions }): Promise; - focus(params: { selector: string, options: types.TimeoutOptions }): Promise; + dblclick(params: { selector: string, options: types.PointerActionOptions & types.MouseMultiClickOptions & types.TimeoutOptions & { force?: boolean }, isPage?: boolean}): Promise; + dispatchEvent(params: { selector: string, type: string, eventInit: Object | undefined, options: types.TimeoutOptions, isPage?: boolean }): Promise; + evaluateExpression(params: { expression: string, isFunction: boolean, arg: any, isPage?: boolean }): Promise; + evaluateExpressionHandle(params: { expression: string, isFunction: boolean, arg: any, isPage?: boolean }): Promise; + fill(params: { selector: string, value: string, options: types.NavigatingActionWaitOptions, isPage?: boolean }): Promise; + focus(params: { selector: string, options: types.TimeoutOptions, isPage?: boolean }): Promise; frameElement(): Promise; - getAttribute(params: { selector: string, name: string, options: types.TimeoutOptions }): Promise; - goto(params: { url: string, options: types.GotoOptions }): Promise; - hover(params: { selector: string, options: types.PointerActionOptions & types.TimeoutOptions & { force?: boolean } }): Promise; - innerHTML(params: { selector: string, options: types.TimeoutOptions }): Promise; - innerText(params: { selector: string, options: types.TimeoutOptions }): Promise; - press(params: { selector: string, key: string, options: { delay?: number | undefined } & types.TimeoutOptions & { noWaitAfter?: boolean } }): Promise; - querySelector(params: { selector: string }): Promise; - querySelectorAll(params: { selector: string }): Promise; - selectOption(params: { selector: string, values: string | ElementHandleChannel | types.SelectOption | string[] | ElementHandleChannel[] | types.SelectOption[] | null, options: types.NavigatingActionWaitOptions }): Promise; - setContent(params: { html: string, options: types.NavigateOptions }): Promise; - setInputFiles(params: { selector: string, files: { name: string, mimeType: string, buffer: string }[], options: types.NavigatingActionWaitOptions }): Promise; - textContent(params: { selector: string, options: types.TimeoutOptions }): Promise; + getAttribute(params: { selector: string, name: string, options: types.TimeoutOptions, isPage?: boolean }): Promise; + goto(params: { url: string, options: types.GotoOptions, isPage?: boolean }): Promise; + hover(params: { selector: string, options: types.PointerActionOptions & types.TimeoutOptions & { force?: boolean }, isPage?: boolean }): Promise; + innerHTML(params: { selector: string, options: types.TimeoutOptions, isPage?: boolean }): Promise; + innerText(params: { selector: string, options: types.TimeoutOptions, isPage?: boolean }): Promise; + press(params: { selector: string, key: string, options: { delay?: number | undefined } & types.TimeoutOptions & { noWaitAfter?: boolean }, isPage?: boolean }): Promise; + querySelector(params: { selector: string, isPage?: boolean }): Promise; + querySelectorAll(params: { selector: string, isPage?: boolean }): Promise; + selectOption(params: { selector: string, values: string | ElementHandleChannel | types.SelectOption | string[] | ElementHandleChannel[] | types.SelectOption[] | null, options: types.NavigatingActionWaitOptions, isPage?: boolean }): Promise; + setContent(params: { html: string, options: types.NavigateOptions, isPage?: boolean }): Promise; + setInputFiles(params: { selector: string, files: { name: string, mimeType: string, buffer: string }[], options: types.NavigatingActionWaitOptions, isPage?: boolean }): Promise; + textContent(params: { selector: string, options: types.TimeoutOptions, isPage?: boolean }): Promise; title(): Promise; - type(params: { selector: string, text: string, options: { delay?: number | undefined } & types.TimeoutOptions & { noWaitAfter?: boolean } }): Promise; - uncheck(params: { selector: string, options: types.TimeoutOptions & { force?: boolean } & { noWaitAfter?: boolean } }): Promise; - waitForFunction(params: { expression: string, isFunction: boolean, arg: any; options: types.WaitForFunctionOptions }): Promise; - waitForLoadState(params: { state: types.LifecycleEvent, options: types.TimeoutOptions }): Promise; - waitForNavigation(params: { options: types.WaitForNavigationOptions }): Promise; - waitForSelector(params: { selector: string, options: types.WaitForElementOptions }): Promise; + type(params: { selector: string, text: string, options: { delay?: number | undefined } & types.TimeoutOptions & { noWaitAfter?: boolean }, isPage?: boolean }): Promise; + uncheck(params: { selector: string, options: types.TimeoutOptions & { force?: boolean } & { noWaitAfter?: boolean }, isPage?: boolean }): Promise; + waitForFunction(params: { expression: string, isFunction: boolean, arg: any; options: types.WaitForFunctionOptions, isPage?: boolean }): Promise; + waitForLoadState(params: { state: types.LifecycleEvent, options: types.TimeoutOptions, isPage?: boolean }): Promise; + waitForNavigation(params: { options: types.WaitForNavigationOptions, isPage?: boolean }): Promise; + waitForSelector(params: { selector: string, options: types.WaitForElementOptions, isPage?: boolean }): Promise; } export type FrameInitializer = { url: string, @@ -245,7 +245,7 @@ export type RouteInitializer = { export interface ResponseChannel extends Channel { - body(): Promise; + body(): Promise; finished(): Promise; } export type ResponseInitializer = { @@ -290,7 +290,7 @@ export type DialogInitializer = { export interface DownloadChannel extends Channel { - path(): Promise; + path(): Promise; failure(): Promise; delete(): Promise; } diff --git a/src/rpc/client/frame.ts b/src/rpc/client/frame.ts index e7d5fc5ca1..3c3cd5b0b6 100644 --- a/src/rpc/client/frame.ts +++ b/src/rpc/client/frame.ts @@ -60,15 +60,15 @@ export class Frame extends ChannelOwner { } async goto(url: string, options: GotoOptions = {}): Promise { - return Response.fromNullable(await this._channel.goto({ url, options })); + return Response.fromNullable(await this._channel.goto({ url, options, isPage: this._page!._isPageCall })); } async waitForNavigation(options: types.WaitForNavigationOptions = {}): Promise { - return Response.fromNullable(await this._channel.waitForNavigation({ options })); + return Response.fromNullable(await this._channel.waitForNavigation({ options, isPage: this._page!._isPageCall })); } async waitForLoadState(state: types.LifecycleEvent = 'load', options: types.TimeoutOptions = {}): Promise { - await this._channel.waitForLoadState({ state, options }); + await this._channel.waitForLoadState({ state, options, isPage: this._page!._isPageCall }); } async frameElement(): Promise { @@ -79,44 +79,44 @@ export class Frame extends ChannelOwner { async evaluateHandle(pageFunction: Func1, arg?: any): Promise>; async evaluateHandle(pageFunction: Func1, arg: Arg): Promise> { assertMaxArguments(arguments.length, 2); - return JSHandle.from(await this._channel.evaluateExpressionHandle({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) })) as SmartHandle; + return JSHandle.from(await this._channel.evaluateExpressionHandle({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg), isPage: this._page!._isPageCall })) as SmartHandle; } async evaluate(pageFunction: Func1, arg: Arg): Promise; async evaluate(pageFunction: Func1, arg?: any): Promise; async evaluate(pageFunction: Func1, arg: Arg): Promise { assertMaxArguments(arguments.length, 2); - return parseResult(await this._channel.evaluateExpression({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) })); + return parseResult(await this._channel.evaluateExpression({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg), isPage: this._page!._isPageCall })); } async $(selector: string): Promise | null> { - return ElementHandle.fromNullable(await this._channel.querySelector({ selector })) as ElementHandle | null; + return ElementHandle.fromNullable(await this._channel.querySelector({ selector, isPage: this._page!._isPageCall })) as ElementHandle | null; } async waitForSelector(selector: string, options: types.WaitForElementOptions = {}): Promise | null> { - return ElementHandle.fromNullable(await this._channel.waitForSelector({ selector, options })) as ElementHandle | null; + return ElementHandle.fromNullable(await this._channel.waitForSelector({ selector, options, isPage: this._page!._isPageCall })) as ElementHandle | null; } async dispatchEvent(selector: string, type: string, eventInit?: Object, options: types.TimeoutOptions = {}): Promise { - await this._channel.dispatchEvent({ selector, type, eventInit, options }); + await this._channel.dispatchEvent({ selector, type, eventInit, options, isPage: this._page!._isPageCall }); } async $eval(selector: string, pageFunction: FuncOn, arg: Arg): Promise; async $eval(selector: string, pageFunction: FuncOn, arg?: any): Promise; async $eval(selector: string, pageFunction: FuncOn, arg: Arg): Promise { assertMaxArguments(arguments.length, 3); - return await this._channel.$eval({ selector, expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) }); + return await this._channel.$eval({ selector, expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg), isPage: this._page!._isPageCall }); } async $$eval(selector: string, pageFunction: FuncOn, arg: Arg): Promise; async $$eval(selector: string, pageFunction: FuncOn, arg?: any): Promise; async $$eval(selector: string, pageFunction: FuncOn, arg: Arg): Promise { assertMaxArguments(arguments.length, 3); - return await this._channel.$$eval({ selector, expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) }); + return await this._channel.$$eval({ selector, expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg), isPage: this._page!._isPageCall }); } async $$(selector: string): Promise[]> { - const result = await this._channel.querySelectorAll({ selector }); + const result = await this._channel.querySelectorAll({ selector, isPage: this._page!._isPageCall }); return result.map(c => ElementHandle.from(c) as ElementHandle); } @@ -125,7 +125,7 @@ export class Frame extends ChannelOwner { } async setContent(html: string, options: types.NavigateOptions = {}): Promise { - await this._channel.setContent({ html, options }); + await this._channel.setContent({ html, options, isPage: this._page!._isPageCall }); } name(): string { @@ -149,72 +149,72 @@ export class Frame extends ChannelOwner { } async addScriptTag(options: { url?: string, path?: string, content?: string, type?: string }): Promise { - return ElementHandle.from(await this._channel.addScriptTag({ options })); + return ElementHandle.from(await this._channel.addScriptTag({ options, isPage: this._page!._isPageCall })); } async addStyleTag(options: { url?: string; path?: string; content?: string; }): Promise { - return ElementHandle.from(await this._channel.addStyleTag({ options })); + return ElementHandle.from(await this._channel.addStyleTag({ options, isPage: this._page!._isPageCall })); } async click(selector: string, options: types.MouseClickOptions & types.PointerActionWaitOptions & types.NavigatingActionWaitOptions = {}) { - return await this._channel.click({ selector, options }); + return await this._channel.click({ selector, options, isPage: this._page!._isPageCall }); } async dblclick(selector: string, options: types.MouseMultiClickOptions & types.PointerActionWaitOptions & types.NavigatingActionWaitOptions = {}) { - return await this._channel.dblclick({ selector, options }); + return await this._channel.dblclick({ selector, options, isPage: this._page!._isPageCall }); } async fill(selector: string, value: string, options: types.NavigatingActionWaitOptions = {}) { - return await this._channel.fill({ selector, value, options }); + return await this._channel.fill({ selector, value, options, isPage: this._page!._isPageCall }); } async focus(selector: string, options: types.TimeoutOptions = {}) { - await this._channel.focus({ selector, options }); + await this._channel.focus({ selector, options, isPage: this._page!._isPageCall }); } async textContent(selector: string, options: types.TimeoutOptions = {}): Promise { - return await this._channel.textContent({ selector, options }); + return await this._channel.textContent({ selector, options, isPage: this._page!._isPageCall }); } async innerText(selector: string, options: types.TimeoutOptions = {}): Promise { - return await this._channel.innerText({ selector, options }); + return await this._channel.innerText({ selector, options, isPage: this._page!._isPageCall }); } async innerHTML(selector: string, options: types.TimeoutOptions = {}): Promise { - return await this._channel.innerHTML({ selector, options }); + return await this._channel.innerHTML({ selector, options, isPage: this._page!._isPageCall }); } async getAttribute(selector: string, name: string, options: types.TimeoutOptions = {}): Promise { - return await this._channel.getAttribute({ selector, name, options }); + return await this._channel.getAttribute({ selector, name, options, isPage: this._page!._isPageCall }); } async hover(selector: string, options: types.PointerActionOptions & types.PointerActionWaitOptions = {}) { - await this._channel.hover({ selector, options }); + await this._channel.hover({ selector, options, isPage: this._page!._isPageCall }); } async selectOption(selector: string, values: string | ElementHandle | types.SelectOption | string[] | ElementHandle[] | types.SelectOption[] | null, options: types.NavigatingActionWaitOptions = {}): Promise { - return await this._channel.selectOption({ selector, values: convertSelectOptionValues(values), options }); + return await this._channel.selectOption({ selector, values: convertSelectOptionValues(values), options, isPage: this._page!._isPageCall }); } async setInputFiles(selector: string, files: string | types.FilePayload | string[] | types.FilePayload[], options: types.NavigatingActionWaitOptions = {}): Promise { const filePayloads = await normalizeFilePayloads(files); - await this._channel.setInputFiles({ selector, files: filePayloads.map(f => ({ name: f.name, mimeType: f.mimeType, buffer: f.buffer.toString('base64') })), options }); + await this._channel.setInputFiles({ selector, files: filePayloads.map(f => ({ name: f.name, mimeType: f.mimeType, buffer: f.buffer.toString('base64') })), options, isPage: this._page!._isPageCall }); } async type(selector: string, text: string, options: { delay?: number } & types.NavigatingActionWaitOptions = {}) { - await this._channel.type({ selector, text, options }); + await this._channel.type({ selector, text, options, isPage: this._page!._isPageCall }); } async press(selector: string, key: string, options: { delay?: number } & types.NavigatingActionWaitOptions = {}) { - await this._channel.press({ selector, key, options }); + await this._channel.press({ selector, key, options, isPage: this._page!._isPageCall }); } async check(selector: string, options: types.PointerActionWaitOptions & types.NavigatingActionWaitOptions = {}) { - await this._channel.check({ selector, options }); + await this._channel.check({ selector, options, isPage: this._page!._isPageCall }); } async uncheck(selector: string, options: types.PointerActionWaitOptions & types.NavigatingActionWaitOptions = {}) { - await this._channel.uncheck({ selector, options }); + await this._channel.uncheck({ selector, options, isPage: this._page!._isPageCall }); } async waitForTimeout(timeout: number) { @@ -224,7 +224,7 @@ export class Frame extends ChannelOwner { async waitForFunction(pageFunction: Func1, arg: Arg, options?: types.WaitForFunctionOptions): Promise>; async waitForFunction(pageFunction: Func1, arg?: any, options?: types.WaitForFunctionOptions): Promise>; async waitForFunction(pageFunction: Func1, arg: Arg, options: types.WaitForFunctionOptions = {}): Promise> { - return JSHandle.from(await this._channel.waitForFunction({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg), options })) as SmartHandle; + return JSHandle.from(await this._channel.waitForFunction({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg), options, isPage: this._page!._isPageCall })) as SmartHandle; } async title(): Promise { diff --git a/src/rpc/client/network.ts b/src/rpc/client/network.ts index 927797b2f5..5fcec44f59 100644 --- a/src/rpc/client/network.ts +++ b/src/rpc/client/network.ts @@ -205,7 +205,7 @@ export class Response extends ChannelOwner } async body(): Promise { - return await this._channel.body(); + return Buffer.from(await this._channel.body(), 'base64'); } async text(): Promise { diff --git a/src/rpc/client/page.ts b/src/rpc/client/page.ts index a0c02e0da4..90106bee15 100644 --- a/src/rpc/client/page.ts +++ b/src/rpc/client/page.ts @@ -55,6 +55,7 @@ export class Page extends ChannelOwner { readonly _bindings = new Map(); private _pendingWaitForEvents = new Map<(error: Error) => void, string>(); private _timeoutSettings = new TimeoutSettings(); + _isPageCall = false; static from(page: PageChannel): Page { return page._object; @@ -203,45 +204,54 @@ export class Page extends ChannelOwner { this._channel.setDefaultTimeoutNoReply({ timeout }); } + private _attributeToPage(func: () => T): T { + try { + this._isPageCall = true; + return func(); + } finally { + this._isPageCall = false; + } + } + async $(selector: string): Promise | null> { - return await this._mainFrame.$(selector); + return this._attributeToPage(() => this._mainFrame.$(selector)); } async waitForSelector(selector: string, options?: types.WaitForElementOptions): Promise | null> { - return await this._mainFrame.waitForSelector(selector, options); + return this._attributeToPage(() => this._mainFrame.waitForSelector(selector, options)); } async dispatchEvent(selector: string, type: string, eventInit?: Object, options?: types.TimeoutOptions): Promise { - return await this._mainFrame.dispatchEvent(selector, type, eventInit, options); + return this._attributeToPage(() => this._mainFrame.dispatchEvent(selector, type, eventInit, options)); } async evaluateHandle(pageFunction: Func1, arg: Arg): Promise>; async evaluateHandle(pageFunction: Func1, arg?: any): Promise>; async evaluateHandle(pageFunction: Func1, arg: Arg): Promise> { assertMaxArguments(arguments.length, 2); - return await this._mainFrame.evaluateHandle(pageFunction, arg); + return this._attributeToPage(() => this._mainFrame.evaluateHandle(pageFunction, arg)); } async $eval(selector: string, pageFunction: FuncOn, arg: Arg): Promise; async $eval(selector: string, pageFunction: FuncOn, arg?: any): Promise; async $eval(selector: string, pageFunction: FuncOn, arg: Arg): Promise { assertMaxArguments(arguments.length, 3); - return await this._mainFrame.$eval(selector, pageFunction, arg); + return this._attributeToPage(() => this._mainFrame.$eval(selector, pageFunction, arg)); } async $$eval(selector: string, pageFunction: FuncOn, arg: Arg): Promise; async $$eval(selector: string, pageFunction: FuncOn, arg?: any): Promise; async $$eval(selector: string, pageFunction: FuncOn, arg: Arg): Promise { assertMaxArguments(arguments.length, 3); - return await this._mainFrame.$$eval(selector, pageFunction, arg); + return this._attributeToPage(() => this._mainFrame.$$eval(selector, pageFunction, arg)); } async $$(selector: string): Promise[]> { - return await this._mainFrame.$$(selector); + return this._attributeToPage(() => this._mainFrame.$$(selector)); } async addScriptTag(options: { url?: string; path?: string; content?: string; type?: string; }): Promise { - return await this._mainFrame.addScriptTag(options); + return this._attributeToPage(() => this._mainFrame.addScriptTag(options)); } async addStyleTag(options: { url?: string; path?: string; content?: string; }): Promise { @@ -266,19 +276,19 @@ export class Page extends ChannelOwner { } url(): string { - return this.mainFrame().url(); + return this._attributeToPage(() => this._mainFrame.url()); } async content(): Promise { - return this.mainFrame().content(); + return this._attributeToPage(() => this._mainFrame.content()); } async setContent(html: string, options?: types.NavigateOptions): Promise { - return this.mainFrame().setContent(html, options); + return this._attributeToPage(() => this._mainFrame.setContent(html, options)); } async goto(url: string, options?: GotoOptions): Promise { - return this.mainFrame().goto(url, options); + return this._attributeToPage(() => this._mainFrame.goto(url, options)); } async reload(options?: types.NavigateOptions): Promise { @@ -286,11 +296,11 @@ export class Page extends ChannelOwner { } async waitForLoadState(state?: types.LifecycleEvent, options?: types.TimeoutOptions): Promise { - return this._mainFrame.waitForLoadState(state, options); + return this._attributeToPage(() => this._mainFrame.waitForLoadState(state, options)); } async waitForNavigation(options?: types.WaitForNavigationOptions): Promise { - return this._mainFrame.waitForNavigation(options); + return this._attributeToPage(() => this._mainFrame.waitForNavigation(options)); } async waitForRequest(urlOrPredicate: string | RegExp | ((r: Request) => boolean), options: types.TimeoutOptions = {}): Promise { @@ -346,7 +356,7 @@ export class Page extends ChannelOwner { async evaluate(pageFunction: Func1, arg?: any): Promise; async evaluate(pageFunction: Func1, arg: Arg): Promise { assertMaxArguments(arguments.length, 2); - return this.mainFrame().evaluate(pageFunction, arg); + return this._attributeToPage(() => this._mainFrame.evaluate(pageFunction, arg)); } async addInitScript(script: Function | string | { path?: string, content?: string }, arg?: any) { @@ -371,7 +381,7 @@ export class Page extends ChannelOwner { } async title(): Promise { - return this.mainFrame().title(); + return this._attributeToPage(() => this._mainFrame.title()); } async close(options: { runBeforeUnload?: boolean } = {runBeforeUnload: undefined}) { @@ -385,73 +395,73 @@ export class Page extends ChannelOwner { } async click(selector: string, options?: types.MouseClickOptions & types.PointerActionWaitOptions & types.NavigatingActionWaitOptions) { - return this.mainFrame().click(selector, options); + return this._attributeToPage(() => this._mainFrame.click(selector, options)); } async dblclick(selector: string, options?: types.MouseMultiClickOptions & types.PointerActionWaitOptions & types.NavigatingActionWaitOptions) { - return this.mainFrame().dblclick(selector, options); + return this._attributeToPage(() => this._mainFrame.dblclick(selector, options)); } async fill(selector: string, value: string, options?: types.NavigatingActionWaitOptions) { - return this.mainFrame().fill(selector, value, options); + return this._attributeToPage(() => this._mainFrame.fill(selector, value, options)); } async focus(selector: string, options?: types.TimeoutOptions) { - return this.mainFrame().focus(selector, options); + return this._attributeToPage(() => this._mainFrame.focus(selector, options)); } async textContent(selector: string, options?: types.TimeoutOptions): Promise { - return this.mainFrame().textContent(selector, options); + return this._attributeToPage(() => this._mainFrame.textContent(selector, options)); } async innerText(selector: string, options?: types.TimeoutOptions): Promise { - return this.mainFrame().innerText(selector, options); + return this._attributeToPage(() => this._mainFrame.innerText(selector, options)); } async innerHTML(selector: string, options?: types.TimeoutOptions): Promise { - return this.mainFrame().innerHTML(selector, options); + return this._attributeToPage(() => this._mainFrame.innerHTML(selector, options)); } async getAttribute(selector: string, name: string, options?: types.TimeoutOptions): Promise { - return this.mainFrame().getAttribute(selector, name, options); + return this._attributeToPage(() => this._mainFrame.getAttribute(selector, name, options)); } async hover(selector: string, options?: types.PointerActionOptions & types.PointerActionWaitOptions) { - return this.mainFrame().hover(selector, options); + return this._attributeToPage(() => this._mainFrame.hover(selector, options)); } async selectOption(selector: string, values: string | ElementHandle | types.SelectOption | string[] | ElementHandle[] | types.SelectOption[] | null, options?: types.NavigatingActionWaitOptions): Promise { - return this.mainFrame().selectOption(selector, values, options); + return this._attributeToPage(() => this._mainFrame.selectOption(selector, values, options)); } async setInputFiles(selector: string, files: string | types.FilePayload | string[] | types.FilePayload[], options?: types.NavigatingActionWaitOptions): Promise { - return this.mainFrame().setInputFiles(selector, files, options); + return this._attributeToPage(() => this._mainFrame.setInputFiles(selector, files, options)); } async type(selector: string, text: string, options?: { delay?: number } & types.NavigatingActionWaitOptions) { - return this.mainFrame().type(selector, text, options); + return this._attributeToPage(() => this._mainFrame.type(selector, text, options)); } async press(selector: string, key: string, options?: { delay?: number } & types.NavigatingActionWaitOptions) { - return this.mainFrame().press(selector, key, options); + return this._attributeToPage(() => this._mainFrame.press(selector, key, options)); } async check(selector: string, options?: types.PointerActionWaitOptions & types.NavigatingActionWaitOptions) { - return this.mainFrame().check(selector, options); + return this._attributeToPage(() => this._mainFrame.check(selector, options)); } async uncheck(selector: string, options?: types.PointerActionWaitOptions & types.NavigatingActionWaitOptions) { - return this.mainFrame().uncheck(selector, options); + return this._attributeToPage(() => this._mainFrame.uncheck(selector, options)); } async waitForTimeout(timeout: number) { - await this.mainFrame().waitForTimeout(timeout); + await this._mainFrame.waitForTimeout(timeout); } async waitForFunction(pageFunction: Func1, arg: Arg, options?: types.WaitForFunctionOptions): Promise>; async waitForFunction(pageFunction: Func1, arg?: any, options?: types.WaitForFunctionOptions): Promise>; async waitForFunction(pageFunction: Func1, arg: Arg, options?: types.WaitForFunctionOptions): Promise> { - return this.mainFrame().waitForFunction(pageFunction, arg, options); + return this._attributeToPage(() => this._mainFrame.waitForFunction(pageFunction, arg, options)); } workers(): Worker[] { diff --git a/src/rpc/dispatcher.ts b/src/rpc/dispatcher.ts index 81015994d9..9e801eb5da 100644 --- a/src/rpc/dispatcher.ts +++ b/src/rpc/dispatcher.ts @@ -23,7 +23,7 @@ export class Dispatcher extends EventEmitter implements Chann readonly _guid: string; readonly _type: string; protected _scope: DispatcherScope; - _object: any; + _object: Type; constructor(scope: DispatcherScope, object: Type, type: string, initializer: Initializer, guid = type + '@' + helper.guid()) { super(); diff --git a/src/rpc/server/downloadDispatcher.ts b/src/rpc/server/downloadDispatcher.ts index a313b8c9d6..c03af0222d 100644 --- a/src/rpc/server/downloadDispatcher.ts +++ b/src/rpc/server/downloadDispatcher.ts @@ -32,7 +32,7 @@ export class DownloadDispatcher extends Dispatcher { + async path(): Promise { return this._object.path(); } diff --git a/src/rpc/server/frameDispatcher.ts b/src/rpc/server/frameDispatcher.ts index fb72249f56..217befd9aa 100644 --- a/src/rpc/server/frameDispatcher.ts +++ b/src/rpc/server/frameDispatcher.ts @@ -46,52 +46,63 @@ export class FrameDispatcher extends Dispatcher impleme this._frame = frame; } - async goto(params: { url: string, options: types.GotoOptions }): Promise { - return ResponseDispatcher.fromNullable(this._scope, await this._frame.goto(params.url, params.options)); + async goto(params: { url: string, options: types.GotoOptions, isPage?: boolean }): Promise { + const target = params.isPage ? this._frame._page : this._frame; + return ResponseDispatcher.fromNullable(this._scope, await target.goto(params.url, params.options)); } - async waitForLoadState(params: { state?: 'load' | 'domcontentloaded' | 'networkidle', options?: types.TimeoutOptions }): Promise { - await this._frame.waitForLoadState(params.state, params.options); + async waitForLoadState(params: { state?: 'load' | 'domcontentloaded' | 'networkidle', options?: types.TimeoutOptions, isPage?: boolean }): Promise { + const target = params.isPage ? this._frame._page : this._frame; + await target.waitForLoadState(params.state, params.options); } - async waitForNavigation(params: { options?: types.WaitForNavigationOptions }): Promise { - return ResponseDispatcher.fromNullable(this._scope, await this._frame.waitForNavigation(params.options)); + async waitForNavigation(params: { options?: types.WaitForNavigationOptions, isPage?: boolean }): Promise { + const target = params.isPage ? this._frame._page : this._frame; + return ResponseDispatcher.fromNullable(this._scope, await target.waitForNavigation(params.options)); } async frameElement(): Promise { return ElementHandleDispatcher.fromElement(this._scope, await this._frame.frameElement()); } - async evaluateExpression(params: { expression: string, isFunction: boolean, arg: any }): Promise { - return serializeResult(await this._frame._evaluateExpression(params.expression, params.isFunction, parseArgument(params.arg))); + async evaluateExpression(params: { expression: string, isFunction: boolean, arg: any, isPage?: boolean }): Promise { + const target = params.isPage ? this._frame._page : this._frame; + return serializeResult(await target._evaluateExpression(params.expression, params.isFunction, parseArgument(params.arg))); } - async evaluateExpressionHandle(params: { expression: string, isFunction: boolean, arg: any}): Promise { - return ElementHandleDispatcher.fromElement(this._scope, await this._frame._evaluateExpressionHandle(params.expression, params.isFunction, parseArgument(params.arg))); + async evaluateExpressionHandle(params: { expression: string, isFunction: boolean, arg: any, isPage?: boolean }): Promise { + const target = params.isPage ? this._frame._page : this._frame; + return ElementHandleDispatcher.fromElement(this._scope, await target._evaluateExpressionHandle(params.expression, params.isFunction, parseArgument(params.arg))); } - async waitForSelector(params: { selector: string, options: types.WaitForElementOptions }): Promise { - return ElementHandleDispatcher.fromNullableElement(this._scope, await this._frame.waitForSelector(params.selector, params.options)); + async waitForSelector(params: { selector: string, options: types.WaitForElementOptions, isPage?: boolean }): Promise { + const target = params.isPage ? this._frame._page : this._frame; + return ElementHandleDispatcher.fromNullableElement(this._scope, await target.waitForSelector(params.selector, params.options)); } - async dispatchEvent(params: { selector: string, type: string, eventInit: Object | undefined, options: types.TimeoutOptions }): Promise { - return this._frame.dispatchEvent(params.selector, params.type, params.eventInit, params.options); + async dispatchEvent(params: { selector: string, type: string, eventInit: Object | undefined, options: types.TimeoutOptions, isPage?: boolean }): Promise { + const target = params.isPage ? this._frame._page : this._frame; + return target.dispatchEvent(params.selector, params.type, params.eventInit, params.options); } - async $eval(params: { selector: string, expression: string, isFunction: boolean, arg: any }): Promise { - return serializeResult(await this._frame._$evalExpression(params.selector, params.expression, params.isFunction, parseArgument(params.arg))); + async $eval(params: { selector: string, expression: string, isFunction: boolean, arg: any, isPage?: boolean }): Promise { + const target = params.isPage ? this._frame._page : this._frame; + return serializeResult(await target._$evalExpression(params.selector, params.expression, params.isFunction, parseArgument(params.arg))); } - async $$eval(params: { selector: string, expression: string, isFunction: boolean, arg: any }): Promise { - return serializeResult(await this._frame._$$evalExpression(params.selector, params.expression, params.isFunction, parseArgument(params.arg))); + async $$eval(params: { selector: string, expression: string, isFunction: boolean, arg: any, isPage?: boolean }): Promise { + const target = params.isPage ? this._frame._page : this._frame; + return serializeResult(await target._$$evalExpression(params.selector, params.expression, params.isFunction, parseArgument(params.arg))); } - async querySelector(params: { selector: string }): Promise { - return ElementHandleDispatcher.fromNullableElement(this._scope, await this._frame.$(params.selector)); + async querySelector(params: { selector: string, isPage?: boolean }): Promise { + const target = params.isPage ? this._frame._page : this._frame; + return ElementHandleDispatcher.fromNullableElement(this._scope, await target.$(params.selector)); } - async querySelectorAll(params: { selector: string }): Promise { - const elements = await this._frame.$$(params.selector); + async querySelectorAll(params: { selector: string, isPage?: boolean }): Promise { + const target = params.isPage ? this._frame._page : this._frame; + const elements = await target.$$(params.selector); return elements.map(e => ElementHandleDispatcher.fromElement(this._scope, e)); } @@ -99,80 +110,99 @@ export class FrameDispatcher extends Dispatcher impleme return await this._frame.content(); } - async setContent(params: { html: string, options: types.NavigateOptions }): Promise { - await this._frame.setContent(params.html, params.options); + async setContent(params: { html: string, options: types.NavigateOptions, isPage?: boolean }): Promise { + const target = params.isPage ? this._frame._page : this._frame; + await target.setContent(params.html, params.options); } - async addScriptTag(params: { options: { url?: string | undefined, path?: string | undefined, content?: string | undefined, type?: string | undefined } }): Promise { - return ElementHandleDispatcher.fromElement(this._scope, await this._frame.addScriptTag(params.options)); + async addScriptTag(params: { options: { url?: string | undefined, path?: string | undefined, content?: string | undefined, type?: string | undefined }, isPage?: boolean }): Promise { + const target = params.isPage ? this._frame._page : this._frame; + return ElementHandleDispatcher.fromElement(this._scope, await target.addScriptTag(params.options)); } - async addStyleTag(params: { options: { url?: string | undefined, path?: string | undefined, content?: string | undefined } }): Promise { - return ElementHandleDispatcher.fromElement(this._scope, await this._frame.addStyleTag(params.options)); + async addStyleTag(params: { options: { url?: string | undefined, path?: string | undefined, content?: string | undefined }, isPage?: boolean }): Promise { + const target = params.isPage ? this._frame._page : this._frame; + return ElementHandleDispatcher.fromElement(this._scope, await target.addStyleTag(params.options)); } - async click(params: { selector: string, options: types.PointerActionOptions & types.MouseClickOptions & types.TimeoutOptions & { force?: boolean } & { noWaitAfter?: boolean } }): Promise { - await this._frame.click(params.selector, params.options); + async click(params: { selector: string, options: types.PointerActionOptions & types.MouseClickOptions & types.TimeoutOptions & { force?: boolean } & { noWaitAfter?: boolean }, isPage?: boolean }): Promise { + const target = params.isPage ? this._frame._page : this._frame; + await target.click(params.selector, params.options); } - async dblclick(params: { selector: string, options: types.PointerActionOptions & types.MouseMultiClickOptions & types.TimeoutOptions & { force?: boolean }}): Promise { - await this._frame.dblclick(params.selector, params.options); + async dblclick(params: { selector: string, options: types.PointerActionOptions & types.MouseMultiClickOptions & types.TimeoutOptions & { force?: boolean }, isPage?: boolean }): Promise { + const target = params.isPage ? this._frame._page : this._frame; + await target.dblclick(params.selector, params.options); } - async fill(params: { selector: string, value: string, options: types.NavigatingActionWaitOptions }): Promise { - await this._frame.fill(params.selector, params.value, params.options); + async fill(params: { selector: string, value: string, options: types.NavigatingActionWaitOptions, isPage?: boolean }): Promise { + const target = params.isPage ? this._frame._page : this._frame; + await target.fill(params.selector, params.value, params.options); } - async focus(params: { selector: string, options: types.TimeoutOptions }): Promise { - await this._frame.focus(params.selector, params.options); + async focus(params: { selector: string, options: types.TimeoutOptions, isPage?: boolean }): Promise { + const target = params.isPage ? this._frame._page : this._frame; + await target.focus(params.selector, params.options); } - async textContent(params: { selector: string, options: types.TimeoutOptions }): Promise { - return await this._frame.textContent(params.selector, params.options); + async textContent(params: { selector: string, options: types.TimeoutOptions, isPage?: boolean }): Promise { + const target = params.isPage ? this._frame._page : this._frame; + return await target.textContent(params.selector, params.options); } - async innerText(params: { selector: string, options: types.TimeoutOptions }): Promise { - return await this._frame.innerText(params.selector, params.options); + async innerText(params: { selector: string, options: types.TimeoutOptions, isPage?: boolean }): Promise { + const target = params.isPage ? this._frame._page : this._frame; + return await target.innerText(params.selector, params.options); } - async innerHTML(params: { selector: string, options: types.TimeoutOptions }): Promise { - return await this._frame.innerHTML(params.selector, params.options); + async innerHTML(params: { selector: string, options: types.TimeoutOptions, isPage?: boolean }): Promise { + const target = params.isPage ? this._frame._page : this._frame; + return await target.innerHTML(params.selector, params.options); } - async getAttribute(params: { selector: string, name: string, options: types.TimeoutOptions }): Promise { - return await this._frame.getAttribute(params.selector, params.name, params.options); + async getAttribute(params: { selector: string, name: string, options: types.TimeoutOptions, isPage?: boolean }): Promise { + const target = params.isPage ? this._frame._page : this._frame; + return await target.getAttribute(params.selector, params.name, params.options); } - async hover(params: { selector: string, options: types.PointerActionOptions & types.TimeoutOptions & { force?: boolean } }): Promise { - await this._frame.hover(params.selector, params.options); + async hover(params: { selector: string, options: types.PointerActionOptions & types.TimeoutOptions & { force?: boolean }, isPage?: boolean }): Promise { + const target = params.isPage ? this._frame._page : this._frame; + await target.hover(params.selector, params.options); } - async selectOption(params: { selector: string, values: string | ElementHandleChannel | types.SelectOption | string[] | ElementHandleChannel[] | types.SelectOption[] | null, options: types.NavigatingActionWaitOptions }): Promise { - return this._frame.selectOption(params.selector, convertSelectOptionValues(params.values), params.options); + async selectOption(params: { selector: string, values: string | ElementHandleChannel | types.SelectOption | string[] | ElementHandleChannel[] | types.SelectOption[] | null, options: types.NavigatingActionWaitOptions, isPage?: boolean }): Promise { + const target = params.isPage ? this._frame._page : this._frame; + return target.selectOption(params.selector, convertSelectOptionValues(params.values), params.options); } - async setInputFiles(params: { selector: string, files: { name: string, mimeType: string, buffer: string }[], options: types.NavigatingActionWaitOptions }): Promise { - await this._frame.setInputFiles(params.selector, params.files.map(f => ({ name: f.name, mimeType: f.mimeType, buffer: Buffer.from(f.buffer, 'base64') })), params.options); + async setInputFiles(params: { selector: string, files: { name: string, mimeType: string, buffer: string }[], options: types.NavigatingActionWaitOptions, isPage?: boolean }): Promise { + const target = params.isPage ? this._frame._page : this._frame; + await target.setInputFiles(params.selector, params.files.map(f => ({ name: f.name, mimeType: f.mimeType, buffer: Buffer.from(f.buffer, 'base64') })), params.options); } - async type(params: { selector: string, text: string, options: { delay?: number | undefined } & types.TimeoutOptions & { noWaitAfter?: boolean } }): Promise { - await this._frame.type(params.selector, params.text, params.options); + async type(params: { selector: string, text: string, options: { delay?: number | undefined } & types.TimeoutOptions & { noWaitAfter?: boolean }, isPage?: boolean }): Promise { + const target = params.isPage ? this._frame._page : this._frame; + await target.type(params.selector, params.text, params.options); } - async press(params: { selector: string, key: string, options: { delay?: number | undefined } & types.TimeoutOptions & { noWaitAfter?: boolean } }): Promise { - await this._frame.press(params.selector, params.key, params.options); + async press(params: { selector: string, key: string, options: { delay?: number | undefined } & types.TimeoutOptions & { noWaitAfter?: boolean }, isPage?: boolean }): Promise { + const target = params.isPage ? this._frame._page : this._frame; + await target.press(params.selector, params.key, params.options); } - async check(params: { selector: string, options: types.TimeoutOptions & { force?: boolean } & { noWaitAfter?: boolean } }): Promise { - await this._frame.check(params.selector, params.options); + async check(params: { selector: string, options: types.TimeoutOptions & { force?: boolean } & { noWaitAfter?: boolean }, isPage?: boolean }): Promise { + const target = params.isPage ? this._frame._page : this._frame; + await target.check(params.selector, params.options); } - async uncheck(params: { selector: string, options: types.TimeoutOptions & { force?: boolean } & { noWaitAfter?: boolean } }): Promise { - await this._frame.uncheck(params.selector, params.options); + async uncheck(params: { selector: string, options: types.TimeoutOptions & { force?: boolean } & { noWaitAfter?: boolean }, isPage?: boolean }): Promise { + const target = params.isPage ? this._frame._page : this._frame; + await target.uncheck(params.selector, params.options); } - async waitForFunction(params: { expression: string, isFunction: boolean, arg: any; options: types.WaitForFunctionOptions }): Promise { - return ElementHandleDispatcher.from(this._scope, await this._frame._waitForFunctionExpression(params.expression, params.isFunction, parseArgument(params.arg), params.options)); + async waitForFunction(params: { expression: string, isFunction: boolean, arg: any; options: types.WaitForFunctionOptions, isPage?: boolean }): Promise { + const target = params.isPage ? this._frame._page : this._frame; + return ElementHandleDispatcher.from(this._scope, await target._waitForFunctionExpression(params.expression, params.isFunction, parseArgument(params.arg), params.options)); } async title(): Promise { diff --git a/src/rpc/server/networkDispatchers.ts b/src/rpc/server/networkDispatchers.ts index 983238e912..cae5c4a8ca 100644 --- a/src/rpc/server/networkDispatchers.ts +++ b/src/rpc/server/networkDispatchers.ts @@ -75,8 +75,8 @@ export class ResponseDispatcher extends Dispatcher { - return await this._object.body(); + async body(): Promise { + return (await this._object.body()).toString('base64'); } } diff --git a/test/autowaiting.spec.js b/test/autowaiting.spec.js index 42b706e249..3a961e3eac 100644 --- a/test/autowaiting.spec.js +++ b/test/autowaiting.spec.js @@ -15,7 +15,7 @@ * limitations under the License. */ -const {FFOX, CHROMIUM, WEBKIT} = require('./utils').testOptions(browserType); +const {FFOX, CHROMIUM, WEBKIT, USES_HOOKS} = require('./utils').testOptions(browserType); describe('Auto waiting', () => { it('should await navigation when clicking anchor', async({page, server}) => { @@ -187,7 +187,7 @@ describe('Auto waiting', () => { await page.click('input[type=submit]'); await page.goto(server.EMPTY_PAGE); }); - it('should report navigation in the log when clicking anchor', async({page, server}) => { + it.skip(USES_HOOKS)('should report navigation in the log when clicking anchor', async({page, server}) => { await page.setContent(`click me`); const __testHookAfterPointerAction = () => new Promise(f => setTimeout(f, 6000)); const error = await page.click('a', { timeout: 5000, __testHookAfterPointerAction }).catch(e => e); diff --git a/test/chromium/launcher.spec.js b/test/chromium/launcher.spec.js index 769e3aadd8..8d51b92cd7 100644 --- a/test/chromium/launcher.spec.js +++ b/test/chromium/launcher.spec.js @@ -17,7 +17,7 @@ const path = require('path'); const utils = require('../utils'); const {makeUserDataDir, removeUserDataDir} = utils; -const {FFOX, CHROMIUM, WEBKIT, WIN} = utils.testOptions(browserType); +const {FFOX, CHROMIUM, WEBKIT, WIN, USES_HOOKS} = utils.testOptions(browserType); describe('launcher', function() { it('should throw with remote-debugging-pipe argument', async({browserType, defaultBrowserOptions}) => { @@ -32,7 +32,7 @@ describe('launcher', function() { const browser = await browserType.launchServer(options); await browser.close(); }); - it('should open devtools when "devtools: true" option is given', async({browserType, defaultBrowserOptions}) => { + it.skip(USES_HOOKS)('should open devtools when "devtools: true" option is given', async({browserType, defaultBrowserOptions}) => { let devtoolsCallback; const devtoolsPromise = new Promise(f => devtoolsCallback = f); const __testHookForDevTools = devtools => devtools.__testHookOnBinding = parsed => { diff --git a/test/click.spec.js b/test/click.spec.js index a61f560a31..313d4dc8a6 100644 --- a/test/click.spec.js +++ b/test/click.spec.js @@ -16,7 +16,7 @@ */ const utils = require('./utils'); -const {FFOX, CHROMIUM, WEBKIT, WIN} = utils.testOptions(browserType); +const {FFOX, CHROMIUM, WEBKIT, WIN, USES_HOOKS} = utils.testOptions(browserType); async function giveItAChanceToClick(page) { for (let i = 0; i < 5; i++) @@ -66,7 +66,7 @@ describe('Page.click', function() { ]).catch(e => {}); await context.close(); }); - it('should avoid side effects after timeout', async({page, server}) => { + it.skip(USES_HOOKS)('should avoid side effects after timeout', async({page, server}) => { await page.goto(server.PREFIX + '/input/button.html'); const error = await page.click('button', { timeout: 2000, __testHookBeforePointerAction: () => new Promise(f => setTimeout(f, 2500))}).catch(e => e); await page.waitForTimeout(5000); // Give it some time to click after the test hook is done waiting. @@ -707,7 +707,7 @@ describe('Page.click', function() { expect(await page.evaluate(() => window.clicked)).toBe(undefined); expect(error.message).toContain('Element is outside of the viewport'); }); - it('should fail when element jumps during hit testing', async({page, server}) => { + it.skip(USES_HOOKS)('should fail when element jumps during hit testing', async({page, server}) => { await page.setContent(''); let clicked = false; const handle = await page.$('button'); @@ -745,7 +745,7 @@ describe('Page.click', function() { await page.click('button'); expect(await page.evaluate(() => window.result)).toBe(1); }); - it.fail(true)('should retarget when element is recycled during hit testing', async ({page, server}) => { + it.skip(USES_HOOKS).fail(true)('should retarget when element is recycled during hit testing', async ({page, server}) => { await page.goto(server.PREFIX + '/react.html'); await page.evaluate(() => { renderComponent(e('div', {}, [e(MyButton, { name: 'button1' }), e(MyButton, { name: 'button2' })] )); @@ -759,7 +759,7 @@ describe('Page.click', function() { expect(await page.evaluate(() => window.button1)).toBe(true); expect(await page.evaluate(() => window.button2)).toBe(undefined); }); - it.fail(true)('should report that selector does not match anymore', async ({page, server}) => { + it.skip(USES_HOOKS).fail(true)('should report that selector does not match anymore', async ({page, server}) => { await page.goto(server.PREFIX + '/react.html'); await page.evaluate(() => { renderComponent(e('div', {}, [e(MyButton, { name: 'button1' }), e(MyButton, { name: 'button2' })] )); @@ -777,7 +777,7 @@ describe('Page.click', function() { expect(error.message).toContain('Timeout 3000ms exceeded during page.dblclick.'); expect(error.message).toContain('element does not match the selector anymore'); }); - it.fail(true)('should retarget when element is recycled before enabled check', async ({page, server}) => { + it.skip(USES_HOOKS).fail(true)('should retarget when element is recycled before enabled check', async ({page, server}) => { await page.goto(server.PREFIX + '/react.html'); await page.evaluate(() => { renderComponent(e('div', {}, [e(MyButton, { name: 'button1' }), e(MyButton, { name: 'button2', disabled: true })] )); @@ -791,7 +791,7 @@ describe('Page.click', function() { expect(await page.evaluate(() => window.button1)).toBe(true); expect(await page.evaluate(() => window.button2)).toBe(undefined); }); - it.fail(true)('should not retarget the handle when element is recycled', async ({page, server}) => { + it.skip(USES_HOOKS).fail(true)('should not retarget the handle when element is recycled', async ({page, server}) => { await page.goto(server.PREFIX + '/react.html'); await page.evaluate(() => { renderComponent(e('div', {}, [e(MyButton, { name: 'button1' }), e(MyButton, { name: 'button2', disabled: true })] )); diff --git a/test/defaultbrowsercontext.spec.js b/test/defaultbrowsercontext.spec.js index 19b4fd4e20..913a717d0e 100644 --- a/test/defaultbrowsercontext.spec.js +++ b/test/defaultbrowsercontext.spec.js @@ -18,7 +18,7 @@ const fs = require('fs'); const utils = require('./utils'); const {makeUserDataDir, removeUserDataDir} = utils; -const {FFOX, MAC, CHROMIUM, WEBKIT, WIN} = utils.testOptions(browserType); +const {FFOX, MAC, CHROMIUM, WEBKIT, WIN, USES_HOOKS} = utils.testOptions(browserType); describe('launchPersistentContext()', function() { async function launch(state, options = {}) { @@ -353,14 +353,14 @@ describe('launchPersistentContext()', function() { await browserContext.close(); await removeUserDataDir(userDataDir); }); - it('should handle timeout', async({browserType, defaultBrowserOptions}) => { + it.skip(USES_HOOKS)('should handle timeout', async({browserType, defaultBrowserOptions}) => { const userDataDir = await makeUserDataDir(); const options = { ...defaultBrowserOptions, timeout: 5000, __testHookBeforeCreateBrowser: () => new Promise(f => setTimeout(f, 6000)) }; const error = await browserType.launchPersistentContext(userDataDir, options).catch(e => e); expect(error.message).toContain(`Timeout 5000ms exceeded during browserType.launchPersistentContext.`); await removeUserDataDir(userDataDir); }); - it('should handle exception', async({browserType, defaultBrowserOptions}) => { + it.skip(USES_HOOKS)('should handle exception', async({browserType, defaultBrowserOptions}) => { const userDataDir = await makeUserDataDir(); const e = new Error('Dummy'); const options = { ...defaultBrowserOptions, __testHookBeforeCreateBrowser: () => { throw e; } }; diff --git a/test/evaluation.spec.js b/test/evaluation.spec.js index 0acc46d384..60c584f230 100644 --- a/test/evaluation.spec.js +++ b/test/evaluation.spec.js @@ -17,7 +17,7 @@ const utils = require('./utils'); const path = require('path'); -const {FFOX, CHROMIUM, WEBKIT} = utils.testOptions(browserType); +const {FFOX, CHROMIUM, WEBKIT, USES_HOOKS} = utils.testOptions(browserType); describe('Page.evaluate', function() { it('should work', async({page, server}) => { @@ -574,14 +574,14 @@ describe('Frame.evaluate', function() { else expect(page._delegate._contextIdToContext.size).toBe(count); } - it('should dispose context on navigation', async({page, server}) => { + it.skip(USES_HOOKS)('should dispose context on navigation', async({page, server}) => { await page.goto(server.PREFIX + '/frames/one-frame.html'); expect(page.frames().length).toBe(2); expectContexts(page, 4); await page.goto(server.EMPTY_PAGE); expectContexts(page, 2); }); - it('should dispose context on cross-origin navigation', async({page, server}) => { + it.skip(USES_HOOKS)('should dispose context on cross-origin navigation', async({page, server}) => { await page.goto(server.PREFIX + '/frames/one-frame.html'); expect(page.frames().length).toBe(2); expectContexts(page, 4); diff --git a/test/launcher.spec.js b/test/launcher.spec.js index 610be5f38c..5dea06ee73 100644 --- a/test/launcher.spec.js +++ b/test/launcher.spec.js @@ -18,7 +18,7 @@ const path = require('path'); const fs = require('fs'); const utils = require('./utils'); -const {FFOX, CHROMIUM, WEBKIT} = utils.testOptions(browserType); +const {FFOX, CHROMIUM, WEBKIT, USES_HOOKS} = utils.testOptions(browserType); describe('Playwright', function() { describe('browserType.launch', function() { @@ -50,20 +50,20 @@ describe('Playwright', function() { await browserType.launch(options).catch(e => waitError = e); expect(waitError.message).toContain('Failed to launch'); }); - it('should handle timeout', async({browserType, defaultBrowserOptions}) => { + it.skip(USES_HOOKS)('should handle timeout', async({browserType, defaultBrowserOptions}) => { const options = { ...defaultBrowserOptions, timeout: 5000, __testHookBeforeCreateBrowser: () => new Promise(f => setTimeout(f, 6000)) }; const error = await browserType.launch(options).catch(e => e); expect(error.message).toContain(`Timeout 5000ms exceeded during browserType.launch.`); expect(error.message).toContain(`[browser] `); expect(error.message).toContain(`[browser] pid=`); }); - it('should handle exception', async({browserType, defaultBrowserOptions}) => { + it.skip(USES_HOOKS)('should handle exception', async({browserType, defaultBrowserOptions}) => { const e = new Error('Dummy'); const options = { ...defaultBrowserOptions, __testHookBeforeCreateBrowser: () => { throw e; }, timeout: 9000 }; const error = await browserType.launch(options).catch(e => e); expect(error).toBe(e); }); - it('should report launch log', async({browserType, defaultBrowserOptions}) => { + it.skip(USES_HOOKS)('should report launch log', async({browserType, defaultBrowserOptions}) => { const e = new Error('Dummy'); const options = { ...defaultBrowserOptions, __testHookBeforeCreateBrowser: () => { throw e; }, timeout: 9000 }; const error = await browserType.launch(options).catch(e => e); @@ -293,7 +293,7 @@ describe('browserType.connect', function() { await browserServer._checkLeaks(); await browserServer.close(); }); - it.slow()('should handle exceptions during connect', async({browserType, defaultBrowserOptions, server}) => { + it.skip(USES_HOOKS).slow()('should handle exceptions during connect', async({browserType, defaultBrowserOptions, server}) => { const browserServer = await browserType.launchServer(defaultBrowserOptions); const __testHookBeforeCreateBrowser = () => { throw new Error('Dummy') }; const error = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint(), __testHookBeforeCreateBrowser }).catch(e => e); diff --git a/test/queryselector.spec.js b/test/queryselector.spec.js index 6ec24f4b61..559db88c0e 100644 --- a/test/queryselector.spec.js +++ b/test/queryselector.spec.js @@ -17,7 +17,7 @@ const path = require('path'); const utils = require('./utils'); -const {FFOX, CHROMIUM, WEBKIT} = utils.testOptions(browserType); +const {FFOX, CHROMIUM, WEBKIT, USES_HOOKS} = utils.testOptions(browserType); describe('Page.$eval', function() { it('should work with css selector', async({page, server}) => { @@ -515,7 +515,7 @@ describe('text selector', () => { expect(await page.$$eval(`text=lowo`, els => els.map(e => e.outerHTML).join(''))).toBe('
helloworld
helloworld'); }); - it('create', async ({page}) => { + it.skip(USES_HOOKS)('create', async ({page}) => { await page.setContent(`
yo
"ya
ye ye
`); expect(await playwright.selectors._createSelector('text', await page.$('div'))).toBe('yo'); expect(await playwright.selectors._createSelector('text', await page.$('div:nth-child(2)'))).toBe('"\\"ya"'); @@ -744,7 +744,7 @@ describe('attribute selector', () => { }); describe('selectors.register', () => { - it('should work', async ({page}) => { + it.skip(USES_HOOKS)('should work', async ({page}) => { const createTagSelector = () => ({ create(root, target) { return target.nodeName; diff --git a/test/recorder.spec.js b/test/recorder.spec.js index e721d9620e..8c32705758 100644 --- a/test/recorder.spec.js +++ b/test/recorder.spec.js @@ -15,7 +15,7 @@ */ const { Writable } = require('stream'); -const {FFOX, CHROMIUM, WEBKIT} = require('./utils').testOptions(browserType); +const {FFOX, CHROMIUM, WEBKIT, USES_HOOKS} = require('./utils').testOptions(browserType); const pattern = [ '[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)', @@ -56,7 +56,7 @@ class WritableBuffer { } } -describe('Recorder', function() { +describe.skip(USES_HOOKS)('Recorder', function() { beforeEach(async state => { state.context = await state.browser.newContext(); state.output = new WritableBuffer(); diff --git a/test/screenshot.spec.js b/test/screenshot.spec.js index a8f52bb236..602a758e2e 100644 --- a/test/screenshot.spec.js +++ b/test/screenshot.spec.js @@ -16,7 +16,7 @@ */ const utils = require('./utils'); -const {FFOX, CHROMIUM, WEBKIT} = utils.testOptions(browserType); +const {FFOX, CHROMIUM, WEBKIT, USES_HOOKS} = utils.testOptions(browserType); const {PNG} = require('pngjs'); // Firefox headful produces a different image. @@ -474,7 +474,7 @@ describe.skip(ffheadful)('ElementHandle.screenshot', function() { await utils.verifyViewport(page, 456, 789); await context.close(); }); - it('should restore viewport after page screenshot and exception', async({ browser, server }) => { + it.skip(USES_HOOKS)('should restore viewport after page screenshot and exception', async({ browser, server }) => { const context = await browser.newContext({ viewport: { width: 350, height: 360 } }); const page = await context.newPage(); await page.goto(server.PREFIX + '/grid.html'); @@ -484,7 +484,7 @@ describe.skip(ffheadful)('ElementHandle.screenshot', function() { await utils.verifyViewport(page, 350, 360); await context.close(); }); - it('should restore viewport after page screenshot and timeout', async({ browser, server }) => { + it.skip(USES_HOOKS)('should restore viewport after page screenshot and timeout', async({ browser, server }) => { const context = await browser.newContext({ viewport: { width: 350, height: 360 } }); const page = await context.newPage(); await page.goto(server.PREFIX + '/grid.html'); @@ -526,7 +526,7 @@ describe.skip(ffheadful)('ElementHandle.screenshot', function() { expect(sizeBefore.height).toBe(sizeAfter.height); await context.close(); }); - it('should restore viewport after element screenshot and exception', async({server, browser}) => { + it.skip(USES_HOOKS)('should restore viewport after element screenshot and exception', async({server, browser}) => { const context = await browser.newContext({ viewport: { width: 350, height: 360 } }); const page = await context.newPage(); await page.setContent(`
`); diff --git a/test/utils.js b/test/utils.js index db34709b5b..0600b14c74 100644 --- a/test/utils.js +++ b/test/utils.js @@ -200,6 +200,7 @@ const utils = module.exports = { browserType, GOLDEN_DIR, OUTPUT_DIR, + USES_HOOKS: !!process.env.PWCHANNEL }; },