Skip to content

Commit

Permalink
feat(dragAndDrop): page.dragAndDrop (#6910)
Browse files Browse the repository at this point in the history
  • Loading branch information
JoelEinbinder committed Jul 19, 2021
1 parent d72efbe commit 56ada37
Show file tree
Hide file tree
Showing 12 changed files with 229 additions and 48 deletions.
14 changes: 14 additions & 0 deletions docs/src/api/class-frame.md
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,20 @@ Optional event-specific initialization properties.

### option: Frame.dispatchEvent.timeout = %%-input-timeout-%%

## async method: Frame.dragAndDrop

### param: Frame.dragAndDrop.source = %%-input-source-%%

### param: Frame.dragAndDrop.target = %%-input-target-%%

### option: Frame.dragAndDrop.force = %%-input-force-%%

### option: Frame.dragAndDrop.noWaitAfter = %%-input-no-wait-after-%%

### option: Frame.dragAndDrop.timeout = %%-input-timeout-%%

### option: Frame.dragAndDrop.trial = %%-input-trial-%%

## async method: Frame.evalOnSelector
* langs:
- alias-python: eval_on_selector
Expand Down
14 changes: 14 additions & 0 deletions docs/src/api/class-page.md
Original file line number Diff line number Diff line change
Expand Up @@ -811,6 +811,20 @@ Optional event-specific initialization properties.

### option: Page.dispatchEvent.timeout = %%-input-timeout-%%

## async method: Page.dragAndDrop

### param: Page.dragAndDrop.source = %%-input-source-%%

### param: Page.dragAndDrop.target = %%-input-target-%%

### option: Page.dragAndDrop.force = %%-input-force-%%

### option: Page.dragAndDrop.noWaitAfter = %%-input-no-wait-after-%%

### option: Page.dragAndDrop.timeout = %%-input-timeout-%%

### option: Page.dragAndDrop.trial = %%-input-trial-%%

## async method: Page.emulateMedia

This method changes the `CSS media type` through the `media` argument, and/or the `'prefers-colors-scheme'` media feature, using the `colorScheme` argument.
Expand Down
12 changes: 11 additions & 1 deletion docs/src/api/params.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,17 @@ Whether to bypass the [actionability](./actionability.md) checks. Defaults to `f
## input-selector
- `selector` <[string]>

A selector to search for element. If there are multiple elements satisfying the selector, the first will be used. See
A selector to search for an element. If there are multiple elements satisfying the selector, the first will be used. See
[working with selectors](./selectors.md) for more details.

## input-source
- `source` <[string]>
A selector to search for an element to drag. If there are multiple elements satisfying the selector, the first will be used. See
[working with selectors](./selectors.md) for more details.

## input-target
- `target` <[string]>
A selector to search for an element to drop onto. If there are multiple elements satisfying the selector, the first will be used. See
[working with selectors](./selectors.md) for more details.

## input-position
Expand Down
6 changes: 6 additions & 0 deletions src/client/frame.ts
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,12 @@ export class Frame extends ChannelOwner<channels.FrameChannel, channels.FrameIni
});
}

async dragAndDrop(source: string, target: string, options: channels.FrameDragAndDropOptions = {}) {
return this._wrapApiCall(async (channel: channels.FrameChannel) => {
return await channel.dragAndDrop({ source, target, ...options });
});
}

async tap(selector: string, options: channels.FrameTapOptions = {}) {
return this._wrapApiCall(async (channel: channels.FrameChannel) => {
return await channel.tap({ selector, ...options });
Expand Down
4 changes: 4 additions & 0 deletions src/client/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,10 @@ export class Page extends ChannelOwner<channels.PageChannel, channels.PageInitia
return this._mainFrame.click(selector, options);
}

async dragAndDrop(source: string, target: string, options?: channels.FrameDragAndDropOptions) {
return this._mainFrame.dragAndDrop(source, target, options);
}

async dblclick(selector: string, options?: channels.FrameDblclickOptions) {
return this._mainFrame.dblclick(selector, options);
}
Expand Down
4 changes: 4 additions & 0 deletions src/dispatchers/frameDispatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ export class FrameDispatcher extends Dispatcher<Frame, channels.FrameInitializer
return await this._frame.dblclick(metadata, params.selector, params);
}

async dragAndDrop(params: channels.FrameDragAndDropParams, metadata: CallMetadata): Promise<void> {
return await this._frame.dragAndDrop(metadata, params.source, params.target, params);
}

async tap(params: channels.FrameTapParams, metadata: CallMetadata): Promise<void> {
return await this._frame.tap(metadata, params.selector, params);
}
Expand Down
16 changes: 16 additions & 0 deletions src/protocol/channels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1310,6 +1310,7 @@ export interface FrameChannel extends Channel {
check(params: FrameCheckParams, metadata?: Metadata): Promise<FrameCheckResult>;
click(params: FrameClickParams, metadata?: Metadata): Promise<FrameClickResult>;
content(params?: FrameContentParams, metadata?: Metadata): Promise<FrameContentResult>;
dragAndDrop(params: FrameDragAndDropParams, metadata?: Metadata): Promise<FrameDragAndDropResult>;
dblclick(params: FrameDblclickParams, metadata?: Metadata): Promise<FrameDblclickResult>;
dispatchEvent(params: FrameDispatchEventParams, metadata?: Metadata): Promise<FrameDispatchEventResult>;
evaluateExpression(params: FrameEvaluateExpressionParams, metadata?: Metadata): Promise<FrameEvaluateExpressionResult>;
Expand Down Expand Up @@ -1448,6 +1449,21 @@ export type FrameContentOptions = {};
export type FrameContentResult = {
value: string,
};
export type FrameDragAndDropParams = {
source: string,
target: string,
force?: boolean,
noWaitAfter?: boolean,
timeout?: number,
trial?: boolean,
};
export type FrameDragAndDropOptions = {
force?: boolean,
noWaitAfter?: boolean,
timeout?: number,
trial?: boolean,
};
export type FrameDragAndDropResult = void;
export type FrameDblclickParams = {
selector: string,
force?: boolean,
Expand Down
9 changes: 9 additions & 0 deletions src/protocol/protocol.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1177,6 +1177,15 @@ Frame:
returns:
value: string

dragAndDrop:
parameters:
source: string
target: string
force: boolean?
noWaitAfter: boolean?
timeout: number?
trial: boolean?

dblclick:
parameters:
selector: string
Expand Down
8 changes: 8 additions & 0 deletions src/protocol/validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -587,6 +587,14 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
trial: tOptional(tBoolean),
});
scheme.FrameContentParams = tOptional(tObject({}));
scheme.FrameDragAndDropParams = tObject({
source: tString,
target: tString,
force: tOptional(tBoolean),
noWaitAfter: tOptional(tBoolean),
timeout: tOptional(tNumber),
trial: tOptional(tBoolean),
});
scheme.FrameDblclickParams = tObject({
selector: tString,
force: tOptional(tBoolean),
Expand Down
24 changes: 24 additions & 0 deletions src/server/frames.ts
Original file line number Diff line number Diff line change
Expand Up @@ -982,6 +982,30 @@ export class Frame extends SdkObject {
}, this._page._timeoutSettings.timeout(options));
}

async dragAndDrop(metadata: CallMetadata, source: string, target: string, options: types.PointerActionWaitOptions & types.NavigatingActionWaitOptions = {}) {
const controller = new ProgressController(metadata, this);
await controller.run(async progress => {
await dom.assertDone(await this._retryWithProgressIfNotConnected(progress, source, async handle => {
return handle._retryPointerAction(progress, 'move and down', false, async point => {
await this._page.mouse.move(point.x, point.y);
await this._page.mouse.down();
}, {
...options,
timeout: progress.timeUntilDeadline(),
});
}));
await dom.assertDone(await this._retryWithProgressIfNotConnected(progress, target, async handle => {
return handle._retryPointerAction(progress, 'move and up', false, async point => {
await this._page.mouse.move(point.x, point.y);
await this._page.mouse.up();
}, {
...options,
timeout: progress.timeUntilDeadline(),
});
}));
}, this._page._timeoutSettings.timeout(options));
}

async tap(metadata: CallMetadata, selector: string, options: types.PointerActionWaitOptions & types.NavigatingActionWaitOptions) {
const controller = new ProgressController(metadata, this);
return controller.run(async progress => {
Expand Down
6 changes: 6 additions & 0 deletions tests/page/page-drag.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,12 @@ it.describe('Drag and drop', () => {
expect(await page.$eval('#target', target => target.contains(document.querySelector('#source')))).toBe(true); // could not find source in target
});

it('should work with the helper method', async ({page, server}) => {
await page.goto(server.PREFIX + '/drag-n-drop.html');
await page.dragAndDrop('#source', '#target');
expect(await page.$eval('#target', target => target.contains(document.querySelector('#source')))).toBe(true); // could not find source in target
});

async function trackEvents(target: ElementHandle) {
const eventsHandle = await target.evaluateHandle(target => {
const events: string[] = [];
Expand Down
Loading

0 comments on commit 56ada37

Please sign in to comment.