Cypress テストの保守性を向上させる:spread コマンドでテストをわかりやすく


spread コマンドは、Cypress テストにおいて、配列を個々の要素に展開するために使用されます。これは、.then() コマンドと似ていますが、常に配列のような構造の subject を想定しています。

構文

cy.get('[data-testid="my-elements"]').spread((element1, element2, ...) => {
  // 個々の要素に対して操作を実行
});

使い方

spread コマンドは、配列を返す Cypress コマンドの後にチェーンすることができます。例えば、以下のコードは、data-testid="my-elements" 属性を持つすべての要素を取得し、それぞれの要素に対して textContent プロパティを取得します。

cy.get('[data-testid="my-elements"]').spread((element1, element2, ...) => {
  cy.wrap(element1).should('have.text', '要素 1 のテキスト');
  cy.wrap(element2).should('have.text', '要素 2 のテキスト');
  // ...
});

利点

spread コマンドを使用する利点は次のとおりです。

  • テストの保守性を向上させることができます。
  • 繰り返し処理をより簡潔に記述することができます。
  • コードをより読みやすく、理解しやすくすることができます。

注意点

spread コマンドを使用する際には、以下の点に注意する必要があります。

  • 戻り値が DOM 要素の場合は、.spread() の後に .then() などのコマンドをチェーンすることはできません。
  • 戻り値が null または undefined の場合、subject は変更されません。
  • subject が常に配列のような構造であることを確認する必要があります。

以下の例は、spread コマンドを使用して、いくつかのクッキーを取得し、それぞれのクッキーの名前と値をログに出力する方法を示しています。

cy.getCookies().spread((cookie1, cookie2, ...) => {
  console.log(`Cookie name: ${cookie1.name}`);
  console.log(`Cookie value: ${cookie1.value}`);
  // ...
});


配列を個々の要素に展開する

この例では、data-testid="my-elements" 属性を持つすべての要素を取得し、それぞれの要素に対して textContent プロパティを取得します。

cy.get('[data-testid="my-elements"]').spread((element1, element2, ...) => {
  cy.wrap(element1).should('have.text', '要素 1 のテキスト');
  cy.wrap(element2).should('have.text', '要素 2 のテキスト');
  // ...
});

オブジェクトの配列をループする

この例では、users という名前の変数に格納されたオブジェクトの配列をループし、それぞれのオブジェクトの nameemail プロパティをログに出力します。

const users = [
  { name: 'John Doe', email: '[email protected]' },
  { name: 'Jane Doe', email: '[email protected]' },
  // ...
];

cy.wrap(users).spread((user1, user2, ...) => {
  console.log(`User name: ${user1.name}`);
  console.log(`User email: ${user1.email}`);
  // ...
});

API レスポンスからデータを抽出する

この例では、API エンドポイントから JSON データを取得し、そのデータを使用して複数の DOM 要素を更新します。

cy.request('https://jsonplaceholder.typicode.com/todos/1')
  .spread((response, status) => {
    expect(status).to.equal(200);
    const todo = response.body;

    cy.get('[data-testid="todo-title"]').type(todo.title);
    cy.get('[data-testid="todo-description"]').type(todo.completed);
  });

カスタムコマンドを作成する

この例では、spread コマンドを使用して、要素のリストをカンマ区切りの文字列に変換するカスタムコマンドを作成します。

Cypress.Commands.add('stringifyElements', (elements) => {
  return cy.wrap(elements).spread((element1, element2, ...) => {
    return `${element1.textContent}, ${element2.textContent}, ...`;
  });
});

cy.get('[data-testid="my-elements"]').stringifyElements().should('equal', '要素 1 のテキスト, 要素 2 のテキスト, ...');

テストのセットアップとティアダウンに使用する

この例では、spread コマンドを使用して、テストのセットアップとティアダウンに必要なデータを複数の変数に格納します。

beforeEach(() => {
  cy.fixture('data.json').spread((user, todos) => {
    cy.wrap(user).as('currentUser');
    cy.wrap(todos).as('todos');
  });
});

afterEach(() => {
  // ...
});


forEach メソッドを使用する

forEach メソッドは、配列の各要素に対して関数を呼び出すための JavaScript の標準メソッドです。以下は、forEach メソッドを使用して spread コマンドと同じことを行う方法の例です。

cy.get('[data-testid="my-elements"]').forEach((element) => {
  cy.wrap(element).should('have.text', element.textContent);
});

each コマンドを使用する

each コマンドは、Cypress のカスタムコマンドであり、配列の各要素に対して一連の Cypress コマンドを実行するために使用できます。以下は、each コマンドを使用して spread コマンドと同じことを行う方法の例です。

cy.get('[data-testid="my-elements"]').each((element) => {
  cy.wrap(element).should('have.text', element.textContent);
});

for ループを使用する

for ループは、配列の各要素を反復処理するためのもう 1 つの方法です。以下は、for ループを使用して spread コマンドと同じことを行う方法の例です。

const elements = cy.get('[data-testid="my-elements"]');

for (let i = 0; i < elements.length; i++) {
  cy.wrap(elements[i]).should('have.text', elements[i].textContent);
}

.then() コマンドを使用する

.then() コマンドは、Promise を解決するために使用できます。以下は、.then() コマンドを使用して spread コマンドと同じことを行う方法の例です。

cy.get('[data-testid="my-elements"]').then((elements) => {
  elements.forEach((element) => {
    cy.wrap(element).should('have.text', element.textContent);
  });
});

どの方法を選択するべきか

どの方法を選択するかは、状況によって異なります。一般的には、以下の点が考慮されます。

  • 柔軟性
    for ループや .then() コマンドは、spread コマンドよりも柔軟性が高い場合がある。
  • 読みやすさ
    forEach メソッドや each コマンドは、spread コマンドよりも読みやすい場合がある。
  • 簡潔さ
    spread コマンドは、他の方法と比べて簡潔なことが多いです。