mirror of
https://github.com/puppeteer/puppeteer
synced 2024-06-14 14:02:48 +00:00
feat: implement improved Drag n' Drop APIs (#10651)
This commit is contained in:
parent
67f72de274
commit
9342bac263
@ -4,7 +4,7 @@ sidebar_label: ElementHandle.drag
|
|||||||
|
|
||||||
# ElementHandle.drag() method
|
# ElementHandle.drag() method
|
||||||
|
|
||||||
This method creates and captures a dragevent from the element.
|
Drags an element over the given element or point.
|
||||||
|
|
||||||
#### Signature:
|
#### Signature:
|
||||||
|
|
||||||
@ -12,18 +12,20 @@ This method creates and captures a dragevent from the element.
|
|||||||
class ElementHandle {
|
class ElementHandle {
|
||||||
drag(
|
drag(
|
||||||
this: ElementHandle<Element>,
|
this: ElementHandle<Element>,
|
||||||
target: Point
|
target: Point | ElementHandle<Element>
|
||||||
): Promise<Protocol.Input.DragData>;
|
): Promise<Protocol.Input.DragData | void>;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Parameters
|
## Parameters
|
||||||
|
|
||||||
| Parameter | Type | Description |
|
| Parameter | Type | Description |
|
||||||
| --------- | ------------------------------------------------------------ | ----------- |
|
| --------- | --------------------------------------------------------------------------------------------- | ----------- |
|
||||||
| this | [ElementHandle](./puppeteer.elementhandle.md)<Element> | |
|
| this | [ElementHandle](./puppeteer.elementhandle.md)<Element> | |
|
||||||
| target | [Point](./puppeteer.point.md) | |
|
| target | [Point](./puppeteer.point.md) \| [ElementHandle](./puppeteer.elementhandle.md)<Element> | |
|
||||||
|
|
||||||
**Returns:**
|
**Returns:**
|
||||||
|
|
||||||
Promise<Protocol.Input.DragData>
|
Promise<Protocol.Input.DragData \| void>
|
||||||
|
|
||||||
|
DEPRECATED. When drag interception is enabled, the drag payload is returned.
|
||||||
|
@ -4,7 +4,9 @@ sidebar_label: ElementHandle.dragAndDrop
|
|||||||
|
|
||||||
# ElementHandle.dragAndDrop() method
|
# ElementHandle.dragAndDrop() method
|
||||||
|
|
||||||
This method triggers a dragenter, dragover, and drop on the element.
|
> Warning: This API is now obsolete.
|
||||||
|
>
|
||||||
|
> Use `ElementHandle.drop` instead.
|
||||||
|
|
||||||
#### Signature:
|
#### Signature:
|
||||||
|
|
||||||
|
@ -4,7 +4,9 @@ sidebar_label: ElementHandle.dragEnter
|
|||||||
|
|
||||||
# ElementHandle.dragEnter() method
|
# ElementHandle.dragEnter() method
|
||||||
|
|
||||||
This method creates a `dragenter` event on the element.
|
> Warning: This API is now obsolete.
|
||||||
|
>
|
||||||
|
> Do not use. `dragenter` will automatically be performed during dragging.
|
||||||
|
|
||||||
#### Signature:
|
#### Signature:
|
||||||
|
|
||||||
|
@ -4,7 +4,9 @@ sidebar_label: ElementHandle.dragOver
|
|||||||
|
|
||||||
# ElementHandle.dragOver() method
|
# ElementHandle.dragOver() method
|
||||||
|
|
||||||
This method creates a `dragover` event on the element.
|
> Warning: This API is now obsolete.
|
||||||
|
>
|
||||||
|
> Do not use. `dragover` will automatically be performed during dragging.
|
||||||
|
|
||||||
#### Signature:
|
#### Signature:
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ sidebar_label: ElementHandle.drop
|
|||||||
|
|
||||||
# ElementHandle.drop() method
|
# ElementHandle.drop() method
|
||||||
|
|
||||||
This method triggers a drop on the element.
|
Drops the given element onto the current one.
|
||||||
|
|
||||||
#### Signature:
|
#### Signature:
|
||||||
|
|
||||||
@ -12,17 +12,17 @@ This method triggers a drop on the element.
|
|||||||
class ElementHandle {
|
class ElementHandle {
|
||||||
drop(
|
drop(
|
||||||
this: ElementHandle<Element>,
|
this: ElementHandle<Element>,
|
||||||
data?: Protocol.Input.DragData
|
element: ElementHandle<Element>
|
||||||
): Promise<void>;
|
): Promise<void>;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Parameters
|
## Parameters
|
||||||
|
|
||||||
| Parameter | Type | Description |
|
| Parameter | Type | Description |
|
||||||
| --------- | ------------------------------------------------------------ | ------------ |
|
| --------- | ------------------------------------------------------------ | ----------- |
|
||||||
| this | [ElementHandle](./puppeteer.elementhandle.md)<Element> | |
|
| this | [ElementHandle](./puppeteer.elementhandle.md)<Element> | |
|
||||||
| data | Protocol.Input.DragData | _(Optional)_ |
|
| element | [ElementHandle](./puppeteer.elementhandle.md)<Element> | |
|
||||||
|
|
||||||
**Returns:**
|
**Returns:**
|
||||||
|
|
||||||
|
31
docs/api/puppeteer.elementhandle.drop_1.md
Normal file
31
docs/api/puppeteer.elementhandle.drop_1.md
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
---
|
||||||
|
sidebar_label: ElementHandle.drop_1
|
||||||
|
---
|
||||||
|
|
||||||
|
# ElementHandle.drop() method
|
||||||
|
|
||||||
|
> Warning: This API is now obsolete.
|
||||||
|
>
|
||||||
|
> No longer supported.
|
||||||
|
|
||||||
|
#### Signature:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
class ElementHandle {
|
||||||
|
drop(
|
||||||
|
this: ElementHandle<Element>,
|
||||||
|
data?: Protocol.Input.DragData
|
||||||
|
): Promise<void>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Parameters
|
||||||
|
|
||||||
|
| Parameter | Type | Description |
|
||||||
|
| --------- | ------------------------------------------------------------ | ------------ |
|
||||||
|
| this | [ElementHandle](./puppeteer.elementhandle.md)<Element> | |
|
||||||
|
| data | Protocol.Input.DragData | _(Optional)_ |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
|
||||||
|
Promise<void>
|
@ -61,11 +61,12 @@ The constructor for this class is marked as internal. Third-party code should no
|
|||||||
| [clickablePoint(offset)](./puppeteer.elementhandle.clickablepoint.md) | | Returns the middle point within an element unless a specific offset is provided. |
|
| [clickablePoint(offset)](./puppeteer.elementhandle.clickablepoint.md) | | Returns the middle point within an element unless a specific offset is provided. |
|
||||||
| [contentFrame(this)](./puppeteer.elementhandle.contentframe.md) | | Resolves the frame associated with the element, if any. Always exists for HTMLIFrameElements. |
|
| [contentFrame(this)](./puppeteer.elementhandle.contentframe.md) | | Resolves the frame associated with the element, if any. Always exists for HTMLIFrameElements. |
|
||||||
| [contentFrame()](./puppeteer.elementhandle.contentframe_1.md) | | |
|
| [contentFrame()](./puppeteer.elementhandle.contentframe_1.md) | | |
|
||||||
| [drag(this, target)](./puppeteer.elementhandle.drag.md) | | This method creates and captures a dragevent from the element. |
|
| [drag(this, target)](./puppeteer.elementhandle.drag.md) | | Drags an element over the given element or point. |
|
||||||
| [dragAndDrop(this, target, options)](./puppeteer.elementhandle.draganddrop.md) | | This method triggers a dragenter, dragover, and drop on the element. |
|
| [dragAndDrop(this, target, options)](./puppeteer.elementhandle.draganddrop.md) | | |
|
||||||
| [dragEnter(this, data)](./puppeteer.elementhandle.dragenter.md) | | This method creates a <code>dragenter</code> event on the element. |
|
| [dragEnter(this, data)](./puppeteer.elementhandle.dragenter.md) | | |
|
||||||
| [dragOver(this, data)](./puppeteer.elementhandle.dragover.md) | | This method creates a <code>dragover</code> event on the element. |
|
| [dragOver(this, data)](./puppeteer.elementhandle.dragover.md) | | |
|
||||||
| [drop(this, data)](./puppeteer.elementhandle.drop.md) | | This method triggers a drop on the element. |
|
| [drop(this, element)](./puppeteer.elementhandle.drop.md) | | Drops the given element onto the current one. |
|
||||||
|
| [drop(this, data)](./puppeteer.elementhandle.drop_1.md) | | |
|
||||||
| [focus()](./puppeteer.elementhandle.focus.md) | | Calls [focus](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus) on the element. |
|
| [focus()](./puppeteer.elementhandle.focus.md) | | Calls [focus](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus) on the element. |
|
||||||
| [hover(this)](./puppeteer.elementhandle.hover.md) | | This method scrolls element into view if needed, and then uses [Page](./puppeteer.page.md) to hover over the center of the element. If the element is detached from DOM, the method throws an error. |
|
| [hover(this)](./puppeteer.elementhandle.hover.md) | | This method scrolls element into view if needed, and then uses [Page](./puppeteer.page.md) to hover over the center of the element. If the element is detached from DOM, the method throws an error. |
|
||||||
| [isHidden()](./puppeteer.elementhandle.ishidden.md) | | Checks if an element is hidden using the same mechanism as [ElementHandle.waitForSelector()](./puppeteer.elementhandle.waitforselector.md). |
|
| [isHidden()](./puppeteer.elementhandle.ishidden.md) | | Checks if an element is hidden using the same mechanism as [ElementHandle.waitForSelector()](./puppeteer.elementhandle.waitforselector.md). |
|
||||||
|
@ -4,6 +4,10 @@ sidebar_label: Page.isDragInterceptionEnabled
|
|||||||
|
|
||||||
# Page.isDragInterceptionEnabled() method
|
# Page.isDragInterceptionEnabled() method
|
||||||
|
|
||||||
|
> Warning: This API is now obsolete.
|
||||||
|
>
|
||||||
|
> We no longer support intercepting drag payloads. Use the new drag APIs found on [ElementHandle](./puppeteer.elementhandle.md) to drag (or just use the [Page.mouse](./puppeteer.page.mouse.md)).
|
||||||
|
|
||||||
`true` if drag events are being intercepted, `false` otherwise.
|
`true` if drag events are being intercepted, `false` otherwise.
|
||||||
|
|
||||||
#### Signature:
|
#### Signature:
|
||||||
|
@ -4,6 +4,10 @@ sidebar_label: Page.setDragInterception
|
|||||||
|
|
||||||
# Page.setDragInterception() method
|
# Page.setDragInterception() method
|
||||||
|
|
||||||
|
> Warning: This API is now obsolete.
|
||||||
|
>
|
||||||
|
> We no longer support intercepting drag payloads. Use the new drag APIs found on [ElementHandle](./puppeteer.elementhandle.md) to drag (or just use the [Page.mouse](./puppeteer.page.mouse.md)).
|
||||||
|
|
||||||
#### Signature:
|
#### Signature:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
@ -21,7 +25,3 @@ class Page {
|
|||||||
**Returns:**
|
**Returns:**
|
||||||
|
|
||||||
Promise<void>
|
Promise<void>
|
||||||
|
|
||||||
## Remarks
|
|
||||||
|
|
||||||
Activating drag interception enables the `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.
|
|
||||||
|
@ -31,6 +31,7 @@ import {KeyInput} from '../common/USKeyboardLayout.js';
|
|||||||
import {isString, withSourcePuppeteerURLIfNone} from '../common/util.js';
|
import {isString, withSourcePuppeteerURLIfNone} from '../common/util.js';
|
||||||
import {assert} from '../util/assert.js';
|
import {assert} from '../util/assert.js';
|
||||||
import {AsyncIterableUtil} from '../util/AsyncIterableUtil.js';
|
import {AsyncIterableUtil} from '../util/AsyncIterableUtil.js';
|
||||||
|
import {throwIfDisposed} from '../util/decorators.js';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
KeyboardTypeOptions,
|
KeyboardTypeOptions,
|
||||||
@ -731,59 +732,134 @@ export abstract class ElementHandle<
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method creates and captures a dragevent from the element.
|
* Drags an element over the given element or point.
|
||||||
|
*
|
||||||
|
* @returns DEPRECATED. When drag interception is enabled, the drag payload is
|
||||||
|
* returned.
|
||||||
*/
|
*/
|
||||||
|
@throwIfDisposed()
|
||||||
|
@ElementHandle.bindIsolatedHandle
|
||||||
async drag(
|
async drag(
|
||||||
this: ElementHandle<Element>,
|
this: ElementHandle<Element>,
|
||||||
target: Point
|
target: Point | ElementHandle<Element>
|
||||||
): Promise<Protocol.Input.DragData>;
|
): Promise<Protocol.Input.DragData | void> {
|
||||||
async drag(this: ElementHandle<Element>): Promise<Protocol.Input.DragData> {
|
await this.scrollIntoViewIfNeeded();
|
||||||
throw new Error('Not implemented');
|
const page = this.frame.page();
|
||||||
|
if (page.isDragInterceptionEnabled()) {
|
||||||
|
const source = await this.clickablePoint();
|
||||||
|
if (target instanceof ElementHandle) {
|
||||||
|
target = await target.clickablePoint();
|
||||||
|
}
|
||||||
|
return await page.mouse.drag(source, target);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (!page._isDragging) {
|
||||||
|
page._isDragging = true;
|
||||||
|
await this.hover();
|
||||||
|
await page.mouse.down();
|
||||||
|
}
|
||||||
|
if (target instanceof ElementHandle) {
|
||||||
|
await target.hover();
|
||||||
|
} else {
|
||||||
|
await page.mouse.move(target.x, target.y);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
page._isDragging = false;
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method creates a `dragenter` event on the element.
|
* @deprecated Do not use. `dragenter` will automatically be performed during dragging.
|
||||||
*/
|
*/
|
||||||
|
@throwIfDisposed()
|
||||||
|
@ElementHandle.bindIsolatedHandle
|
||||||
async dragEnter(
|
async dragEnter(
|
||||||
this: ElementHandle<Element>,
|
this: ElementHandle<Element>,
|
||||||
data?: Protocol.Input.DragData
|
data: Protocol.Input.DragData = {items: [], dragOperationsMask: 1}
|
||||||
): Promise<void>;
|
): Promise<void> {
|
||||||
async dragEnter(this: ElementHandle<Element>): Promise<void> {
|
const page = this.frame.page();
|
||||||
throw new Error('Not implemented');
|
await this.scrollIntoViewIfNeeded();
|
||||||
|
const target = await this.clickablePoint();
|
||||||
|
await page.mouse.dragEnter(target, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method creates a `dragover` event on the element.
|
* @deprecated Do not use. `dragover` will automatically be performed during dragging.
|
||||||
*/
|
*/
|
||||||
|
@throwIfDisposed()
|
||||||
|
@ElementHandle.bindIsolatedHandle
|
||||||
async dragOver(
|
async dragOver(
|
||||||
this: ElementHandle<Element>,
|
this: ElementHandle<Element>,
|
||||||
data?: Protocol.Input.DragData
|
data: Protocol.Input.DragData = {items: [], dragOperationsMask: 1}
|
||||||
): Promise<void>;
|
): Promise<void> {
|
||||||
async dragOver(this: ElementHandle<Element>): Promise<void> {
|
const page = this.frame.page();
|
||||||
throw new Error('Not implemented');
|
await this.scrollIntoViewIfNeeded();
|
||||||
|
const target = await this.clickablePoint();
|
||||||
|
await page.mouse.dragOver(target, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method triggers a drop on the element.
|
* Drops the given element onto the current one.
|
||||||
|
*/
|
||||||
|
async drop(
|
||||||
|
this: ElementHandle<Element>,
|
||||||
|
element: ElementHandle<Element>
|
||||||
|
): Promise<void>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated No longer supported.
|
||||||
*/
|
*/
|
||||||
async drop(
|
async drop(
|
||||||
this: ElementHandle<Element>,
|
this: ElementHandle<Element>,
|
||||||
data?: Protocol.Input.DragData
|
data?: Protocol.Input.DragData
|
||||||
): Promise<void>;
|
): Promise<void>;
|
||||||
async drop(this: ElementHandle<Element>): Promise<void> {
|
|
||||||
throw new Error('Not implemented');
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
@throwIfDisposed()
|
||||||
|
@ElementHandle.bindIsolatedHandle
|
||||||
|
async drop(
|
||||||
|
this: ElementHandle<Element>,
|
||||||
|
dataOrElement: ElementHandle<Element> | Protocol.Input.DragData = {
|
||||||
|
items: [],
|
||||||
|
dragOperationsMask: 1,
|
||||||
|
}
|
||||||
|
): Promise<void> {
|
||||||
|
const page = this.frame.page();
|
||||||
|
if ('items' in dataOrElement) {
|
||||||
|
await this.scrollIntoViewIfNeeded();
|
||||||
|
const destination = await this.clickablePoint();
|
||||||
|
await page.mouse.drop(destination, dataOrElement);
|
||||||
|
} else {
|
||||||
|
// Note if the rest errors, we still want dragging off because the errors
|
||||||
|
// is most likely something implying the mouse is no longer dragging.
|
||||||
|
await dataOrElement.drag(this);
|
||||||
|
page._isDragging = false;
|
||||||
|
await page.mouse.up();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method triggers a dragenter, dragover, and drop on the element.
|
* @deprecated Use `ElementHandle.drop` instead.
|
||||||
*/
|
*/
|
||||||
|
@throwIfDisposed()
|
||||||
|
@ElementHandle.bindIsolatedHandle
|
||||||
async dragAndDrop(
|
async dragAndDrop(
|
||||||
this: ElementHandle<Element>,
|
this: ElementHandle<Element>,
|
||||||
target: ElementHandle<Node>,
|
target: ElementHandle<Node>,
|
||||||
options?: {delay: number}
|
options?: {delay: number}
|
||||||
): Promise<void>;
|
): Promise<void> {
|
||||||
async dragAndDrop(this: ElementHandle<Element>): Promise<void> {
|
const page = this.frame.page();
|
||||||
throw new Error('Not implemented');
|
assert(
|
||||||
|
page.isDragInterceptionEnabled(),
|
||||||
|
'Drag Interception is not enabled!'
|
||||||
|
);
|
||||||
|
await this.scrollIntoViewIfNeeded();
|
||||||
|
const startPoint = await this.clickablePoint();
|
||||||
|
const targetPoint = await target.clickablePoint();
|
||||||
|
await page.mouse.dragAndDrop(startPoint, targetPoint, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -509,6 +509,11 @@ export abstract class Page
|
|||||||
extends EventEmitter<PageEvents>
|
extends EventEmitter<PageEvents>
|
||||||
implements AsyncDisposable, Disposable
|
implements AsyncDisposable, Disposable
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
_isDragging = false;
|
||||||
|
|
||||||
#requestHandlers = new WeakMap<Handler<HTTPRequest>, Handler<HTTPRequest>>();
|
#requestHandlers = new WeakMap<Handler<HTTPRequest>, Handler<HTTPRequest>>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -527,6 +532,10 @@ export abstract class Page
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* `true` if drag events are being intercepted, `false` otherwise.
|
* `true` if drag events are being intercepted, `false` otherwise.
|
||||||
|
*
|
||||||
|
* @deprecated We no longer support intercepting drag payloads. Use the new
|
||||||
|
* drag APIs found on {@link ElementHandle} to drag (or just use the
|
||||||
|
* {@link Page.mouse}).
|
||||||
*/
|
*/
|
||||||
isDragInterceptionEnabled(): boolean {
|
isDragInterceptionEnabled(): boolean {
|
||||||
throw new Error('Not implemented');
|
throw new Error('Not implemented');
|
||||||
@ -791,10 +800,9 @@ export abstract class Page
|
|||||||
/**
|
/**
|
||||||
* @param enabled - Whether to enable drag interception.
|
* @param enabled - Whether to enable drag interception.
|
||||||
*
|
*
|
||||||
* @remarks
|
* @deprecated We no longer support intercepting drag payloads. Use the new
|
||||||
* Activating drag interception enables the `Input.drag`,
|
* drag APIs found on {@link ElementHandle} to drag (or just use the
|
||||||
* methods This provides the capability to capture drag events emitted
|
* {@link Page.mouse}).
|
||||||
* on the page, which can then be used to simulate drag-and-drop.
|
|
||||||
*/
|
*/
|
||||||
async setDragInterception(enabled: boolean): Promise<void>;
|
async setDragInterception(enabled: boolean): Promise<void>;
|
||||||
async setDragInterception(): Promise<void> {
|
async setDragInterception(): Promise<void> {
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
import {Protocol} from 'devtools-protocol';
|
import {Protocol} from 'devtools-protocol';
|
||||||
|
|
||||||
import {CDPSession} from '../api/CDPSession.js';
|
import {CDPSession} from '../api/CDPSession.js';
|
||||||
import {AutofillData, ElementHandle, Point} from '../api/ElementHandle.js';
|
import {AutofillData, ElementHandle} from '../api/ElementHandle.js';
|
||||||
import {Page, ScreenshotOptions} from '../api/Page.js';
|
import {Page, ScreenshotOptions} from '../api/Page.js';
|
||||||
import {assert} from '../util/assert.js';
|
import {assert} from '../util/assert.js';
|
||||||
import {throwIfDisposed} from '../util/decorators.js';
|
import {throwIfDisposed} from '../util/decorators.js';
|
||||||
@ -103,74 +103,6 @@ export class CdpElementHandle<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This method creates and captures a dragevent from the element.
|
|
||||||
*/
|
|
||||||
@throwIfDisposed()
|
|
||||||
@ElementHandle.bindIsolatedHandle
|
|
||||||
override async drag(
|
|
||||||
this: CdpElementHandle<Element>,
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
@throwIfDisposed()
|
|
||||||
@ElementHandle.bindIsolatedHandle
|
|
||||||
override async dragEnter(
|
|
||||||
this: CdpElementHandle<Element>,
|
|
||||||
data: Protocol.Input.DragData = {items: [], dragOperationsMask: 1}
|
|
||||||
): Promise<void> {
|
|
||||||
await this.scrollIntoViewIfNeeded();
|
|
||||||
const target = await this.clickablePoint();
|
|
||||||
await this.#page.mouse.dragEnter(target, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
@throwIfDisposed()
|
|
||||||
@ElementHandle.bindIsolatedHandle
|
|
||||||
override async dragOver(
|
|
||||||
this: CdpElementHandle<Element>,
|
|
||||||
data: Protocol.Input.DragData = {items: [], dragOperationsMask: 1}
|
|
||||||
): Promise<void> {
|
|
||||||
await this.scrollIntoViewIfNeeded();
|
|
||||||
const target = await this.clickablePoint();
|
|
||||||
await this.#page.mouse.dragOver(target, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
@throwIfDisposed()
|
|
||||||
@ElementHandle.bindIsolatedHandle
|
|
||||||
override async drop(
|
|
||||||
this: CdpElementHandle<Element>,
|
|
||||||
data: Protocol.Input.DragData = {items: [], dragOperationsMask: 1}
|
|
||||||
): Promise<void> {
|
|
||||||
await this.scrollIntoViewIfNeeded();
|
|
||||||
const destination = await this.clickablePoint();
|
|
||||||
await this.#page.mouse.drop(destination, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
@throwIfDisposed()
|
|
||||||
@ElementHandle.bindIsolatedHandle
|
|
||||||
override async dragAndDrop(
|
|
||||||
this: CdpElementHandle<Element>,
|
|
||||||
target: CdpElementHandle<Node>,
|
|
||||||
options?: {delay: number}
|
|
||||||
): Promise<void> {
|
|
||||||
assert(
|
|
||||||
this.#page.isDragInterceptionEnabled(),
|
|
||||||
'Drag Interception is not enabled!'
|
|
||||||
);
|
|
||||||
await this.scrollIntoViewIfNeeded();
|
|
||||||
const startPoint = await this.clickablePoint();
|
|
||||||
const targetPoint = await target.clickablePoint();
|
|
||||||
await this.#page.mouse.dragAndDrop(startPoint, targetPoint, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
@throwIfDisposed()
|
@throwIfDisposed()
|
||||||
@ElementHandle.bindIsolatedHandle
|
@ElementHandle.bindIsolatedHandle
|
||||||
override async uploadFile(
|
override async uploadFile(
|
||||||
|
@ -702,6 +702,10 @@ export class BidiPage extends Page {
|
|||||||
'default' in pptrFunction ? pptrFunction.default : pptrFunction
|
'default' in pptrFunction ? pptrFunction.default : pptrFunction
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override isDragInterceptionEnabled(): boolean {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function isConsoleLogEntry(
|
function isConsoleLogEntry(
|
||||||
|
@ -41,6 +41,24 @@
|
|||||||
"parameters": ["webDriverBiDi"],
|
"parameters": ["webDriverBiDi"],
|
||||||
"expectations": ["PASS"]
|
"expectations": ["PASS"]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"testIdPattern": "[drag-and-drop.spec] *",
|
||||||
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
|
"parameters": ["webDriverBiDi"],
|
||||||
|
"expectations": ["PASS"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"testIdPattern": "[drag-and-drop.spec] *",
|
||||||
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
|
"parameters": ["firefox"],
|
||||||
|
"expectations": ["FAIL"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"testIdPattern": "[drag-and-drop.spec] Legacy Drag n' Drop *",
|
||||||
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
|
"parameters": ["webDriverBiDi"],
|
||||||
|
"expectations": ["SKIP"]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"testIdPattern": "[elementhandle.spec] *",
|
"testIdPattern": "[elementhandle.spec] *",
|
||||||
"platforms": ["darwin", "linux", "win32"],
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
@ -1691,6 +1709,12 @@
|
|||||||
"parameters": ["cdp", "firefox"],
|
"parameters": ["cdp", "firefox"],
|
||||||
"expectations": ["FAIL"]
|
"expectations": ["FAIL"]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"testIdPattern": "[drag-and-drop.spec] Drag n' Drop should drag and drop",
|
||||||
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
|
"parameters": ["cdp", "chrome"],
|
||||||
|
"expectations": ["FAIL"]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"testIdPattern": "[elementhandle.spec] ElementHandle specs ElementHandle.boundingBox should handle nested frames",
|
"testIdPattern": "[elementhandle.spec] ElementHandle specs ElementHandle.boundingBox should handle nested frames",
|
||||||
"platforms": ["darwin", "linux", "win32"],
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
|
@ -13,24 +13,21 @@
|
|||||||
<body>
|
<body>
|
||||||
<div id="drag" draggable="true">drag me</div>
|
<div id="drag" draggable="true">drag me</div>
|
||||||
<div id="drop"></div>
|
<div id="drop"></div>
|
||||||
|
<div id="drag-state">0</div>
|
||||||
<script>
|
<script>
|
||||||
window.didDragStart = false;
|
|
||||||
window.didDragEnter = false;
|
|
||||||
window.didDragOver = false;
|
|
||||||
window.didDrop = false;
|
|
||||||
const drag = document.getElementById('drag');
|
const drag = document.getElementById('drag');
|
||||||
const drop = document.getElementById('drop');
|
const drop = document.getElementById('drop');
|
||||||
drag.addEventListener('dragstart', function(event) {
|
drag.addEventListener('dragstart', function(event) {
|
||||||
event.dataTransfer.setData('id', event.target.id);
|
event.dataTransfer.setData('id', event.target.id);
|
||||||
window.didDragStart = true;
|
document.getElementById('drag-state').textContent += '1';
|
||||||
});
|
});
|
||||||
drop.addEventListener('dragenter', function(event) {
|
drop.addEventListener('dragenter', function(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
window.didDragEnter = true;
|
document.getElementById('drag-state').textContent += '2';
|
||||||
});
|
});
|
||||||
drop.addEventListener('dragover', function(event) {
|
drop.addEventListener('dragover', function(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
window.didDragOver = true;
|
document.getElementById('drag-state').textContent += '3';
|
||||||
});
|
});
|
||||||
drop.addEventListener('drop', function(event) {
|
drop.addEventListener('drop', function(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@ -38,7 +35,7 @@
|
|||||||
const el = document.getElementById(id);
|
const el = document.getElementById(id);
|
||||||
if (el) {
|
if (el) {
|
||||||
event.target.appendChild(el);
|
event.target.appendChild(el);
|
||||||
window.didDrop = true;
|
document.getElementById('drag-state').textContent += '4';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -14,11 +14,23 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import assert from 'assert';
|
||||||
|
|
||||||
import expect from 'expect';
|
import expect from 'expect';
|
||||||
|
|
||||||
import {getTestState, setupTestBrowserHooks} from './mocha-utils.js';
|
import {getTestState, setupTestBrowserHooks} from './mocha-utils.js';
|
||||||
|
|
||||||
describe('Input.drag', function () {
|
async function getDragState() {
|
||||||
|
const {page} = await getTestState({skipLaunch: true});
|
||||||
|
return parseInt(
|
||||||
|
await page.$eval('#drag-state', element => {
|
||||||
|
return element.innerHTML;
|
||||||
|
}),
|
||||||
|
10
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("Legacy Drag n' Drop", function () {
|
||||||
setupTestBrowserHooks();
|
setupTestBrowserHooks();
|
||||||
|
|
||||||
it('should throw an exception if not enabled before usage', async () => {
|
it('should throw an exception if not enabled before usage', async () => {
|
||||||
@ -45,12 +57,9 @@ describe('Input.drag', function () {
|
|||||||
using draggable = (await page.$('#drag'))!;
|
using draggable = (await page.$('#drag'))!;
|
||||||
const data = await draggable.drag({x: 1, y: 1});
|
const data = await draggable.drag({x: 1, y: 1});
|
||||||
|
|
||||||
|
assert(data instanceof Object);
|
||||||
expect(data.items).toHaveLength(1);
|
expect(data.items).toHaveLength(1);
|
||||||
expect(
|
expect(await getDragState()).toBe(1);
|
||||||
await page.evaluate(() => {
|
|
||||||
return (globalThis as any).didDragStart;
|
|
||||||
})
|
|
||||||
).toBe(true);
|
|
||||||
});
|
});
|
||||||
it('should emit a dragEnter', async () => {
|
it('should emit a dragEnter', async () => {
|
||||||
const {page, server} = await getTestState();
|
const {page, server} = await getTestState();
|
||||||
@ -61,19 +70,11 @@ describe('Input.drag', function () {
|
|||||||
expect(page.isDragInterceptionEnabled()).toBe(true);
|
expect(page.isDragInterceptionEnabled()).toBe(true);
|
||||||
using draggable = (await page.$('#drag'))!;
|
using draggable = (await page.$('#drag'))!;
|
||||||
const data = await draggable.drag({x: 1, y: 1});
|
const data = await draggable.drag({x: 1, y: 1});
|
||||||
|
assert(data instanceof Object);
|
||||||
using dropzone = (await page.$('#drop'))!;
|
using dropzone = (await page.$('#drop'))!;
|
||||||
await dropzone.dragEnter(data);
|
await dropzone.dragEnter(data);
|
||||||
|
|
||||||
expect(
|
expect(await getDragState()).toBe(12);
|
||||||
await page.evaluate(() => {
|
|
||||||
return (globalThis as any).didDragStart;
|
|
||||||
})
|
|
||||||
).toBe(true);
|
|
||||||
expect(
|
|
||||||
await page.evaluate(() => {
|
|
||||||
return (globalThis as any).didDragEnter;
|
|
||||||
})
|
|
||||||
).toBe(true);
|
|
||||||
});
|
});
|
||||||
it('should emit a dragOver event', async () => {
|
it('should emit a dragOver event', async () => {
|
||||||
const {page, server} = await getTestState();
|
const {page, server} = await getTestState();
|
||||||
@ -84,25 +85,12 @@ describe('Input.drag', function () {
|
|||||||
expect(page.isDragInterceptionEnabled()).toBe(true);
|
expect(page.isDragInterceptionEnabled()).toBe(true);
|
||||||
using draggable = (await page.$('#drag'))!;
|
using draggable = (await page.$('#drag'))!;
|
||||||
const data = await draggable.drag({x: 1, y: 1});
|
const data = await draggable.drag({x: 1, y: 1});
|
||||||
|
assert(data instanceof Object);
|
||||||
using dropzone = (await page.$('#drop'))!;
|
using dropzone = (await page.$('#drop'))!;
|
||||||
await dropzone.dragEnter(data);
|
await dropzone.dragEnter(data);
|
||||||
await dropzone.dragOver(data);
|
await dropzone.dragOver(data);
|
||||||
|
|
||||||
expect(
|
expect(await getDragState()).toBe(123);
|
||||||
await page.evaluate(() => {
|
|
||||||
return (globalThis as any).didDragStart;
|
|
||||||
})
|
|
||||||
).toBe(true);
|
|
||||||
expect(
|
|
||||||
await page.evaluate(() => {
|
|
||||||
return (globalThis as any).didDragEnter;
|
|
||||||
})
|
|
||||||
).toBe(true);
|
|
||||||
expect(
|
|
||||||
await page.evaluate(() => {
|
|
||||||
return (globalThis as any).didDragOver;
|
|
||||||
})
|
|
||||||
).toBe(true);
|
|
||||||
});
|
});
|
||||||
it('can be dropped', async () => {
|
it('can be dropped', async () => {
|
||||||
const {page, server} = await getTestState();
|
const {page, server} = await getTestState();
|
||||||
@ -114,30 +102,12 @@ describe('Input.drag', function () {
|
|||||||
using draggable = (await page.$('#drag'))!;
|
using draggable = (await page.$('#drag'))!;
|
||||||
using dropzone = (await page.$('#drop'))!;
|
using dropzone = (await page.$('#drop'))!;
|
||||||
const data = await draggable.drag({x: 1, y: 1});
|
const data = await draggable.drag({x: 1, y: 1});
|
||||||
|
assert(data instanceof Object);
|
||||||
await dropzone.dragEnter(data);
|
await dropzone.dragEnter(data);
|
||||||
await dropzone.dragOver(data);
|
await dropzone.dragOver(data);
|
||||||
await dropzone.drop(data);
|
await dropzone.drop(data);
|
||||||
|
|
||||||
expect(
|
expect(await getDragState()).toBe(12334);
|
||||||
await page.evaluate(() => {
|
|
||||||
return (globalThis as any).didDragStart;
|
|
||||||
})
|
|
||||||
).toBe(true);
|
|
||||||
expect(
|
|
||||||
await page.evaluate(() => {
|
|
||||||
return (globalThis as any).didDragEnter;
|
|
||||||
})
|
|
||||||
).toBe(true);
|
|
||||||
expect(
|
|
||||||
await page.evaluate(() => {
|
|
||||||
return (globalThis as any).didDragOver;
|
|
||||||
})
|
|
||||||
).toBe(true);
|
|
||||||
expect(
|
|
||||||
await page.evaluate(() => {
|
|
||||||
return (globalThis as any).didDrop;
|
|
||||||
})
|
|
||||||
).toBe(true);
|
|
||||||
});
|
});
|
||||||
it('can be dragged and dropped with a single function', async () => {
|
it('can be dragged and dropped with a single function', async () => {
|
||||||
const {page, server} = await getTestState();
|
const {page, server} = await getTestState();
|
||||||
@ -150,44 +120,59 @@ describe('Input.drag', function () {
|
|||||||
using dropzone = (await page.$('#drop'))!;
|
using dropzone = (await page.$('#drop'))!;
|
||||||
await draggable.dragAndDrop(dropzone);
|
await draggable.dragAndDrop(dropzone);
|
||||||
|
|
||||||
expect(
|
expect(await getDragState()).toBe(12334);
|
||||||
await page.evaluate(() => {
|
|
||||||
return (globalThis as any).didDragStart;
|
|
||||||
})
|
|
||||||
).toBe(true);
|
|
||||||
expect(
|
|
||||||
await page.evaluate(() => {
|
|
||||||
return (globalThis as any).didDragEnter;
|
|
||||||
})
|
|
||||||
).toBe(true);
|
|
||||||
expect(
|
|
||||||
await page.evaluate(() => {
|
|
||||||
return (globalThis as any).didDragOver;
|
|
||||||
})
|
|
||||||
).toBe(true);
|
|
||||||
expect(
|
|
||||||
await page.evaluate(() => {
|
|
||||||
return (globalThis as any).didDrop;
|
|
||||||
})
|
|
||||||
).toBe(true);
|
|
||||||
});
|
});
|
||||||
it('can be disabled', async () => {
|
});
|
||||||
|
|
||||||
|
describe("Drag n' Drop", () => {
|
||||||
|
setupTestBrowserHooks();
|
||||||
|
|
||||||
|
it('should drop', async () => {
|
||||||
const {page, server} = await getTestState();
|
const {page, server} = await getTestState();
|
||||||
|
|
||||||
await page.goto(server.PREFIX + '/input/drag-and-drop.html');
|
await page.goto(server.PREFIX + '/input/drag-and-drop.html');
|
||||||
expect(page.isDragInterceptionEnabled()).toBe(false);
|
|
||||||
await page.setDragInterception(true);
|
|
||||||
expect(page.isDragInterceptionEnabled()).toBe(true);
|
|
||||||
using draggable = (await page.$('#drag'))!;
|
|
||||||
await draggable.drag({x: 1, y: 1});
|
|
||||||
await page.setDragInterception(false);
|
|
||||||
|
|
||||||
try {
|
using draggable = await page.$('#drag');
|
||||||
await draggable.drag({x: 1, y: 1});
|
assert(draggable);
|
||||||
} catch (error) {
|
using dropzone = await page.$('#drop');
|
||||||
expect((error as Error).message).toContain(
|
assert(dropzone);
|
||||||
'Drag Interception is not enabled!'
|
|
||||||
);
|
await dropzone.drop(draggable);
|
||||||
}
|
|
||||||
|
expect(await getDragState()).toBe(1234);
|
||||||
|
});
|
||||||
|
it('should drop using mouse', async () => {
|
||||||
|
const {page, server} = await getTestState();
|
||||||
|
|
||||||
|
await page.goto(server.PREFIX + '/input/drag-and-drop.html');
|
||||||
|
|
||||||
|
using draggable = await page.$('#drag');
|
||||||
|
assert(draggable);
|
||||||
|
using dropzone = await page.$('#drop');
|
||||||
|
assert(dropzone);
|
||||||
|
|
||||||
|
await draggable.hover();
|
||||||
|
await page.mouse.down();
|
||||||
|
await dropzone.hover();
|
||||||
|
|
||||||
|
expect(await getDragState()).toBe(123);
|
||||||
|
|
||||||
|
await page.mouse.up();
|
||||||
|
expect(await getDragState()).toBe(1234);
|
||||||
|
});
|
||||||
|
it('should drag and drop', async () => {
|
||||||
|
const {page, server} = await getTestState();
|
||||||
|
|
||||||
|
await page.goto(server.PREFIX + '/input/drag-and-drop.html');
|
||||||
|
|
||||||
|
using draggable = await page.$('#drag');
|
||||||
|
assert(draggable);
|
||||||
|
using dropzone = await page.$('#drop');
|
||||||
|
assert(dropzone);
|
||||||
|
|
||||||
|
await draggable.drag(dropzone);
|
||||||
|
await dropzone.drop(draggable);
|
||||||
|
|
||||||
|
expect(await getDragState()).toBe(1234);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user