LoginSignup
0
0

Cypressを使って、1つの画面を開きながら、別の画面に指示を送る

Posted at

Cypressは基本1つのブラウザを操作するテストツールですが、今回2つのブラウザを操作したいシチュエーションになり、何か方法はないかと色々試してみたので、それの記事をまとめたいと思います。

結論から言うと

2つのブラウザを同時にテストすることはできないが、1つの画面を開きながら、別の画面のAPIを操作することはできる

どんなシチュエーション?

websocketのイメージ.png
画面Aの入力フィールドに文章入力後、「送信」ボタンを押すと、
画面Bにwebsocket通知がされるようになっている。
スクリーンショット 2024-04-13 0.34.22.png

この時のAのメッセージ送信APIが叩かれたら、正しくwebsocket通知がされるかをCypressでテストしたい。

つまずいたこと

Cypressは1つのブラウザ内で動作するので、テスト実行時に複数のタブをサポートできない。つまり、2つ以上の画面を開いてテストすることは不可能。

解決策

複数の画面を使って操作したい内容が、APIを叩く行為だった場合、cypress内で直接APIを叩けばいい。
公式にある通り、CypressにはHTTP リクエストを作成する機能があります。

cy.request('POST', 'http://localhost:8888/users/admin', { name: 'Jane' }).then(
  (response) => {
    // response.body is automatically serialized into JSON
    expect(response.body).to.have.property('name', 'Jane') // true
  }
)

引用元 Cypressのリクエスト作成について↓

これを使えば、Bの画面を開いた状態で、A画面で叩きたかったAPIを直接叩いて、Bの画面で通知を受け取ることが可能です。

実際にコードを見てみます

A画面のvue.js

<template>
    <a>送りたいメッセージ<a>
    <input v-model="message" data-cy="message">
    <button @click="sendMessage" data-cy="send">送信</button>
</template>

<script>
export default {
  
  data() {
    return {
      message: "",
    };
  },
  methods: {
    sendMessage() {
        let result = await axios.post(
            process.env.VUE_APP_SEND_MESSAGE_API,
            {message: this.message}
        )
    },
  },
}

見た目はこんな感じ
画面Aの例.png

B画面のvue.js

<template>
    <p>画面B</p>
    <p>受け取ったメッセージ<p>
    <p data-cy="message">{{message}}<p>
</template>

<script>
export default {
    data() {
        return {
            message: ""
        };
    },
    async created() {
        this.connection = new WebSocket(process.env.VUE_APP_WEBSOCKET);
        this.connection.onmessage = (event) => {
            console.log('受け取ったmessage', event);
            let parsed = JSON.parse(event.data);
            this.message = parsed.message;
        };
        this.connection.onopen = () => this.connection.send("B画面");
    }
}
</script>

見た目はこんな感じ

Cypressでテストを書いていく!

// 画面Bを開く
cy.visit('/b')
// websocketの接続情報が登録されるのを待つ...🔴下に補足あり
cy.wait(3*1000)

// A画面にあるメッセージ送信APIを直接叩いている
cy.request({
    method: 'POST',
    url: 'メーセージを送信するボタンについてたエンドポイント ⭐️下に補足あり',
    body:{
        message: "テストメッセージ"
    }
}).then((response) => {
    // A画面で送信されたメッセージが、表示されているかの確認
    cy.get([data-cy="message"]).should('have.text', "テストメッセージ");
});

shoudは、想定される表示になるのを(4秒まで)待って判定してくれるメソッドなので、通知が遅れても拾ってくれます。遅れすぎる場合は、

cy.get([data-cy="message"], { timeout: 3*1000 }).should('have.text', "テストメッセージ");

こんな感じにして、表示を待つ時間を伸ばしても良さそうです。

補足
🔴...このwaitがないと、どのブラウザが開かれて、通知を送る場合どのブラウザに送るのかの住所になるconnection_idを貼る時間がないため、websocket通知が飛ばないことがあったので注意。waitを入れたら解消されました。

⭐️...url: 'メーセージを送信するボタンについてたエンドポイント'は、
叩きたいAPIを実際に叩くと、開発者ツールのネットワークでも確認できます。
スクリーンショット 2024-04-13 0.08.47.png

CypressでWebsocketのテストを行うことについて

Cypressのcy.request()コマンドは REST エンドポイントのみに限定されているため、websocketのテストをすることは既存のものでは難しいようです。

また「cypress websocket」で調べると、日本語の記事が全然出てきません。(2024年4月時点)
海外の方が作ってくれたwebsocketのテストツールがgitHubで公開されていますが、自分には正直難しかった…。そのため、できる限り、簡単に、直感的にwebsocketを叩けないかということで、こういった方法をとりました。しかし、これはWebsocket通知のトリガーがRESTエンドポイントであることが必須条件であることに加え、本来のWebsocketのテストツールを使った方法ではないので、邪道だと思います。

CypressのWebsocket通知テストについては、まだまだ情報が少ないので、わかったら共有していきたいです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0