如何在Playwright中通过拖拽重新排序Material React Table行
解决Material React Table行拖拽排序的Playwright测试问题
问题根源
Material React Table(MRT)的行排序依赖react-beautiful-dnd这类拖拽库,这类库要求必须拖拽专门的拖拽手柄元素,而非任意单元格/行;同时对拖拽动作的连续性、触发位置有严格要求,普通的dragTo或简单mouse事件组合无法满足库的内部触发条件。
修正方案
- 定位拖拽手柄:MRT为可排序行提供了默认的拖拽手柄(类名通常为
.mrt-draggable-handle),必须以此为拖拽起点 - 使用稳定选择器:避免依赖动态生成的CSS类(如
css-1xdn0p8),改用表格结构或MRT自带的类名定位 - 模拟真实拖拽流程:增加必要的延迟、步骤,匹配用户真实拖拽的动作节奏
修正后的测试代码
test('testing MUI Draggable table', async ({ page }) => { await page.goto('https://www.material-react-table.com/docs/guides/row-ordering-dnd'); // 滚动到表格区域(替代多次PageDown,更稳定) await page.locator('table').scrollIntoViewIfNeeded(); // 定位源行的拖拽手柄和目标行 const sourceHandle = page.locator('table') .getByRole('row', { name: "Kohler" }) .locator('.mrt-draggable-handle'); const targetRow = page.locator('table') .getByRole('row', { name: "McCullough" }); // 方法1:使用locator的dragTo方法,配置合适的参数 await sourceHandle.dragTo(targetRow, { force: true, // 强制触发拖拽,绕过部分拖拽库的校验 delay: 100, // 按下鼠标后延迟再开始移动,模拟用户停顿 steps: 10 // 分步骤移动,更贴近真实拖拽 }); // 方法2:手动模拟完整拖拽流程(备用方案) // const targetBox = await targetRow.boundingBox(); // await sourceHandle.hover(); // await page.mouse.down(); // // 等待拖拽激活状态(MRT会显示拖拽预览) // await page.waitForTimeout(300); // // 移动到目标行的中心位置 // await page.mouse.move( // targetBox.x + targetBox.width / 2, // targetBox.y + targetBox.height / 2, // { steps: 10 } // ); // // 停留片刻再松开,确保拖拽库完成位置更新 // await page.waitForTimeout(200); // await page.mouse.up(); // 验证排序是否生效(可选) const rowsAfterDrag = await page.locator('table').getByRole('row').allTextContents(); expect(rowsAfterDrag.some(row => row.includes('Kohler') && rowsAfterDrag.indexOf(row) > rowsAfterDrag.findIndex(r => r.includes('McCullough')))).toBeTruthy(); });
关键注意事项
- 必须拖拽手柄:直接拖拽行或单元格无法触发MRT的排序逻辑,拖拽库只会响应手柄元素的拖拽事件
- 避免动态CSS类:
css-xxx类名是MUI动态生成的,刷新页面后会变化,改用.mrt-draggable-handle这类固定类名或data-testid属性定位 - 增加延迟/步骤:拖拽库需要时间识别拖拽状态,过快的模拟动作会被忽略,通过
delay、steps或waitForTimeout调整节奏 - 确保元素可见:用
scrollIntoViewIfNeeded()替代多次PageDown,更可靠地让目标元素进入视口
内容的提问来源于stack exchange,提问作者LNixon
相关产品推荐
相关产品推荐

