【问题标题】:Selenium WebDriver - Unable to drag and drop element in IE11Selenium WebDriver - 无法在 IE11 中拖放元素
【发布时间】:2020-03-16 12:11:23
【问题描述】:

我正在尝试将一个元素从侧面板拖放到表单中。我写的拖放代码如下所示。

Actions builder = new Actions(driver);
builder.dragAndDrop(source, target).build().perform();

这在除 IE11 之外的所有浏览器中都可以正常工作。

我尝试了其他方法,例如

方法 1 -

builder.clickAndHold(source)
        .moveToElement(target)
        .release(target)
        .build()
        .perform();

方法 2 -

builder.clickAndHold(source)
    .pause(Duration.ofSeconds(1))
    .moveByOffset(-1, -1)
    .pause(Duration.ofSeconds(1))
    .moveToElement(target)
    .pause(Duration.ofSeconds(1))
    .moveToElement(target)
    .pause(Duration.ofSeconds(1))
    .release(target)
    .build()
    .perform();

但没有任何效果。

所有选项在页面上什么都不做,但它们正在执行而没有任何错误。我还尝试了不同 stackoverflow/gitHub 链接中给出的所有 javascript 解决方案,但没有任何效果。

谁能帮我解决这个问题?

编辑 1-

正如我之前提到的,我已经尝试了所有可能/提到的解决方案,但没有一个有效。这是我的代码。

package dragAndDrop;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.Charset;

import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.testng.annotations.Test;

public class DryRunIE{

    WebDriver driver;

