SocketPoxy v0.1.1 SocketProxy View Source

Convinience for testing multiple socket connections.

When testing a Phoenix.Channel you might run into one of the following situations:

  • You want to make sure that a message is received on a specific user’s socket
  • You want to terminate the transport process.

If you ever found yourself in one of these situations this library might come in handy.

When using the functions provided by Phoenix.ChannelTest to connect to a socket or join a channel the socket or channel will be linked to the pid of the test. The test process will receive all the Phoenix.Socket.Message and Phoenix.Socket.Broadcast that would otherwise pushed to the client.

Unfortunately this way it is impossible to assert that a message was sent on a specific socket, nor is it possible to to realy close the socket because the transport_pid of the socket is the test itself.

This is where SocketProxy comes in. It proxies the socket connection through a seperate process and tags the messages so that its origin can be asserted on.

Example

defmodule SocketProxyWeb.RoomChannelTest do
  use SocketProxyWeb.ChannelCase
  use SocketProxy

  alias SocketProxyWeb.RoomChannel
  alias SocketProxyWeb.UserSocket

  describe "using the pids as identifiers" do
    setup do
      {:ok, proxy_pid} = start_proxy()
      params = %{"name" => "alice"}
      {:ok, socket} = connect_proxy(proxy_pid, UserSocket, params)
      socket = subscribe_and_join_proxy!(socket, RoomChannel, "room:1")

      {:ok, proxy_pid: proxy_pid, proxy_socket: socket}
    end

    test "assertions on the socket", %{proxy_socket: socket} do
      assert_push_on socket, "msg", %{"body" => "Welcome alice!"}
      refute_push_on socket, "msg", %{"body" => "Get out of here!"}
      refute_broadcast_on socket, "shout", %{"body" => "Hello World!"}
    end

    test "assertions on the proxy's pid", %{proxy_pid: pid} do
      assert_push_on pid, "msg", %{"body" => "Welcome alice!"}
    end

    test "good old assert_receive", %{proxy_pid: pid} do
      assert_receive {^pid, %Phoenix.Socket.Message{
        payload: %{"body" => "Welcome alice!"}
      }}
    end

    test "pushing messages", %{proxy_socket: socket} do
      push(socket, "shout", %{"body" => "Hello World!"})
      assert_broadcast_on socket, "shout", %{"body" => "Hello World!"}
    end
  end

  describe "using custom identifiers" do
    setup do
      {:ok, proxy_pid} = start_proxy(:alice_socket)
      params = %{"name" => "alice"}
      {:ok, socket} = connect_proxy(proxy_pid, UserSocket, params)
      socket = subscribe_and_join_proxy!(socket, RoomChannel, "room:1")

      :ok
    end

    test "assertions on the custom identifier" do
      assert_push_on :alice_socket, "msg", %{"body" => "Welcome alice!"}
      refute_push_on :alice_socket, "msg", %{"body" => "Get out of here!"}
    end
  end
end

Link to this section Summary

Functions

Asserts the channel has broadcasted a message back to the client on the given socket with the given event and payload within timeout. Works somilar to Phoenix.ChannelTest.assert_broadcast/2

Asserts the channel has pushed a message back to the client on the given socket with the given event and payload within timeout. Works somilar to Phoenix.ChannelTest.assert_push/2

Asserts the channel has replied on the given socket to the given message within timeout. Works similar to Phoenix.ChannelTest.assert_reply/4

Establishes a socket connection. Basically the same thing as Phoenix.ChanneText.connect/2 does but instead of binding the process to the test it binds to the proxy

Refutes the channel has broadcasted a message back to the client on the given socket with the given event and payload within timeout. Works somilar to Phoenix.ChannelTest.refute_broadcast/2

Refutes the channel has pushed a message back to the client on the given socket with the given event and payload within timeout. Works somilar to Phoenix.ChannelTest.refute_push/2

Refutes the channel has replied on the given socket to the given message within timeout. Works similar to Phoenix.ChannelTest.refute_reply/4

Starts a proxy. This must always be invoked first! It accepts an indentifier for the forwarded messages as argument. When no indentifier was provided it will use the pid proxy as identifier

Subscribes and joins the socket to the channel and links it to the proxy. See Phoenix.ChannelTest.subscribe_and_join/4 for further details

Subscribes and joins the socket to the channel and links it to the proxy. See Phoenix.ChannelTest.subscribe_and_join!/4 for further details

Link to this section Functions

Link to this macro assert_broadcast_on(id, event, payload, timeout \\ 100) View Source (macro)

Asserts the channel has broadcasted a message back to the client on the given socket with the given event and payload within timeout. Works somilar to Phoenix.ChannelTest.assert_broadcast/2.

Link to this macro assert_push_on(id_or_socket, event, payload, timeout \\ 100) View Source (macro)

Asserts the channel has pushed a message back to the client on the given socket with the given event and payload within timeout. Works somilar to Phoenix.ChannelTest.assert_push/2.

Link to this macro assert_reply_on(id_or_socket, ref, status, payload \\ Macro.escape(%{}), timeout \\ 100) View Source (macro)

Asserts the channel has replied on the given socket to the given message within timeout. Works similar to Phoenix.ChannelTest.assert_reply/4.

Link to this macro connect_proxy(pid, handler, params \\ %{}) View Source (macro)
connect_proxy(pid(), atom(), map()) :: {:ok, Phoenix.Socket.t()}

Establishes a socket connection. Basically the same thing as Phoenix.ChanneText.connect/2 does but instead of binding the process to the test it binds to the proxy.

Link to this macro refute_broadcast_on(id, event, payload, timeout \\ 100) View Source (macro)

Refutes the channel has broadcasted a message back to the client on the given socket with the given event and payload within timeout. Works somilar to Phoenix.ChannelTest.refute_broadcast/2.

Link to this macro refute_push_on(id, event, payload, timeout \\ 100) View Source (macro)

Refutes the channel has pushed a message back to the client on the given socket with the given event and payload within timeout. Works somilar to Phoenix.ChannelTest.refute_push/2.

Link to this macro refute_reply_on(id_or_socket, ref, status, payload \\ Macro.escape(%{}), timeout \\ 100) View Source (macro)

Refutes the channel has replied on the given socket to the given message within timeout. Works similar to Phoenix.ChannelTest.refute_reply/4.

Link to this function start_proxy(id \\ nil) View Source
start_proxy(term() | nil) :: GenServer.on_start()

Starts a proxy. This must always be invoked first! It accepts an indentifier for the forwarded messages as argument. When no indentifier was provided it will use the pid proxy as identifier.

Link to this function subscribe_and_join_proxy(socket, channel, topic, params \\ %{}) View Source
subscribe_and_join_proxy(Phoenix.Socket.t(), atom(), String.t(), map()) ::
  {:ok, Phoenix.Socket.t()}

Subscribes and joins the socket to the channel and links it to the proxy. See Phoenix.ChannelTest.subscribe_and_join/4 for further details.

Link to this function subscribe_and_join_proxy!(socket, channel, topic, params \\ %{}) View Source
subscribe_and_join_proxy!(Phoenix.Socket.t(), atom(), String.t(), map()) ::
  Phoenix.Socket.t()

Subscribes and joins the socket to the channel and links it to the proxy. See Phoenix.ChannelTest.subscribe_and_join!/4 for further details.