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