Cypress で XHR エラーになってしまう場合の対象方法

こんにちは、WESEEK でエンジニアをしている宮沢です。普段はオープンソースな wiki である GROWI を開発しています。今回はそんな GROWI のビジュアルリグレッションテストで利用している Cypress で発生した XHR エラーの対処方法について解説していきます。

エラー内容

今回紹介するエラー内容は以下の赤丸で囲った部分となっています。スクリーンショットは実際の GROWI のログイン画面です。

実際にエラーが発生した Cypress のコードは以下のようになっています。具体的は、/login に遷移して、あらかじめ登録されているユーザーネームとパスワードを入力、 ログインボタンを押してログインをするという Cypress のカスタムコマンドです。 使う場合は cy.login(username, password) このような感じで書きます。

Cypress.Commands.add('login', (username, password) => {
  cy.session(username, () => {
    cy.visit('/login');
    cy.get('.usernameForLogin').type(username);
    cy.get('.passwordForLogin').type(password);
    cy.get('.btnSubmitForLogin').click();
  });
});

エラー原因

ログインボタンを押下した際に走る /api/v3/login のレスポンスを待たずにログインが必要なページに遷移しようとすることで、ブラウザにユーザーのセッションデータが正常に保存されなかったことが原因と見ています。

試しに、ログインボタンの押下(cy.get('.btnSubmitForLogin').click()) の後に、cy.wait(10000) を入れたところ XHR エラーが出ず正常にログイン処理を行うことができました。

以上のことから /api/v3/login のレスポンスを待てば良さそうということが分かったので、そのようなコードに直していきます。

対処方法

Cypress には intercept という API があります。これはアプリケーション内で走る HTTP リクエストに対してスパイやスタブをができる API になっています。

今回はスパイのみでいいのでドキュメントを参考にすると以下のようなコードになります。第一引数にメソッド名、第二引数に URL が入ります。as を使うとエイリアスを作ることができます。作成したエイリアスを cy.waitに入れると /api/v3/login の完了を待つことができます。

cy.intercept('POST', '/api/v3/login').as('login');
// Do something
cy.wait('@login');

以上のコードをエラーが発生していたカスタムコマンドに入れた結果正常に動作しました。

Cypress.Commands.add('login', (username, password) => {
  cy.session(username, () => {
    cy.visit('/login');
    cy.get('.usernameForLogin').type(username);
    cy.get('.passwordForLogin').type(password);

    cy.intercept('POST', '/_api/v3/login').as('login');
    cy.get('.btnSubmitForLogin').click();
    cy.wait('@login')
  });
});