Skip to content

Commit

Permalink
feat(drag): page.dragAndDrop
Browse files Browse the repository at this point in the history
  • Loading branch information
JoelEinbinder committed Jul 12, 2021
1 parent eb31b9e commit 361513c
Show file tree
Hide file tree
Showing 11 changed files with 165 additions and 0 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.selector1
- `selector1` <[string]>

### param: Frame.dragAndDrop.selector2
- `selector2` <[string]>
### option: Frame.dragAndDrop.force = %%-input-force-%%

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

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

### option: Frame.dragAndDrop.timeout = %%-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.selector1
- `selector1` <[string]>

### param: Page.dragAndDrop.selector2
- `selector2` <[string]>
### option: Page.dragAndDrop.force = %%-input-force-%%

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

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

### option: Page.dragAndDrop.timeout = %%-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
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(selector1: string, selector2: string, options: channels.FrameDragAndDropOptions = {}) {
return this._wrapApiCall(async (channel: channels.FrameChannel) => {
return await channel.dragAndDrop({ selector1, selector2, ...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(selector1: string, selector2: string, options?: channels.FrameDragAndDropOptions) {
return this._mainFrame.dragAndDrop(selector1, selector2, 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.selector1, params.selector2, 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 = {
selector1: string,
selector2: 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:
selector1: string
selector2: 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({
selector1: tString,
selector2: tString,
force: tOptional(tBoolean),
noWaitAfter: tOptional(tBoolean),
timeout: tOptional(tNumber),
trial: tOptional(tBoolean),
});
scheme.FrameDblclickParams = tObject({
selector: tString,
force: tOptional(tBoolean),
Expand Down
18 changes: 18 additions & 0 deletions src/server/frames.ts
Original file line number Diff line number Diff line change
Expand Up @@ -982,6 +982,24 @@ export class Frame extends SdkObject {
}, this._page._timeoutSettings.timeout(options));
}

async dragAndDrop(metadata: CallMetadata, selector1: string, selector2: string, options: types.PointerActionWaitOptions & types.NavigatingActionWaitOptions = {}) {
const controller = new ProgressController(metadata, this);
await controller.run(async progress => {
await dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector1, 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);
}));
await dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector2, 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);
}));
}, 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
66 changes: 66 additions & 0 deletions types/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1425,6 +1425,39 @@ export interface Page {
timeout?: number;
}): Promise<void>;

/**
* @param selector1
* @param selector2
* @param options
*/
dragAndDrop(selector1: string, selector2: string, options?: {
/**
* Whether to bypass the [actionability](https://playwright.dev/docs/actionability) checks. Defaults to `false`.
*/
force?: boolean;

/**
* Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can
* opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as navigating to
* inaccessible pages. Defaults to `false`.
*/
noWaitAfter?: boolean;

/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
* [browserContext.setDefaultTimeout(timeout)](https://playwright.dev/docs/api/class-browsercontext#browser-context-set-default-timeout)
* or [page.setDefaultTimeout(timeout)](https://playwright.dev/docs/api/class-page#page-set-default-timeout) methods.
*/
timeout?: number;

/**
* When set, this method only performs the [actionability](https://playwright.dev/docs/actionability) checks and skips the action. Defaults to
* `false`. Useful to wait until the element is ready for the action without performing it.
*/
trial?: boolean;
}): Promise<void>;

/**
* 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 Expand Up @@ -3649,6 +3682,39 @@ export interface Frame {
timeout?: number;
}): Promise<void>;

/**
* @param selector1
* @param selector2
* @param options
*/
dragAndDrop(selector1: string, selector2: string, options?: {
/**
* Whether to bypass the [actionability](https://playwright.dev/docs/actionability) checks. Defaults to `false`.
*/
force?: boolean;

/**
* Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can
* opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as navigating to
* inaccessible pages. Defaults to `false`.
*/
noWaitAfter?: boolean;

/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
* [browserContext.setDefaultTimeout(timeout)](https://playwright.dev/docs/api/class-browsercontext#browser-context-set-default-timeout)
* or [page.setDefaultTimeout(timeout)](https://playwright.dev/docs/api/class-page#page-set-default-timeout) methods.
*/
timeout?: number;

/**
* When set, this method only performs the [actionability](https://playwright.dev/docs/actionability) checks and skips the action. Defaults to
* `false`. Useful to wait until the element is ready for the action without performing it.
*/
trial?: boolean;
}): Promise<void>;

/**
* This method waits for an element matching `selector`, waits for [actionability](https://playwright.dev/docs/actionability) checks, focuses the
* element, fills it and triggers an `input` event after filling. Note that you can pass an empty string to clear the input
Expand Down

0 comments on commit 361513c

Please sign in to comment.