频道规格

频道规格通过`type: :channel` 标记,或者如果您已通过将它们放置在`spec/channels` 中来设置`config.infer_spec_type_from_file_location!`。

频道规格是`ActionCable::Channel::TestCase` 的一个薄包装器,除了 RSpec 自己的行为和期望之外,还包括它提供的所有行为和断言。

它还包含来自`ActionCable::Connection::TestCase` 的助手,使其能够测试连接行为。

背景

给定 Action Cable 测试可用

并且一个名为“app/channels/chat_channel.rb” 的文件,其中包含

class ChatChannel < ApplicationCable::Channel
  def subscribed
    reject unless params[:room_id].present?
  end

  def speak(data)
    ActionCable.server.broadcast(
      "chat_#{params[:room_id]}", text: data['message']
    )
  end

  def echo(data)
    data.delete("action")
    transmit data
  end
end

一个简单的通过示例

给定一个名为“spec/channels/chatchannelspec.rb” 的文件,其中包含

require "rails_helper"

RSpec.describe ChatChannel, type: :channel do
  it "successfully subscribes" do
    subscribe room_id: 42
    expect(subscription).to be_confirmed
  end
end

我运行`rspec spec/channels/chat_channel_spec.rb` 时

然后该示例应该通过。

验证订阅被拒绝

给定一个名为“spec/channels/chatchannelspec.rb” 的文件,其中包含

require "rails_helper"

RSpec.describe ChatChannel, type: :channel do
  it "rejects subscription" do
    subscribe room_id: nil
    expect(subscription).to be_rejected
  end
end

我运行`rspec spec/channels/chat_channel_spec.rb` 时

然后该示例应该通过。

执行操作并检查传输

给定一个名为“spec/channels/chatchannelspec.rb” 的文件,其中包含

require "rails_helper"

RSpec.describe ChatChannel, type: :channel do
  it "successfully subscribes" do
    subscribe room_id: 42

    perform :echo, foo: 'bar'
    expect(transmissions.last).to eq('foo' => 'bar')
  end
end

我运行`rspec spec/channels/chat_channel_spec.rb` 时

然后该示例应该通过。

带有 url 参数的成功连接

给定一个名为“app/channels/application_cable/connection.rb” 的文件,其中包含

class ApplicationCable::Connection < ActionCable::Connection::Base
  identified_by :user_id

  def connect
    self.user_id = request.params[:user_id]
    reject_unauthorized_connection unless user_id.present?
  end
end

并且一个名为“spec/channels/connection_spec.rb” 的文件,其中包含

require "rails_helper"

RSpec.describe ApplicationCable::Connection, type: :channel do
  it "successfully connects" do
    connect "/cable?user_id=323"
    expect(connection.user_id).to eq "323"
  end
end

我运行`rspec spec/channels/connection_spec.rb` 时

然后该示例应该通过。

带有 cookie 的成功连接

给定一个名为“app/channels/application_cable/connection.rb” 的文件,其中包含

class ApplicationCable::Connection < ActionCable::Connection::Base
  identified_by :user_id

  def connect
    self.user_id = cookies.signed[:user_id]
    reject_unauthorized_connection unless user_id.present?
  end
end

并且一个名为“spec/channels/connection_spec.rb” 的文件,其中包含

require "rails_helper"

RSpec.describe ApplicationCable::Connection, type: :channel do
  it "successfully connects" do
    cookies.signed[:user_id] = "324"

    connect "/cable"
    expect(connection.user_id).to eq "324"
  end
end

我运行`rspec spec/channels/connection_spec.rb` 时

然后该示例应该通过。

带有标头的成功连接

给定一个名为“app/channels/application_cable/connection.rb” 的文件,其中包含

class ApplicationCable::Connection < ActionCable::Connection::Base
  identified_by :user_id

  def connect
    self.user_id = request.headers["x-user-id"]
    reject_unauthorized_connection unless user_id.present?
  end
end

并且一个名为“spec/channels/connection_spec.rb” 的文件,其中包含

require "rails_helper"

RSpec.describe ApplicationCable::Connection, type: :channel do
  it "successfully connects" do
    connect "/cable", headers: { "X-USER-ID" => "325" }
    expect(connection.user_id).to eq "325"
  end
end

我运行`rspec spec/channels/connection_spec.rb` 时

然后该示例应该通过。

被拒绝的连接

给定一个名为“app/channels/application_cable/connection.rb” 的文件,其中包含

class ApplicationCable::Connection < ActionCable::Connection::Base
  identified_by :user_id

  def connect
    self.user_id = request.params[:user_id]
    reject_unauthorized_connection unless user_id.present?
  end
end

并且一个名为“spec/channels/connection_spec.rb” 的文件,其中包含

require "rails_helper"

RSpec.describe ApplicationCable::Connection, type: :channel do
  it "rejects connection" do
    expect { connect "/cable?user_id=" }.to have_rejected_connection
  end
end

我运行`rspec spec/channels/connection_spec.rb` 时

然后该示例应该通过。

断开连接

给定一个名为“app/channels/application_cable/connection.rb” 的文件,其中包含

class ApplicationCable::Connection < ActionCable::Connection::Base
  identified_by :user_id

  def connect
    self.user_id = request.params[:user_id]
    reject_unauthorized_connection unless user_id.present?
  end

  def disconnect
    $stdout.puts "User #{user_id} disconnected"
  end
end

并且一个名为“spec/channels/connection_spec.rb” 的文件,其中包含

require "rails_helper"

RSpec.describe ApplicationCable::Connection, type: :channel do
  it "disconnects" do
    connect "/cable?user_id=42"
    expect { disconnect }.to output(/User 42 disconnected/).to_stdout
  end
end

我运行`rspec spec/channels/connection_spec.rb` 时

然后该示例应该通过。