mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
chore: reuse input code across vendors (#62)
This commit is contained in:
parent
ef847b1941
commit
c4c8d498bd
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
85
src/input.ts
85
src/input.ts
@ -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.');
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user