    @Test
    public void dragAndDrop() {

        System.setProperty("webdriver.ie.driver", System.getProperty("user.dir") + "/Drivers/IEDriverServer.exe");
        driver = new InternetExplorerDriver();

        driver.get("https://jqueryui.com/droppable/");
        driver.manage().window().maximize();
        driver.switchTo().frame(0);

        try {
            //simulateDragAndDrop(driver.findElement(By.id("draggable")), driver.findElement(By.id("droppable")));
            //simulateDragDrop(driver.findElement(By.id("draggable")), driver.findElement(By.id("droppable")));
            dragAndDropHelper();
        } catch (Exception e) {
            e.printStackTrace();
        }

        driver.quit();
        try {
            Runtime.getRuntime().exec("taskkill /F /IM IEDriverServer.exe");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void simulateDragAndDrop(WebElement elementToDrag, WebElement target) throws Exception {

        JavascriptExecutor js = (JavascriptExecutor) driver;
        String script = "function createEvent(typeOfEvent) {" + "var event = document.createEvent(\"CustomEvent\");"
                + "event.initCustomEvent(typeOfEvent,true, true, null); " + "event.dataTransfer = { " + "data: {}, "
                + "setData: function (key, value) { this.data[key] = value; }, " + "getData: function (key) { "
                + "return this.data[key]; " + "} " + "}; " + "return event;" + "}"
                + "function dispatchEvent(element, event,transferData) { " + "" + "if (transferData !== undefined) { "
                + "event.dataTransfer = transferData; " + "} " + "" + "if (element.dispatchEvent) { "
                + "element.dispatchEvent(event); " + "} " + "" + "else if (element.fireEvent) { "
                + "element.fireEvent(\"on\" + event.type,event); " + "}" + "}" + ""
                + "function simulateHTML5DragAndDrop(element,target) { "
                + "var dragStartEvent =createEvent('dragstart'); " + "dispatchEvent(element, dragStartEvent); "
                + "var dropEvent = createEvent('drop'); "
                + "dispatchEvent(target, dropEvent,dragStartEvent.dataTransfer); "
                + "var dragEndEvent = createEvent('dragend'); "
                + "dispatchEvent(element, dragEndEvent,dropEvent.dataTransfer);" + "}" + ""
                + "var elementToDrag = arguments[0];" + "var targetElem = arguments[1];" + ""
                + "simulateHTML5DragAndDrop(elementToDrag,targetElem);";
        js.executeScript(script, elementToDrag, target);
    }

    private void simulateDragDrop(WebElement ele_source, WebElement ele_target) {
        final String JS_DnD =
                "var src=arguments[0],tgt=arguments[1];var dataTransfer={dropEffe" +
                "ct:'',effectAllowed:'all',files:[],items:{},types:[],setData:fun" +
                "ction(format,data){this.items[format]=data;this.types.append(for" +
                "mat);},getData:function(format){return this.items[format];},clea" +
                "rData:function(format){}};var emit=function(event,target){var ev" +
                "t=document.createEvent('Event');evt.initEvent(event,true,false);" +
                "evt.dataTransfer=dataTransfer;target.dispatchEvent(evt);};emit('" +
                "dragstart',src);emit('dragenter',tgt);emit('dragover',tgt);emit(" +
                "'drop',tgt);emit('dragend',src);";

                // drag and drop item two into the bin
                ((JavascriptExecutor)driver).executeScript(JS_DnD, ele_source, ele_target);
    }

    private void dragAndDropHelper() {

        String script = null;
        try {
            script = readFile(System.getProperty("user.dir") + "\\drag_and_drop_helper.js");
        } catch (IOException e) {
            e.printStackTrace();
        }

        JavascriptExecutor js = (JavascriptExecutor) driver;
        js.executeScript(script + "$('#draggable').simulateDragDrop({ dropTarget: '#droppable'});");
        System.out.println();
    }

    // helper method
    private static String readFile(String file) throws IOException {
        Charset cs = Charset.forName("UTF-8");
        FileInputStream stream = new FileInputStream(file);
        try {
            Reader reader = new BufferedReader(new InputStreamReader(stream, cs));
            StringBuilder builder = new StringBuilder();
            char[] buffer = new char[8192];
            int read;
            while ((read = reader.read(buffer, 0, buffer.length)) > 0) {
                builder.append(buffer, 0, read);
            }
            return builder.toString();
        } finally {
            stream.close();
        }
    }
}

我已经尝试过以下功能一一取消注释并执行,但所有功能都成功执行,页面上没有任何反应。

注意:我从https://gist.github.com/rcorreia/2362544 获得了 drag_and_drop_helper.js。

我在这里有什么遗漏或做错了吗?

谢谢, 钱德雷什·帕玛

【问题讨论】:

    标签: javascript selenium selenium-webdriver internet-explorer-11


    【解决方案1】:

    似乎是 IE11 的一个已知问题,没有人能够修复。

    在 Selenium 存储库中打开了一个相关的 GitHub 问题,但由于缺乏可工作的、可重现的示例,它已被关闭:

    https://github.com/SeleniumHQ/selenium/issues/6354

    StackExchange 上的其他用户自 2016 年以来一直看到此问题,但没有真正解决:

    Unable to Automate Drag and Drop for IE11 : Selenium WebDriver(无工作分辨率)

    https://sqa.stackexchange.com/questions/22534/why-drag-and-drop-is-not-working-in-selenium-webdriver/26500(没有接受的答案,但有人赞成)

    我的猜测是 IE 驱动程序只是不稳定,拖放可能在某些网站上有效,但在其他网站上无效,原因不明。在 Selenium 存储库中打开 GitHub 问题可能会更好,并提供一个工作代码示例/URL,其中拖放绝对不起作用,一直。

    【讨论】:

    • 您提到...IE 驱动程序只是片状... 没有任何证据。这是很不合理的。作为记录,如果拖放可以在其他浏览器上使用,那么它也可以在 IE 上使用。
    • 我提到这是一个猜测,这是基于多个关于拖放在 Chrome/Firefox 上成功运行但不是 IE 的报告——其中一些问题可以追溯到 2015 年、2016 年以及许多报告都是一样的,大多数都没有任何解决方案。我的回答语言不代表我说的是canon,只是我个人对IE驱动的困扰,在反复观察的基础上的猜测。
    【解决方案2】:

    现在使用 Selenium 拖放是有问题的。这里描述了拖放的模拟:How to simulate HTML5 Drag and Drop in Selenium Webdriver?

    【讨论】:

    • 这个问题是特定于 HTML5 拖放问题。基于 JS 的拖放仍然有效。
    • @Frank - 感谢您的意见。请看我下面的帖子。我已经尝试过在不同线程上发布的每个 javascript 解决方案,但它们都不起作用。请查看代码,如果我遗漏任何内容,请告诉我。
    【解决方案3】:

    我尝试了这个帖子中的答案:Unable to Automate Drag and Drop for IE11 : Selenium WebDriver(Christine 也提到过)。它可以在 IE11 中使用代码中的测试页面和drag and drop page of w3schools 很好地工作。只需在代码中将自己的网址和两个元素的id替换成自己的即可。

    ----------------------------------- - - - - - - - - -编辑 - - - - - - - - - - - - - - - - ------------------------------

    您提供的网站是关于 jQuery 拖放的。它与 HTML5 拖放不同。此外,拖放元素在 iframe 中。我们首先需要使用switchTo() 来访问 iframe。您可以查看下面的代码,它可以在 IE 中正常运行:

    import org.openqa.selenium.By;
    import org.openqa.selenium.WebDriver; 
    import org.openqa.selenium.ie.InternetExplorerDriver; 
    import org.openqa.selenium.WebElement; 
    import org.openqa.selenium.interactions.Actions;
    
    public class IEauto {
        public static void main(String[] args) { 
    
         //add the IE web driver path here.. 
          System.setProperty("webdriver.ie.driver","C:\\yourpath\\IEDriverServer_x64_3.14.0\\IEDriverServer.exe");             
          WebDriver driver = new InternetExplorerDriver(); 
    
         //replace the URL of the web page here.. 
          driver.get("https://jqueryui.com/droppable/"); 
         //int size = driver.findElements(By.tagName("iframe")).size();
          driver.switchTo().frame(0);
    
          WebElement ele_source = driver.findElement(By.id("draggable"));
          WebElement ele_target = driver.findElement(By.id("droppable"));
    
          Actions builder = new Actions(driver);
          builder.dragAndDrop(ele_source, ele_target).build().perform();
        } 
    }
    

    结果是这样的:

    【讨论】:

    • 感谢您的意见。请看我下面的帖子。我已经尝试过在不同线程上发布的每个 javascript 解决方案,但它们都不起作用。请查看代码,如果我遗漏任何内容,请告诉我。
    • 从您的代码中的网站,您正在模拟 jQuery 拖放,它与 HTML5 拖放不同。也可以参考this thread模拟jQuery拖拽的解决方案。
    • @ChandreshParmar 我更新了我的答案。请查看我的示例代码,它可以在 IE 11 中正常运行。
    【解决方案4】:

    我也遇到了同样的问题。请在下面找到用于拖放的自定义 java-script 函数。

    1) 创建 DragDrop.js 文件并将以下代码粘贴到其中

