module RageCableHelpers

def __build_cable_env(url, headers)

def __build_cable_env(url, headers)
  uri = URI.parse(url)
  uri.path = "/#{uri.path}" unless uri.path.start_with?("/")
  uri.host ||= default_host
  uri.scheme ||= "http"
  env = Rack::MockRequest.env_for(uri.to_s, __normalize_rack_headers(headers))
  env["REQUEST_METHOD"] = "GET"
  cookie_header = current_session.cookie_jar.for(uri)
  env["HTTP_COOKIE"] = cookie_header unless cookie_header.empty?
  env
end

def __cable_cookie_uri

def __cable_cookie_uri
  URI.parse("http://#{default_host}/")
end

def __cable_test_protocol

def __cable_test_protocol
  @__cable_test_protocol ||= Class.new do
    def supports_rpc?
      true
    end
    def subscribe(connection, stream, params)
      stream_id = Digest::MD5.hexdigest(params.to_s)
      connection.subscribe("cable:#{stream}:#{stream_id}")
    end
    def broadcast(*)
    end
    def serialize(params, data)
      { identifier: params.to_json, message: data }.to_json
    end
  end.new
end

def __channel_class

def __channel_class
  if !respond_to?(:described_class) || !described_class.is_a?(Class) || !described_class.ancestors.include?(Rage::Cable::Channel)
    raise ArgumentError, "`subscribe` expects the described class to inherit from Rage::Cable::Channel"
  end
  described_class
end

def __connection_class

def __connection_class
  if respond_to?(:described_class) && described_class.is_a?(Class) && described_class <= Rage::Cable::Connection
    described_class
  elsif Object.const_defined?("RageCable::Connection")
    RageCable::Connection
  elsif Object.const_defined?("ApplicationCable::Connection")
    ApplicationCable::Connection
  else
    Rage::Cable::Connection
  end
end

def __stub_cable_protocol!

def __stub_cable_protocol!
  allow(Rage.cable).to receive(:__protocol).and_return(__cable_test_protocol)
end

def __stub_iodine_defer!

def __stub_iodine_defer!
  allow(Iodine).to receive(:defer) do |&block|
    block&.call
    true
  end
end

def broadcast(*)

def broadcast(*)
end

def connect(url, headers: nil)

def connect(url, headers: nil)
  env = __build_cable_env(url, headers || {})
  @__cable_connection = __connection_class.new(env)
  @__cable_connection.connect
  unless @__cable_connection.rejected?
    env["rage.identified_by"] = @__cable_connection.__identified_by_map
    env["rage.cable"] = {}
  end
  @__cable_connection
end

def connection

def connection
  raise "No connection found. Call `connect` before `connection`." unless @__cable_connection
  @__cable_connection
end

def cookies

def cookies
  @__cable_cookies ||= MockCookies.new(self)
end

def perform(action, data = {})

def perform(action, data = {})
  raise "No subscription found. Call `subscribe` before `perform`." unless subscription
  payload = (data || {}).each_with_object({ "action" => action.to_s }) do |(key, value), memo|
    memo[key.to_s] = value
  end
  action_name = action.to_sym
  unless subscription.channel.__has_action?(action_name)
    raise ArgumentError, "Unable to process #{subscription.channel.class.name}##{action_name}"
  end
  subscription.channel.__run_action(action_name, payload)
end

def serialize(params, data)

def serialize(params, data)
  { identifier: params.to_json, message: data }.to_json
end

def session

def session
  @__cable_session ||= Rage::Session.new(cookies)
end

def stub_connection(identified_by = {})

def stub_connection(identified_by = {})
  @__cable_stubbed_connection = MockWebSocketConnection.new({
    "rage.cable" => {},
    "rage.identified_by" => identified_by.transform_keys(&:to_sym)
  })
end

def subscribe(params = {})

def subscribe(params = {})
  __stub_cable_protocol!
  __stub_iodine_defer!
  channel_class = __channel_class
  channel_class.__register_actions
  params = (params || {}).each_with_object({}) { |(k, v), memo| memo[k.to_sym] = v }
  params[:channel] = channel_class.name
  cable_connection = @__cable_stubbed_connection || stub_connection
  channel = channel_class.new(cable_connection, params, cable_connection.env["rage.identified_by"])
  channel.__run_action(:subscribed)
  unless channel.subscription_rejected?
    cable_connection.env["rage.cable"][params.to_json] = channel
  end
  @__subscription = MockSubscription.new(channel, cable_connection)
end

def subscribe(connection, stream, params)

def subscribe(connection, stream, params)
  stream_id = Digest::MD5.hexdigest(params.to_s)
  connection.subscribe("cable:#{stream}:#{stream_id}")
end

def subscription

def subscription
  raise "No subscription found. Call `subscribe` before `subscription`." unless @__subscription
  @__subscription
end

def supports_rpc?

def supports_rpc?
  true
end

def transmissions

def transmissions
  return [] unless subscription
  subscription.connection.messages.map do |message|
    parsed_message = begin
      JSON.parse(message)
    rescue JSON::ParserError, TypeError
      message
    end
    if parsed_message.is_a?(Hash)
      parsed_message["message"] || parsed_message[:message] || parsed_message
    else
      parsed_message
    end
  end
end