Skip to content

Commit 631f76d

Browse files
authored
chore(rpc): remove union types from page and handles (#2912)
1 parent b6fd4dc commit 631f76d

File tree

8 files changed

+84
-37
lines changed

8 files changed

+84
-37
lines changed

src/rpc/channels.ts

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ export interface PageChannel extends Channel {
157157
mouseClick(params: { x: number, y: number, delay?: number, button?: types.MouseButton, clickCount?: number }): Promise<void>;
158158

159159
accessibilitySnapshot(params: { interestingOnly?: boolean, root?: ElementHandleChannel }): Promise<types.SerializedAXNode | null>;
160-
pdf: (params: types.PDFOptions) => Promise<Binary>;
160+
pdf: (params: PDFOptions) => Promise<Binary>;
161161

162162
crStartJSCoverage(params: types.JSCoverageOptions): Promise<void>;
163163
crStopJSCoverage(): Promise<types.JSCoverageEntry[]>;
@@ -196,9 +196,9 @@ export interface FrameChannel extends Channel {
196196
press(params: { selector: string, key: string, delay?: number, noWaitAfter?: boolean } & types.TimeoutOptions & PageAttribution): Promise<void>;
197197
querySelector(params: { selector: string} & PageAttribution): Promise<ElementHandleChannel | null>;
198198
querySelectorAll(params: { selector: string} & PageAttribution): Promise<ElementHandleChannel[]>;
199-
selectOption(params: { selector: string, values: string | ElementHandleChannel | types.SelectOption | string[] | ElementHandleChannel[] | types.SelectOption[] | null } & types.NavigatingActionWaitOptions & PageAttribution): Promise<string[]>;
199+
selectOption(params: { selector: string, elements?: ElementHandleChannel[], options?: types.SelectOption[] } & types.NavigatingActionWaitOptions & PageAttribution): Promise<string[]>;
200200
setContent(params: { html: string } & types.NavigateOptions & PageAttribution): Promise<void>;
201-
setInputFiles(params: { selector: string, files: { name: string, mimeType: string, buffer: string }[] } & types.NavigatingActionWaitOptions & PageAttribution): Promise<void>;
201+
setInputFiles(params: { selector: string, files: { name: string, mimeType: string, buffer: Binary }[] } & types.NavigatingActionWaitOptions & PageAttribution): Promise<void>;
202202
textContent(params: { selector: string } & types.TimeoutOptions & PageAttribution): Promise<string | null>;
203203
title(): Promise<string>;
204204
type(params: { selector: string, text: string, delay?: number, noWaitAfter?: boolean } & types.TimeoutOptions & PageAttribution): Promise<void>;
@@ -260,9 +260,9 @@ export interface ElementHandleChannel extends JSHandleChannel {
260260
querySelectorAll(params: { selector: string }): Promise<ElementHandleChannel[]>;
261261
screenshot(params: types.ElementScreenshotOptions): Promise<Binary>;
262262
scrollIntoViewIfNeeded(params: types.TimeoutOptions): Promise<void>;
263-
selectOption(params: { values: string | ElementHandleChannel | types.SelectOption | string[] | ElementHandleChannel[] | types.SelectOption[] | null } & types.NavigatingActionWaitOptions): string[] | Promise<string[]>;
263+
selectOption(params: { elements?: ElementHandleChannel[], options?: types.SelectOption[] } & types.NavigatingActionWaitOptions): string[] | Promise<string[]>;
264264
selectText(params: types.TimeoutOptions): Promise<void>;
265-
setInputFiles(params: { files: string | string[] | types.FilePayload | types.FilePayload[] } & types.NavigatingActionWaitOptions): Promise<void>;
265+
setInputFiles(params: { files: { name: string, mimeType: string, buffer: Binary }[] } & types.NavigatingActionWaitOptions): Promise<void>;
266266
textContent(): Promise<string | null>;
267267
type(params: { text: string, delay?: number, noWaitAfter?: boolean } & types.TimeoutOptions): Promise<void>;
268268
uncheck(params: { force?: boolean, noWaitAfter?: boolean } & types.TimeoutOptions): Promise<void>;
@@ -364,3 +364,20 @@ export interface CDPSessionChannel extends Channel {
364364
detach(): Promise<void>;
365365
}
366366
export type CDPSessionInitializer = {};
367+
368+
369+
export type PDFOptions = {
370+
scale?: number,
371+
displayHeaderFooter?: boolean,
372+
headerTemplate?: string,
373+
footerTemplate?: string,
374+
printBackground?: boolean,
375+
landscape?: boolean,
376+
pageRanges?: string,
377+
format?: string,
378+
width?: string,
379+
height?: string,
380+
preferCSSPageSize?: boolean,
381+
margin?: {top?: string, bottom?: string, left?: string, right?: string},
382+
path?: string,
383+
}

src/rpc/client/elementHandle.ts

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import { ElementHandleChannel, JSHandleInitializer } from '../channels';
1919
import { Frame } from './frame';
2020
import { FuncOn, JSHandle, serializeArgument, parseResult } from './jsHandle';
2121
import { ChannelOwner } from './channelOwner';
22+
import { helper, assert } from '../../helper';
23+
import { normalizeFilePayloads } from '../serializers';
2224

2325
export class ElementHandle<T extends Node = Node> extends JSHandle<T> {
2426
readonly _elementChannel: ElementHandleChannel;
@@ -85,7 +87,7 @@ export class ElementHandle<T extends Node = Node> extends JSHandle<T> {
8587
}
8688

8789
async selectOption(values: string | ElementHandle | types.SelectOption | string[] | ElementHandle[] | types.SelectOption[] | null, options: types.NavigatingActionWaitOptions = {}): Promise<string[]> {
88-
return await this._elementChannel.selectOption({ values: convertSelectOptionValues(values), ...options });
90+
return await this._elementChannel.selectOption({ ...convertSelectOptionValues(values), ...options });
8991
}
9092

9193
async fill(value: string, options: types.NavigatingActionWaitOptions = {}): Promise<void> {
@@ -97,7 +99,7 @@ export class ElementHandle<T extends Node = Node> extends JSHandle<T> {
9799
}
98100

99101
async setInputFiles(files: string | types.FilePayload | string[] | types.FilePayload[], options: types.NavigatingActionWaitOptions = {}) {
100-
await this._elementChannel.setInputFiles({ files, ...options });
102+
await this._elementChannel.setInputFiles({ files: await convertInputFiles(files), ...options });
101103
}
102104

103105
async focus(): Promise<void> {
@@ -149,10 +151,24 @@ export class ElementHandle<T extends Node = Node> extends JSHandle<T> {
149151
}
150152
}
151153

152-
export function convertSelectOptionValues(values: string | ElementHandle | types.SelectOption | string[] | ElementHandle[] | types.SelectOption[] | null): string | ElementHandleChannel | types.SelectOption | string[] | ElementHandleChannel[] | types.SelectOption[] | null {
153-
if (values instanceof ElementHandle)
154-
return values._elementChannel;
155-
if (Array.isArray(values) && values.length && values[0] instanceof ElementHandle)
156-
return (values as ElementHandle[]).map((v: ElementHandle) => v._elementChannel);
157-
return values as any;
154+
export function convertSelectOptionValues(values: string | ElementHandle | types.SelectOption | string[] | ElementHandle[] | types.SelectOption[] | null): { elements?: ElementHandleChannel[], options?: types.SelectOption[] } {
155+
if (!values)
156+
return {};
157+
if (!Array.isArray(values))
158+
values = [ values as any ];
159+
if (!values.length)
160+
return {};
161+
if ((values as any[]).includes(null))
162+
assert(false, 'Value items must not be null');
163+
164+
if (values[0] instanceof ElementHandle)
165+
return { elements: (values as ElementHandle[]).map((v: ElementHandle) => v._elementChannel) };
166+
if (helper.isString(values[0]))
167+
return { options: (values as string[]).map(value => ({ value })) };
168+
return { options: values as types.SelectOption[] };
169+
}
170+
171+
export async function convertInputFiles(files: string | types.FilePayload | string[] | types.FilePayload[]): Promise<{ name: string, mimeType: string, buffer: string }[]> {
172+
const filePayloads = await normalizeFilePayloads(files);
173+
return filePayloads.map(f => ({ name: f.name, mimeType: f.mimeType, buffer: f.buffer.toString('base64') }));
158174
}

src/rpc/client/frame.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,11 @@ import * as types from '../../types';
2020
import { FrameChannel, FrameInitializer } from '../channels';
2121
import { BrowserContext } from './browserContext';
2222
import { ChannelOwner } from './channelOwner';
23-
import { ElementHandle, convertSelectOptionValues } from './elementHandle';
23+
import { ElementHandle, convertSelectOptionValues, convertInputFiles } from './elementHandle';
2424
import { JSHandle, Func1, FuncOn, SmartHandle, serializeArgument, parseResult } from './jsHandle';
2525
import * as network from './network';
2626
import { Response } from './network';
2727
import { Page } from './page';
28-
import { normalizeFilePayloads } from '../serializers';
2928

3029
export type GotoOptions = types.NavigateOptions & {
3130
referer?: string,
@@ -192,12 +191,11 @@ export class Frame extends ChannelOwner<FrameChannel, FrameInitializer> {
192191
}
193192

194193
async selectOption(selector: string, values: string | ElementHandle | types.SelectOption | string[] | ElementHandle[] | types.SelectOption[] | null, options: types.NavigatingActionWaitOptions = {}): Promise<string[]> {
195-
return await this._channel.selectOption({ selector, values: convertSelectOptionValues(values), ...options, isPage: this._page!._isPageCall });
194+
return await this._channel.selectOption({ selector, ...convertSelectOptionValues(values), ...options, isPage: this._page!._isPageCall });
196195
}
197196

198197
async setInputFiles(selector: string, files: string | types.FilePayload | string[] | types.FilePayload[], options: types.NavigatingActionWaitOptions = {}): Promise<void> {
199-
const filePayloads = await normalizeFilePayloads(files);
200-
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 });
198+
await this._channel.setInputFiles({ selector, files: await convertInputFiles(files), ...options, isPage: this._page!._isPageCall });
201199
}
202200

203201
async type(selector: string, text: string, options: { delay?: number } & types.NavigatingActionWaitOptions = {}) {

src/rpc/client/page.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import { Events } from '../../events';
2121
import { assert, assertMaxArguments, helper, Listener } from '../../helper';
2222
import { TimeoutSettings } from '../../timeoutSettings';
2323
import * as types from '../../types';
24-
import { BindingCallChannel, BindingCallInitializer, PageChannel, PageInitializer } from '../channels';
24+
import { BindingCallChannel, BindingCallInitializer, PageChannel, PageInitializer, PDFOptions } from '../channels';
2525
import { parseError, serializeError } from '../serializers';
2626
import { Accessibility } from './accessibility';
2727
import { BrowserContext } from './browserContext';
@@ -500,7 +500,19 @@ export class Page extends ChannelOwner<PageChannel, PageInitializer> {
500500
}
501501

502502
async pdf(options: types.PDFOptions = {}): Promise<Buffer> {
503-
const binary = await this._channel.pdf(options);
503+
const transportOptions: PDFOptions = { ...options } as PDFOptions;
504+
if (transportOptions.margin)
505+
transportOptions.margin = { ...transportOptions.margin };
506+
if (typeof options.width === 'number')
507+
transportOptions.width = options.width + 'px';
508+
if (typeof options.height === 'number')
509+
transportOptions.height = options.height + 'px';
510+
for (const margin of ['top', 'right', 'bottom', 'left']) {
511+
const index = margin as 'top' | 'right' | 'bottom' | 'left';
512+
if (options.margin && typeof options.margin[index] === 'number')
513+
transportOptions.margin![index] = transportOptions.margin![index] + 'px';
514+
}
515+
const binary = await this._channel.pdf(transportOptions);
504516
return Buffer.from(binary, 'base64');
505517
}
506518
}

src/rpc/server/elementHandlerDispatcher.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,8 @@ export class ElementHandleDispatcher extends JSHandleDispatcher implements Eleme
8585
await this._elementHandle.dblclick(params);
8686
}
8787

88-
async selectOption(params: { values: string | ElementHandleChannel | types.SelectOption | string[] | ElementHandleChannel[] | types.SelectOption[] | null } & types.NavigatingActionWaitOptions): Promise<string[]> {
89-
return this._elementHandle.selectOption(convertSelectOptionValues(params.values), params);
88+
async selectOption(params: { elements?: ElementHandleChannel[], options?: types.SelectOption[] } & types.NavigatingActionWaitOptions): Promise<string[]> {
89+
return this._elementHandle.selectOption(convertSelectOptionValues(params.elements, params.options), params);
9090
}
9191

9292
async fill(params: { value: string } & types.NavigatingActionWaitOptions) {
@@ -97,8 +97,8 @@ export class ElementHandleDispatcher extends JSHandleDispatcher implements Eleme
9797
await this._elementHandle.selectText(params);
9898
}
9999

100-
async setInputFiles(params: { files: string | types.FilePayload | string[] | types.FilePayload[] } & types.NavigatingActionWaitOptions) {
101-
await this._elementHandle.setInputFiles(params.files, params);
100+
async setInputFiles(params: { files: { name: string, mimeType: string, buffer: string }[] } & types.NavigatingActionWaitOptions) {
101+
await this._elementHandle.setInputFiles(convertInputFiles(params.files), params);
102102
}
103103

104104
async focus() {
@@ -148,10 +148,14 @@ export class ElementHandleDispatcher extends JSHandleDispatcher implements Eleme
148148
}
149149
}
150150

151-
export function convertSelectOptionValues(values: string | ElementHandleChannel | types.SelectOption | string[] | ElementHandleChannel[] | types.SelectOption[] | null): string | ElementHandle | types.SelectOption | string[] | ElementHandle[] | types.SelectOption[] | null {
152-
if (values instanceof ElementHandleDispatcher)
153-
return values._elementHandle;
154-
if (Array.isArray(values) && values.length && values[0] instanceof ElementHandle)
155-
return (values as ElementHandleDispatcher[]).map((v: ElementHandleDispatcher) => v._elementHandle);
156-
return values as any;
151+
export function convertSelectOptionValues(elements?: ElementHandleChannel[], options?: types.SelectOption[]): string | ElementHandle | types.SelectOption | string[] | ElementHandle[] | types.SelectOption[] | null {
152+
if (elements)
153+
return elements.map(v => (v as ElementHandleDispatcher)._elementHandle);
154+
if (options)
155+
return options;
156+
return null;
157+
}
158+
159+
export function convertInputFiles(files: { name: string, mimeType: string, buffer: string }[]): types.FilePayload[] {
160+
return files.map(f => ({ name: f.name, mimeType: f.mimeType, buffer: Buffer.from(f.buffer, 'base64') }));
157161
}

src/rpc/server/frameDispatcher.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import { Frame } from '../../frames';
1818
import * as types from '../../types';
1919
import { ElementHandleChannel, FrameChannel, FrameInitializer, JSHandleChannel, ResponseChannel, PageAttribution } from '../channels';
2020
import { Dispatcher, DispatcherScope, lookupNullableDispatcher, existingDispatcher } from './dispatcher';
21-
import { convertSelectOptionValues, ElementHandleDispatcher, createHandle } from './elementHandlerDispatcher';
21+
import { convertSelectOptionValues, ElementHandleDispatcher, createHandle, convertInputFiles } from './elementHandlerDispatcher';
2222
import { parseArgument, serializeResult } from './jsHandleDispatcher';
2323
import { ResponseDispatcher } from './networkDispatchers';
2424

@@ -163,14 +163,14 @@ export class FrameDispatcher extends Dispatcher<Frame, FrameInitializer> impleme
163163
await target.hover(params.selector, params);
164164
}
165165

166-
async selectOption(params: { selector: string, values: string | ElementHandleChannel | types.SelectOption | string[] | ElementHandleChannel[] | types.SelectOption[] | null } & types.NavigatingActionWaitOptions & PageAttribution): Promise<string[]> {
166+
async selectOption(params: { selector: string, elements?: ElementHandleChannel[], options?: types.SelectOption[] } & types.NavigatingActionWaitOptions & PageAttribution): Promise<string[]> {
167167
const target = params.isPage ? this._frame._page : this._frame;
168-
return target.selectOption(params.selector, convertSelectOptionValues(params.values), params);
168+
return target.selectOption(params.selector, convertSelectOptionValues(params.elements, params.options), params);
169169
}
170170

171171
async setInputFiles(params: { selector: string, files: { name: string, mimeType: string, buffer: string }[] } & types.NavigatingActionWaitOptions & PageAttribution): Promise<void> {
172172
const target = params.isPage ? this._frame._page : this._frame;
173-
await target.setInputFiles(params.selector, params.files.map(f => ({ name: f.name, mimeType: f.mimeType, buffer: Buffer.from(f.buffer, 'base64') })), params);
173+
await target.setInputFiles(params.selector, convertInputFiles(params.files), params);
174174
}
175175

176176
async type(params: { selector: string, text: string } & { delay?: number | undefined } & types.TimeoutOptions & { noWaitAfter?: boolean } & PageAttribution): Promise<void> {

src/rpc/server/pageDispatcher.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import { Frame } from '../../frames';
2020
import { Request } from '../../network';
2121
import { Page, Worker } from '../../page';
2222
import * as types from '../../types';
23-
import { BindingCallChannel, BindingCallInitializer, ElementHandleChannel, PageChannel, PageInitializer, ResponseChannel, WorkerInitializer, WorkerChannel, JSHandleChannel, Binary } from '../channels';
23+
import { BindingCallChannel, BindingCallInitializer, ElementHandleChannel, PageChannel, PageInitializer, ResponseChannel, WorkerInitializer, WorkerChannel, JSHandleChannel, Binary, PDFOptions } from '../channels';
2424
import { Dispatcher, DispatcherScope, lookupDispatcher, lookupNullableDispatcher } from './dispatcher';
2525
import { parseError, serializeError } from '../serializers';
2626
import { ConsoleMessageDispatcher } from './consoleMessageDispatcher';
@@ -185,7 +185,7 @@ export class PageDispatcher extends Dispatcher<Page, PageInitializer> implements
185185
});
186186
}
187187

188-
async pdf(params: types.PDFOptions): Promise<Binary> {
188+
async pdf(params: PDFOptions): Promise<Binary> {
189189
if (!this._page.pdf)
190190
throw new Error('PDF generation is only supported for Headless Chromium');
191191
const binary = await this._page.pdf(params);

test/page.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -946,7 +946,7 @@ describe('Page.selectOption', function() {
946946
it('should select multiple options with attributes', async({page, server}) => {
947947
await page.goto(server.PREFIX + '/input/select.html');
948948
await page.evaluate(() => makeMultiple());
949-
await page.selectOption('select', ['blue', { label: 'Green' }, { index: 4 }]);
949+
await page.selectOption('select', [{ value: 'blue' }, { label: 'Green' }, { index: 4 }]);
950950
expect(await page.evaluate(() => result.onInput)).toEqual(['blue', 'gray', 'green']);
951951
expect(await page.evaluate(() => result.onChange)).toEqual(['blue', 'gray', 'green']);
952952
});

0 commit comments

Comments
 (0)