您如何使用 Capybara 测试 ActionCable?

How do you test ActionCable with Capybara?

我试过这个解决方案 https://gist.github.com/alexeyrazuvaev/98448c9935352fac5ee96e139bc3bd72 但它不适用于我的测试。尝试在浏览器中重现它,它按预期工作。我无法弄清楚我的测试有什么问题。

这是例子:

scenario 'they see their name and message in the chat box', js: true do
  find('textarea#message_content').send_keys(:enter)
  is_expected.to have_selector('p', text: /^#{current_user.name}|foobar$/)
end

其他信息:

cable.yml

redis: &default
  adapter: redis
  url: redis://localhost:6379/1

production: *default
development: *default
test: *default

spec/support/capybara.rb

Capybara.javascript_driver = :webkit
Capybara.server = :puma

Capybara::Webkit.configure do |config|
  config.allow_url("https://code.jquery.com/jquery-3.3.1.min.js")
end

test.log

# ...
Started GET "/cable" for 127.0.0.1 at 2018-01-30 11:21:16 +0800
Started GET "/cable/" [WebSocket] for 127.0.0.1 at 2018-01-30 11:21:16 +0800
Successfully upgraded to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: Upgrade, HTTP_UPGRADE: websocket)
  User Load (0.7ms)  SELECT  "users".* FROM "users" WHERE "users"."id" =  ORDER BY "users"."id" ASC LIMIT   [["id", 1], ["LIMIT", 1]]
Registered connection (Z2lkOi8vY2hhdHRlci9Vc2VyLzE)
ConversationChannel is transmitting the subscription confirmation
ConversationChannel is streaming from conversation_channel_1
Finished "/cable/" [WebSocket] for 127.0.0.1 at 2018-01-30 11:21:18 +0800
ConversationChannel stopped streaming from conversation_channel_1
# ...

向浏览器测试时的服务器日志

# ...
Started GET "/cable" for 127.0.0.1 at 2018-01-29 09:02:02 +0800
Started GET "/cable/" [WebSocket] for 127.0.0.1 at 2018-01-29 09:02:02 +0800
Successfully upgraded to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: Upgrade, HTTP_UPGRADE: websocket)
  User Load (1.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" =  ORDER BY "users"."id" ASC LIMIT   [["id", 1], ["LIMIT", 1]]
Registered connection (Z2lkOi8vY2hhdHRlci9Vc2VyLzE)
ConversationChannel is transmitting the subscription confirmation
ConversationChannel is streaming from conversation_channel_11
ConversationChannel#send_message({"content"=>"foobar\n", "conversation_id"=>"11"})
   (0.2ms)  BEGIN
  Conversation Load (0.3ms)  SELECT  "conversations".* FROM "conversations" WHERE "conversations"."id" =  LIMIT   [["id", 11], ["LIMIT", 1]]
   (0.6ms)  SELECT "users"."id" FROM "users" INNER JOIN "user_conversations" ON "users"."id" = "user_conversations"."user_id" WHERE "user_conversations"."conversation_id" =   [["conversation_id", 11]]
  SQL (12.5ms)  INSERT INTO "messages" ("content", "user_id", "conversation_id", "created_at", "updated_at") VALUES (, , , , ) RETURNING "id"  [["content", "foobar\n"], ["user_id", 1], ["conversation_id", 11], ["created_at", "2018-01-29 01:02:18.272060"], ["updated_at", "2018-01-29 01:02:18.272060"]]
   (12.4ms)  COMMIT
  Rendered messages/_message.html.erb (0.8ms)
[ActionCable] Broadcasting to conversation_channel_11: {:message=>"<p>John Doe: foobar\n</p>\n"}
ConversationChannel transmitting {"message"=>"<p>John Doe: foobar\n</p>\n"} (via streamed from conversation_channel_11)

因为这适用于 selenium 驱动程序而不是 capybara-webkit,所以有两种可能性之一。

  1. capybara-webkit 不能与 websockets 一起正常工作。如果你用 Qt 4.x 编译它,这将是真的正在连接。

  2. 您在页面的 JS 中使用了 ES6+ 功能。 capybara-webkit 使用的 QtWebkit 非常过时,基本上相当于 6-7 年前的 Safari 版本,这意味着它不支持 ES6+。因此,如果你在你的代码中使用了任何 ES6+ methods/features 而没有 polyfilling and/or transpiling capybara-webkit 将不会 运行 JS。由于 actioncable 确实在日志中显示连接,因此它至少 运行ning 了你的一些 JS,因此启用 'raise_javascript_errors- https://github.com/thoughtbot/capybara-webkit#configuration - in yourcapybara-webkit` 配置可能会显示一个关于您在不支持按键处理程序中使用的某些方法的错误。