Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(dragAndDrop): page.dragAndDrop #6910

Merged
merged 3 commits into from
Jul 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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