docs: api.d.ts and types.d.ts

All api interfaces and types live in these two files.
Interfaces and selected types are exported from api.d.ts.
This commit is contained in:
Dmitry Gozman 2019-12-13 16:28:25 -08:00
parent 32fa26be97
commit 44e5ca3db8
19 changed files with 226 additions and 170 deletions

54
src/api.d.ts vendored Normal file
View file

@ -0,0 +1,54 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import * as types from './types';
export type Point = types.Point;
export type HttpHeaders = types.HttpHeaders;
export interface Keyboard {
down(key: string, options?: { text?: string }): Promise<void>;
press(key: string, options?: { text?: string, delay?: number }): Promise<void>;
sendCharacters(text: string): Promise<void>;
type(text: string, options?: { delay?: number }): Promise<void>;
up(key: string): Promise<void>;
}
export interface Mouse {
move(x: number, y: number, options?: { steps?: number }): Promise<void>;
down(options?: { button?: types.MouseButton, clickCount?: number }): Promise<void>;
up(options?: { button?: types.MouseButton, clickCount?: number }): Promise<void>;
click(x: number, y: number, options?: types.ClickOptions): Promise<void>;
dblclick(x: number, y: number, options?: types.DoubleClickOptions): Promise<void>;
tripleclick(x: number, y: number, options?: types.TripleClickOptions): Promise<void>;
}
export interface Request {
url(): string;
resourceType(): string;
method(): string;
postData(): string | undefined;
headers(): types.HttpHeaders;
isNavigationRequest(): boolean;
redirectChain(): Request[];
failure(): { errorText: string; } | null;
response(): Response | null;
frame(): Frame | null;
}
export interface Response {
request(): Request;
url(): string;
ok(): boolean;
status(): number;
statusText(): string;
headers(): types.HttpHeaders;
buffer(): Promise<Buffer>;
text(): Promise<string>;
json(): Promise<any>;
remoteAddress(): types.NetworkRemoteAddress;
frame(): Frame | null;
}
export interface Frame {
}

View file

@ -1,10 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import * as chromium from './chromium/api';
import * as firefox from './firefox/api';
import * as webkit from './webkit/api';
export const Chromium = chromium;
export const Firefox = firefox;
export const WebKit = webkit;

View file

@ -425,7 +425,7 @@ export class FrameManager extends EventEmitter implements PageDelegate {
this._page._onFileChooserOpened(handle); this._page._onFileChooserOpened(handle);
} }
setExtraHTTPHeaders(extraHTTPHeaders: network.Headers): Promise<void> { setExtraHTTPHeaders(extraHTTPHeaders: types.HttpHeaders): Promise<void> {
return this._networkManager.setExtraHTTPHeaders(extraHTTPHeaders); return this._networkManager.setExtraHTTPHeaders(extraHTTPHeaders);
} }

View file

