feat: add drag-and-drop support (#7150)

This commit adds drag-and-drop support, leveraging new additions to the CDP Input domain (Input.setInterceptDrags, Input.dispatchDragEvent, and Input.dragIntercepted).
This commit is contained in:
Dan Park 2021-06-04 03:25:36 -07:00 committed by Mathias Bynens
parent 0295b1c773
commit a91b8aca37
7 changed files with 591 additions and 4 deletions

View File

@ -155,6 +155,7 @@
* [page.goto(url[, options])](#pagegotourl-options) * [page.goto(url[, options])](#pagegotourl-options)
* [page.hover(selector)](#pagehoverselector) * [page.hover(selector)](#pagehoverselector)
* [page.isClosed()](#pageisclosed) * [page.isClosed()](#pageisclosed)
* [page.isDragInterceptionEnabled](#pageisdraginterceptionenabled)
* [page.isJavaScriptEnabled()](#pageisjavascriptenabled) * [page.isJavaScriptEnabled()](#pageisjavascriptenabled)
* [page.keyboard](#pagekeyboard) * [page.keyboard](#pagekeyboard)
* [page.mainFrame()](#pagemainframe) * [page.mainFrame()](#pagemainframe)
@ -171,6 +172,7 @@
* [page.setCookie(...cookies)](#pagesetcookiecookies) * [page.setCookie(...cookies)](#pagesetcookiecookies)
* [page.setDefaultNavigationTimeout(timeout)](#pagesetdefaultnavigationtimeouttimeout) * [page.setDefaultNavigationTimeout(timeout)](#pagesetdefaultnavigationtimeouttimeout)
* [page.setDefaultTimeout(timeout)](#pagesetdefaulttimeouttimeout) * [page.setDefaultTimeout(timeout)](#pagesetdefaulttimeouttimeout)
* [page.setDragInterception(enabled)](#pagesetdraginterceptionenabled)
* [page.setExtraHTTPHeaders(headers)](#pagesetextrahttpheadersheaders) * [page.setExtraHTTPHeaders(headers)](#pagesetextrahttpheadersheaders)
* [page.setGeolocation(options)](#pagesetgeolocationoptions) * [page.setGeolocation(options)](#pagesetgeolocationoptions)
* [page.setJavaScriptEnabled(enabled)](#pagesetjavascriptenabledenabled) * [page.setJavaScriptEnabled(enabled)](#pagesetjavascriptenabledenabled)
@ -214,6 +216,11 @@
- [class: Mouse](#class-mouse) - [class: Mouse](#class-mouse)
* [mouse.click(x, y[, options])](#mouseclickx-y-options) * [mouse.click(x, y[, options])](#mouseclickx-y-options)
* [mouse.down([options])](#mousedownoptions) * [mouse.down([options])](#mousedownoptions)
* [mouse.drag(start, target)](#mousedragstart-target)
* [mouse.dragAndDrop(start, target[, options])](#mousedraganddropstart-target-options)
* [mouse.dragEnter(target, data)](#mousedragentertarget-data)
* [mouse.dragOver(target, data)](#mousedragovertarget-data)
* [mouse.drop(target, data)](#mousedroptarget-data)
* [mouse.move(x, y[, options])](#mousemovex-y-options) * [mouse.move(x, y[, options])](#mousemovex-y-options)
* [mouse.up([options])](#mouseupoptions) * [mouse.up([options])](#mouseupoptions)
* [mouse.wheel([options])](#mousewheeloptions) * [mouse.wheel([options])](#mousewheeloptions)
@ -294,8 +301,14 @@
* [elementHandle.boundingBox()](#elementhandleboundingbox) * [elementHandle.boundingBox()](#elementhandleboundingbox)
* [elementHandle.boxModel()](#elementhandleboxmodel) * [elementHandle.boxModel()](#elementhandleboxmodel)
* [elementHandle.click([options])](#elementhandleclickoptions) * [elementHandle.click([options])](#elementhandleclickoptions)
* [elementHandle.clickablePoint()](#elementhandleclickablepoint)
* [elementHandle.contentFrame()](#elementhandlecontentframe) * [elementHandle.contentFrame()](#elementhandlecontentframe)
* [elementHandle.dispose()](#elementhandledispose) * [elementHandle.dispose()](#elementhandledispose)
* [elementHandle.drag(target)](#elementhandledragtarget)
* [elementHandle.dragAndDrop(target[, options])](#elementhandledraganddroptarget-options)
* [elementHandle.dragEnter([data])](#elementhandledragenterdata)
* [elementHandle.dragOver([data])](#elementhandledragoverdata)
* [elementHandle.drop([data])](#elementhandledropdata)
* [elementHandle.evaluate(pageFunction[, ...args])](#elementhandleevaluatepagefunction-args) * [elementHandle.evaluate(pageFunction[, ...args])](#elementhandleevaluatepagefunction-args)
* [elementHandle.evaluateHandle(pageFunction[, ...args])](#elementhandleevaluatehandlepagefunction-args) * [elementHandle.evaluateHandle(pageFunction[, ...args])](#elementhandleevaluatehandlepagefunction-args)
* [elementHandle.executionContext()](#elementhandleexecutioncontext) * [elementHandle.executionContext()](#elementhandleexecutioncontext)
@ -1919,6 +1932,12 @@ Shortcut for [page.mainFrame().hover(selector)](#framehoverselector).
Indicates that the page has been closed. Indicates that the page has been closed.
#### page.isDragInterceptionEnabled
- returns: <[boolean]>
Indicates that drag events are being intercepted.
#### page.isJavaScriptEnabled() #### page.isJavaScriptEnabled()
- returns: <[boolean]> - returns: <[boolean]>
@ -2183,6 +2202,13 @@ This setting will change the default maximum time for the following methods and
> **NOTE** [`page.setDefaultNavigationTimeout`](#pagesetdefaultnavigationtimeouttimeout) takes priority over [`page.setDefaultTimeout`](#pagesetdefaulttimeouttimeout) > **NOTE** [`page.setDefaultNavigationTimeout`](#pagesetdefaultnavigationtimeouttimeout) takes priority over [`page.setDefaultTimeout`](#pagesetdefaulttimeouttimeout)
#### page.setDragInterception(enabled)
- `enabled` <[boolean]>
- returns: <[Promise]>
Enables the Input.drag methods. This provides the capability to cpature drag events emitted on the page, which can then be used to simulate drag-and-drop.
#### page.setExtraHTTPHeaders(headers) #### page.setExtraHTTPHeaders(headers)
- `headers` <[Object]> An object containing additional HTTP headers to be sent with every request. All header values must be strings. - `headers` <[Object]> An object containing additional HTTP headers to be sent with every request. All header values must be strings.
@ -2958,6 +2984,62 @@ Shortcut for [`mouse.move`](#mousemovex-y-options), [`mouse.down`](#mousedownopt
Dispatches a `mousedown` event. Dispatches a `mousedown` event.
#### mouse.drag(start, target)
- `start` <[Object]> the position to start dragging from
- `x` <[number]> x coordinate
- `y` <[number]> y coordinate
- `target` <[Object]> the position to drag to
- `x` <[number]> x coordinate
- `y` <[number]> y coordinate
- returns: <[Promise<[DragData]>]>
This method creates and captures a dragevent from a given point.
#### mouse.dragAndDrop(start, target[, options])
- `start` <[Object]>
- `x` <[number]> x coordinate
- `y` <[number]> y coordinate
- `target` <[Object]>
- `x` <[number]> x coordinate
- `y` <[number]> y coordinate
- `options` <[Object]>
- `delay` <[number]> how long to delay before dropping onto the target point
- returns: <[Promise<[DragData]>]>
This method drags from a given start point and drops onto a target point.
#### mouse.dragEnter(target, data)
- `target` <[Object]>
- `x` <[number]> x coordinate
- `y` <[number]> y coordinate
- `data` <[Object]>
- returns: <[Promise]]>
This method triggers a dragenter event from the target point.
#### mouse.dragOver(target, data)
- `target` <[Object]>
- `x` <[number]> x coordinate
- `y` <[number]> y coordinate
- `data` <[Object]>
- returns: <[Promise]]>
This method triggers a dragover event from the target point.
#### mouse.drop(target, data)
- `target` <[Object]>
- `x` <[number]> x coordinate
- `y` <[number]> y coordinate
- `data` <[Object]>
- returns: <[Promise]]>
This method triggers a drop event from the target point.
#### mouse.move(x, y[, options]) #### mouse.move(x, y[, options])
- `x` <[number]> - `x` <[number]>
@ -4033,6 +4115,10 @@ This method returns boxes of the element, or `null` if the element is not visibl
This method scrolls element into view if needed, and then uses [page.mouse](#pagemouse) to click in the center of the element. This method scrolls element into view if needed, and then uses [page.mouse](#pagemouse) to click in the center of the element.
If the element is detached from DOM, the method throws an error. If the element is detached from DOM, the method throws an error.
#### elementHandle.clickablePoint()
- returns: <[Promise<[Point]>]> Resolves to the x, y point that describes the element's position.
#### elementHandle.contentFrame() #### elementHandle.contentFrame()
- returns: <[Promise]<?[Frame]>> Resolves to the content frame for element handles referencing iframe nodes, or null otherwise - returns: <[Promise]<?[Frame]>> Resolves to the content frame for element handles referencing iframe nodes, or null otherwise
@ -4043,6 +4129,45 @@ If the element is detached from DOM, the method throws an error.
The `elementHandle.dispose` method stops referencing the element handle. The `elementHandle.dispose` method stops referencing the element handle.
#### elementHandle.drag(target)
- `target` <[Object]>
- `x` <[number]> x coordinate
- `y` <[number]> y coordinate
- returns: <[Promise<[DragData]>]>
This method creates and captures a drag event from the element.
#### elementHandle.dragAndDrop(target[, options])
- `target` <[ElementHandle]>
- `options` <[Object]>
- `delay` <[number]> how long to delay before dropping onto the target element
- returns: <[Promise]>
This method will drag a given element and drop it onto a target element.
#### elementHandle.dragEnter([data])
- `data` <[Object]> drag data created from `element.drag`
- returns: <[Promise]>
This method will trigger a dragenter event from the given element.
#### elementHandle.dragOver([data])
- `data` <[Object]> drag data created from `element.drag`
- returns: <[Promise]>
This method will trigger a dragover event from the given element.
#### elementHandle.drop([data])
- `data` <[Object]> drag data created from `element.drag`
- returns: <[Promise]>
This method will trigger a drop event from the given element.
#### elementHandle.evaluate(pageFunction[, ...args]) #### elementHandle.evaluate(pageFunction[, ...args])
- `pageFunction` <[function]\([Object]\)> Function to be evaluated in browser context - `pageFunction` <[function]\([Object]\)> Function to be evaluated in browser context

View File

@ -17,6 +17,8 @@
import { assert } from './assert.js'; import { assert } from './assert.js';
import { CDPSession } from './Connection.js'; import { CDPSession } from './Connection.js';
import { keyDefinitions, KeyDefinition, KeyInput } from './USKeyboardLayout.js'; import { keyDefinitions, KeyDefinition, KeyInput } from './USKeyboardLayout.js';
import { Protocol } from 'devtools-protocol';
import { Point } from './JSHandle.js';
type KeyDescription = Required< type KeyDescription = Required<
Pick<KeyDefinition, 'keyCode' | 'key' | 'text' | 'code' | 'location'> Pick<KeyDefinition, 'keyCode' | 'key' | 'text' | 'code' | 'location'>
@ -485,6 +487,98 @@ export class Mouse {
pointerType: 'mouse', pointerType: 'mouse',
}); });
} }
/**
* Dispatches a `drag` event.
* @param start - starting point for drag
* @param target - point to drag to
* ```
*/
async drag(start: Point, target: Point): Promise<Protocol.Input.DragData> {
const promise = new Promise<Protocol.Input.DragData>((resolve) => {
this._client.once('Input.dragIntercepted', (event) =>
resolve(event.data)
);
});
await this.move(start.x, start.y);
await this.down();
await this.move(target.x, target.y);
return promise;
}
/**
* Dispatches a `dragenter` event.
* @param target - point for emitting `dragenter` event
* ```
*/
async dragEnter(target: Point, data: Protocol.Input.DragData): Promise<void> {
await this._client.send('Input.dispatchDragEvent', {
type: 'dragEnter',
x: target.x,
y: target.y,
modifiers: this._keyboard._modifiers,
data,
});
}
/**
* Dispatches a `dragover` event.
* @param target - point for emitting `dragover` event
* ```
*/
async dragOver(target: Point, data: Protocol.Input.DragData): Promise<void> {
await this._client.send('Input.dispatchDragEvent', {
type: 'dragOver',
x: target.x,
y: target.y,
modifiers: this._keyboard._modifiers,
data,
});
}
/**
* Performs a dragenter, dragover, and drop in sequence.
* @param target - point to drop on
* @param data - drag data containing items and operations mask
* @param options - An object of options. Accepts delay which,
* if specified, is the time to wait between `dragover` and `drop` in milliseconds.
* Defaults to 0.
* ```
*/
async drop(target: Point, data: Protocol.Input.DragData): Promise<void> {
await this._client.send('Input.dispatchDragEvent', {
type: 'drop',
x: target.x,
y: target.y,
modifiers: this._keyboard._modifiers,
data,
});
}
/**
* Performs a drag, dragenter, dragover, and drop in sequence.
* @param target - point to drag from
* @param target - point to drop on
* @param options - An object of options. Accepts delay which,
* if specified, is the time to wait between `dragover` and `drop` in milliseconds.
* Defaults to 0.
* ```
*/
async dragAndDrop(
start: Point,
target: Point,
options: { delay?: number } = {}
): Promise<void> {
const { delay = null } = options;
const data = await this.drag(start, target);
await this.dragEnter(target, data);
await this.dragOver(target, data);
if (delay) {
await new Promise((resolve) => setTimeout(resolve, delay));
}
await this.drop(target, data);
await this.up();
}
} }
/** /**

View File

@ -411,7 +411,7 @@ export class ElementHandle<
if (error) throw new Error(error); if (error) throw new Error(error);
} }
private async _clickablePoint(): Promise<{ x: number; y: number }> { async clickablePoint(): Promise<Point> {
const [result, layoutMetrics] = await Promise.all([ const [result, layoutMetrics] = await Promise.all([
this._client this._client
.send('DOM.getContentQuads', { .send('DOM.getContentQuads', {
@ -482,7 +482,7 @@ export class ElementHandle<
*/ */
async hover(): Promise<void> { async hover(): Promise<void> {
await this._scrollIntoViewIfNeeded(); await this._scrollIntoViewIfNeeded();
const { x, y } = await this._clickablePoint(); const { x, y } = await this.clickablePoint();
await this._page.mouse.move(x, y); await this._page.mouse.move(x, y);
} }
@ -493,10 +493,69 @@ export class ElementHandle<
*/ */
async click(options: ClickOptions = {}): Promise<void> { async click(options: ClickOptions = {}): Promise<void> {
await this._scrollIntoViewIfNeeded(); await this._scrollIntoViewIfNeeded();
const { x, y } = await this._clickablePoint(); const { x, y } = await this.clickablePoint();
await this._page.mouse.click(x, y, options); await this._page.mouse.click(x, y, options);
} }
/**
* This method creates and captures a dragevent from the element.
*/
async drag(target: Point): Promise<Protocol.Input.DragData> {
assert(
this._page.isDragInterceptionEnabled,
'Drag Interception is not enabled!'
);
await this._scrollIntoViewIfNeeded();
const start = await this.clickablePoint();
return await this._page.mouse.drag(start, target);
}
/**
* This method creates a `dragenter` event on the element.
*/
async dragEnter(
data: Protocol.Input.DragData = { items: [], dragOperationsMask: 1 }
): Promise<void> {
await this._scrollIntoViewIfNeeded();
const target = await this.clickablePoint();
await this._page.mouse.dragEnter(target, data);
}
/**
* This method creates a `dragover` event on the element.
*/
async dragOver(
data: Protocol.Input.DragData = { items: [], dragOperationsMask: 1 }
): Promise<void> {
await this._scrollIntoViewIfNeeded();
const target = await this.clickablePoint();
await this._page.mouse.dragOver(target, data);
}
/**
* This method triggers a drop on the element.
*/
async drop(
data: Protocol.Input.DragData = { items: [], dragOperationsMask: 1 }
): Promise<void> {
await this._scrollIntoViewIfNeeded();
const destination = await this.clickablePoint();
await this._page.mouse.drop(destination, data);
}
/**
* This method triggers a dragenter, dragover, and drop on the element.
*/
async dragAndDrop(
target: ElementHandle,
options?: { delay: number }
): Promise<void> {
await this._scrollIntoViewIfNeeded();
const startPoint = await this.clickablePoint();
const targetPoint = await target.clickablePoint();
await this._page.mouse.dragAndDrop(startPoint, targetPoint, options);
}
/** /**
* Triggers a `change` and `input` event once all the provided options have been * Triggers a `change` and `input` event once all the provided options have been
* selected. If there's no `<select>` element matching `selector`, the method * selected. If there's no `<select>` element matching `selector`, the method
@ -621,7 +680,7 @@ export class ElementHandle<
*/ */
async tap(): Promise<void> { async tap(): Promise<void> {
await this._scrollIntoViewIfNeeded(); await this._scrollIntoViewIfNeeded();
const { x, y } = await this._clickablePoint(); const { x, y } = await this.clickablePoint();
await this._page.touchscreen.tap(x, y); await this._page.touchscreen.tap(x, y);
} }
@ -982,6 +1041,14 @@ export interface PressOptions {
text?: string; text?: string;
} }
/**
* @public
*/
export interface Point {
x: number;
y: number;
}
function computeQuadArea(quad: Array<{ x: number; y: number }>): number { function computeQuadArea(quad: Array<{ x: number; y: number }>): number {
/* Compute sum of all directed areas of adjacent triangles /* Compute sum of all directed areas of adjacent triangles
https://en.wikipedia.org/wiki/Polygon#Simple_polygons https://en.wikipedia.org/wiki/Polygon#Simple_polygons

View File

@ -463,6 +463,7 @@ export class Page extends EventEmitter {
private _fileChooserInterceptors = new Set<Function>(); private _fileChooserInterceptors = new Set<Function>();
private _disconnectPromise?: Promise<Error>; private _disconnectPromise?: Promise<Error>;
private _userDragInterceptionEnabled = false;
/** /**
* @internal * @internal
@ -748,6 +749,10 @@ export class Page extends EventEmitter {
return this._accessibility; return this._accessibility;
} }
get isDragInterceptionEnabled(): boolean {
return this._userDragInterceptionEnabled;
}
/** /**
* @returns An array of all frames attached to the page. * @returns An array of all frames attached to the page.
*/ */
@ -799,6 +804,19 @@ export class Page extends EventEmitter {
return this._frameManager.networkManager().setRequestInterception(value); return this._frameManager.networkManager().setRequestInterception(value);
} }
/**
* @param enabled - Whether to enable drag interception.
*
* @remarks
* Activating drag interception enables the {@link Input.drag},
* methods This provides the capability to capture drag events emitted
* on the page, which can then be used to simulate drag-and-drop.
*/
async setDragInterception(enabled: boolean): Promise<void> {
this._userDragInterceptionEnabled = enabled;
return this._client.send('Input.setInterceptDrags', { enabled });
}
/** /**
* @param enabled - When `true`, enables offline mode for the page. * @param enabled - When `true`, enables offline mode for the page.
*/ */

View File

@ -0,0 +1,46 @@
<!DOCTYPE html>
<html>
<head>
<title>Drag-and-drop test</title>
<style>
#drop {
width: 5em;
height: 5em;
border: 1px solid black;
}
</style>
</head>
<body>
<div id="drag" draggable="true">drag me</div>
<div id="drop"></div>
<script>
window.didDragStart = false;
window.didDragEnter = false;
window.didDragOver = false;
window.didDrop = false;
var drag = document.getElementById('drag');
var drop = document.getElementById('drop');
drag.addEventListener('dragstart', function(e) {
e.dataTransfer.setData('id', e.target.id);
window.didDragStart = true;
});
drop.addEventListener('dragenter', function(e) {
e.preventDefault();
window.didDragEnter = true;
});
drop.addEventListener('dragover', function(e) {
e.preventDefault();
window.didDragOver = true;
});
drop.addEventListener('drop', function(e) {
e.preventDefault();
var id = e.dataTransfer.getData('id');
var el = document.getElementById(id);
if (el) {
e.target.appendChild(el);
window.didDrop = true;
}
});
</script>
</body>
</html>

125
test/drag-and-drop.spec.ts Normal file
View File

@ -0,0 +1,125 @@
/**
* Copyright 2021 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import expect from 'expect';
import {
getTestState,
setupTestPageAndContextHooks,
setupTestBrowserHooks,
describeChromeOnly,
} from './mocha-utils'; // eslint-disable-line import/extensions
describeChromeOnly('Input.drag', function () {
setupTestBrowserHooks();
setupTestPageAndContextHooks();
it('should throw an exception if not enabled before usage', async () => {
const { page, server } = getTestState();
await page.goto(server.PREFIX + '/input/drag-and-drop.html');
const draggable = await page.$('#drag');
try {
await draggable.drag({ x: 1, y: 1 });
} catch (error) {
expect(error.message).toContain('Drag Interception is not enabled!');
}
});
it('should emit a dragIntercepted event when dragged', async () => {
const { page, server } = getTestState();
await page.goto(server.PREFIX + '/input/drag-and-drop.html');
await page.setDragInterception(true);
const draggable = await page.$('#drag');
const data = await draggable.drag({ x: 1, y: 1 });
expect(data.items.length).toBe(1);
expect(await page.evaluate(() => globalThis.didDragStart)).toBe(true);
});
it('should emit a dragEnter', async () => {
const { page, server } = getTestState();
await page.goto(server.PREFIX + '/input/drag-and-drop.html');
await page.setDragInterception(true);
const draggable = await page.$('#drag');
const data = await draggable.drag({ x: 1, y: 1 });
const dropzone = await page.$('#drop');
await dropzone.dragEnter(data);
expect(await page.evaluate(() => globalThis.didDragStart)).toBe(true);
expect(await page.evaluate(() => globalThis.didDragEnter)).toBe(true);
});
it('should emit a dragOver event', async () => {
const { page, server } = getTestState();
await page.goto(server.PREFIX + '/input/drag-and-drop.html');
await page.setDragInterception(true);
const draggable = await page.$('#drag');
const data = await draggable.drag({ x: 1, y: 1 });
const dropzone = await page.$('#drop');
await dropzone.dragEnter(data);
await dropzone.dragOver(data);
expect(await page.evaluate(() => globalThis.didDragStart)).toBe(true);
expect(await page.evaluate(() => globalThis.didDragEnter)).toBe(true);
expect(await page.evaluate(() => globalThis.didDragOver)).toBe(true);
});
it('can be dropped', async () => {
const { page, server } = getTestState();
await page.goto(server.PREFIX + '/input/drag-and-drop.html');
await page.setDragInterception(true);
const draggable = await page.$('#drag');
const dropzone = await page.$('#drop');
const data = await draggable.drag({ x: 1, y: 1 });
await dropzone.dragEnter(data);
await dropzone.dragOver(data);
await dropzone.drop(data);
expect(await page.evaluate(() => globalThis.didDragStart)).toBe(true);
expect(await page.evaluate(() => globalThis.didDragEnter)).toBe(true);
expect(await page.evaluate(() => globalThis.didDragOver)).toBe(true);
expect(await page.evaluate(() => globalThis.didDrop)).toBe(true);
});
it('can be dragged and dropped with a single function', async () => {
const { page, server } = getTestState();
await page.goto(server.PREFIX + '/input/drag-and-drop.html');
await page.setDragInterception(true);
const draggable = await page.$('#drag');
const dropzone = await page.$('#drop');
await draggable.dragAndDrop(dropzone);
expect(await page.evaluate(() => globalThis.didDragStart)).toBe(true);
expect(await page.evaluate(() => globalThis.didDragEnter)).toBe(true);
expect(await page.evaluate(() => globalThis.didDragOver)).toBe(true);
expect(await page.evaluate(() => globalThis.didDrop)).toBe(true);
});
it('can be disabled', async () => {
const { page, server } = getTestState();
await page.goto(server.PREFIX + '/input/drag-and-drop.html');
await page.setDragInterception(true);
const draggable = await page.$('#drag');
await draggable.drag({ x: 1, y: 1 });
await page.setDragInterception(false);
try {
await draggable.drag({ x: 1, y: 1 });
} catch (error) {
expect(error.message).toContain('Drag Interception is not enabled!');
}
});
});

View File

@ -385,6 +385,41 @@ function compareDocumentations(actual, expected) {
expectedName: 'KeyInput', expectedName: 'KeyInput',
}, },
], ],
[
'Method ElementHandle.drag() target',
{
actualName: 'Object',
expectedName: 'Point',
},
],
[
'Method ElementHandle.dragAndDrop() target',
{
actualName: 'ElementHandle',
expectedName: 'ElementHandle<Element>',
},
],
[
'Method ElementHandle.dragEnter() data',
{
actualName: 'Object',
expectedName: 'DragData',
},
],
[
'Method ElementHandle.dragOver() data',
{
actualName: 'Object',
expectedName: 'DragData',
},
],
[
'Method ElementHandle.drop() data',
{
actualName: 'Object',
expectedName: 'DragData',
},
],
[ [
'Method Keyboard.down() key', 'Method Keyboard.down() key',
{ {
@ -413,6 +448,83 @@ function compareDocumentations(actual, expected) {
expectedName: 'MouseOptions', expectedName: 'MouseOptions',
}, },
], ],
[
'Method Mouse.drag() start',
{
actualName: 'Object',
expectedName: 'Point',
},
],
[
'Method Mouse.drag() target',
{
actualName: 'Object',
expectedName: 'Point',
},
],
[
'Method Mouse.dragAndDrop() start',
{
actualName: 'Object',
expectedName: 'Point',
},
],
[
'Method Mouse.dragAndDrop() target',
{
actualName: 'Object',
expectedName: 'Point',
},
],
[
'Method Mouse.dragAndDrop() target',
{
actualName: 'Object',
expectedName: 'Point',
},
],
[
'Method Mouse.dragEnter() target',
{
actualName: 'Object',
expectedName: 'Point',
},
],
[
'Method Mouse.dragEnter() data',
{
actualName: 'Object',
expectedName: 'DragData',
},
],
[
'Method Mouse.dragOver() target',
{
actualName: 'Object',
expectedName: 'Point',
},
],
[
'Method Mouse.dragOver() data',
{
actualName: 'Object',
expectedName: 'DragData',
},
],
[
'Method Mouse.drop() target',
{
actualName: 'Object',
expectedName: 'Point',
},
],
[
'Method Mouse.drop() data',
{
actualName: 'Object',
expectedName: 'DragData',
},
],
[ [
'Method Mouse.up() options', 'Method Mouse.up() options',
{ {