/** * Copyright (c) Microsoft Corporation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import * as types from '../../types'; import { ElementHandleChannel, JSHandleInitializer } from '../channels'; import { Frame } from './frame'; import { FuncOn, JSHandle, serializeArgument, parseResult } from './jsHandle'; import { ConnectionScope } from './connection'; export class ElementHandle extends JSHandle { readonly _elementChannel: ElementHandleChannel; static from(handle: ElementHandleChannel): ElementHandle { return (handle as any)._object; } static fromNullable(handle: ElementHandleChannel | null): ElementHandle | null { return handle ? ElementHandle.from(handle) : null; } constructor(scope: ConnectionScope, guid: string, initializer: JSHandleInitializer) { super(scope, guid, initializer); this._elementChannel = this._channel as ElementHandleChannel; } asElement(): ElementHandle | null { return this; } async ownerFrame(): Promise { return Frame.fromNullable(await this._elementChannel.ownerFrame()); } async contentFrame(): Promise { return Frame.fromNullable(await this._elementChannel.contentFrame()); } async getAttribute(name: string): Promise { return await this._elementChannel.getAttribute({ name }); } async textContent(): Promise { return await this._elementChannel.textContent(); } async innerText(): Promise { return await this._elementChannel.innerText(); } async innerHTML(): Promise { return await this._elementChannel.innerHTML(); } async dispatchEvent(type: string, eventInit: Object = {}) { await this._elementChannel.dispatchEvent({ type, eventInit }); } async scrollIntoViewIfNeeded(options: types.TimeoutOptions = {}) { await this._elementChannel.scrollIntoViewIfNeeded(options); } async hover(options: types.PointerActionOptions & types.PointerActionWaitOptions = {}): Promise { await this._elementChannel.hover(options); } async click(options: types.MouseClickOptions & types.PointerActionWaitOptions & types.NavigatingActionWaitOptions = {}): Promise { return await this._elementChannel.click(options); } async dblclick(options: types.MouseMultiClickOptions & types.PointerActionWaitOptions & types.NavigatingActionWaitOptions = {}): Promise { return await this._elementChannel.dblclick(options); } async selectOption(values: string | ElementHandle | types.SelectOption | string[] | ElementHandle[] | types.SelectOption[] | null, options: types.NavigatingActionWaitOptions = {}): Promise { return await this._elementChannel.selectOption({ values: convertSelectOptionValues(values), ...options }); } async fill(value: string, options: types.NavigatingActionWaitOptions = {}): Promise { return await this._elementChannel.fill({ value, ...options }); } async selectText(options: types.TimeoutOptions): Promise { await this._elementChannel.selectText(options); } async setInputFiles(files: string | types.FilePayload | string[] | types.FilePayload[], options: types.NavigatingActionWaitOptions = {}) { await this._elementChannel.setInputFiles({ files, ...options }); } async focus(): Promise { await this._elementChannel.focus(); } async type(text: string, options: { delay?: number } & types.NavigatingActionWaitOptions = {}): Promise { await this._elementChannel.type({ text, ...options }); } async press(key: string, options: { delay?: number } & types.NavigatingActionWaitOptions = {}): Promise { await this._elementChannel.press({ key, ...options }); } async check(options: types.PointerActionWaitOptions & types.NavigatingActionWaitOptions = {}) { return await this._elementChannel.check(options); } async uncheck(options: types.PointerActionWaitOptions & types.NavigatingActionWaitOptions = {}) { return await this._elementChannel.uncheck(options); } async boundingBox(): Promise { return await this._elementChannel.boundingBox(); } async screenshot(options: types.ElementScreenshotOptions = {}): Promise { return Buffer.from(await this._elementChannel.screenshot(options), 'base64'); } async $(selector: string): Promise | null> { return ElementHandle.fromNullable(await this._elementChannel.querySelector({ selector })) as ElementHandle | null; } async $$(selector: string): Promise[]> { return (await this._elementChannel.querySelectorAll({ selector })).map(h => ElementHandle.from(h) as ElementHandle); } 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 { return parseResult(await this._elementChannel.evalOnSelector({ selector, expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(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 { return parseResult(await this._elementChannel.evalOnSelectorAll({ selector, expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) })); } } export function convertSelectOptionValues(values: string | ElementHandle | types.SelectOption | string[] | ElementHandle[] | types.SelectOption[] | null): string | ElementHandleChannel | types.SelectOption | string[] | ElementHandleChannel[] | types.SelectOption[] | null { if (values instanceof ElementHandle) return values._elementChannel; if (Array.isArray(values) && values.length && values[0] instanceof ElementHandle) return (values as ElementHandle[]).map((v: ElementHandle) => v._elementChannel); return values as any; }