当目标元素和目标元素在不同的帧中时,如何使用 selenium-webdriver 执行拖放?

Posted

技术标签:

【中文标题】当目标元素和目标元素在不同的帧中时,如何使用 selenium-webdriver 执行拖放?【英文标题】:How to perform drag and drop using selenium-webdriver when target and destination element are in different frames? 【发布时间】:2012-08-07 12:04:31 【问题描述】:

我必须将图像拖放到 CQ5 组件中。图像和组件在不同的框架中。

这是在目标框架处于活动状态时无法作为 webelement destination 工作的代码。

new Actions(driver).dragAndDrop(target, destination).perform();

我也尝试在动作之间切换帧:

    Actions builder = new Actions(driver);
    Actions action = builder.clickAndHold(target);
    driver.switchTo().frame("newFrame"); //switching frames
    builder.moveToElement(destination);
    builder.release(destination);
    builder.build();
    action.perform();

这也不起作用。然后,我尝试通过偏移量移动图像

new Actions(driver).dragAndDropBy(target,  x, y).perform(); // x and y 

这移动了图像但组件没有捕获它,可能是因为动作太快了。有什么办法可以做到这样的拖放吗?

提前致谢。

【问题讨论】:

不打算添加作为答案,因为它不能解决你的问题,但我在尝试让 Selenium 在 CQ 中工作时遇到了同样的麻烦。我发现在 CQ 中有时您可以双击而不是尝试使用拖放。例如,在添加组件时,双击 parsys 将带您进入可以添加的组件列表(在同一框架内)。在此处选择一个组件将直接带您进入该新组件的编辑对话框。内容查找器也可以这样做吗? 【参考方案1】:

你需要把它分成两部分。

// grab your element
Actions builder = new Actions(driver);
Actions action = builder.clickAndHold(target);
builder.build();
action.perform();

// switch to the frame (you havent told webdriver to un-grab
driver.switchTo().frame("newFrame"); //switching frames

// move and drop
Actions builder = new Actions(driver);
Actions action = builder.moveToElement(destination);
builder.release(destination);
builder.build();
action.perform();

【讨论】:

你真的试过这段代码吗?如何在两个不同的操作之间共享一个元素?【参考方案2】:

似乎 selenium / webdriver 拖放存在一些问题。我已经向 selenium 的人提交了一个缺陷,http://code.google.com/p/selenium/issues/detail?id=4420

希望我们能得到一些积极的回应。

【讨论】:

【参考方案3】:

我和你有同样的prb。我不能将两个元素从一帧拖放到花药。 ansers 鞋面是正确的,但从 selenium 3 开始,这个解决方案不再有效。 工作箭头是将源元素(在 clickAndHol 之后)移动到位置 0,0,然后将其移动到第二帧下。例如 150,150。

 Actions builder = new Actions(driver);
 // switsh to the source frame
 driver.switchTo().frame("sourceFrame");
 // take the element with mouse 
 builder.clickAndHold(sourceElt).build().perfom();
 // move mouse to the top of the source frame
 builder.moveToElement(sourceElt, 0, 0 ).build().perfom();
 // move the mouse under the target frame (specific to your case)
 builder.moveToElement(sourceElt, 150,200).build().perfom();
 // switsh to the target frame
 driver.switchTo().frame("targetFrame");
 builder.moveToElement(targetElt).build().perform();
 builder.release(target).build().perform();      

希望我也能帮助你。

【讨论】:

【参考方案4】:

有人找到 Adob​​e CQ 5.5 的解决方案吗?

我在使用 adobe CQ 5.5 时遇到了同样的问题,我尝试了多种不同的方法,我可以将图像放到拖放区,但是一旦出现,图像似乎仍然不活跃并且丢弃它没有意义。我发现这是因为鼠标指针没有随着图像移动,这就是为什么丢弃没有意义。我添加了将鼠标移动到放置区域的代码,但看起来命令是单独工作的,所以仍然无法放置,请提供任何建议。

这是我的代码(不适用于 CQ 5.5)

String handle = driver.getWindowHandle(); // for main window

// 切换到窗口可以选择图像

driver.switchTo().window(handle);
WebElement dragble = driver.findElement(By.xpath("//xpath"));

Actions builder = new Actions(driver);
builder.clickAndHold(dragble);
Action action2 = builder.build();
action2.perform();

// 然后,切换到 iframe

driver.switchTo().frame("cq-cf-frame");
WebElement droppable = driver.findElement(By.cssSelector("#cssSelector of droppable"));

// 机器人将鼠标指向可放置区域

Point coordinates = driver.findElement(By.cssSelector("#cssSelector of droppable")).getLocation();
Robot robot = new Robot();

// 查找可放置元素的位置

int x = driver.findElement(By.cssSelector("#ext-comp-1271")).getLocation().getX();
int y = driver.findElement(By.cssSelector("#ext-comp-1271")).getLocation().getY();

// 将可拖动移动到可放置

builder = new Actions(driver);
builder.moveByOffset(x,y).perform().
builder.build();
builder.release();
robot.mouseMove(coordinates.getX(),coordinates.getY()+120);
builder.release(droppable).perform();

