chore(rpc): remove union types from page and handles (#2912)

This commit is contained in:
Pavel Feldman 2020-07-10 15:39:11 -07:00 committed by GitHub
parent b6fd4dc56c
commit 631f76df75
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 84 additions and 37 deletions

View File

@ -157,7 +157,7 @@ export interface PageChannel extends Channel {
mouseClick(params: { x: number, y: number, delay?: number, button?: types.MouseButton, clickCount?: number }): Promise<void>;
accessibilitySnapshot(params: { interestingOnly?: boolean, root?: ElementHandleChannel }): Promise<types.SerializedAXNode | null>;
pdf: (params: types.PDFOptions) => Promise<Binary>;
pdf: (params: PDFOptions) => Promise<Binary>;
crStartJSCoverage(params: types.JSCoverageOptions): Promise<void>;
crStopJSCoverage(): Promise<types.JSCoverageEntry[]>;
@ -196,9 +196,9 @@ export interface FrameChannel extends Channel {
press(params: { selector: string, key: string, delay?: number, noWaitAfter?: boolean } & types.TimeoutOptions & PageAttribution): Promise<void>;
querySelector(params: { selector: string} & PageAttribution): Promise<ElementHandleChannel | null>;
querySelectorAll(params: { selector: string} & PageAttribution): Promise<ElementHandleChannel[]>;
selectOption(params: { selector: string, values: string | ElementHandleChannel | types.SelectOption | string[] | ElementHandleChannel[] | types.SelectOption[] | null } & types.NavigatingActionWaitOptions & PageAttribution): Promise<string[]>;
selectOption(params: { selector: string, elements?: ElementHandleChannel[], options?: types.SelectOption[] } & types.NavigatingActionWaitOptions & PageAttribution): Promise<string[]>;
setContent(params: { html: string } & types.NavigateOptions & PageAttribution): Promise<void>;
setInputFiles(params: { selector: string, files: { name: string, mimeType: string, buffer: string }[] } & types.NavigatingActionWaitOptions & PageAttribution): Promise<void>;
setInputFiles(params: { selector: string, files: { name: string, mimeType: string, buffer: Binary }[] } & types.NavigatingActionWaitOptions & PageAttribution): Promise<void>;
textContent(params: { selector: string } & types.TimeoutOptions & PageAttribution): Promise<string | null>;
title(): Promise<string>;
type(params: { selector: string, text: string, delay?: number, noWaitAfter?: boolean } & types.TimeoutOptions & PageAttribution): Promise<void>;
@ -260,9 +260,9 @@ export interface ElementHandleChannel extends JSHandleChannel {
querySelectorAll(params: { selector: string }): Promise<ElementHandleChannel[]>;
screenshot(params: types.ElementScreenshotOptions): Promise<Binary>;
scrollIntoViewIfNeeded(params: types.TimeoutOptions): Promise<void>;
selectOption(params: { values: string | ElementHandleChannel | types.SelectOption | string[] | ElementHandleChannel[] | types.SelectOption[] | null } & types.NavigatingActionWaitOptions): string[] | Promise<string[]>;
selectOption(params: { elements?: ElementHandleChannel[], options?: types.SelectOption[] } & types.NavigatingActionWaitOptions): string[] | Promise<string[]>;
selectText(params: types.TimeoutOptions): Promise<void>;
setInputFiles(params: { files: string | string[] | types.FilePayload | types.FilePayload[] } & types.NavigatingActionWaitOptions): Promise<void>;
setInputFiles(params: { files: { name: string, mimeType: string, buffer: Binary }[] } & types.NavigatingActionWaitOptions): Promise<void>;
textContent(): Promise<string | null>;
type(params: { text: string, delay?: number, noWaitAfter?: boolean } & types.TimeoutOptions): Promise<void>;
uncheck(params: { force?: boolean, noWaitAfter?: boolean } & types.TimeoutOptions): Promise<void>;
@ -364,3 +364,20 @@ export interface CDPSessionChannel extends Channel {
detach(): Promise<void>;
}
export type CDPSessionInitializer = {};
export type PDFOptions = {
scale?: number,
displayHeaderFooter?: boolean,
headerTemplate?: string,
footerTemplate?: string,
printBackground?: boolean,
landscape?: boolean,
pageRanges?: string,
format?: string,
width?: string,
height?: string,
preferCSSPageSize?: boolean,
margin?: {top?: string, bottom?: string, left?: string, right?: string},
path?: string,
}

View File

@ -19,6 +19,8 @@ import { ElementHandleChannel, JSHandleInitializer } from '../channels';
import { Frame } from './frame';
import { FuncOn, JSHandle, serializeArgument, parseResult } from './jsHandle';
import { ChannelOwner } from './channelOwner';
import { helper, assert } from '../../helper';
import { normalizeFilePayloads } from '../serializers';
export class ElementHandle<T extends Node = Node> extends JSHandle<T> {
readonly _elementChannel: ElementHandleChannel;
@ -85,7 +87,7 @@ export class ElementHandle<T extends Node = Node> extends JSHandle<T> {
}
async selectOption(values: string | ElementHandle | types.SelectOption | string[] | ElementHandle[] | types.SelectOption[] | null, options: types.NavigatingActionWaitOptions = {}): Promise<string[]> {
return await this._elementChannel.selectOption({ values: convertSelectOptionValues(values), ...options });
return await this._elementChannel.selectOption({ ...convertSelectOptionValues(values), ...options });
}
async fill(value: string, options: types.NavigatingActionWaitOptions = {}): Promise<void> {
@ -97,7 +99,7 @@ export class ElementHandle<T extends Node = Node> extends JSHandle<T> {
}
async setInputFiles(files: string | types.FilePayload | string[] | types.FilePayload[], options: types.NavigatingActionWaitOptions = {}) {
await this._elementChannel.setInputFiles({ files, ...options });
await this._elementChannel.setInputFiles({ files: await convertInputFiles(files), ...options });
}
async focus(): Promise<void> {
@ -149,10 +151,24 @@ export class ElementHandle<T extends Node = Node> extends JSHandle<T> {
}
}
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;
export function convertSelectOptionValues(values: string | ElementHandle | types.SelectOption | string[] | ElementHandle[] | types.SelectOption[] | null): { elements?: ElementHandleChannel[], options?: types.SelectOption[] } {
if (!values)
return {};
if (!Array.isArray(values))
values = [ values as any ];
if (!values.length)
return {};
if ((values as any[]).includes(null))
assert(false, 'Value items must not be null');
if (values[0] instanceof ElementHandle)
return { elements: (values as ElementHandle[]).map((v: ElementHandle) => v._elementChannel) };
if (helper.isString(values[0]))
return { options: (values as string[]).map(value => ({ value })) };
return { options: values as types.SelectOption[] };
}
export async function convertInputFiles(files: string | types.FilePayload | string[] | types.FilePayload[]): Promise<{ name: string, mimeType: string, buffer: string }[]> {
const filePayloads = await normalizeFilePayloads(files);
return filePayloads.map(f => ({ name: f.name, mimeType: f.mimeType, buffer: f.buffer.toString('base64') }));
}

View File

@ -20,12 +20,11 @@ import * as types from '../../types';
import { FrameChannel, FrameInitializer } from '../channels';
import { BrowserContext } from './browserContext';
import { ChannelOwner } from './channelOwner';
import { ElementHandle, convertSelectOptionValues } from './elementHandle';
import { ElementHandle, convertSelectOptionValues, convertInputFiles } from './elementHandle';
import { JSHandle, Func1, FuncOn, SmartHandle, serializeArgument, parseResult } from './jsHandle';
import * as network from './network';
import { Response } from './network';
import { Page } from './page';
import { normalizeFilePayloads } from '../serializers';
export type GotoOptions = types.NavigateOptions & {
referer?: string,
@ -192,12 +191,11 @@ export class Frame extends ChannelOwner<FrameChannel, FrameInitializer> {
}
async selectOption(selector: string, values: string | ElementHandle | types.SelectOption | string[] | ElementHandle[] | types.SelectOption[] | null, options: types.NavigatingActionWaitOptions = {}): Promise<string[]> {
return await this._channel.selectOption({ selector, values: convertSelectOptionValues(values), ...options, isPage: this._page!._isPageCall });
return await this._channel.selectOption({ selector, ...convertSelectOptionValues(values), ...options, isPage: this._page!._isPageCall });
}
async setInputFiles(selector: string, files: string | types.FilePayload | string[] | types.FilePayload[], options: types.NavigatingActionWaitOptions = {}): Promise<void> {
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, isPage: this._page!._isPageCall });
await this._channel.setInputFiles({ selector, files: await convertInputFiles(files), ...options, isPage: this._page!._isPageCall });
}
async type(selector: string, text: string, options: { delay?: number } & types.NavigatingActionWaitOptions = {}) {

View File

@ -21,7 +21,7 @@ import { Events } from '../../events';
import { assert, assertMaxArguments, helper, Listener } from '../../helper';
import { TimeoutSettings } from '../../timeoutSettings';
import * as types from '../../types';
import { BindingCallChannel, BindingCallInitializer, PageChannel, PageInitializer } from '../channels';
import { BindingCallChannel, BindingCallInitializer, PageChannel, PageInitializer, PDFOptions } from '../channels';
import { parseError, serializeError } from '../serializers';
import { Accessibility } from './accessibility';
import { BrowserContext } from './browserContext';
@ -500,7 +500,19 @@ export class Page extends ChannelOwner<PageChannel, PageInitializer> {
}
async pdf(options: types.PDFOptions = {}): Promise<Buffer> {
const binary = await this._channel.pdf(options);
const transportOptions: PDFOptions = { ...options } as PDFOptions;
if (transportOptions.margin)
transportOptions.margin = { ...transportOptions.margin };
if (typeof options.width === 'number')
transportOptions.width = options.width + 'px';
if (typeof options.height === 'number')
transportOptions.height = options.height + 'px';
for (const margin of ['top', 'right', 'bottom', 'left']) {
const index = margin as 'top' | 'right' | 'bottom' | 'left';
if (options.margin && typeof options.margin[index] === 'number')
transportOptions.margin![index] = transportOptions.margin![index] + 'px';
}
const binary = await this._channel.pdf(transportOptions);
return Buffer.from(binary, 'base64');
}
}

View File

@ -85,8 +85,8 @@ export class ElementHandleDispatcher extends JSHandleDispatcher implements Eleme
await this._elementHandle.dblclick(params);
}
async selectOption(params: { values: string | ElementHandleChannel | types.SelectOption | string[] | ElementHandleChannel[] | types.SelectOption[] | null } & types.NavigatingActionWaitOptions): Promise<string[]> {
return this._elementHandle.selectOption(convertSelectOptionValues(params.values), params);
async selectOption(params: { elements?: ElementHandleChannel[], options?: types.SelectOption[] } & types.NavigatingActionWaitOptions): Promise<string[]> {
return this._elementHandle.selectOption(convertSelectOptionValues(params.elements, params.options), params);
}
async fill(params: { value: string } & types.NavigatingActionWaitOptions) {
@ -97,8 +97,8 @@ export class ElementHandleDispatcher extends JSHandleDispatcher implements Eleme
await this._elementHandle.selectText(params);
}
async setInputFiles(params: { files: string | types.FilePayload | string[] | types.FilePayload[] } & types.NavigatingActionWaitOptions) {
await this._elementHandle.setInputFiles(params.files, params);
async setInputFiles(params: { files: { name: string, mimeType: string, buffer: string }[] } & types.NavigatingActionWaitOptions) {
await this._elementHandle.setInputFiles(convertInputFiles(params.files), params);
}
async focus() {
@ -148,10 +148,14 @@ export class ElementHandleDispatcher extends JSHandleDispatcher implements Eleme
}
}
export function convertSelectOptionValues(values: string | ElementHandleChannel | types.SelectOption | string[] | ElementHandleChannel[] | types.SelectOption[] | null): string | ElementHandle | types.SelectOption | string[] | ElementHandle[] | types.SelectOption[] | null {
if (values instanceof ElementHandleDispatcher)
return values._elementHandle;
if (Array.isArray(values) && values.length && values[0] instanceof ElementHandle)
return (values as ElementHandleDispatcher[]).map((v: ElementHandleDispatcher) => v._elementHandle);
return values as any;
export function convertSelectOptionValues(elements?: ElementHandleChannel[], options?: types.SelectOption[]): string | ElementHandle | types.SelectOption | string[] | ElementHandle[] | types.SelectOption[] | null {
if (elements)
return elements.map(v => (v as ElementHandleDispatcher)._elementHandle);
if (options)
return options;
return null;
}
export function convertInputFiles(files: { name: string, mimeType: string, buffer: string }[]): types.FilePayload[] {
return files.map(f => ({ name: f.name, mimeType: f.mimeType, buffer: Buffer.from(f.buffer, 'base64') }));
}

View File

@ -18,7 +18,7 @@ import { Frame } from '../../frames';
import * as types from '../../types';
import { ElementHandleChannel, FrameChannel, FrameInitializer, JSHandleChannel, ResponseChannel, PageAttribution } from '../channels';
import { Dispatcher, DispatcherScope, lookupNullableDispatcher, existingDispatcher } from './dispatcher';
import { convertSelectOptionValues, ElementHandleDispatcher, createHandle } from './elementHandlerDispatcher';
import { convertSelectOptionValues, ElementHandleDispatcher, createHandle, convertInputFiles } from './elementHandlerDispatcher';
import { parseArgument, serializeResult } from './jsHandleDispatcher';
import { ResponseDispatcher } from './networkDispatchers';
@ -163,14 +163,14 @@ export class FrameDispatcher extends Dispatcher<Frame, FrameInitializer> impleme
await target.hover(params.selector, params);
}
async selectOption(params: { selector: string, values: string | ElementHandleChannel | types.SelectOption | string[] | ElementHandleChannel[] | types.SelectOption[] | null } & types.NavigatingActionWaitOptions & PageAttribution): Promise<string[]> {
async selectOption(params: { selector: string, elements?: ElementHandleChannel[], options?: types.SelectOption[] } & types.NavigatingActionWaitOptions & PageAttribution): Promise<string[]> {
const target = params.isPage ? this._frame._page : this._frame;
return target.selectOption(params.selector, convertSelectOptionValues(params.values), params);
return target.selectOption(params.selector, convertSelectOptionValues(params.elements, params.options), params);
}
async setInputFiles(params: { selector: string, files: { name: string, mimeType: string, buffer: string }[] } & types.NavigatingActionWaitOptions & PageAttribution): Promise<void> {
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);
await target.setInputFiles(params.selector, convertInputFiles(params.files), params);
}
async type(params: { selector: string, text: string } & { delay?: number | undefined } & types.TimeoutOptions & { noWaitAfter?: boolean } & PageAttribution): Promise<void> {

View File

@ -20,7 +20,7 @@ import { Frame } from '../../frames';
import { Request } from '../../network';
import { Page, Worker } from '../../page';
import * as types from '../../types';
import { BindingCallChannel, BindingCallInitializer, ElementHandleChannel, PageChannel, PageInitializer, ResponseChannel, WorkerInitializer, WorkerChannel, JSHandleChannel, Binary } from '../channels';
import { BindingCallChannel, BindingCallInitializer, ElementHandleChannel, PageChannel, PageInitializer, ResponseChannel, WorkerInitializer, WorkerChannel, JSHandleChannel, Binary, PDFOptions } from '../channels';
import { Dispatcher, DispatcherScope, lookupDispatcher, lookupNullableDispatcher } from './dispatcher';
import { parseError, serializeError } from '../serializers';
import { ConsoleMessageDispatcher } from './consoleMessageDispatcher';
@ -185,7 +185,7 @@ export class PageDispatcher extends Dispatcher<Page, PageInitializer> implements
});
}
async pdf(params: types.PDFOptions): Promise<Binary> {
async pdf(params: PDFOptions): Promise<Binary> {
if (!this._page.pdf)
throw new Error('PDF generation is only supported for Headless Chromium');
const binary = await this._page.pdf(params);

View File

@ -946,7 +946,7 @@ describe('Page.selectOption', function() {
it('should select multiple options with attributes', async({page, server}) => {
await page.goto(server.PREFIX + '/input/select.html');
await page.evaluate(() => makeMultiple());
await page.selectOption('select', ['blue', { label: 'Green' }, { index: 4 }]);
await page.selectOption('select', [{ value: 'blue' }, { label: 'Green' }, { index: 4 }]);
expect(await page.evaluate(() => result.onInput)).toEqual(['blue', 'gray', 'green']);
expect(await page.evaluate(() => result.onChange)).toEqual(['blue', 'gray', 'green']);
});