web-dev-qa-db-ja.com

パペットでドラッグアンドドロップアクションをシミュレートするにはどうすればよいですか?

アプリケーションにReact-DnD(ドラッグアンドドロップ)があります。 E2Eでテストしてください。

シミュレーションしたいのは、特定の要素をドラッグして特定の場所にドロップすることです。どうすればよいですか?

私が持っているのは:

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

このコードを使用すると、選択は行われますが、ドラッグは機能しません。これをどのように実装すればよいですか?

8
Khushi

次のメソッドを使用すると、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();
8
Grant Miller

以下は、操り人形師のドラッグアンドドロップに使用しているスニペットです。

//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 dragAndDrop(page, originSelector, destinationSelector) {
  await page.waitFor(originSelector)
  await page.waitFor(destinationSelector)
  const Origin = await page.$(originSelector)
  const destination = await page.$(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でのドラッグアンドドロップのサポートはまだ 完全ではない 実装されていることに注意してください。

0
Moshisho

Puppeteer固有のソリューションはどれも機能しなかったので、ネイティブjavascriptをファイルに書き込んでPuppeteer(私の場合はJest)にインポートしました。

drag-and-drop.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);
}

test.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関数よりもわずかに多くの作業が必要ですが、ドラッグアンドドロップをより詳細に制御する必要がある他の人にとっては、これがコピーアンドペーストのソリューションとして十分簡単であることを願っています。

0
pappy