webdriverio icon indicating copy to clipboard operation
webdriverio copied to clipboard

[🐛 Bug]: Drag drop is not working

Open sashantkhatri opened this issue 3 years ago • 47 comments

Have you read the Contributing Guidelines on issues?

WebdriverIO Version

7.16.13

Node.js Version

v16.13.1

Mode

WDIO Testrunner

Which capabilities are you using?

{
    
        // maxInstances can get overwritten per capability. So if you have an in-house Selenium
        // grid with only 5 firefox instances available you can make sure that not more than
        // 5 instances get started at a time.
        maxInstances: 5,
        //
        browserName: 'chrome',
        acceptInsecureCerts: true
        // If outputDir is provided WebdriverIO can capture driver session logs
        // it is possible to configure which logTypes to include/exclude.
        // excludeDriverLogs: ['*'], // pass '*' to exclude all driver session logs
        // excludeDriverLogs: ['bugreport', 'server'],
    }

What happened?

I tried to drag $(modelSchemaString.replace("[MODEL_NAME]", 'Calendar')) element and drop to $("//div[@id='mfgx-data-flow-diagram']")_ but I could not get success. Adding the dragAndDrop method below for reference

    async dragAndDrop() {
        var modelSchemaString = "//div[@id='toolbox-stub-[MODEL_NAME]']";
        await $(modelSchemaString.replace("[MODEL_NAME]", 'Calendar')).waitForDisplayed({ timeout: 120000 });
        const target = await $("//div[@id='mfgx-data-flow-diagram']");
        await $(modelSchemaString.replace("[MODEL_NAME]", 'Calendar')).dragAndDrop(target)
        await browser.pause(5000)
        await $(modelSchemaString.replace("[MODEL_NAME]", 'CalendarEvent')).dragAndDrop(target)
        await browser.pause(5000)
    }

Element details of source element $(modelSchemaString.replace("[MODEL_NAME]", 'Calendar')) is : image

Element details of target element $("//div[@id='mfgx-data-flow-diagram']") is : image

Element dragging is successful in my case but dropping is not getting success.

What is your expected behavior?

Drag and drop should happen successfully.

How to reproduce the bug.

Added details in What happened section

Relevant log output

No log file was generated.

Code of Conduct

  • [X] I agree to follow this project's Code of Conduct

Is there an existing issue for this?

  • [X] I have searched the existing issues

sashantkhatri avatar Feb 17 '22 07:02 sashantkhatri

@sashan4u007 do you have a reproducible example?

christian-bromann avatar Feb 22 '22 13:02 christian-bromann

Same issue on my side, drag and drop is not working, please see reproducible example :

  browser.url('https://www.w3schools.com/html/html5_draganddrop.asp');
  $('#accept-choices').click();
  const draggable = $('#div1 img[draggable="true"]');
  const droppable = $('#div2');
  draggable.waitForDisplayed();
  droppable.waitForDisplayed();
  draggable.dragAndDrop(droppable);

  browser.pause(5000);

lacell75 avatar Mar 10 '22 10:03 lacell75

@lacell75 thanks for providing the example, could you tell us how your capabilities look like?

christian-bromann avatar Mar 10 '22 10:03 christian-bromann

My capabilities, I'm using a hub and chrome Version 99.0.4844.51 :

 capabilities: [
    {
      maxInstances: 4,
      browserName: 'chrome',
      acceptInsecureCerts: true,
      'goog:chromeOptions': {
        args: ['--disable-backgrounding-occluded-windows', '--window-size=1980,1080', '--disable-gpu'],
      },
    },
  ],

lacell75 avatar Mar 10 '22 10:03 lacell75

We would appreciate any help on this. Have a look at our contributing guidelines and reach out if you have any questions. Cheers!

christian-bromann avatar Mar 10 '22 10:03 christian-bromann

@sashan4u007 , @lacell75 Can you please use the following method and see if it solves your problem?

async dndAction(sourceElement: WebdriverIO.Element, targetElement: WebdriverIO.Element) {

        let sX = await sourceElement.getLocation("x");

        let sY = await sourceElement.getLocation("y");

        let tX = await targetElement.getLocation("x");

        let tY = await targetElement.getLocation("y");

        await browser.performActions([
            {
                "type": "pointer",

                "id": "mouseClick1",

                "actions": [
                    {
                        "type": "pointerMove",
                        "duration": 0,
                        "x": sX,
                        "y": sY
                    },
                    {
                        "type": "pointerDown",
                        "button": 0
                    },
                    {
                        "type": "pause",
                        "duration": 500
                    },
                    {
                        "type": "pointerMove",
                        "duration": 1000,
                        "x": tX,
                        "y": tY
                    },
                    {
                        "type": "pointerUp",
                        "button": 0
                    },
                    {
                        "type": "pause",
                        "duration": 500
                    }
                ]
            }
        ]);

        await browser.releaseActions();

        await browser.pause(1000);
    }

