使用Selenium执行元素拖拽操作失败的技术问询
I'm trying to drag the "Time" tile to the position of the "Approvals" tile on my page, but the drag-and-drop operation isn't working. Below is the code I'm using, along with the HTML structure of the source and target elements:
My Current Drag-and-Drop Code
String sSource = "//*[@id=\"PTNUI_LAND_REC14$1_row_0\"]"; String sTarget = "//*[@id=\"PTNUI_LAND_REC14$1_row_1\"]"; WebElement wSource = TestBase.wDriver.findElement(By.xpath(sSource)); WebElement wTarget = TestBase.wDriver.findElement(By.xpath(sTarget)); Actions aActions = new Actions(TestBase.wDriver); Action aDragAndDrop = aActions.clickAndHold(wSource).moveToElement(wTarget).release(wTarget).build(); aDragAndDrop.perform();
Page HTML Elements
Source Element (Approvals Tile Container)
<div class="ps_grid-row nuitile rsz_w1 rsz_h1" id="PTNUI_LAND_REC14$1_row_0" tx="1.0577777777777777" ty="1" gx=".1.0577777777777777." gy=".1."> <div class="ps_grid-cell"> <div id="win0divPTNUI_LAND_REC_GROUPLET$13" class="ps_box-group psc_layout nuilp " tabindex="0" draggable="true" aria-dropeffect="move" aria-grabbed="false" droppable="true"> <h2 class="ps_groupleth"><span class="ps-label" id="PTNUI_LAND_REC_GROUPLET_LBL$13">Approvals</span></h2>
Target Element (Time Tile Container)
<div class="ps_grid-row nuitile rsz_w1 rsz_h1" id="PTNUI_LAND_REC14$1_row_1" tx="2.057777777777778" ty="1" gx=".2.057777777777778." gy=".1."> <div class="ps_grid-cell"> <div id="win0divPTNUI_LAND_REC_GROUPLET$14" class="ps_box-group psc_layout nuilp " tabindex="0" draggable="true" aria-dropeffect="move" aria-grabbed="false" droppable="true"> <div id="win0groupletPTNUI_LAND_REC_GROUPLET$14" class="ps_box-grouplet"><img id="PT_PORTAL_CLEAR_DOT$14" class="ps_process" src="/cs/p91h25r2x/cache/PT_PORTAL_CLEAR_DOT_1.gif" alt=""></div> <h2 class="ps_groupleth"><span class="ps-label" id="PTNUI_LAND_REC_GROUPLET_LBL$14">Time</span></h2></div></div>
Potential Issues & Fixes
1. Reversed Source/Target Elements
Looking at your requirement, you need to drag the Time tile to the Approvals tile's position—but your current code has the source and target reversed:
- Your source points to the Approvals tile container (
PTNUI_LAND_REC14$1_row_0) - Your target points to the Time tile container (
PTNUI_LAND_REC14$1_row_1)
Fix this by swapping the XPath values:
// Source: Time tile's container String sSource = "//*[@id=\"PTNUI_LAND_REC14$1_row_1\"]"; // Target: Approvals tile's container String sTarget = "//*[@id=\"PTNUI_LAND_REC14$1_row_0\"]";
2. Targeting the Wrong Draggable Element
The actual draggable component in your HTML is the inner div.ps_box-group element (marked with draggable="true"), not the outer ps_grid-row container. Targeting the parent row won't trigger the page's drag-and-drop logic. Adjust your XPath to point to the correct draggable nodes:
// Source: Time tile's draggable div String sSource = "//div[@id='win0divPTNUI_LAND_REC_GROUPLET$14']"; // Target: Approvals tile's draggable div String sTarget = "//div[@id='win0divPTNUI_LAND_REC_GROUPLET$13']";
3. Use Selenium's Built-in dragAndDrop() Method
The dragAndDrop() method is more reliable than manually chaining clickAndHold → moveToElement → release, as it's optimized for standard drag-and-drop interactions:
WebElement wSource = TestBase.wDriver.findElement(By.xpath(sSource)); WebElement wTarget = TestBase.wDriver.findElement(By.xpath(sTarget)); // Wait for elements to be interactive new WebDriverWait(TestBase.wDriver, Duration.ofSeconds(10)) .until(ExpectedConditions.elementToBeClickable(wSource)); new WebDriverWait(TestBase.wDriver, Duration.ofSeconds(10)) .until(ExpectedConditions.elementToBeClickable(wTarget)); Actions aActions = new Actions(TestBase.wDriver); aActions.dragAndDrop(wSource, wTarget).perform();
4. Simulate a More Human-like Drag Motion
If the above fixes don't work, try mimicking real user behavior by adding a pause and targeting the center of the target element:
Actions aActions = new Actions(TestBase.wDriver); aActions.clickAndHold(wSource) // Move to the center of the target element .moveToElement(wTarget, wTarget.getSize().width/2, wTarget.getSize().height/2) .pause(Duration.ofMillis(500)) // Pause to simulate a natural drag .release() .perform();
内容的提问来源于stack exchange,提问作者Pradeep Ganesh

