- ページを開く
- ActionCableのブロードキャストを実行する
- ブロードキャストの結果画面が変更されるのを確認する
というテストがあるときに、2がActionCableの該当チャンネルのsubscribeより前に実行されてしまいテストが失敗する、という事象があった。
なのでsubscribeを待つためのヘルパーメソッドを書いてみた。asyncアダプタ想定で、subscriber情報を持っているハッシュの個数が0より大きくなればsubscribe完了しているだろう、と判断した。
def wait_for_websocket_connection Timeout.timeout(Capybara.default_max_wait_time) do until ActionCable.server.pubsub.send(:subscriber_map).instance_variable_get(:@subscribers).count > 0 sleep 0.5 end end end
だいぶナイーブな実装なのでうまく動かないケースもありそうだけど、とりあえずこれで。
2024/02/06追記
ActionCableへの購読は、まず内部用のチャンネル(ActionCable::Connection::InternalChannel) を購読してから専用のチャンネルを購読する、という流れになるので、上記のコードだとタイミングによってはまだチャンネルの購読が完了していない事がある。そこを次のようなコードで改善してみた。しばらくこれで様子見
# `stream_for current_user ` のようにして購読している前提 def wait_for_websocket_connection(user) channel = NotificationChannel.broadcasting_for(user) block = lambda do s = ActionCable.server.pubsub.send(:subscriber_map).instance_variable_get(:@subscribers) s.key?(channel) && s[channel].count > 0 end Timeout.timeout(Capybara.default_max_wait_time) do sleep 0.5 until block.call end end