tzurp avatar Apr 02 '22 17:04 tzurp

How can this be implemented on lacell75 reproducible example?

davefogo avatar Jun 16 '22 18:06 davefogo

@davefogo instead of: draggable.dragAndDrop(droppable);

use: dndAction(draggable, droppable);

tzurp avatar Jun 17 '22 12:06 tzurp

Thanks @davefogo for providing another reproducible example in https://github.com/webdriverio/webdriverio/issues/8436. Any investigations/contributions to this would be appreciated.

christian-bromann avatar Jun 20 '22 15:06 christian-bromann

@davefogo instead of: draggable.dragAndDrop(droppable);

use: dndAction(draggable, droppable);

I have the same problem. Can't drop a li element (when I drag a li element and try to move it to the 2nd li, it's not moving, only pressed). I tried different options: dragAndDrop(), performActions(), html-dnd, etc. Nothing helped me.

Elimes7 avatar Jun 27 '22 07:06 Elimes7

I got the same issue, too. The mouse pointer moves to the element, click and hold, but no movement after that... "@wdio/cli": "^7.19.7"

Any help is appreciated

spazbg avatar Jul 05 '22 08:07 spazbg

Yes, any update on this issue? It just holds the element doesn't drop to the target location.

tv2022 avatar Sep 02 '22 23:09 tv2022

Got the same issue, it drags the source element but moves to my mouse cursor instead of target element.

I've worked out a workaround based on this article, which is to call drag events directly to simulate drag and drop actions, this works if your web app is using HTML native drag and drop.

Code sample:

dragAndDropByEvents(src, dest) {

    this.browser.execute((src, dest) => {
        const createBubbledEvent = (type, props = {}) => {
            // eslint-disable-next-line
            const event = new DragEvent(type, {bubbles: true});
            Object.assign(event, props);
            return event;
        };

        src.dispatchEvent(createBubbledEvent('dragstart', {}));
        dest.dispatchEvent(createBubbledEvent('drop', {}));
        src.dispatchEvent(createBubbledEvent('dragend', {}));
    }, src, dest);
}

May need to provide DataTransfer object if needed, depends on your drag events implementation.

kshen-deputy avatar Oct 12 '22 00:10 kshen-deputy

@christian-bromann Thanks for pointing me to this issue. Let me know what kind of help I can provide in order to get this issue fix. Any sort of help is needed from my side. Ready to provide that at any moment on time

iamatharva avatar Oct 19 '22 17:10 iamatharva

Any kind of suggestion for fixes or different implementations of our dragAndDrop command would be appreciated.

christian-bromann avatar Oct 19 '22 17:10 christian-bromann

So I figured out that this issue is actually related to the application someone is automating. If we hit the URL mentioned in the example link and follow their steps WDIO works completely fine. But for applications using vue.js, the WDIO drag and drop doesn't work Someone pointed this here In my opinion, the general or global behaviour of this feature is missing.

Somehow we pass the dragged item to the local cursor which is not expected and it should stay with the automated chrome action.

iamatharva avatar Oct 19 '22 17:10 iamatharva

@iamatharva If this is blocking you, then you can use this in the mean time until we figure out the bug issue. I have used this package and it works pretty well. https://www.npmjs.com/package/html-dnd

ducle91 avatar Oct 19 '22 17:10 ducle91

@iamatharva If this is blocking you, then you can use this in the mean time until we figure out the bug issue. I have used this package and it works pretty well. https://www.npmjs.com/package/html-dnd

Worked for me

SMdoras91 avatar Oct 27 '22 09:10 SMdoras91

@ducle91 and @SMdoras91 It didn't work for me. If you can share some example implementations here I can try with this too.

iamatharva avatar Oct 27 '22 13:10 iamatharva

It's not wokring for Angualr CDK drag drop. Perform actions and html-dnd also didn't work. can someone let me know how to make this work? Reproducible code.

    await browser.url('https://material.angular.io/cdk/drag-drop/overview');
    const draggable = await $(`(.//div[text()='Get to work'])[1]`);
    const dropTo = await $(`(.//div[text()='Get up'])[1]`);
    await draggable.dragAndDrop(dropTo);

tv2022 avatar Nov 08 '22 04:11 tv2022

I'm also seeing this issue. It seems like this has been broken since 2019. Is anyone looking into a fix for this?https://github.com/webdriverio/webdriverio/issues/4134

MaxboDev avatar Nov 08 '22 10:11 MaxboDev

@M4sterShake it is not entirely broken folks. There are many ways you can implement a drag&drop behavior and it is almost impossible to guarantee the command works for all of them. I am happy to revisit this issue once v8 is released but generally you all have all capabilities to build a drag&drop function yourself by using the performActions command.

christian-bromann avatar Nov 08 '22 17:11 christian-bromann

