Delegate StubConnection#pubsub and StubConnection#config to ActionCable.server

Previously, `ActionCable::Channel::ConnectionStub` would
throw a `NoMethodError` when the channel under test calls
`stop_stream_for`, as shown in the example below:

```ruby
class ChatChannel < ActionCable::Channel::Base
  def subscribed
    stream_from "test"
  end

  def unsubscribed
    stop_stream_from "test"
  end
end

class ChatChannelTest < ActionCable::Channel::TestCase
  test "unsubscribe" do
    stub_connection

    subscribe

    # `unsubscribe` raises `NoMethodError` as `pubsub` does not
      exist on `ActionCable::Channel::ConnectionStub`
    unsubscribe

    assert_no_streams
  end
end
```

Calling `unsubscribe` causes an exception as `stop_stream_from` calls
`pubsub` when unsubscribing, which is not implemented in
`ActionCable::Channel::ConnectionStub`.

This commit fixes this issue by assigning the `ActionCable.server`
singleton to a `@server` instance variable in
`ActionCable::Channel::ConnectionStub`. This lets us delegate
the `config` and `pubsub` method calls to it.
This commit is contained in:
julianfssen 2023-07-09 23:59:31 +08:00
parent d137eb54bb
commit 9c5175e067
3 changed files with 24 additions and 2 deletions

@ -1,3 +1,12 @@
* Add a `@server` instance variable referencing the `ActionCable.server`
singleton to `ActionCable::Channel::ConnectionStub`
This lets us delegate the `pubsub` and `config` method calls
to the server. This fixes `NoMethodError` errors when testing
channel logic that call `pubsub` (e.g. `stop_stream_for`).
*Julian Foo*
* Added `health_check_path` and `health_check_application` config to
mount a given health check rack app on a given path.
Useful when mounting Action Cable standalone.

@ -47,9 +47,12 @@ def start_periodic_timers; end
end
class ConnectionStub
attr_reader :transmissions, :identifiers, :subscriptions, :logger, :config
attr_reader :server, :transmissions, :identifiers, :subscriptions, :logger
delegate :pubsub, :config, to: :server
def initialize(identifiers = {})
@server = ActionCable.server
@transmissions = []
identifiers.each do |identifier, val|
@ -59,7 +62,6 @@ def initialize(identifiers = {})
@subscriptions = ActionCable::Connection::Subscriptions.new(self)
@identifiers = identifiers.keys
@logger = ActiveSupport::TaggedLogging.new ActiveSupport::Logger.new(StringIO.new)
@config = ActionCable::Server::Configuration.new
end
def transmit(cable_message)

@ -88,6 +88,10 @@ class StreamsTestChannel < ActionCable::Channel::Base
def subscribed
stream_from "test_#{params[:id] || 0}"
end
def unsubscribed
stop_stream_from "test_#{params[:id] || 0}"
end
end
class StreamsTestChannelTest < ActionCable::Channel::TestCase
@ -102,6 +106,13 @@ def test_stream_with_params
assert_has_stream "test_42"
end
def test_unsubscribe_from_stream
subscribe
unsubscribe
assert_no_streams
end
end
class StreamsForTestChannel < ActionCable::Channel::Base