Skip to content

Commit

Permalink
Enhance minitest matcher to support records as arguments (palkan#16)
Browse files Browse the repository at this point in the history
  • Loading branch information
TheSmartnik authored and palkan committed Dec 19, 2017
1 parent 0aaab70 commit c362340
Show file tree
Hide file tree
Showing 7 changed files with 172 additions and 18 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Change log

## (2017-12-19) ([@thesmartnik][])

- Update minitest's `assert_broadcast_on` and `assert_broadcasts` matchers to support a record as an argument.

See https://github.com/palkan/action-cable-testing/issues/11

## (2017-11-27) ([@thesmartnik][])

- Update `have_broadcasted_to` matcher to support a record as an argument.
Expand Down
36 changes: 35 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,16 @@ class ExampleTest < ActionDispatch::IntegrationTest

def test_broadcasts
room = rooms(:office)

assert_broadcast_on("messages:#{room.id}", text: 'Hello!') do
post "/say/#{room.id}", xhr: true, params: { message: 'Hello!' }
end

# When testing broadcast to an object outside of channel test,
# channel should be explicitly specified
assert_broadcast_on(room, { text: 'Hello!' }, { channel: ChatChannel } do
post "/say/#{room.id}", xhr: true, params: { message: 'Hello!' }
end
end
end
```
Expand Down Expand Up @@ -121,6 +127,34 @@ class ChatChannelTest < ActionCable::Channel::TestCase
end
end
```
When broadcasting to an object:

```ruby
class ChatChannelTest < ActionCable::Channel::TestCase
include ActionCable::TestHelper

def setup
@room = Room.find 1

stub_connection(user: users[:john])
subscribe room_number: room.id
end

def test_broadcating
assert_broadcasts(@room, 1) do
perform :speak, message: "I'm here!"
end
end

# or

def test_broadcasted_data
assert_broadcasts_on(@room, text: "I'm here!", from: "John") do
perform :speak, message: "I'm here!"
end
end
end
```

### RSpec Usage

Expand Down
36 changes: 35 additions & 1 deletion features/Minitest.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,16 @@ class ExampleTest < ActionDispatch::IntegrationTest

def test_broadcasts
room = rooms(:office)

assert_broadcast_on("messages:#{room.id}", text: 'Hello!') do
post "/say/#{room.id}", xhr: true, params: { message: 'Hello!' }
end

# When testing broadcast to an object outside of channel test,
# channel should be explicitly specified
assert_broadcast_on(room, { text: 'Hello!' }, { channel: ChatChannel } do
post "/say/#{room.id}", xhr: true, params: { message: 'Hello!' }
end
end
end
```
Expand Down Expand Up @@ -100,6 +106,34 @@ class ChatChannelTest < ActionCable::Channel::TestCase
end
end
```
When broadcasting to an object:

```ruby
class ChatChannelTest < ActionCable::Channel::TestCase
include ActionCable::TestHelper

def setup
@room = Room.find 1

stub_connection(user: users[:john])
subscribe room_number: room.id
end

def test_broadcating
assert_broadcasts(@room, 1) do
perform :speak, message: "I'm here!"
end
end

# or

def test_broadcasted_data
assert_broadcasts_on(@room, text: "I'm here!", from: "John") do
perform :speak, message: "I'm here!"
end
end
end
```

### Generators

Expand Down
2 changes: 1 addition & 1 deletion features/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,4 @@ end

Bug reports and pull requests are welcome on GitHub at https://github.com/palkan/action-cable-testing.

[Action Cable]: http:https://guides.rubyonrails.org/action_cable_overview.html
[Action Cable]: http:https://guides.rubyonrails.org/action_cable_overview.html
45 changes: 30 additions & 15 deletions lib/action_cable/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
module ActionCable
# Provides helper methods for testing Action Cable broadcasting
module TestHelper
CHANNEL_NOT_FOUND = ArgumentError.new("Broadcastnig channel can't be infered. Please, specify it with `:channel`")

def before_setup # :nodoc:
server = ActionCable.server
test_adapter = ActionCable::SubscriptionAdapter::Test.new(server)
Expand Down Expand Up @@ -42,15 +44,17 @@ def after_teardown # :nodoc:
# end
# end
#
def assert_broadcasts(channel, number)
def assert_broadcasts(target, number, channel: nil)
stream = stream(target, channel)

if block_given?
original_count = broadcasts_size(channel)
original_count = broadcasts_size(stream)
yield
new_count = broadcasts_size(channel)
assert_equal number, new_count - original_count, "#{number} broadcasts to #{channel} expected, but #{new_count - original_count} were sent"
new_count = broadcasts_size(stream)
assert_equal number, new_count - original_count, "#{number} broadcasts to #{stream} expected, but #{new_count - original_count} were sent"
else
actual_count = broadcasts_size(channel)
assert_equal number, actual_count, "#{number} broadcasts to #{channel} expected, but #{actual_count} were sent"
actual_count = broadcasts_size(stream)
assert_equal number, actual_count, "#{number} broadcasts to #{stream} expected, but #{actual_count} were sent"
end
end

Expand All @@ -74,8 +78,8 @@ def assert_broadcasts(channel, number)
#
# assert_broadcasts 'messages', 0, &block
#
def assert_no_broadcasts(channel, &block)
assert_broadcasts channel, 0, &block
def assert_no_broadcasts(target, &block)
assert_broadcasts target, 0, &block
end

# Asserts that the specified message has been sent to the channel.
Expand All @@ -93,28 +97,30 @@ def assert_no_broadcasts(channel, &block)
# end
# end
#
def assert_broadcast_on(channel, data)
def assert_broadcast_on(target, data, channel: nil)
# Encode to JSON and back–we want to use this value to compare
# with decoded JSON.
# Comparing JSON strings doesn't work due to the order if the keys.
serialized_msg =
ActiveSupport::JSON.decode(ActiveSupport::JSON.encode(data))
new_messages = broadcasts(channel)
stream = stream(target, channel)

new_messages = broadcasts(stream)
if block_given?
old_messages = new_messages
clear_messages(channel)
clear_messages(stream)

yield
new_messages = broadcasts(channel)
clear_messages(channel)
new_messages = broadcasts(stream)
clear_messages(stream)

# Restore all sent messages
(old_messages + new_messages).each { |m| pubsub_adapter.broadcast(channel, m) }
(old_messages + new_messages).each { |m| pubsub_adapter.broadcast(stream, m) }
end

message = new_messages.find { |msg| ActiveSupport::JSON.decode(msg) == serialized_msg }

assert message, "No messages sent with #{data} to #{channel}"
assert message, "No messages sent with #{data} to #{stream}"
end

def pubsub_adapter # :nodoc:
Expand All @@ -127,5 +133,14 @@ def pubsub_adapter # :nodoc:
def broadcasts_size(channel) # :nodoc:
broadcasts(channel).size
end

def stream(target, channel = nil)
return target if target.is_a?(String)

channel ||= @subscription
raise CHANNEL_NOT_FOUND unless channel && channel.respond_to?(:channel_name)

channel.broadcasting_for([channel.channel_name, target])
end
end
end
22 changes: 22 additions & 0 deletions test/channel/test_case_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,12 @@ def broadcast(data)
text: data["message"], user_id: user_id
)
end

def broadcast_to_user(data)
user = User.new user_id

self.class.broadcast_to user, text: data["message"]
end
end

class BroadcastsTestChannelTest < ActionCable::Channel::TestCase
Expand All @@ -163,4 +169,20 @@ def test_broadcast_matchers_included
perform :broadcast, message: "SOS"
end
end

def test_broadcast_to_object
user = User.new(2017)

assert_broadcasts(user, 1) do
perform :broadcast_to_user, text: "SOS"
end
end

def test_broadcast_to_object_with_data
user = User.new(2017)

assert_broadcast_on(user, text: "SOS") do
perform :broadcast_to_user, message: "SOS"
end
end
end
43 changes: 43 additions & 0 deletions test/test_helper_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

require_relative "test_helper"

class BroadcastChannel < ActionCable::Channel::Base
end

class TransmissionsTest < ActionCable::TestCase
def test_assert_broadcasts
assert_nothing_raised do
Expand Down Expand Up @@ -59,6 +62,26 @@ def test_assert_broadcasts_message_too_many_sent

assert_match(/1 .* but 2/, error.message)
end

def test_assert_broadcast_to_object
user = User.new(42)

assert_nothing_raised do
assert_broadcasts user, 1, channel: BroadcastChannel do
BroadcastChannel.broadcast_to user, text: "text"
end
end
end

def test_assert_broadcast_to_object_without_channel
user = User.new(42)

assert_raises ArgumentError do
assert_broadcasts user, 1 do
BroadcastChannel.broadcast_to user, text: "text"
end
end
end
end

class TransmitedDataTest < ActionCable::TestCase
Expand Down Expand Up @@ -100,4 +123,24 @@ def test_assert_broadcast_on_message

assert_match(/No messages sent/, error.message)
end

def test_assert_broadcast_on_object
user = User.new(42)

assert_nothing_raised do
assert_broadcast_on user, { text: "text" }, { channel: BroadcastChannel } do
BroadcastChannel.broadcast_to user, text: "text"
end
end
end

def test_assert_broadcast_on_object_without_channel
user = User.new(42)

assert_raises ArgumentError do
assert_broadcast_on user, text: "text" do
BroadcastChannel.broadcast_to user, text: "text"
end
end
end
end

0 comments on commit c362340

Please sign in to comment.