技術メモ

日々学んだことのメモを残します。

Cypressで特定の要素にドラッグ&ドロップする方法

はじめに

Cyressである要素を別の要素領域内にドラッグ&ドロップする操作を行いたいと思い、そのやり方を調べました。

今回のサンプルアプリ

今回は下記のサイトを元に、Cypressで動かすVueアプリを実装しました。

下図は実装後の画面です。

ドラッグ&ドロップのサンプルアプリ

各Category内の「ProductA」「ProductB」などがドラッグの対象となっており、ドラッグした要素を別のCategory領域にドロップすると、移動させることができます。
今回はCategoryA内の「ProductA」をCategoryBにドラッグ&ドロップで移動させる操作を、Cypressで行うようにします。

ProductAをCategoryBに移動

実装方法

結論から先に書くと、以下のコードで実現することができます。ProductA、CategoryBのdiv要素にそれぞれdata-cy属性を追加し名称を設定しています。

describe('ドラッグ&ドロップ操作の検証', () => {
  beforeEach(() => {
    cy.visit('http://localhost:XXXX/')
  })
  it("ProductAをCategoryAからCategoryBに移動させる", () => {
    const dataTransfer = new DataTransfer();
    
    // ProductAをドラッグ
    cy.get("[data-cy='ProductA']")
      .trigger("dragstart", { dataTransfer });

    // CategoryBにドロップ。
    cy.get("[data-cy='Category_B']")
      .trigger("drop", { dataTransfer });
  });
});

引っかかったところ

最初に"dataTransfer"をtriggerのオプションに指定せず、実行していました。

// ProductAをドラッグ
cy.get("[data-cy='ProductA']")
    .trigger("dragstart");

するとCypress上で下図のエラーで落ちました。

Cypressのエラー画面

"effectAllowed"を設定するように指示されています。effetctedAllowはDataTransferのプロパティです。

Cypress内部でDataTransferオブジェクトを使用するようなのでdragstart、dropの各イベントのtriggerのオプションにDataTransferオブジェクトを渡すように設定すると、エラーが起きずドラッグ&ドロップの操作が通りました。

余談

Cypressのドキュメントのrecipesドラッグ&ドロップのE2Eテストのサンプルが記載されています。

このサンプルでは、mousemoveイベントでx,yの移動距離をセットしてドラッグ&ドロップを行う仕様でした。

function movePiece (number, x, y) {
      cy.get(`.piece-${number}`)
      .trigger('mousedown', { which: 1 })
      .trigger('mousemove', { clientX: x, clientY: y })
      .trigger('mouseup', { force: true })
    }

今回の用途は特定の要素領域にドロップしたかったので参考にはしなかったですが、スライダー形式のUIであればこれを使えば良さそうです。

参考