【讨论】:

【参考方案5】:

以上发布的解决方案在 CQ 5.5 和 CQ 5.6 下对我不起作用

这行得通:

    Actions builder = new Actions(driver);
    builder.clickAndHold(sideKickComponent);
    Action action = builder.build();
    action.perform();

    driver.switchTo().frame("cq-cf-frame");
    builder = new Actions(driver);
    builder.moveToElement(destination).perform();
    builder.build();
    builder.release();
    builder.release(destination).perform();     

这种方法可以方便地放置组件:

public void addComponentByDragAndDrop(String sideKickComponentName, WebElement destination)
        driver.switchTo().defaultContent();
        WebElement sidekick = driver.findElement(By.id("cq-sk"));
        List<WebElement> components =sidekick.findElements(By.tagName("button"));
        WebElement sideKickComponent = null;
        for (WebElement webElement : components) 
            if (webElement.getText().equals(sideKickComponentName)) 
                sideKickComponent = webElement;
                break;
            
        
        if (sideKickComponent == null) 
            fail("SideKick component with the name: "+sideKickComponentName + " was not found.");
        
        Actions builder = new Actions(driver);
        builder.clickAndHold(sideKickComponent);
        Action action = builder.build();
        action.perform();

        driver.switchTo().frame(Consts.CQ_MAIN_FRAME);
        builder = new Actions(driver);
        builder.moveToElement(destination).perform();
        builder.build();
        builder.release();
        builder.release(destination).perform();     
    

【讨论】:

【参考方案6】:

以下代码有效,希望对您有所帮助:

WebElement dragElement = (WebElement) elements.get(sourceElement);
Actions builder = new Actions(driver);          
Actions action = builder.clickAndHold(dragElement);
action.build().perform();
driver.switchTo().frame("cq-cf-frame");   
WebElement dropElement = driver.findElement(By.id("ext-comp-1411"));
builder.moveToElement(dropElement).build().perform();
//click the destination 
builder.click(dropElement).build().perform();
//back to main page to release the hold mouse
driver.switchTo().defaultContent();
builder.release(dragElement).build().perform();

【讨论】:

【参考方案7】:

要从一个 iframe 拖放到另一个 iframe,您需要在源 Web 元素的 iframe 中引用您的所有操作。为此,您应该获取目标 iframe 的父级并使用它进行操作,即 CqFrameParent,它是具有目标 iframe 的 div。

由于源和目标属于单个 iframe,因此无需进行 iframe 的切换即可。

builder.moveElement(CqFrameParent(), targetX, targetY).build().perform();
builder.release().build().perform();

【讨论】:

【参考方案8】:

创建动作类的对象

Actions act=new Actions(driver);

找到我们需要拖动的元素xpath

WebElement drag=driver.findElement(By.xpath("put x path"));

找到我们需要放置的元素xpath

WebElement drop=driver.findElement(By.xpath("put x path"));

将元素拖到目的地

act.dragAndDrop(drag, drop).build().perform();

要在 CQ 中使用拖放功能,请先使用双击功能并放置任何组件,然后尝试上述方法。

【讨论】:

【参考方案9】:

此代码适用于 CQ 5.5

driver.switchTo().defaultContent();

Actions builder = new Actions(driver);
builder.clickAndHold(target);
Action action = builder.build();
action.perform();

driver.switchTo().frame("cq-cf-frame");
builder.moveToElement(destination);
builder.release(destination);     
action = builder.build();
action.perform();

【讨论】:

【参考方案10】:
String source = "xpath_of_source";
String destination = "xpath_of_destination";

// grab your element
Actions builder = new Actions(driver);
Actions action = builder.clickAndHold(driver.findElement(By.xpath(source)));
builder.build();
action.perform();

// switch to the frame
driver.switchTo().frame("newFrame"); //switching frames

// move and drop
builder = new Actions(driver);
action = builder.moveToElement(driver.findElement(By.xpath(destination)));
builder.release(driver.findElement(By.xpath(destination)));
builder.build();
action.perform();

【讨论】:

【参考方案11】:

Selenium webdriver 提供拖放功能。试试这个

WebElement element = driver.findElement(By.name("source"));
WebElement target = driver.findElement(By.name("target"));

(new Actions(driver)).dragAndDrop(element, target).perform(); 

【讨论】:

以上是关于当目标元素和目标元素在不同的帧中时,如何使用 selenium-webdriver 执行拖放?的主要内容,如果未能解决你的问题,请参考以下文章

仅在不在视图中时滚动到元素 - jQuery

仅当元素悬停在 AngularJS 中时,如何分配变量?

仅在 xcode 中启动 iPhone 目标,而不是 OSwatch 目标,当两者都存在于项目中时

两个元素上的 CSS 背景混合模式

当 UICollectionView 位于 iOS 中的自定义 TableViewCell 中时,如何为 UICollectionView 实现委托和数据源方法,目标 C

js如何给目标元素的兄弟元素更改样式