You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Playwright中通过拖拽重新排序Material React Table行

解决Material React Table行拖拽排序的Playwright测试问题

问题根源

Material React Table(MRT)的行排序依赖react-beautiful-dnd这类拖拽库,这类库要求必须拖拽专门的拖拽手柄元素,而非任意单元格/行;同时对拖拽动作的连续性、触发位置有严格要求,普通的dragTo或简单mouse事件组合无法满足库的内部触发条件。

修正方案

  1. 定位拖拽手柄:MRT为可排序行提供了默认的拖拽手柄(类名通常为.mrt-draggable-handle),必须以此为拖拽起点
  2. 使用稳定选择器:避免依赖动态生成的CSS类(如css-1xdn0p8),改用表格结构或MRT自带的类名定位
  3. 模拟真实拖拽流程:增加必要的延迟、步骤,匹配用户真实拖拽的动作节奏

修正后的测试代码

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 00:56:28