Playwrightでドラッグ&ドロップをテストする方法

Playwrightでドラッグする方法

PlaywrightでテストをするときにWebサイトによってはドラッグ&ドロップ(要素を長押しして移動する操作)が必要になることがあります。

例えば下図のようなUIで1番目の要素を右の2番目または下の6番目と入れ替えるなどです。

https://shadcn-drag-and-drop.vercel.app

この記事では、Playwrightを使ってドラッグやドラッグ&ドロップをテストする方法を解説します。

page.dragAndDrop() を使う方法

Playwrightには、シンプルにドラッグ&ドロップ操作を実現できる page.dragAndDrop() メソッドがあります。

example.spec.js
import { test, expect } from '@playwright/test'

test('drag and drop test', async ({ page }) => {
  await page.goto('https://www.w3schools.com/html/html5_draganddrop.asp')
  await page.dragAndDrop('#img1', '#div2')

  const item = page.locator('#div2 #img1')
  const count = await item.count()
  expect(count).toBe(1)

  await page.screenshot({ path: 'drag-and-drop.png' })
})

page.dragAndDrop() sample

以下のように第3引数に要素のドラッグ&ドロップする位置(x, y)を指定することもできます。

example.spec.js
await page.dragAndDrop('#source', '#target', {
  sourcePosition: { x: 34, y: 7 },
  targetPosition: { x: 10, y: 20 },
})

mouseのAPIを使ってカスタムドラッグ操作を再現する

より細かい操作やカスタム実装されたドラッグ&ドロップに対応するには、page.mouseを使います。

以下のようにboundingBox()を使用すれば要素のx, y, width, heightの値を取得できるので、これを元に要素の中心の位置を計算して、mouse.move() → mouse.down() → mouse.move() → mouse.up() でドラッグ&ドロップを実装しています。

example.spec.js
import { test } from '@playwright/test'

test('1. Short Pill を 2. Medium Length Pill の位置にドラッグ', async ({ page }) => {
  await page.goto('https://shadcn-drag-and-drop.vercel.app/')

  const shortPill = await page.getByText('1. Short Pill').nth(0)
  const mediumPill = await page.getByText('2. Medium Length Pill').nth(0)

  const shortBox = await shortPill.boundingBox()
  const mediumBox = await mediumPill.boundingBox()

  if (!shortBox || !mediumBox) throw new Error('要素の位置が取得できません')

  // ドラッグ操作
  await page.mouse.move(shortBox.x + shortBox.width / 2, shortBox.y + shortBox.height / 2)
  await page.mouse.down()
  await page.mouse.move(mediumBox.x + mediumBox.width / 2, mediumBox.y + mediumBox.height / 2, { steps: 10 })
  await page.mouse.up()

  // スクリーンショット保存
  await page.screenshot({ path: 'after-drag.png', fullPage: true })
})

page.mouse.move() sample

mouse APIを使用したため長いコードになっていますが、page.dragAndDrop()を使用した場合はセレクタで直接指定できるので短く書けます。

example.spec.js
import { test } from '@playwright/test'

test('dragAndDrop Sample', async ({ page }) => {
  await page.goto('https://shadcn-drag-and-drop.vercel.app/')

  // セレクタで直接指定してドラッグ&ドロップ
  await page.dragAndDrop('text=1. Short Pill', 'text=2. Medium Length Pill')

  // スクリーンショット保存
  await page.screenshot({ path: 'dragAndDropSample.png', fullPage: true })
})

まとめ

Playwrightでは、page.dragAndDrop() または mouse API でドラッグ&ドロップのテストができます。

通常はpage.dragAndDrop() を使用して、より細かい操作の場合はmouse APIを使用すると良いでしょう。