chore: reuse input code across vendors (#62)

This commit is contained in:
Pavel Feldman 2019-11-22 16:47:50 -08:00 committed by Dmitry Gozman
parent ef847b1941
commit c4c8d498bd
4 changed files with 132 additions and 219 deletions

View File

@ -16,7 +16,7 @@
*/
import { assert } from '../helper';
import { Modifier, Button } from '../input';
import * as input from '../input';
import { keyDefinitions } from '../USKeyboardLayout';
import { CDPSession } from './Connection';
@ -28,7 +28,7 @@ type KeyDescription = {
location: number,
};
const kModifiers: Modifier[] = ['Alt', 'Control', 'Meta', 'Shift'];
const kModifiers: input.Modifier[] = ['Alt', 'Control', 'Meta', 'Shift'];
export class Keyboard {
private _client: CDPSession;
@ -157,12 +157,12 @@ export class Keyboard {
await this.up(key);
}
async _ensureModifiers(modifiers: Modifier[]): Promise<Modifier[]> {
async _ensureModifiers(modifiers: input.Modifier[]): Promise<input.Modifier[]> {
for (const modifier of modifiers) {
if (!kModifiers.includes(modifier))
throw new Error('Uknown modifier ' + modifier);
}
const restore: Modifier[] = [];
const restore: input.Modifier[] = [];
const promises: Promise<void>[] = [];
for (const key of kModifiers) {
const needDown = modifiers.includes(key);
@ -179,12 +179,12 @@ export class Keyboard {
}
}
export class Mouse {
export class Mouse implements input.MouseOperations {
private _client: CDPSession;
private _keyboard: Keyboard;
private _x = 0;
private _y = 0;
private _button: 'none' | Button = 'none';
private _button: 'none' | input.Button = 'none';
constructor(client: CDPSession, keyboard: Keyboard) {
this._client = client;
@ -207,75 +207,7 @@ export class Mouse {
}
}
async click(x: number, y: number, options: { delay?: number; button?: Button; clickCount?: number; } = {}) {
const {delay = null} = options;
if (delay !== null) {
await Promise.all([
this.move(x, y),
this.down(options),
]);
await new Promise(f => setTimeout(f, delay));
await this.up(options);
} else {
await Promise.all([
this.move(x, y),
this.down(options),
this.up(options),
]);
}
}
async dblclick(x: number, y: number, options: { delay?: number; button?: Button; } = {}) {
const { delay = null } = options;
if (delay !== null) {
await this.move(x, y);
await this.down({ ...options, clickCount: 1 });
await new Promise(f => setTimeout(f, delay));
await this.up({ ...options, clickCount: 1 });
await new Promise(f => setTimeout(f, delay));
await this.down({ ...options, clickCount: 2 });
await new Promise(f => setTimeout(f, delay));
await this.up({ ...options, clickCount: 2 });
} else {
await Promise.all([
this.move(x, y),
this.down({ ...options, clickCount: 1 }),
this.up({ ...options, clickCount: 1 }),
this.down({ ...options, clickCount: 2 }),
this.up({ ...options, clickCount: 2 }),
]);
}
}
async tripleclick(x: number, y: number, options: { delay?: number; button?: Button; } = {}) {
const { delay = null } = options;
if (delay !== null) {
await this.move(x, y);
await this.down({ ...options, clickCount: 1 });
await new Promise(f => setTimeout(f, delay));
await this.up({ ...options, clickCount: 1 });
await new Promise(f => setTimeout(f, delay));
await this.down({ ...options, clickCount: 2 });
await new Promise(f => setTimeout(f, delay));
await this.up({ ...options, clickCount: 2 });
await new Promise(f => setTimeout(f, delay));
await this.down({ ...options, clickCount: 3 });
await new Promise(f => setTimeout(f, delay));
await this.up({ ...options, clickCount: 3 });
} else {
await Promise.all([
this.move(x, y),
this.down({ ...options, clickCount: 1 }),
this.up({ ...options, clickCount: 1 }),
this.down({ ...options, clickCount: 2 }),
this.up({ ...options, clickCount: 2 }),
this.down({ ...options, clickCount: 3 }),
this.up({ ...options, clickCount: 3 }),
]);
}
}
async down(options: { button?: Button; clickCount?: number; } = {}) {
async down(options: { button?: input.Button; clickCount?: number; } = {}) {
const {button = 'left', clickCount = 1} = options;
this._button = button;
await this._client.send('Input.dispatchMouseEvent', {
@ -288,7 +220,7 @@ export class Mouse {
});
}
async up(options: { button?: Button; clickCount?: number; } = {}) {
async up(options: { button?: input.Button; clickCount?: number; } = {}) {
const {button = 'left', clickCount = 1} = options;
this._button = 'none';
await this._client.send('Input.dispatchMouseEvent', {
@ -300,4 +232,16 @@ export class Mouse {
clickCount
});
}
async click(x: number, y: number, options?: input.ClickOptions) {
await new input.MouseClicker(this).click(x, y, options);
}
async dblclick(x: number, y: number, options?: input.ClickOptions) {
await new input.MouseClicker(this).dblclick(x, y, options);
}
async tripleclick(x: number, y: number, options?: input.ClickOptions) {
await new input.MouseClicker(this).tripleclick(x, y, options);
}
}

View File

@ -17,7 +17,7 @@
import { keyDefinitions } from '../USKeyboardLayout';
import { JugglerSession } from './Connection';
import { Button, ClickOptions, MultiClickOptions } from '../input';
import * as input from '../input';
interface KeyDescription {
keyCode: number;
@ -156,12 +156,13 @@ export class Keyboard {
}
}
export class Mouse {
export class Mouse implements input.MouseOperations {
_client: any;
_keyboard: Keyboard;
_x: number;
_y: number;
_buttons: number;
constructor(client, keyboard: Keyboard) {
this._client = client;
this._keyboard = keyboard;
@ -187,73 +188,6 @@ export class Mouse {
}
}
async click(x: number, y: number, options: ClickOptions = {}) {
const {delay = null} = options;
if (delay !== null) {
await Promise.all([
this.move(x, y),
this.down(options),
]);
await new Promise(f => setTimeout(f, delay));
await this.up(options);
} else {
await Promise.all([
this.move(x, y),
this.down(options),
this.up(options),
]);
}
}
async dblclick(x: number, y: number, options: MultiClickOptions = {}) {
const { delay = null } = options;
if (delay !== null) {
await this.move(x, y);
await this.down({ ...options, clickCount: 1 });
await new Promise(f => setTimeout(f, delay));
await this.up({ ...options, clickCount: 1 });
await new Promise(f => setTimeout(f, delay));
await this.down({ ...options, clickCount: 2 });
await new Promise(f => setTimeout(f, delay));
await this.up({ ...options, clickCount: 2 });
} else {
await Promise.all([
this.move(x, y),
this.down({ ...options, clickCount: 1 }),
this.up({ ...options, clickCount: 1 }),
this.down({ ...options, clickCount: 2 }),
this.up({ ...options, clickCount: 2 }),
]);
}
}
async tripleclick(x: number, y: number, options: MultiClickOptions = {}) {
const { delay = null } = options;
if (delay !== null) {
await this.move(x, y);
await this.down({ ...options, clickCount: 1 });
await new Promise(f => setTimeout(f, delay));
await this.up({ ...options, clickCount: 1 });
await new Promise(f => setTimeout(f, delay));
await this.down({ ...options, clickCount: 2 });
await new Promise(f => setTimeout(f, delay));
await this.up({ ...options, clickCount: 2 });
await new Promise(f => setTimeout(f, delay));
await this.down({ ...options, clickCount: 3 });
await new Promise(f => setTimeout(f, delay));
await this.up({ ...options, clickCount: 3 });
} else {
await Promise.all([
this.move(x, y),
this.down({ ...options, clickCount: 1 }),
this.up({ ...options, clickCount: 1 }),
this.down({ ...options, clickCount: 2 }),
this.up({ ...options, clickCount: 2 }),
this.down({ ...options, clickCount: 3 }),
this.up({ ...options, clickCount: 3 }),
]);
}
}
async down(options: { button?: string; clickCount?: number; } | undefined = {}) {
const {
button = 'left',
@ -306,4 +240,16 @@ export class Mouse {
buttons: this._buttons,
});
}
async click(x: number, y: number, options?: input.ClickOptions) {
await new input.MouseClicker(this).click(x, y, options);
}
async dblclick(x: number, y: number, options?: input.ClickOptions) {
await new input.MouseClicker(this).dblclick(x, y, options);
}
async tripleclick(x: number, y: number, options?: input.ClickOptions) {
await new input.MouseClicker(this).tripleclick(x, y, options);
}
}

View File

@ -1,6 +1,3 @@
import { assert } from "console";
import { helper } from "./helper";
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
@ -34,6 +31,88 @@ export type SelectOption = {
index?: number;
};
export interface MouseOperations {
move(x: number, y: number, options?: { steps?: number; }): Promise<void>;
down(options?: { button?: Button; clickCount?: number; }): Promise<void>;
up(options?: { button?: Button; clickCount?: number; }): Promise<void>;
}
export class MouseClicker {
private _operations: MouseOperations;
constructor(operations: MouseOperations) {
this._operations = operations;
}
async click(x: number, y: number, options: ClickOptions = {}) {
const {delay = null} = options;
if (delay !== null) {
await Promise.all([
this._operations.move(x, y),
this._operations.down(options),
]);
await new Promise(f => setTimeout(f, delay));
await this._operations.up(options);
} else {
await Promise.all([
this._operations.move(x, y),
this._operations.down(options),
this._operations.up(options),
]);
}
}
async dblclick(x: number, y: number, options: MultiClickOptions = {}) {
const { delay = null } = options;
if (delay !== null) {
await this._operations.move(x, y);
await this._operations.down({ ...options, clickCount: 1 });
await new Promise(f => setTimeout(f, delay));
await this._operations.up({ ...options, clickCount: 1 });
await new Promise(f => setTimeout(f, delay));
await this._operations.down({ ...options, clickCount: 2 });
await new Promise(f => setTimeout(f, delay));
await this._operations.up({ ...options, clickCount: 2 });
} else {
await Promise.all([
this._operations.move(x, y),
this._operations.down({ ...options, clickCount: 1 }),
this._operations.up({ ...options, clickCount: 1 }),
this._operations.down({ ...options, clickCount: 2 }),
this._operations.up({ ...options, clickCount: 2 }),
]);
}
}
async tripleclick(x: number, y: number, options: MultiClickOptions = {}) {
const { delay = null } = options;
if (delay !== null) {
await this._operations.move(x, y);
await this._operations.down({ ...options, clickCount: 1 });
await new Promise(f => setTimeout(f, delay));
await this._operations.up({ ...options, clickCount: 1 });
await new Promise(f => setTimeout(f, delay));
await this._operations.down({ ...options, clickCount: 2 });
await new Promise(f => setTimeout(f, delay));
await this._operations.up({ ...options, clickCount: 2 });
await new Promise(f => setTimeout(f, delay));
await this._operations.down({ ...options, clickCount: 3 });
await new Promise(f => setTimeout(f, delay));
await this._operations.up({ ...options, clickCount: 3 });
} else {
await Promise.all([
this._operations.move(x, y),
this._operations.down({ ...options, clickCount: 1 }),
this._operations.up({ ...options, clickCount: 1 }),
this._operations.down({ ...options, clickCount: 2 }),
this._operations.up({ ...options, clickCount: 2 }),
this._operations.down({ ...options, clickCount: 3 }),
this._operations.up({ ...options, clickCount: 3 }),
]);
}
}
}
export const selectFunction = (element: HTMLSelectElement, ...optionsToSelect: (Node | SelectOption)[]) => {
if (element.nodeName.toLowerCase() !== 'select')
throw new Error('Element is not a <select> element.');

View File

@ -15,10 +15,10 @@
* limitations under the License.
*/
import { TargetSession } from './Connection';
import { assert } from '../helper';
import * as input from '../input';
import { keyDefinitions } from '../USKeyboardLayout';
import { MultiClickOptions, ClickOptions } from '../input';
import { TargetSession } from './Connection';
type KeyDescription = {
keyCode: number,
@ -188,7 +188,7 @@ export class Keyboard {
}
}
export class Mouse {
export class Mouse implements input.MouseOperations {
private _client: TargetSession;
private _keyboard: Keyboard;
private _x = 0;
@ -216,74 +216,6 @@ export class Mouse {
}
}
async click(x: number, y: number, options: ClickOptions = {}) {
const {delay = null} = options;
if (delay !== null) {
await Promise.all([
this.move(x, y),
this.down(options),
]);
await new Promise(f => setTimeout(f, delay));
await this.up(options);
} else {
await Promise.all([
this.move(x, y),
this.down(options),
this.up(options),
]);
}
}
async dblclick(x: number, y: number, options: MultiClickOptions = {}) {
const { delay = null } = options;
if (delay !== null) {
await this.move(x, y);
await this.down({ ...options, clickCount: 1 });
await new Promise(f => setTimeout(f, delay));
await this.up({ ...options, clickCount: 1 });
await new Promise(f => setTimeout(f, delay));
await this.down({ ...options, clickCount: 2 });
await new Promise(f => setTimeout(f, delay));
await this.up({ ...options, clickCount: 2 });
} else {
await Promise.all([
this.move(x, y),
this.down({ ...options, clickCount: 1 }),
this.up({ ...options, clickCount: 1 }),
this.down({ ...options, clickCount: 2 }),
this.up({ ...options, clickCount: 2 }),
]);
}
}
async tripleclick(x: number, y: number, options: MultiClickOptions = {}) {
const { delay = null } = options;
if (delay !== null) {
await this.move(x, y);
await this.down({ ...options, clickCount: 1 });
await new Promise(f => setTimeout(f, delay));
await this.up({ ...options, clickCount: 1 });
await new Promise(f => setTimeout(f, delay));
await this.down({ ...options, clickCount: 2 });
await new Promise(f => setTimeout(f, delay));
await this.up({ ...options, clickCount: 2 });
await new Promise(f => setTimeout(f, delay));
await this.down({ ...options, clickCount: 3 });
await new Promise(f => setTimeout(f, delay));
await this.up({ ...options, clickCount: 3 });
} else {
await Promise.all([
this.move(x, y),
this.down({ ...options, clickCount: 1 }),
this.up({ ...options, clickCount: 1 }),
this.down({ ...options, clickCount: 2 }),
this.up({ ...options, clickCount: 2 }),
this.down({ ...options, clickCount: 3 }),
this.up({ ...options, clickCount: 3 }),
]);
}
}
async down(options: { button?: Button; clickCount?: number; } = {}) {
const {button = 'left', clickCount = 1} = options;
this._button = button;
@ -309,4 +241,16 @@ export class Mouse {
clickCount
});
}
async click(x: number, y: number, options?: input.ClickOptions) {
await new input.MouseClicker(this).click(x, y, options);
}
async dblclick(x: number, y: number, options?: input.ClickOptions) {
await new input.MouseClicker(this).dblclick(x, y, options);
}
async tripleclick(x: number, y: number, options?: input.ClickOptions) {
await new input.MouseClicker(this).tripleclick(x, y, options);
}
}