class RSpec::Rails::Matchers::ActionCable::HaveBroadcastedTo

rubocop: disable Metrics/ClassLength @private

Public Class Methods

new(target, channel:) click to toggle source
# File lib/rspec/rails/matchers/action_cable/have_broadcasted_to.rb, line 8
def initialize(target, channel:)
  @target = target
  @channel = channel
  @block = proc { }
  @data = nil
  set_expected_number(:exactly, 1)
end

Public Instance Methods

at_least(count) click to toggle source
# File lib/rspec/rails/matchers/action_cable/have_broadcasted_to.rb, line 28
def at_least(count)
  set_expected_number(:at_least, count)
  self
end
at_most(count) click to toggle source
# File lib/rspec/rails/matchers/action_cable/have_broadcasted_to.rb, line 33
def at_most(count)
  set_expected_number(:at_most, count)
  self
end
description() click to toggle source
# File lib/rspec/rails/matchers/action_cable/have_broadcasted_to.rb, line 54
def description
  "have broadcasted #{base_description}"
end
exactly(count) click to toggle source
# File lib/rspec/rails/matchers/action_cable/have_broadcasted_to.rb, line 23
def exactly(count)
  set_expected_number(:exactly, count)
  self
end
failure_message() click to toggle source
# File lib/rspec/rails/matchers/action_cable/have_broadcasted_to.rb, line 58
def failure_message
  "expected to broadcast #{base_message}".tap do |msg|
    if @unmatching_msgs.any?
      msg << "\nBroadcasted messages to #{stream}:"
      @unmatching_msgs.each do |data|
        msg << "\n   #{data}"
      end
    end
  end
end
failure_message_when_negated() click to toggle source
# File lib/rspec/rails/matchers/action_cable/have_broadcasted_to.rb, line 69
def failure_message_when_negated
  "expected not to broadcast #{base_message}"
end
from_channel(channel) click to toggle source
# File lib/rspec/rails/matchers/action_cable/have_broadcasted_to.rb, line 95
def from_channel(channel)
  @channel = channel
  self
end
matches?(proc) click to toggle source
# File lib/rspec/rails/matchers/action_cable/have_broadcasted_to.rb, line 85
def matches?(proc)
  raise ArgumentError, "have_broadcasted_to and broadcast_to only support block expectations" unless Proc === proc

  original_sent_messages_count = pubsub_adapter.broadcasts(stream).size
  proc.call
  in_block_messages = pubsub_adapter.broadcasts(stream).drop(original_sent_messages_count)

  check(in_block_messages)
end
message_expectation_modifier() click to toggle source
# File lib/rspec/rails/matchers/action_cable/have_broadcasted_to.rb, line 73
def message_expectation_modifier
  case @expectation_type
  when :exactly then "exactly"
  when :at_most then "at most"
  when :at_least then "at least"
  end
end
once() click to toggle source
# File lib/rspec/rails/matchers/action_cable/have_broadcasted_to.rb, line 42
def once
  exactly(:once)
end
supports_block_expectations?() click to toggle source
# File lib/rspec/rails/matchers/action_cable/have_broadcasted_to.rb, line 81
def supports_block_expectations?
  true
end
thrice() click to toggle source
# File lib/rspec/rails/matchers/action_cable/have_broadcasted_to.rb, line 50
def thrice
  exactly(:thrice)
end
times() click to toggle source
# File lib/rspec/rails/matchers/action_cable/have_broadcasted_to.rb, line 38
def times
  self
end
twice() click to toggle source
# File lib/rspec/rails/matchers/action_cable/have_broadcasted_to.rb, line 46
def twice
  exactly(:twice)
end
with(data = nil, &block) click to toggle source
# File lib/rspec/rails/matchers/action_cable/have_broadcasted_to.rb, line 16
def with(data = nil, &block)
  @data = data
  @data = @data.with_indifferent_access if @data.is_a?(Hash)
  @block = block if block
  self
end

Private Instance Methods

base_description() click to toggle source
# File lib/rspec/rails/matchers/action_cable/have_broadcasted_to.rb, line 147
def base_description
  "#{message_expectation_modifier} #{@expected_number} messages to #{stream}".tap do |msg|
    msg << " with #{data_description(@data)}" unless @data.nil?
  end
end
base_message() click to toggle source
# File lib/rspec/rails/matchers/action_cable/have_broadcasted_to.rb, line 153
def base_message
  "#{base_description}, but broadcast #{@matching_msgs_count}"
end
check(messages) click to toggle source
# File lib/rspec/rails/matchers/action_cable/have_broadcasted_to.rb, line 114
def check(messages)
  @matching_msgs, @unmatching_msgs = messages.partition do |msg|
    decoded = ActiveSupport::JSON.decode(msg)
    decoded = decoded.with_indifferent_access if decoded.is_a?(Hash)

    if @data.nil? || values_match?(@data, decoded)
      @block.call(decoded)
      true
    else
      false
    end
  end

  @matching_msgs_count = @matching_msgs.size

  case @expectation_type
  when :exactly then @expected_number == @matching_msgs_count
  when :at_most then @expected_number >= @matching_msgs_count
  when :at_least then @expected_number <= @matching_msgs_count
  end
end
check_channel_presence() click to toggle source
# File lib/rspec/rails/matchers/action_cable/have_broadcasted_to.rb, line 169
def check_channel_presence
  return if @channel.present? && @channel.respond_to?(:channel_name)

  error_msg = "Broadcasting channel can't be inferred. Please, specify it with `from_channel`"
  raise ArgumentError, error_msg
end
data_description(data) click to toggle source
# File lib/rspec/rails/matchers/action_cable/have_broadcasted_to.rb, line 157
def data_description(data)
  if data.is_a?(RSpec::Matchers::Composable)
    data.description
  else
    data.inspect
  end
end
pubsub_adapter() click to toggle source
# File lib/rspec/rails/matchers/action_cable/have_broadcasted_to.rb, line 165
def pubsub_adapter
  ::ActionCable.server.pubsub
end
set_expected_number(relativity, count) click to toggle source
# File lib/rspec/rails/matchers/action_cable/have_broadcasted_to.rb, line 136
def set_expected_number(relativity, count)
  @expectation_type = relativity
  @expected_number =
    case count
    when :once then 1
    when :twice then 2
    when :thrice then 3
    else Integer(count)
    end
end
stream() click to toggle source
# File lib/rspec/rails/matchers/action_cable/have_broadcasted_to.rb, line 102
def stream
  @stream ||= case @target
              when String
                @target
              when Symbol
                @target.to_s
              else
                check_channel_presence
                @channel.broadcasting_for(@target)
              end
end