@ -16,9 +16,10 @@
*/ */
import * as input from '../input'; import * as input from '../input';
import * as types from '../types';
import { CDPSession } from './Connection'; import { CDPSession } from './Connection';
function toModifiersMask(modifiers: Set<input.Modifier>): number { function toModifiersMask(modifiers: Set<types.ModifierKey>): number {
let mask = 0; let mask = 0;
if (modifiers.has('Alt')) if (modifiers.has('Alt'))
mask |= 1; mask |= 1;
@ -38,7 +39,7 @@ export class RawKeyboardImpl implements input.RawKeyboard {
this._client = client; this._client = client;
} }
async keydown(modifiers: Set<input.Modifier>, code: string, keyCode: number, keyCodeWithoutLocation: number, key: string, location: number, autoRepeat: boolean, text: string | undefined): Promise<void> { async keydown(modifiers: Set<types.ModifierKey>, code: string, keyCode: number, keyCodeWithoutLocation: number, key: string, location: number, autoRepeat: boolean, text: string | undefined): Promise<void> {
await this._client.send('Input.dispatchKeyEvent', { await this._client.send('Input.dispatchKeyEvent', {
type: text ? 'keyDown' : 'rawKeyDown', type: text ? 'keyDown' : 'rawKeyDown',
modifiers: toModifiersMask(modifiers), modifiers: toModifiersMask(modifiers),
@ -53,7 +54,7 @@ export class RawKeyboardImpl implements input.RawKeyboard {
}); });
} }
async keyup(modifiers: Set<input.Modifier>, code: string, keyCode: number, keyCodeWithoutLocation: number, key: string, location: number): Promise<void> { async keyup(modifiers: Set<types.ModifierKey>, code: string, keyCode: number, keyCodeWithoutLocation: number, key: string, location: number): Promise<void> {
await this._client.send('Input.dispatchKeyEvent', { await this._client.send('Input.dispatchKeyEvent', {
type: 'keyUp', type: 'keyUp',
modifiers: toModifiersMask(modifiers), modifiers: toModifiersMask(modifiers),
@ -76,7 +77,7 @@ export class RawMouseImpl implements input.RawMouse {
this._client = client; this._client = client;
} }
async move(x: number, y: number, button: input.Button | 'none', buttons: Set<input.Button>, modifiers: Set<input.Modifier>): Promise<void> { async move(x: number, y: number, button: types.MouseButton | 'none', buttons: Set<types.MouseButton>, modifiers: Set<types.ModifierKey>): Promise<void> {
await this._client.send('Input.dispatchMouseEvent', { await this._client.send('Input.dispatchMouseEvent', {
type: 'mouseMoved', type: 'mouseMoved',
button, button,
@ -86,7 +87,7 @@ export class RawMouseImpl implements input.RawMouse {
}); });
} }
async down(x: number, y: number, button: input.Button, buttons: Set<input.Button>, modifiers: Set<input.Modifier>, clickCount: number): Promise<void> { async down(x: number, y: number, button: types.MouseButton, buttons: Set<types.MouseButton>, modifiers: Set<types.ModifierKey>, clickCount: number): Promise<void> {
await this._client.send('Input.dispatchMouseEvent', { await this._client.send('Input.dispatchMouseEvent', {
type: 'mousePressed', type: 'mousePressed',
button, button,
@ -97,7 +98,7 @@ export class RawMouseImpl implements input.RawMouse {
}); });
} }
async up(x: number, y: number, button: input.Button, buttons: Set<input.Button>, modifiers: Set<input.Modifier>, clickCount: number): Promise<void> { async up(x: number, y: number, button: types.MouseButton, buttons: Set<types.MouseButton>, modifiers: Set<types.ModifierKey>, clickCount: number): Promise<void> {
await this._client.send('Input.dispatchMouseEvent', { await this._client.send('Input.dispatchMouseEvent', {
type: 'mouseReleased', type: 'mouseReleased',
button, button,

View file

@ -22,6 +22,7 @@ import { assert, debugError, helper } from '../helper';
import { Protocol } from './protocol'; import { Protocol } from './protocol';
import * as network from '../network'; import * as network from '../network';
import * as frames from '../frames'; import * as frames from '../frames';
import * as types from '../types';
export const NetworkManagerEvents = { export const NetworkManagerEvents = {
Request: Symbol('Events.NetworkManager.Request'), Request: Symbol('Events.NetworkManager.Request'),
@ -36,7 +37,7 @@ export class NetworkManager extends EventEmitter {
private _frameManager: FrameManager; private _frameManager: FrameManager;
private _requestIdToRequest = new Map<string, InterceptableRequest>(); private _requestIdToRequest = new Map<string, InterceptableRequest>();
private _requestIdToRequestWillBeSentEvent = new Map<string, Protocol.Network.requestWillBeSentPayload>(); private _requestIdToRequestWillBeSentEvent = new Map<string, Protocol.Network.requestWillBeSentPayload>();
private _extraHTTPHeaders: network.Headers = {}; private _extraHTTPHeaders: types.HttpHeaders = {};
private _offline = false; private _offline = false;
private _credentials: {username: string, password: string} | null = null; private _credentials: {username: string, password: string} | null = null;
private _attemptedAuthentications = new Set<string>(); private _attemptedAuthentications = new Set<string>();
@ -70,7 +71,7 @@ export class NetworkManager extends EventEmitter {
await this._updateProtocolRequestInterception(); await this._updateProtocolRequestInterception();
} }
async setExtraHTTPHeaders(extraHTTPHeaders: network.Headers) { async setExtraHTTPHeaders(extraHTTPHeaders: types.HttpHeaders) {
this._extraHTTPHeaders = {}; this._extraHTTPHeaders = {};
for (const key of Object.keys(extraHTTPHeaders)) { for (const key of Object.keys(extraHTTPHeaders)) {
const value = extraHTTPHeaders[key]; const value = extraHTTPHeaders[key];
@ -80,7 +81,7 @@ export class NetworkManager extends EventEmitter {
await this._client.send('Network.setExtraHTTPHeaders', { headers: this._extraHTTPHeaders }); await this._client.send('Network.setExtraHTTPHeaders', { headers: this._extraHTTPHeaders });
} }
extraHTTPHeaders(): network.Headers { extraHTTPHeaders(): types.HttpHeaders {
return Object.assign({}, this._extraHTTPHeaders); return Object.assign({}, this._extraHTTPHeaders);
} }
@ -204,7 +205,7 @@ export class NetworkManager extends EventEmitter {
} }
_createResponse(request: InterceptableRequest, responsePayload: Protocol.Network.Response): network.Response { _createResponse(request: InterceptableRequest, responsePayload: Protocol.Network.Response): network.Response {
const remoteAddress: network.RemoteAddress = { ip: responsePayload.remoteIPAddress, port: responsePayload.remotePort }; const remoteAddress: types.NetworkRemoteAddress = { ip: responsePayload.remoteIPAddress, port: responsePayload.remotePort };
const getResponseBody = async () => { const getResponseBody = async () => {
const response = await this._client.send('Network.getResponseBody', { requestId: request._requestId }); const response = await this._client.send('Network.getResponseBody', { requestId: request._requestId });
return Buffer.from(response.body, response.base64Encoded ? 'base64' : 'utf8'); return Buffer.from(response.body, response.base64Encoded ? 'base64' : 'utf8');
@ -393,8 +394,8 @@ function headersArray(headers: { [s: string]: string; }): { name: string; value:
return result; return result;
} }
function headersObject(headers: Protocol.Network.Headers): network.Headers { function headersObject(headers: Protocol.Network.Headers): types.HttpHeaders {
const result: network.Headers = {}; const result: types.HttpHeaders = {};
for (const key of Object.keys(headers)) for (const key of Object.keys(headers))
result[key.toLowerCase()] = headers[key]; result[key.toLowerCase()] = headers[key];
return result; return result;

View file

@ -111,7 +111,7 @@ export class FrameExecutionContext extends js.ExecutionContext {
_$eval: types.$Eval<string | ScopedSelector> = async (selector, pageFunction, ...args) => { _$eval: types.$Eval<string | ScopedSelector> = async (selector, pageFunction, ...args) => {
const elementHandle = await this._$(selector); const elementHandle = await this._$(selector);
if (!elementHandle) if (!elementHandle)
throw new Error(`Error: failed to find element matching selector "${types.selectorToString(selector)}"`); throw new Error(`Error: failed to find element matching selector "${helper.selectorToString(selector)}"`);
const result = await elementHandle.evaluate(pageFunction, ...args as any); const result = await elementHandle.evaluate(pageFunction, ...args as any);
await elementHandle.dispose(); await elementHandle.dispose();
return result; return result;
@ -279,9 +279,9 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
return { point, scrollX, scrollY }; return { point, scrollX, scrollY };
} }
async _performPointerAction(action: (point: types.Point) => Promise<void>, options?: input.PointerActionOptions): Promise<void> { async _performPointerAction(action: (point: types.Point) => Promise<void>, options?: types.PointerActionOptions): Promise<void> {
const point = await this._ensurePointerActionPoint(options ? options.relativePoint : undefined); const point = await this._ensurePointerActionPoint(options ? options.relativePoint : undefined);
let restoreModifiers: input.Modifier[] | undefined; let restoreModifiers: types.ModifierKey[] | undefined;
if (options && options.modifiers) if (options && options.modifiers)
restoreModifiers = await this._page.keyboard._ensureModifiers(options.modifiers); restoreModifiers = await this._page.keyboard._ensureModifiers(options.modifiers);
await action(point); await action(point);
@ -289,23 +289,23 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
await this._page.keyboard._ensureModifiers(restoreModifiers); await this._page.keyboard._ensureModifiers(restoreModifiers);
} }
hover(options?: input.PointerActionOptions): Promise<void> { hover(options?: types.PointerActionOptions): Promise<void> {
return this._performPointerAction(point => this._page.mouse.move(point.x, point.y), options); return this._performPointerAction(point => this._page.mouse.move(point.x, point.y), options);
} }
click(options?: input.ClickOptions): Promise<void> { click(options?: types.ClickOptions): Promise<void> {
return this._performPointerAction(point => this._page.mouse.click(point.x, point.y, options), options); return this._performPointerAction(point => this._page.mouse.click(point.x, point.y, options), options);
} }
dblclick(options?: input.MultiClickOptions): Promise<void> { dblclick(options?: types.DoubleClickOptions): Promise<void> {
return this._performPointerAction(point => this._page.mouse.dblclick(point.x, point.y, options), options); return this._performPointerAction(point => this._page.mouse.dblclick(point.x, point.y, options), options);
} }
tripleclick(options?: input.MultiClickOptions): Promise<void> { tripleclick(options?: types.TripleClickOptions): Promise<void> {
return this._performPointerAction(point => this._page.mouse.tripleclick(point.x, point.y, options), options); return this._performPointerAction(point => this._page.mouse.tripleclick(point.x, point.y, options), options);
} }
async select(...values: (string | ElementHandle | input.SelectOption)[]): Promise<string[]> { async select(...values: (string | ElementHandle | types.SelectOption)[]): Promise<string[]> {
const options = values.map(value => typeof value === 'object' ? value : { value }); const options = values.map(value => typeof value === 'object' ? value : { value });
for (const option of options) { for (const option of options) {
if (option instanceof ElementHandle) if (option instanceof ElementHandle)
@ -369,7 +369,7 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
} }
private _scopedSelector(selector: string | types.Selector): string | ScopedSelector { private _scopedSelector(selector: string | types.Selector): string | ScopedSelector {
selector = types.clearSelector(selector); selector = helper.clearSelector(selector);
if (helper.isString(selector)) if (helper.isString(selector))
selector = { selector }; selector = { selector };
return { scope: this, selector: selector.selector, visible: selector.visible }; return { scope: this, selector: selector.selector, visible: selector.visible };

View file

@ -296,7 +296,7 @@ export class FrameManager extends EventEmitter implements PageDelegate {
throw error; throw error;
} }
setExtraHTTPHeaders(extraHTTPHeaders: network.Headers): Promise<void> { setExtraHTTPHeaders(extraHTTPHeaders: types.HttpHeaders): Promise<void> {
return this._networkManager.setExtraHTTPHeaders(extraHTTPHeaders); return this._networkManager.setExtraHTTPHeaders(extraHTTPHeaders);
} }

View file

@ -17,8 +17,9 @@
import { JugglerSession } from './Connection'; import { JugglerSession } from './Connection';
import * as input from '../input'; import * as input from '../input';
import * as types from '../types';
function toModifiersMask(modifiers: Set<input.Modifier>): number { function toModifiersMask(modifiers: Set<types.ModifierKey>): number {
let mask = 0; let mask = 0;
if (modifiers.has('Alt')) if (modifiers.has('Alt'))
mask |= 1; mask |= 1;
@ -31,7 +32,7 @@ function toModifiersMask(modifiers: Set<input.Modifier>): number {
return mask; return mask;
} }
function toButtonNumber(button: input.Button): number { function toButtonNumber(button: types.MouseButton): number {
if (button === 'left') if (button === 'left')
return 0; return 0;
if (button === 'middle') if (button === 'middle')
@ -40,7 +41,7 @@ function toButtonNumber(button: input.Button): number {
return 2; return 2;
} }
function toButtonsMask(buttons: Set<input.Button>): number { function toButtonsMask(buttons: Set<types.MouseButton>): number {
let mask = 0; let mask = 0;
if (buttons.has('left')) if (buttons.has('left'))
mask |= 1; mask |= 1;
@ -58,7 +59,7 @@ export class RawKeyboardImpl implements input.RawKeyboard {
this._client = client; this._client = client;
} }
async keydown(modifiers: Set<input.Modifier>, code: string, keyCode: number, keyCodeWithoutLocation: number, key: string, location: number, autoRepeat: boolean, text: string | undefined): Promise<void> { async keydown(modifiers: Set<types.ModifierKey>, code: string, keyCode: number, keyCodeWithoutLocation: number, key: string, location: number, autoRepeat: boolean, text: string | undefined): Promise<void> {
if (code === 'MetaLeft') if (code === 'MetaLeft')
code = 'OSLeft'; code = 'OSLeft';
if (code === 'MetaRight') if (code === 'MetaRight')
@ -73,7 +74,7 @@ export class RawKeyboardImpl implements input.RawKeyboard {
}); });
} }
async keyup(modifiers: Set<input.Modifier>, code: string, keyCode: number, keyCodeWithoutLocation: number, key: string, location: number): Promise<void> { async keyup(modifiers: Set<types.ModifierKey>, code: string, keyCode: number, keyCodeWithoutLocation: number, key: string, location: number): Promise<void> {
if (code === 'MetaLeft') if (code === 'MetaLeft')
code = 'OSLeft'; code = 'OSLeft';
if (code === 'MetaRight') if (code === 'MetaRight')
@ -100,7 +101,7 @@ export class RawMouseImpl implements input.RawMouse {
this._client = client; this._client = client;
} }
async move(x: number, y: number, button: input.Button | 'none', buttons: Set<input.Button>, modifiers: Set<input.Modifier>): Promise<void> { async move(x: number, y: number, button: types.MouseButton | 'none', buttons: Set<types.MouseButton>, modifiers: Set<types.ModifierKey>): Promise<void> {
await this._client.send('Page.dispatchMouseEvent', { await this._client.send('Page.dispatchMouseEvent', {
type: 'mousemove', type: 'mousemove',
button: 0, button: 0,
@ -111,7 +112,7 @@ export class RawMouseImpl implements input.RawMouse {
}); });
} }
async down(x: number, y: number, button: input.Button, buttons: Set<input.Button>, modifiers: Set<input.Modifier>, clickCount: number): Promise<void> { async down(x: number, y: number, button: types.MouseButton, buttons: Set<types.MouseButton>, modifiers: Set<types.ModifierKey>, clickCount: number): Promise<void> {
await this._client.send('Page.dispatchMouseEvent', { await this._client.send('Page.dispatchMouseEvent', {
type: 'mousedown', type: 'mousedown',
button: toButtonNumber(button), button: toButtonNumber(button),
@ -123,7 +124,7 @@ export class RawMouseImpl implements input.RawMouse {
}); });
} }
async up(x: number, y: number, button: input.Button, buttons: Set<input.Button>, modifiers: Set<input.Modifier>, clickCount: number): Promise<void> { async up(x: number, y: number, button: types.MouseButton, buttons: Set<types.MouseButton>, modifiers: Set<types.ModifierKey>, clickCount: number): Promise<void> {
await this._client.send('Page.dispatchMouseEvent', { await this._client.send('Page.dispatchMouseEvent', {
type: 'mouseup', type: 'mouseup',
button: toButtonNumber(button), button: toButtonNumber(button),

View file

@ -21,6 +21,7 @@ import { JugglerSession } from './Connection';
import { FrameManager } from './FrameManager'; import { FrameManager } from './FrameManager';
import * as network from '../network'; import * as network from '../network';
import * as frames from '../frames'; import * as frames from '../frames';
import * as types from '../types';
export const NetworkManagerEvents = { export const NetworkManagerEvents = {
RequestFailed: Symbol('NetworkManagerEvents.RequestFailed'), RequestFailed: Symbol('NetworkManagerEvents.RequestFailed'),
@ -54,7 +55,7 @@ export class NetworkManager extends EventEmitter {
helper.removeEventListeners(this._eventListeners); helper.removeEventListeners(this._eventListeners);
} }
async setExtraHTTPHeaders(headers: network.Headers) { async setExtraHTTPHeaders(headers: types.HttpHeaders) {
const array = []; const array = [];
for (const [name, value] of Object.entries(headers)) { for (const [name, value] of Object.entries(headers)) {
assert(helper.isString(value), `Expected value of header "${name}" to be String, but "${typeof value}" is found.`); assert(helper.isString(value), `Expected value of header "${name}" to be String, but "${typeof value}" is found.`);
@ -87,7 +88,7 @@ export class NetworkManager extends EventEmitter {
const request = this._requests.get(event.requestId); const request = this._requests.get(event.requestId);
if (!request) if (!request)
return; return;
const remoteAddress: network.RemoteAddress = { ip: event.remoteIPAddress, port: event.remotePort }; const remoteAddress: types.NetworkRemoteAddress = { ip: event.remoteIPAddress, port: event.remotePort };
const getResponseBody = async () => { const getResponseBody = async () => {
const response = await this._session.send('Network.getResponseBody', { const response = await this._session.send('Network.getResponseBody', {
requestId: request._id requestId: request._id
@ -96,7 +97,7 @@ export class NetworkManager extends EventEmitter {
throw new Error(`Response body for ${request.request.method()} ${request.request.url()} was evicted!`); throw new Error(`Response body for ${request.request.method()} ${request.request.url()} was evicted!`);
return Buffer.from(response.base64body, 'base64'); return Buffer.from(response.base64body, 'base64');
}; };
const headers: network.Headers = {}; const headers: types.HttpHeaders = {};
for (const {name, value} of event.headers) for (const {name, value} of event.headers)
headers[name.toLowerCase()] = value; headers[name.toLowerCase()] = value;
const response = new network.Response(request.request, event.status, event.statusText, headers, remoteAddress, getResponseBody); const response = new network.Response(request.request, event.status, event.statusText, headers, remoteAddress, getResponseBody);
@ -176,7 +177,7 @@ class InterceptableRequest {
this._suspended = payload.suspended; this._suspended = payload.suspended;
this._interceptionHandled = false; this._interceptionHandled = false;
const headers: network.Headers = {}; const headers: types.HttpHeaders = {};
for (const {name, value} of payload.headers) for (const {name, value} of payload.headers)
headers[name.toLowerCase()] = value; headers[name.toLowerCase()] = value;

View file

@ -21,7 +21,6 @@ import * as js from './javascript';
import * as dom from './dom'; import * as dom from './dom';
import * as network from './network'; import * as network from './network';
import { helper, assert, RegisteredListener } from './helper'; import { helper, assert, RegisteredListener } from './helper';
import { ClickOptions, MultiClickOptions, PointerActionOptions, SelectOption } from './input';
import { TimeoutError } from './errors'; import { TimeoutError } from './errors';
import { Events } from './events'; import { Events } from './events';
import { Page } from './page'; import { Page } from './page';
@ -112,7 +111,7 @@ export class Frame {
async $(selector: string | types.Selector): Promise<dom.ElementHandle<Element> | null> { async $(selector: string | types.Selector): Promise<dom.ElementHandle<Element> | null> {
const context = await this._mainContext(); const context = await this._mainContext();
return context._$(types.clearSelector(selector)); return context._$(helper.clearSelector(selector));
} }
async $x(expression: string): Promise<dom.ElementHandle<Element>[]> { async $x(expression: string): Promise<dom.ElementHandle<Element>[]> {
@ -132,7 +131,7 @@ export class Frame {
async $$(selector: string | types.Selector): Promise<dom.ElementHandle<Element>[]> { async $$(selector: string | types.Selector): Promise<dom.ElementHandle<Element>[]> {
const context = await this._mainContext(); const context = await this._mainContext();
return context._$$(types.clearSelector(selector)); return context._$$(helper.clearSelector(selector));
} }
async content(): Promise<string> { async content(): Promise<string> {
@ -306,58 +305,58 @@ export class Frame {
return result; return result;
} }
async click(selector: string | types.Selector, options?: ClickOptions) { async click(selector: string | types.Selector, options?: types.ClickOptions) {
const context = await this._utilityContext(); const context = await this._utilityContext();
const handle = await context._$(types.clearSelector(selector)); const handle = await context._$(helper.clearSelector(selector));
assert(handle, 'No node found for selector: ' + types.selectorToString(selector)); assert(handle, 'No node found for selector: ' + helper.selectorToString(selector));
await handle.click(options); await handle.click(options);
await handle.dispose(); await handle.dispose();
} }
async dblclick(selector: string | types.Selector, options?: MultiClickOptions) { async dblclick(selector: string | types.Selector, options?: types.DoubleClickOptions) {
const context = await this._utilityContext(); const context = await this._utilityContext();
const handle = await context._$(types.clearSelector(selector)); const handle = await context._$(helper.clearSelector(selector));
assert(handle, 'No node found for selector: ' + types.selectorToString(selector)); assert(handle, 'No node found for selector: ' + helper.selectorToString(selector));
await handle.dblclick(options); await handle.dblclick(options);
await handle.dispose(); await handle.dispose();
} }
async tripleclick(selector: string | types.Selector, options?: MultiClickOptions) { async tripleclick(selector: string | types.Selector, options?: types.TripleClickOptions) {
const context = await this._utilityContext(); const context = await this._utilityContext();
const handle = await context._$(types.clearSelector(selector)); const handle = await context._$(helper.clearSelector(selector));
assert(handle, 'No node found for selector: ' + types.selectorToString(selector)); assert(handle, 'No node found for selector: ' + helper.selectorToString(selector));
await handle.tripleclick(options); await handle.tripleclick(options);
await handle.dispose(); await handle.dispose();
} }
async fill(selector: string | types.Selector, value: string) { async fill(selector: string | types.Selector, value: string) {
const context = await this._utilityContext(); const context = await this._utilityContext();
const handle = await context._$(types.clearSelector(selector)); const handle = await context._$(helper.clearSelector(selector));
assert(handle, 'No node found for selector: ' + types.selectorToString(selector)); assert(handle, 'No node found for selector: ' + helper.selectorToString(selector));
await handle.fill(value); await handle.fill(value);
await handle.dispose(); await handle.dispose();
} }
async focus(selector: string | types.Selector) { async focus(selector: string | types.Selector) {
const context = await this._utilityContext(); const context = await this._utilityContext();
const handle = await context._$(types.clearSelector(selector)); const handle = await context._$(helper.clearSelector(selector));
assert(handle, 'No node found for selector: ' + types.selectorToString(selector)); assert(handle, 'No node found for selector: ' + helper.selectorToString(selector));
await handle.focus(); await handle.focus();
await handle.dispose(); await handle.dispose();
} }
async hover(selector: string | types.Selector, options?: PointerActionOptions) { async hover(selector: string | types.Selector, options?: types.PointerActionOptions) {
const context = await this._utilityContext(); const context = await this._utilityContext();
const handle = await context._$(types.clearSelector(selector)); const handle = await context._$(helper.clearSelector(selector));
assert(handle, 'No node found for selector: ' + types.selectorToString(selector)); assert(handle, 'No node found for selector: ' + helper.selectorToString(selector));
await handle.hover(options); await handle.hover(options);
await handle.dispose(); await handle.dispose();
} }
async select(selector: string | types.Selector, ...values: (string | dom.ElementHandle | SelectOption)[]): Promise<string[]> { async select(selector: string | types.Selector, ...values: (string | dom.ElementHandle | types.SelectOption)[]): Promise<string[]> {
const context = await this._utilityContext(); const context = await this._utilityContext();
const handle = await context._$(types.clearSelector(selector)); const handle = await context._$(helper.clearSelector(selector));
assert(handle, 'No node found for selector: ' + types.selectorToString(selector)); assert(handle, 'No node found for selector: ' + helper.selectorToString(selector));
const toDispose: Promise<dom.ElementHandle>[] = []; const toDispose: Promise<dom.ElementHandle>[] = [];
const adoptedValues = await Promise.all(values.map(async value => { const adoptedValues = await Promise.all(values.map(async value => {
if (value instanceof dom.ElementHandle && value.executionContext() !== context) { if (value instanceof dom.ElementHandle && value.executionContext() !== context) {
@ -375,8 +374,8 @@ export class Frame {
async type(selector: string | types.Selector, text: string, options: { delay: (number | undefined); } | undefined) { async type(selector: string | types.Selector, text: string, options: { delay: (number | undefined); } | undefined) {
const context = await this._utilityContext(); const context = await this._utilityContext();
const handle = await context._$(types.clearSelector(selector)); const handle = await context._$(helper.clearSelector(selector));
assert(handle, 'No node found for selector: ' + types.selectorToString(selector)); assert(handle, 'No node found for selector: ' + helper.selectorToString(selector));
await handle.type(text, options); await handle.type(text, options);
await handle.dispose(); await handle.dispose();
} }
@ -393,8 +392,8 @@ export class Frame {
async waitForSelector(selector: string | types.Selector, options: types.TimeoutOptions = {}): Promise<dom.ElementHandle | null> { async waitForSelector(selector: string | types.Selector, options: types.TimeoutOptions = {}): Promise<dom.ElementHandle | null> {
const { timeout = this._page._timeoutSettings.timeout() } = options; const { timeout = this._page._timeoutSettings.timeout() } = options;
const task = dom.waitForSelectorTask(types.clearSelector(selector), timeout); const task = dom.waitForSelectorTask(helper.clearSelector(selector), timeout);
const handle = await this._scheduleRerunnableTask(task, 'utility', timeout, `selector "${types.selectorToString(selector)}"`); const handle = await this._scheduleRerunnableTask(task, 'utility', timeout, `selector "${helper.selectorToString(selector)}"`);
if (!handle.asElement()) { if (!handle.asElement()) {
await handle.dispose(); await handle.dispose();
return null; return null;

View file

@ -16,6 +16,7 @@
*/ */
import * as debug from 'debug'; import * as debug from 'debug';
import * as types from './types';
import { TimeoutError } from './errors'; import { TimeoutError } from './errors';
export const debugError = debug(`playwright:error`); export const debugError = debug(`playwright:error`);
@ -153,6 +154,19 @@ class Helper {
clearTimeout(timeoutTimer); clearTimeout(timeoutTimer);
} }
} }
static selectorToString(selector: string | types.Selector): string {
if (typeof selector === 'string')
return selector;
return `${selector.visible ? '[visible] ' : selector.visible === false ? '[hidden] ' : ''}${selector.selector}`;
}
// Ensures that we don't use accidental properties in selector, e.g. scope.
static clearSelector(selector: string | types.Selector): string | types.Selector {
if (helper.isString(selector))
return selector;
return { selector: selector.selector, visible: selector.visible };
}
} }
export function assert(value: any, message?: string) { export function assert(value: any, message?: string) {

View file

@ -6,34 +6,10 @@ import * as path from 'path';
import { assert, helper } from './helper'; import { assert, helper } from './helper';
import * as types from './types'; import * as types from './types';
import * as keyboardLayout from './usKeyboardLayout'; import * as keyboardLayout from './usKeyboardLayout';
import * as api from './api';
const readFileAsync = helper.promisify(fs.readFile); const readFileAsync = helper.promisify(fs.readFile);
export type Modifier = 'Alt' | 'Control' | 'Meta' | 'Shift';
export type Button = 'left' | 'right' | 'middle';
export type PointerActionOptions = {
modifiers?: Modifier[];
relativePoint?: types.Point;
};
export type ClickOptions = PointerActionOptions & {
delay?: number;
button?: Button;
clickCount?: number;
};
export type MultiClickOptions = PointerActionOptions & {
delay?: number;
button?: Button;
};
export type SelectOption = {
value?: string;
label?: string;
index?: number;
};
export const keypadLocation = keyboardLayout.keypadLocation; export const keypadLocation = keyboardLayout.keypadLocation;
type KeyDescription = { type KeyDescription = {
@ -45,17 +21,17 @@ type KeyDescription = {
location: number, location: number,
}; };
const kModifiers: Modifier[] = ['Alt', 'Control', 'Meta', 'Shift']; const kModifiers: types.ModifierKey[] = ['Alt', 'Control', 'Meta', 'Shift'];
export interface RawKeyboard { export interface RawKeyboard {
keydown(modifiers: Set<Modifier>, code: string, keyCode: number, keyCodeWithoutLocation: number, key: string, location: number, autoRepeat: boolean, text: string | undefined): Promise<void>; keydown(modifiers: Set<types.ModifierKey>, code: string, keyCode: number, keyCodeWithoutLocation: number, key: string, location: number, autoRepeat: boolean, text: string | undefined): Promise<void>;
keyup(modifiers: Set<Modifier>, code: string, keyCode: number, keyCodeWithoutLocation: number, key: string, location: number): Promise<void>; keyup(modifiers: Set<types.ModifierKey>, code: string, keyCode: number, keyCodeWithoutLocation: number, key: string, location: number): Promise<void>;
sendText(text: string): Promise<void>; sendText(text: string): Promise<void>;
} }
export class Keyboard { export class Keyboard implements api.Keyboard {
private _raw: RawKeyboard; private _raw: RawKeyboard;
private _pressedModifiers = new Set<Modifier>(); private _pressedModifiers = new Set<types.ModifierKey>();
private _pressedKeys = new Set<string>(); private _pressedKeys = new Set<string>();
constructor(raw: RawKeyboard) { constructor(raw: RawKeyboard) {
@ -66,8 +42,8 @@ export class Keyboard {
const description = this._keyDescriptionForString(key); const description = this._keyDescriptionForString(key);
const autoRepeat = this._pressedKeys.has(description.code); const autoRepeat = this._pressedKeys.has(description.code);
this._pressedKeys.add(description.code); this._pressedKeys.add(description.code);
if (kModifiers.includes(description.key as Modifier)) if (kModifiers.includes(description.key as types.ModifierKey))
this._pressedModifiers.add(description.key as Modifier); this._pressedModifiers.add(description.key as types.ModifierKey);
const text = options.text === undefined ? description.text : options.text; const text = options.text === undefined ? description.text : options.text;
await this._raw.keydown(this._pressedModifiers, description.code, description.keyCode, description.keyCodeWithoutLocation, description.key, description.location, autoRepeat, text); await this._raw.keydown(this._pressedModifiers, description.code, description.keyCode, description.keyCodeWithoutLocation, description.key, description.location, autoRepeat, text);
} }
@ -123,8 +99,8 @@ export class Keyboard {
async up(key: string) { async up(key: string) {
const description = this._keyDescriptionForString(key); const description = this._keyDescriptionForString(key);
if (kModifiers.includes(description.key as Modifier)) if (kModifiers.includes(description.key as types.ModifierKey))
this._pressedModifiers.delete(description.key as Modifier); this._pressedModifiers.delete(description.key as types.ModifierKey);
this._pressedKeys.delete(description.code); this._pressedKeys.delete(description.code);
await this._raw.keyup(this._pressedModifiers, description.code, description.keyCode, description.keyCodeWithoutLocation, description.key, description.location); await this._raw.keyup(this._pressedModifiers, description.code, description.keyCode, description.keyCodeWithoutLocation, description.key, description.location);
} }
@ -154,12 +130,12 @@ export class Keyboard {
await this.up(key); await this.up(key);
} }
async _ensureModifiers(modifiers: Modifier[]): Promise<Modifier[]> { async _ensureModifiers(modifiers: types.ModifierKey[]): Promise<types.ModifierKey[]> {
for (const modifier of modifiers) { for (const modifier of modifiers) {
if (!kModifiers.includes(modifier)) if (!kModifiers.includes(modifier))
throw new Error('Uknown modifier ' + modifier); throw new Error('Uknown modifier ' + modifier);
} }
const restore: Modifier[] = Array.from(this._pressedModifiers); const restore: types.ModifierKey[] = Array.from(this._pressedModifiers);
const promises: Promise<void>[] = []; const promises: Promise<void>[] = [];
for (const key of kModifiers) { for (const key of kModifiers) {
const needDown = modifiers.includes(key); const needDown = modifiers.includes(key);
@ -173,24 +149,24 @@ export class Keyboard {
return restore; return restore;
} }
_modifiers(): Set<Modifier> { _modifiers(): Set<types.ModifierKey> {
return this._pressedModifiers; return this._pressedModifiers;
} }
} }
export interface RawMouse { export interface RawMouse {
move(x: number, y: number, button: Button | 'none', buttons: Set<Button>, modifiers: Set<Modifier>): Promise<void>; move(x: number, y: number, button: types.MouseButton | 'none', buttons: Set<types.MouseButton>, modifiers: Set<types.ModifierKey>): Promise<void>;
down(x: number, y: number, button: Button, buttons: Set<Button>, modifiers: Set<Modifier>, clickCount: number): Promise<void>; down(x: number, y: number, button: types.MouseButton, buttons: Set<types.MouseButton>, modifiers: Set<types.ModifierKey>, clickCount: number): Promise<void>;
up(x: number, y: number, button: Button, buttons: Set<Button>, modifiers: Set<Modifier>, clickCount: number): Promise<void>; up(x: number, y: number, button: types.MouseButton, buttons: Set<types.MouseButton>, modifiers: Set<types.ModifierKey>, clickCount: number): Promise<void>;
} }
export class Mouse { export class Mouse implements api.Mouse {
private _raw: RawMouse; private _raw: RawMouse;
private _keyboard: Keyboard; private _keyboard: Keyboard;
private _x = 0; private _x = 0;
private _y = 0; private _y = 0;
private _lastButton: 'none' | Button = 'none'; private _lastButton: 'none' | types.MouseButton = 'none';
private _buttons = new Set<Button>(); private _buttons = new Set<types.MouseButton>();
constructor(raw: RawMouse, keyboard: Keyboard) { constructor(raw: RawMouse, keyboard: Keyboard) {
this._raw = raw; this._raw = raw;
@ -210,21 +186,21 @@ export class Mouse {
} }
} }
async down(options: { button?: Button, clickCount?: number } = {}) { async down(options: { button?: types.MouseButton, clickCount?: number } = {}) {
const { button = 'left', clickCount = 1 } = options; const { button = 'left', clickCount = 1 } = options;
this._lastButton = button; this._lastButton = button;
this._buttons.add(button); this._buttons.add(button);
await this._raw.down(this._x, this._y, this._lastButton, this._buttons, this._keyboard._modifiers(), clickCount); await this._raw.down(this._x, this._y, this._lastButton, this._buttons, this._keyboard._modifiers(), clickCount);
} }
async up(options: { button?: Button, clickCount?: number } = {}) { async up(options: { button?: types.MouseButton, clickCount?: number } = {}) {
const { button = 'left', clickCount = 1 } = options; const { button = 'left', clickCount = 1 } = options;
this._lastButton = 'none'; this._lastButton = 'none';
this._buttons.delete(button); this._buttons.delete(button);
await this._raw.up(this._x, this._y, button, this._buttons, this._keyboard._modifiers(), clickCount); await this._raw.up(this._x, this._y, button, this._buttons, this._keyboard._modifiers(), clickCount);
} }
async click(x: number, y: number, options: ClickOptions = {}) { async click(x: number, y: number, options: types.ClickOptions = {}) {
const {delay = null} = options; const {delay = null} = options;
if (delay !== null) { if (delay !== null) {
await Promise.all([ await Promise.all([
@ -242,7 +218,7 @@ export class Mouse {
} }
} }
async dblclick(x: number, y: number, options: MultiClickOptions = {}) { async dblclick(x: number, y: number, options: types.DoubleClickOptions = {}) {
const { delay = null } = options; const { delay = null } = options;
if (delay !== null) { if (delay !== null) {
await this.move(x, y); await this.move(x, y);
@ -264,7 +240,7 @@ export class Mouse {
} }
} }
async tripleclick(x: number, y: number, options: MultiClickOptions = {}) { async tripleclick(x: number, y: number, options: types.TripleClickOptions = {}) {
const { delay = null } = options; const { delay = null } = options;
if (delay !== null) { if (delay !== null) {
await this.move(x, y); await this.move(x, y);
@ -293,7 +269,7 @@ export class Mouse {
} }
} }
export const selectFunction = (node: Node, ...optionsToSelect: (Node | SelectOption)[]) => { export const selectFunction = (node: Node, ...optionsToSelect: (Node | types.SelectOption)[]) => {
if (node.nodeName.toLowerCase() !== 'select') if (node.nodeName.toLowerCase() !== 'select')
throw new Error('Element is not a <select> element.'); throw new Error('Element is not a <select> element.');
const element = node as HTMLSelectElement; const element = node as HTMLSelectElement;

View file

@ -2,6 +2,8 @@
// Licensed under the MIT license. // Licensed under the MIT license.
import * as frames from './frames'; import * as frames from './frames';
import * as types from './types';
import * as api from './api';
import { assert } from './helper'; import { assert } from './helper';
export type NetworkCookie = { export type NetworkCookie = {
@ -67,9 +69,7 @@ export function rewriteCookies(cookies: SetNetworkCookieParam[]): SetNetworkCook
}); });
} }
export type Headers = { [key: string]: string }; export class Request implements api.Request {
export class Request {
private _response: Response | null = null; private _response: Response | null = null;
_redirectChain: Request[]; _redirectChain: Request[];
private _isNavigationRequest: boolean; private _isNavigationRequest: boolean;
@ -78,7 +78,7 @@ export class Request {
private _resourceType: string; private _resourceType: string;
private _method: string; private _method: string;
private _postData: string; private _postData: string;
private _headers: Headers; private _headers: types.HttpHeaders;
private _frame: frames.Frame; private _frame: frames.Frame;
private _waitForResponsePromise: Promise<Response>; private _waitForResponsePromise: Promise<Response>;
private _waitForResponsePromiseCallback: (value?: Response) => void; private _waitForResponsePromiseCallback: (value?: Response) => void;
@ -86,7 +86,7 @@ export class Request {
private _waitForFinishedPromiseCallback: (value?: Response | undefined) => void; private _waitForFinishedPromiseCallback: (value?: Response | undefined) => void;
constructor(frame: frames.Frame | null, redirectChain: Request[], isNavigationRequest: boolean, constructor(frame: frames.Frame | null, redirectChain: Request[], isNavigationRequest: boolean,
url: string, resourceType: string, method: string, postData: string, headers: Headers) { url: string, resourceType: string, method: string, postData: string, headers: types.HttpHeaders) {
this._frame = frame; this._frame = frame;
this._redirectChain = redirectChain; this._redirectChain = redirectChain;
this._isNavigationRequest = isNavigationRequest; this._isNavigationRequest = isNavigationRequest;
@ -120,7 +120,7 @@ export class Request {
return this._postData; return this._postData;
} }
headers(): {[key: string]: string} { headers(): types.HttpHeaders {
return this._headers; return this._headers;
} }
@ -165,26 +165,21 @@ export class Request {
} }
} }
export type RemoteAddress = {
ip: string,
port: number,
};
type GetResponseBodyCallback = () => Promise<Buffer>; type GetResponseBodyCallback = () => Promise<Buffer>;
export class Response { export class Response implements api.Response {
private _request: Request; private _request: Request;
private _contentPromise: Promise<Buffer> | null = null; private _contentPromise: Promise<Buffer> | null = null;
_finishedPromise: Promise<Error | null>; _finishedPromise: Promise<Error | null>;
private _finishedPromiseCallback: any; private _finishedPromiseCallback: any;
private _remoteAddress: RemoteAddress; private _remoteAddress: types.NetworkRemoteAddress;
private _status: number; private _status: number;
private _statusText: string; private _statusText: string;
private _url: string; private _url: string;
private _headers: Headers; private _headers: types.HttpHeaders;
private _getResponseBodyCallback: GetResponseBodyCallback; private _getResponseBodyCallback: GetResponseBodyCallback;
constructor(request: Request, status: number, statusText: string, headers: Headers, remoteAddress: RemoteAddress, getResponseBodyCallback: GetResponseBodyCallback) { constructor(request: Request, status: number, statusText: string, headers: types.HttpHeaders, remoteAddress: types.NetworkRemoteAddress, getResponseBodyCallback: GetResponseBodyCallback) {
this._request = request; this._request = request;
this._status = status; this._status = status;
this._statusText = statusText; this._statusText = statusText;
@ -202,7 +197,7 @@ export class Response {
this._finishedPromiseCallback.call(null, error); this._finishedPromiseCallback.call(null, error);
} }
remoteAddress(): RemoteAddress { remoteAddress(): types.NetworkRemoteAddress {
return this._remoteAddress; return this._remoteAddress;
} }
@ -222,7 +217,7 @@ export class Response {
return this._statusText; return this._statusText;
} }
headers(): object { headers(): types.HttpHeaders {
return this._headers; return this._headers;
} }

View file

@ -49,7 +49,7 @@ export interface PageDelegate {
waitForFrameNavigation(frame: frames.Frame, options?: frames.NavigateOptions): Promise<network.Response | null>; waitForFrameNavigation(frame: frames.Frame, options?: frames.NavigateOptions): Promise<network.Response | null>;
setFrameContent(frame: frames.Frame, html: string, options?: frames.NavigateOptions): Promise<void>; setFrameContent(frame: frames.Frame, html: string, options?: frames.NavigateOptions): Promise<void>;
setExtraHTTPHeaders(extraHTTPHeaders: network.Headers): Promise<void>; setExtraHTTPHeaders(extraHTTPHeaders: types.HttpHeaders): Promise<void>;
setUserAgent(userAgent: string): Promise<void>; setUserAgent(userAgent: string): Promise<void>;
setJavaScriptEnabled(enabled: boolean): Promise<void>; setJavaScriptEnabled(enabled: boolean): Promise<void>;
setBypassCSP(enabled: boolean): Promise<void>; setBypassCSP(enabled: boolean): Promise<void>;
@ -78,7 +78,7 @@ type PageState = {
mediaType: input.MediaType | null; mediaType: input.MediaType | null;
mediaColorScheme: input.MediaColorScheme | null; mediaColorScheme: input.MediaColorScheme | null;
javascriptEnabled: boolean | null; javascriptEnabled: boolean | null;
extraHTTPHeaders: network.Headers | null; extraHTTPHeaders: types.HttpHeaders | null;
bypassCSP: boolean | null; bypassCSP: boolean | null;
cacheEnabled: boolean | null; cacheEnabled: boolean | null;
}; };
@ -257,7 +257,7 @@ export class Page extends EventEmitter {
} }
} }
setExtraHTTPHeaders(headers: network.Headers) { setExtraHTTPHeaders(headers: types.HttpHeaders) {
this._state.extraHTTPHeaders = {...headers}; this._state.extraHTTPHeaders = {...headers};
return this._delegate.setExtraHTTPHeaders(headers); return this._delegate.setExtraHTTPHeaders(headers);
} }
@ -447,15 +447,15 @@ export class Page extends EventEmitter {
return this._closed; return this._closed;
} }
click(selector: string | types.Selector, options?: input.ClickOptions) { click(selector: string | types.Selector, options?: types.ClickOptions) {
return this.mainFrame().click(selector, options); return this.mainFrame().click(selector, options);
} }
dblclick(selector: string | types.Selector, options?: input.MultiClickOptions) { dblclick(selector: string | types.Selector, options?: types.DoubleClickOptions) {
return this.mainFrame().dblclick(selector, options); return this.mainFrame().dblclick(selector, options);
} }
tripleclick(selector: string | types.Selector, options?: input.MultiClickOptions) { tripleclick(selector: string | types.Selector, options?: types.TripleClickOptions) {
return this.mainFrame().tripleclick(selector, options); return this.mainFrame().tripleclick(selector, options);
} }
@ -467,11 +467,11 @@ export class Page extends EventEmitter {
return this.mainFrame().focus(selector); return this.mainFrame().focus(selector);
} }
hover(selector: string | types.Selector, options?: input.PointerActionOptions) { hover(selector: string | types.Selector, options?: types.PointerActionOptions) {
return this.mainFrame().hover(selector, options); return this.mainFrame().hover(selector, options);
} }
select(selector: string | types.Selector, ...values: (string | dom.ElementHandle | input.SelectOption)[]): Promise<string[]> { select(selector: string | types.Selector, ...values: (string | dom.ElementHandle | types.SelectOption)[]): Promise<string[]> {
return this.mainFrame().select(selector, ...values); return this.mainFrame().select(selector, ...values);
} }

View file

@ -2,7 +2,6 @@
// Licensed under the MIT license. // Licensed under the MIT license.
import * as js from './javascript'; import * as js from './javascript';
import { helper } from './helper';
import * as dom from './dom'; import * as dom from './dom';
type Boxed<Args extends any[]> = { [Index in keyof Args]: Args[Index] | js.JSHandle<Args[Index]> }; type Boxed<Args extends any[]> = { [Index in keyof Args]: Args[Index] | js.JSHandle<Args[Index]> };
@ -31,18 +30,41 @@ export type Selector = { selector: string, visible?: boolean };
export type Polling = 'raf' | 'mutation' | number; export type Polling = 'raf' | 'mutation' | number;
export type WaitForFunctionOptions = TimeoutOptions & { polling?: Polling }; export type WaitForFunctionOptions = TimeoutOptions & { polling?: Polling };
export function selectorToString(selector: string | Selector): string { export type ModifierKey = 'Alt' | 'Control' | 'Meta' | 'Shift';
if (typeof selector === 'string') export type MouseButton = 'left' | 'right' | 'middle';
return selector;
return `${selector.visible ? '[visible] ' : selector.visible === false ? '[hidden] ' : ''}${selector.selector}`;
}
// Ensures that we don't use accidental properties in selector, e.g. scope. export type PointerActionOptions = {
export function clearSelector(selector: string | Selector): string | Selector { modifiers?: ModifierKey[];
if (helper.isString(selector)) relativePoint?: Point;
return selector; };
return { selector: selector.selector, visible: selector.visible };
} export type ClickOptions = PointerActionOptions & {
delay?: number;
button?: MouseButton;
clickCount?: number;
};
export type DoubleClickOptions = PointerActionOptions & {
delay?: number;
button?: MouseButton;
};
export type TripleClickOptions = PointerActionOptions & {
delay?: number;
button?: MouseButton;
};
export type SelectOption = {
value?: string;
label?: string;
index?: number;
};
export type HttpHeaders = { [key: string]: string };
export type NetworkRemoteAddress = {
ip: string,
port: number,
};
export type ElementScreenshotOptions = { export type ElementScreenshotOptions = {
type?: 'png' | 'jpeg', type?: 'png' | 'jpeg',

View file

@ -387,7 +387,7 @@ export class FrameManager extends EventEmitter implements PageDelegate {
this._page._onFileChooserOpened(handle); this._page._onFileChooserOpened(handle);
} }
setExtraHTTPHeaders(extraHTTPHeaders: network.Headers): Promise<void> { setExtraHTTPHeaders(extraHTTPHeaders: types.HttpHeaders): Promise<void> {
return this._networkManager.setExtraHTTPHeaders(extraHTTPHeaders); return this._networkManager.setExtraHTTPHeaders(extraHTTPHeaders);
} }

View file

@ -16,11 +16,12 @@
*/ */
import * as input from '../input'; import * as input from '../input';
import * as types from '../types';
import { helper } from '../helper'; import { helper } from '../helper';
import { macEditingCommands } from '../usKeyboardLayout'; import { macEditingCommands } from '../usKeyboardLayout';
import { TargetSession } from './Connection'; import { TargetSession } from './Connection';
function toModifiersMask(modifiers: Set<input.Modifier>): number { function toModifiersMask(modifiers: Set<types.ModifierKey>): number {
// From Source/WebKit/Shared/WebEvent.h // From Source/WebKit/Shared/WebEvent.h
let mask = 0; let mask = 0;
if (modifiers.has('Shift')) if (modifiers.has('Shift'))
@ -41,9 +42,9 @@ export class RawKeyboardImpl implements input.RawKeyboard {
this._session = session; this._session = session;
} }
async keydown(modifiers: Set<input.Modifier>, code: string, keyCode: number, keyCodeWithoutLocation: number, key: string, location: number, autoRepeat: boolean, text: string | undefined): Promise<void> { async keydown(modifiers: Set<types.ModifierKey>, code: string, keyCode: number, keyCodeWithoutLocation: number, key: string, location: number, autoRepeat: boolean, text: string | undefined): Promise<void> {
const parts = []; const parts = [];
for (const modifier of (['Shift', 'Control', 'Alt', 'Meta']) as input.Modifier[]) { for (const modifier of (['Shift', 'Control', 'Alt', 'Meta']) as types.ModifierKey[]) {
if (modifiers.has(modifier)) if (modifiers.has(modifier))
parts.push(modifier); parts.push(modifier);
} }
@ -66,7 +67,7 @@ export class RawKeyboardImpl implements input.RawKeyboard {
}); });
} }
async keyup(modifiers: Set<input.Modifier>, code: string, keyCode: number, keyCodeWithoutLocation: number, key: string, location: number): Promise<void> { async keyup(modifiers: Set<types.ModifierKey>, code: string, keyCode: number, keyCodeWithoutLocation: number, key: string, location: number): Promise<void> {
await this._session.send('Input.dispatchKeyEvent', { await this._session.send('Input.dispatchKeyEvent', {
type: 'keyUp', type: 'keyUp',
modifiers: toModifiersMask(modifiers), modifiers: toModifiersMask(modifiers),
@ -89,7 +90,7 @@ export class RawMouseImpl implements input.RawMouse {
this._client = client; this._client = client;
} }
async move(x: number, y: number, button: input.Button | 'none', buttons: Set<input.Button>, modifiers: Set<input.Modifier>): Promise<void> { async move(x: number, y: number, button: types.MouseButton | 'none', buttons: Set<types.MouseButton>, modifiers: Set<types.ModifierKey>): Promise<void> {
await this._client.send('Input.dispatchMouseEvent', { await this._client.send('Input.dispatchMouseEvent', {
type: 'move', type: 'move',
button, button,
@ -99,7 +100,7 @@ export class RawMouseImpl implements input.RawMouse {
}); });
} }
async down(x: number, y: number, button: input.Button, buttons: Set<input.Button>, modifiers: Set<input.Modifier>, clickCount: number): Promise<void> { async down(x: number, y: number, button: types.MouseButton, buttons: Set<types.MouseButton>, modifiers: Set<types.ModifierKey>, clickCount: number): Promise<void> {
await this._client.send('Input.dispatchMouseEvent', { await this._client.send('Input.dispatchMouseEvent', {
type: 'down', type: 'down',
button, button,
@ -110,7 +111,7 @@ export class RawMouseImpl implements input.RawMouse {
}); });
} }
async up(x: number, y: number, button: input.Button, buttons: Set<input.Button>, modifiers: Set<input.Modifier>, clickCount: number): Promise<void> { async up(x: number, y: number, button: types.MouseButton, buttons: Set<types.MouseButton>, modifiers: Set<types.ModifierKey>, clickCount: number): Promise<void> {
await this._client.send('Input.dispatchMouseEvent', { await this._client.send('Input.dispatchMouseEvent', {
type: 'up', type: 'up',
button, button,

View file

@ -22,6 +22,7 @@ import { assert, helper, RegisteredListener } from '../helper';
import { Protocol } from './protocol'; import { Protocol } from './protocol';
import * as network from '../network'; import * as network from '../network';
import * as frames from '../frames'; import * as frames from '../frames';
import * as types from '../types';
export const NetworkManagerEvents = { export const NetworkManagerEvents = {
Request: Symbol('Events.NetworkManager.Request'), Request: Symbol('Events.NetworkManager.Request'),
@ -34,7 +35,7 @@ export class NetworkManager extends EventEmitter {
private _session: TargetSession; private _session: TargetSession;
private _frameManager: FrameManager; private _frameManager: FrameManager;
private _requestIdToRequest = new Map<string, InterceptableRequest>(); private _requestIdToRequest = new Map<string, InterceptableRequest>();
private _extraHTTPHeaders: network.Headers = {}; private _extraHTTPHeaders: types.HttpHeaders = {};
private _attemptedAuthentications = new Set<string>(); private _attemptedAuthentications = new Set<string>();
private _userCacheDisabled = false; private _userCacheDisabled = false;
private _sessionListeners: RegisteredListener[] = []; private _sessionListeners: RegisteredListener[] = [];
@ -109,7 +110,7 @@ export class NetworkManager extends EventEmitter {
} }
_createResponse(request: InterceptableRequest, responsePayload: Protocol.Network.Response): network.Response { _createResponse(request: InterceptableRequest, responsePayload: Protocol.Network.Response): network.Response {
const remoteAddress: network.RemoteAddress = { ip: '', port: 0 }; const remoteAddress: types.NetworkRemoteAddress = { ip: '', port: 0 };
const getResponseBody = async () => { const getResponseBody = async () => {
const response = await this._session.send('Network.getResponseBody', { requestId: request._requestId }); const response = await this._session.send('Network.getResponseBody', { requestId: request._requestId });
return Buffer.from(response.body, response.base64Encoded ? 'base64' : 'utf8'); return Buffer.from(response.body, response.base64Encoded ? 'base64' : 'utf8');
@ -198,8 +199,8 @@ class InterceptableRequest {
} }
} }
function headersObject(headers: Protocol.Network.Headers): network.Headers { function headersObject(headers: Protocol.Network.Headers): types.HttpHeaders {
const result: network.Headers = {}; const result: types.HttpHeaders = {};
for (const key of Object.keys(headers)) for (const key of Object.keys(headers))
result[key.toLowerCase()] = headers[key]; result[key.toLowerCase()] = headers[key];
return result; return result;

View file

@ -10,6 +10,6 @@
"declaration": true "declaration": true
}, },
"compileOnSave": true, "compileOnSave": true,
"include": ["src/**/*.ts"], "include": ["src/**/*.ts", "src/**/*.d.ts"],
"exclude": ["node_modules"] "exclude": ["node_modules"]
} }