如何在puppeteer中模拟拖放动作?

问题描述 投票:0回答:5

我的应用程序中有 React-DnD(拖放)。我想测试一下 E2E。

我想要模拟的是拖动特定元素并放到特定位置。我该怎么做?

我拥有的是:

//test.js
const mouse = page.mouse;
await mouse.down();
await mouse.move(126, 19);
await page.waitFor(400);

使用此代码,选择已完成,但拖动不起作用。我应该如何实施?

reactjs testing e2e-testing puppeteer
5个回答
17
投票

以下方法将允许您在 Puppeteer 中模拟拖放操作:

const example = await page.$('#example');
const bounding_box = await example.boundingBox();

await page.mouse.move(bounding_box.x + bounding_box.width / 2, bounding_box.y + bounding_box.height / 2);
await page.mouse.down();
await page.mouse.move(126, 19);
await page.mouse.up();

9
投票

Puppeteer 特定的解决方案都不适合我,所以我最终将本机 javascript 写入一个文件并将其导入到 Puppeteer(在我的例子中是 Jest)。

拖放.js

async function dragAndDrop(source, target) {
  await page.evaluate((source, target) => {
    source = document.querySelector('#'+source);

    event = document.createEvent("CustomEvent");
    event.initCustomEvent("mousedown", true, true, null);
    event.clientX = source.getBoundingClientRect().top;
    event.clientY = source.getBoundingClientRect().left;
    source.dispatchEvent(event);

    event = document.createEvent("CustomEvent");
    event.initCustomEvent("dragstart", true, true, null);
    event.clientX = source.getBoundingClientRect().top;
    event.clientY = source.getBoundingClientRect().left;
    source.dispatchEvent(event);

    event = document.createEvent("CustomEvent");
    event.initCustomEvent("drag", true, true, null);
    event.clientX = source.getBoundingClientRect().top;
    event.clientY = source.getBoundingClientRect().left;
    source.dispatchEvent(event);


    target = document.querySelector('#'+target);

    event = document.createEvent("CustomEvent");
    event.initCustomEvent("dragover", true, true, null);
    event.clientX = target.getBoundingClientRect().top;
    event.clientY = target.getBoundingClientRect().left;
    target.dispatchEvent(event);

    event = document.createEvent("CustomEvent");
    event.initCustomEvent("drop", true, true, null);
    event.clientX = target.getBoundingClientRect().top;
    event.clientY = target.getBoundingClientRect().left;
    target.dispatchEvent(event);

    event = document.createEvent("CustomEvent");
    event.initCustomEvent("dragend", true, true, null);
    event.clientX = target.getBoundingClientRect().top;
    event.clientY = target.getBoundingClientRect().left;
    target.dispatchEvent(event);
  }, source, target);
}

测试.js

const dragAndDrop = require('./drag-and-drop')

describe('when dragging and dropping todo', () => {

  it('should change order on DOM', async () => {
    const firstTodo = await page.evaluate(() => document.querySelectorAll('.input-container .input')[0].id);
    const secondTodo = await page.evaluate(() => document.querySelectorAll('.input-container .input')[1].id);

    dragAndDrop(firstTodo, secondTodo);

    const newFirstTodo = await page.evaluate(() => document.querySelectorAll('.input-container .input')[0].id);
    const newSecondTodo = await page.evaluate(() => document.querySelectorAll('.input-container .input')[1].id);

    expect(newFirstTodo).toEqual(secondTodo)
    expect(newSecondTodo).toEqual(firstTodo)
  });
});

比内置的 Puppeteer 功能稍微多一些,但希望对于需要更多控制拖放的其他人来说,这是一个足够简单的复制和粘贴解决方案。


5
投票

这是我在 puppeteer 中用于拖放的片段:

// This assumes only one element will be found for selectors you 
// provide, otherwise there's ambiguity on which element was selected.
// In my code I'm throwing on more than 1 element found

async function dragAndDrop(page, originSelector, destinationSelector) {
  const origin = await page.waitForSelector(originSelector)
  const destination = await page.waitForSelector(destinationSelector)
  const ob = await origin.boundingBox()
  const db = await destination.boundingBox()
    
  console.log(`Dragging from ${ob.x + ob.width / 2}, ${ob.y + ob.height / 2}`)
  await page.mouse.move(ob.x + ob.width / 2, ob.y + ob.height / 2)
  await page.mouse.down()
  console.log(`Dropping at   ${db.x + db.width / 2}, ${db.y + db.height / 2}`)
  await page.mouse.move(db.x + db.width / 2, db.y + db.height / 2)
  await page.mouse.up()
}

请注意,puppeteer 中对拖放的支持仍未完全实现。


3
投票

如果这些示例不适合您,则可能是另一个时间问题。我玩了一段时间,直到这对我有用。 请注意鼠标命令之间的 50 毫秒等待时间和增加的步骤数,这会生成更多移动/拖动事件,并且似乎会产生影响。

// drag node
let elm = await (await page.waitForSelector("#mynode", { visible: true }));
let bounding_box = await elm.boundingBox();
let x = bounding_box.x + bounding_box.width / 2;
let y = bounding_box.y + bounding_box.height / 2;
await page.mouse.move(x, y);
await page.mouse.down();
await page.waitForTimeout(50);
await page.mouse.move(x + 100, y, { steps: 10 });
await page.waitForTimeout(50);
await page.mouse.up();
await page.waitForTimeout(50);

await page.screenshot({ path: 'after-drag.png' });

0
投票

接下来的形式:

    let elm = await (await page.waitForSelector('.YourInitialSelectorForDrag', { visible: true }));
    let bounding_box = await elm.boundingBox() ;

    let elm2 = await (await page.waitForSelector('.YourFinalySelectorForDrop', { visible: true }));
    let bounding_box2 = await elm2.boundingBox() ;

    let x = bounding_box.x + bounding_box.width / 2;
    let y = bounding_box2.y + bounding_box.height / 2;


    await page.mouse.move(x, y);
    await page.mouse.down();
    await delay(200);
    await page.mouse.move(x + 150, y, { steps: 10 });
    await page.mouse.up();
    await delay(200);
© www.soinside.com 2019 - 2024. All rights reserved.