feat: add reset to mouse (#10340)

This commit is contained in:
jrandolf 2023-06-12 19:59:28 +02:00 committed by GitHub
parent 9aee41a53d
commit 35aedc0dbb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 144 additions and 14 deletions

View File

@ -87,5 +87,6 @@ await browser
| [dragOver(target, data)](./puppeteer.mouse.dragover.md) | | Dispatches a <code>dragover</code> event. | | [dragOver(target, data)](./puppeteer.mouse.dragover.md) | | Dispatches a <code>dragover</code> event. |
| [drop(target, data)](./puppeteer.mouse.drop.md) | | Performs a dragenter, dragover, and drop in sequence. | | [drop(target, data)](./puppeteer.mouse.drop.md) | | Performs a dragenter, dragover, and drop in sequence. |
| [move(x, y, options)](./puppeteer.mouse.move.md) | | Moves the mouse to the given coordinate. | | [move(x, y, options)](./puppeteer.mouse.move.md) | | Moves the mouse to the given coordinate. |
| [reset()](./puppeteer.mouse.reset.md) | | Resets the mouse to the default state: No buttons pressed; position at (0,0). |
| [up(options)](./puppeteer.mouse.up.md) | | Releases the mouse. | | [up(options)](./puppeteer.mouse.up.md) | | Releases the mouse. |
| [wheel(options)](./puppeteer.mouse.wheel.md) | | Dispatches a <code>mousewheel</code> event. | | [wheel(options)](./puppeteer.mouse.wheel.md) | | Dispatches a <code>mousewheel</code> event. |

View File

@ -0,0 +1,19 @@
---
sidebar_label: Mouse.reset
---
# Mouse.reset() method
Resets the mouse to the default state: No buttons pressed; position at (0,0).
#### Signature:
```typescript
class Mouse {
reset(): Promise<void>;
}
```
**Returns:**
Promise&lt;void&gt;

View File

@ -598,6 +598,29 @@ export class Mouse {
} }
} }
/**
* Resets the mouse to the default state: No buttons pressed; position at
* (0,0).
*/
async reset(): Promise<void> {
const actions = [];
for (const [flag, button] of [
[MouseButtonFlag.Left, MouseButton.Left],
[MouseButtonFlag.Middle, MouseButton.Middle],
[MouseButtonFlag.Right, MouseButton.Right],
[MouseButtonFlag.Forward, MouseButton.Forward],
[MouseButtonFlag.Back, MouseButton.Back],
] as const) {
if (this.#state.buttons & flag) {
actions.push(this.up({button: button}));
}
}
if (this.#state.position.x !== 0 || this.#state.position.y !== 0) {
actions.push(this.move(0, 0));
}
await Promise.all(actions);
}
/** /**
* Moves the mouse to the given coordinate. * Moves the mouse to the given coordinate.
* *

View File

@ -1457,6 +1457,12 @@
"parameters": ["chrome", "webDriverBiDi"], "parameters": ["chrome", "webDriverBiDi"],
"expectations": ["PASS"] "expectations": ["PASS"]
}, },
{
"testIdPattern": "[mouse.spec] Mouse should reset properly",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["cdp", "firefox"],
"expectations": ["SKIP"]
},
{ {
"testIdPattern": "[mouse.spec] Mouse should select the text with mouse", "testIdPattern": "[mouse.spec] Mouse should select the text with mouse",
"platforms": ["win32"], "platforms": ["win32"],

View File

@ -16,6 +16,8 @@
import os from 'os'; import os from 'os';
import expect from 'expect'; import expect from 'expect';
import {MouseButton} from 'puppeteer-core';
import {Page} from 'puppeteer-core/internal/api/Page.js';
import {KeyInput} from 'puppeteer-core/internal/common/USKeyboardLayout.js'; import {KeyInput} from 'puppeteer-core/internal/common/USKeyboardLayout.js';
import { import {
@ -24,6 +26,16 @@ import {
setupTestPageAndContextHooks, setupTestPageAndContextHooks,
} from './mocha-utils.js'; } from './mocha-utils.js';
interface ClickData {
type: string;
detail: number;
clientX: number;
clientY: number;
isTrusted: boolean;
button: number;
buttons: number;
}
interface Dimensions { interface Dimensions {
x: number; x: number;
y: number; y: number;
@ -267,21 +279,16 @@ describe('Mouse', function () {
await page.mouse.down(); await page.mouse.down();
await expect(page.mouse.down()).rejects.toBeInstanceOf(Error); await expect(page.mouse.down()).rejects.toBeInstanceOf(Error);
}); });
it('should not throw if clicking in parallel', async () => {
const {page, server} = getTestState();
await page.goto(server.EMPTY_PAGE); interface AddMouseDataListenersOptions {
interface ClickData { includeMove?: boolean;
type: string; }
detail: number;
clientX: number;
clientY: number;
isTrusted: boolean;
button: number;
buttons: number;
}
await page.evaluate(() => { const addMouseDataListeners = (
page: Page,
options: AddMouseDataListenersOptions = {}
) => {
return page.evaluate(({includeMove}) => {
const clicks: ClickData[] = []; const clicks: ClickData[] = [];
const mouseEventListener = (event: MouseEvent) => { const mouseEventListener = (event: MouseEvent) => {
clicks.push({ clicks.push({
@ -295,10 +302,20 @@ describe('Mouse', function () {
}); });
}; };
document.addEventListener('mousedown', mouseEventListener); document.addEventListener('mousedown', mouseEventListener);
if (includeMove) {
document.addEventListener('mousemove', mouseEventListener);
}
document.addEventListener('mouseup', mouseEventListener); document.addEventListener('mouseup', mouseEventListener);
document.addEventListener('click', mouseEventListener); document.addEventListener('click', mouseEventListener);
(window as unknown as {clicks: ClickData[]}).clicks = clicks; (window as unknown as {clicks: ClickData[]}).clicks = clicks;
}); }, options);
};
it('should not throw if clicking in parallel', async () => {
const {page, server} = getTestState();
await page.goto(server.EMPTY_PAGE);
await addMouseDataListeners(page);
await Promise.all([page.mouse.click(0, 5), page.mouse.click(6, 10)]); await Promise.all([page.mouse.click(0, 5), page.mouse.click(6, 10)]);
@ -351,4 +368,68 @@ describe('Mouse', function () {
}, },
}); });
}); });
it('should reset properly', async () => {
const {page, server} = getTestState();
await page.goto(server.EMPTY_PAGE);
await page.mouse.move(5, 5);
await Promise.all([
page.mouse.down({button: MouseButton.Left}),
page.mouse.down({button: MouseButton.Middle}),
page.mouse.down({button: MouseButton.Right}),
]);
await addMouseDataListeners(page, {includeMove: true});
await page.mouse.reset();
const data = await page.evaluate(() => {
return (window as unknown as {clicks: ClickData[]}).clicks;
});
const commonAttrs = {
isTrusted: true,
clientY: 5,
clientX: 5,
};
expect(data).toMatchObject([
{
...commonAttrs,
button: 0,
buttons: 6,
detail: 1,
type: 'mouseup',
},
{
...commonAttrs,
button: 0,
buttons: 6,
detail: 1,
type: 'click',
},
{
...commonAttrs,
button: 1,
buttons: 2,
detail: 0,
type: 'mouseup',
},
{
...commonAttrs,
button: 2,
buttons: 0,
detail: 0,
type: 'mouseup',
},
{
...commonAttrs,
button: 0,
buttons: 0,
clientX: 0,
clientY: 0,
detail: 0,
type: 'mousemove',
},
]);
});
}); });