        function customEvent(typeOfEvent) {
        var event = document.createEvent("CustomEvent");
        event.initCustomEvent(typeOfEvent, true, true, null);
        event.dataTransfer = {
            data: {},
            setData: function (key, value) {
                this.data[key] = value;
            },
            getData: function (key) {
                return this.data[key];
            }
        };
        return event;
    }
    function dispatchEvent(element, event, transferData) {
        if (transferData !== undefined) {
            event.dataTransfer = transferData;
        }
        if (element.dispatchEvent) {
            element.dispatchEvent(event);
        } else if (element.fireEvent) {
            element.fireEvent("on" + event.type, event);
        }
    }
    function executeDrageAndDrop(element, target) {
        var dragStartEvent = customEvent('dragstart');
        dispatchEvent(element, dragStartEvent);
        var dropEvent = customEvent('drop');
        dispatchEvent(target, dropEvent, dragStartEvent.dataTransfer);
        var dragEndEvent = customEvent('dragend');
        dispatchEvent(element, dragEndEvent, dropEvent.dataTransfer);
    }
    

    2)使用下面的代码我们可以调用上面的自定义函数(下面是C#代码)

    string script = System.IO.File.ReadAllText(@"{filepath of DragDrop.js file}");
    script = script + "executeDrageAndDrop(arguments[0], arguments[1])";
    IJavaScriptExecutor executor = (IJavaScriptExecutor)driver;
    
    IWebElement source = driver.findElement(By......);
    IWebElement target = driver.findElement(By......);
    
    executor.ExecuteScript(script, source, target);
    

    注意:对于 Java - 将上述 C# 代码转换为 Java 并尝试。我已经尝试过上面的代码,它适用于 IE、Edge 和 Chrome 浏览器。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-09-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-28
      • 2021-07-04
      • 2016-04-15
      相关资源
      最近更新 更多