performActions() is not working in our app, which uses React. Any working examples or tips?

spazbg avatar Nov 08 '22 19:11 spazbg

@M4sterShake it is not entirely broken folks. There are many ways you can implement a drag&drop behavior and it is almost impossible to guarantee the command works for all of them. I am happy to revisit this issue once v8 is released but generally you all have all capabilities to build a drag&drop function yourself by using the performActions command.

@christian-bromann Thanks for responding. You're right, in some cases, this still works. But with performActions also this not working on Angular CDK drag and drop components for some reason. The below core selenium driver command still works for this. Appreciate any clues.

await driver.actions().mouseDown(source)
			.mouseMove(target)
			.mouseUp(target)
			.perform();

tv2022 avatar Nov 08 '22 19:11 tv2022

Selenium uses the same protocol so you should be able to do what they do in WebdriverIO. In fact v8 adds better interfaces to chain actions commands like this, so what you have above will work out of the box.

christian-bromann avatar Nov 08 '22 20:11 christian-bromann

@M4sterShake it is not entirely broken folks. There are many ways you can implement a drag&drop behavior and it is almost impossible to guarantee the command works for all of them. I am happy to revisit this issue once v8 is released but generally you all have all capabilities to build a drag&drop function yourself by using the performActions command.

Thanks @christian-bromann but that's the problem, it doesn't work even when using performActions. It behaves exactly the same as it does when using dragAndDrop. There are many people in https://github.com/webdriverio/webdriverio/issues/4134 that have the same problem. I've tried with many permutations but nothing seems to work. Once pointerDown is fired, mouseMove doesn't seem to work properly anymore. The app being tested is a React app by the way.

MaxboDev avatar Nov 08 '22 20:11 MaxboDev

@christian-bromann Thanks for responding. You're right, in some cases, this still works. But with performActions also this not working on Angular CDK drag and drop components for some reason. The below core selenium driver command still works for this. Appreciate any clues.

await driver.actions().mouseDown(source)
			.mouseMove(target)
			.mouseUp(target)
			.perform();

Hi @tv2022 that sounds interesting but actions doesn't seem to exist on the global driver object. Do you know how I would reference the selenium driver directly? Thanks!

MaxboDev avatar Nov 08 '22 20:11 MaxboDev

@M4sterShake It's just a workaround to unblock ourselves. You can use below code snippet to get the core webdriver session.

import { Executor, HttpClient } from 'selenium-webdriver/http';
import * as webDriver from 'selenium-webdriver';

const sessionId: any = browser.sessionId;
const client: HttpClient = new HttpClient(gridUrl);
const executor: Executor = new Executor(client);
driver = new webDriver.WebDriver(sessionId, executor);

And you also need to find elements using core webdriver like...

const source = await driver.findElement(By.css(`${await src.selector}`);
const target = await driver.findElement(By.css(`${await trg.selector}`)

Then

await driver.actions().mouseDown(source)
			.mouseMove(target)
			.mouseUp(target)
			.perform();

tv2022 avatar Nov 08 '22 23:11 tv2022

@tv2022 do you have a working example for Selenium? I wasn't able to get your code working. I tried the following:

import { remote } from './packages/webdriverio/build/index.js'
const http = await import('selenium-webdriver/http/index.js')
const webDriver = await import('selenium-webdriver')

const browser = await remote({
    capabilities: {
        browserName: 'chrome',
    }
})

const sessionId = browser.sessionId
const client = new http.HttpClient('http://localhost:4444/')
const executor = new http.Executor(client)
const driver = new webDriver.WebDriver(sessionId, executor)

await browser.url('https://material.angular.io/cdk/drag-drop/overview')
await browser.pause(2000)

const source = await driver.findElement(webDriver.By.xpath(`(.//div[text()='Get to work'])[1]`))
const target = await driver.findElement(webDriver.By.xpath(`(.//div[text()='Get up'])[1]`))
const actions = driver.actions({ async: true })
await actions.dragAndDrop(source, target).perform()

await browser.pause(5000)
await browser.deleteSession()

I can see that the drag&drop action selects the element but doesn't move it.

christian-bromann avatar Dec 13 '22 00:12 christian-bromann

@all I can see that the drag action selects the element but doesn't move it. what i am doing wrong

it('LAM SalesTeamRRT', async () => { await leadManagement.salesTeamRRT('A43', 'Automate1324'); const AboutMe = await $("//mat-list-item[contains(@id,'About Me')]") const AddField = await $("//div[@id='cdk-drop-list-0']") await browser.actions([ browser.action('pointer') .move({ duration: 2000, AboutMe, x: 1340, y: 230 }) .down({ button: 0 }) //Code Working till this step .move({ duration: 2000, AddField, x: 950, y: 216 }) .up({ button: 0 }) ])

sarthacastic avatar Dec 15 '22 12:12 sarthacastic