diff --git a/apps/explorer_web/lib/explorer_web/channels/address_channel.ex b/apps/explorer_web/lib/explorer_web/channels/address_channel.ex index 8ee3208e65..db771dc198 100644 --- a/apps/explorer_web/lib/explorer_web/channels/address_channel.ex +++ b/apps/explorer_web/lib/explorer_web/channels/address_channel.ex @@ -1,7 +1,13 @@ defmodule ExplorerWeb.AddressChannel do + @moduledoc """ + Establishes pub/sub channel for address page live updates. + """ use ExplorerWeb, :channel - intercept ["transaction"] + alias ExplorerWeb.AddressTransactionView + alias Phoenix.View + + intercept(["transaction"]) def join("addresses:" <> _address_hash, _params, socket) do {:ok, %{}, socket} @@ -9,8 +15,16 @@ defmodule ExplorerWeb.AddressChannel do def handle_out("transaction", %{transaction: transaction}, socket) do Gettext.put_locale(ExplorerWeb.Gettext, socket.assigns.locale) - rendered = Phoenix.View.render_to_string(ExplorerWeb.AddressTransactionView, "_transaction.html", locale: socket.assigns.locale, transaction: transaction) - push socket, "transaction", %{transaction: rendered} + + rendered = + View.render_to_string( + AddressTransactionView, + "_transaction.html", + locale: socket.assigns.locale, + transaction: transaction + ) + + push(socket, "transaction", %{transaction: rendered}) {:noreply, socket} end end diff --git a/apps/explorer_web/lib/explorer_web/channels/user_socket.ex b/apps/explorer_web/lib/explorer_web/channels/user_socket.ex index caf021bc24..1c76a2124c 100644 --- a/apps/explorer_web/lib/explorer_web/channels/user_socket.ex +++ b/apps/explorer_web/lib/explorer_web/channels/user_socket.ex @@ -1,7 +1,7 @@ defmodule ExplorerWeb.UserSocket do use Phoenix.Socket - channel "addresses:*", ExplorerWeb.AddressChannel + channel("addresses:*", ExplorerWeb.AddressChannel) transport(:websocket, Phoenix.Transports.WebSocket, timeout: 45_000) # transport :longpoll, Phoenix.Transports.LongPoll diff --git a/apps/explorer_web/test/explorer_web/channels/address_channel_test.exs b/apps/explorer_web/test/explorer_web/channels/address_channel_test.exs new file mode 100644 index 0000000000..4a3bbc0e0e --- /dev/null +++ b/apps/explorer_web/test/explorer_web/channels/address_channel_test.exs @@ -0,0 +1,20 @@ +defmodule ExplorerWeb.AddressChannelTest do + use ExplorerWeb.ChannelCase + + describe "addresses channel tests" do + test "subscribed user can receive channel message" do + channel = "addresses" + @endpoint.subscribe(channel) + + ExplorerWeb.Endpoint.broadcast(channel, "transaction", %{body: "test"}) + + receive do + %Phoenix.Socket.Broadcast{event: "transaction", topic: ^channel, payload: %{body: body}} -> + assert body == "test" + after + 5_000 -> + assert false, "Expected message received nothing." + end + end + end +end diff --git a/apps/explorer_web/test/explorer_web/features/viewing_addresses_test.exs b/apps/explorer_web/test/explorer_web/features/viewing_addresses_test.exs index f50f32f108..7c675dee61 100644 --- a/apps/explorer_web/test/explorer_web/features/viewing_addresses_test.exs +++ b/apps/explorer_web/test/explorer_web/features/viewing_addresses_test.exs @@ -148,13 +148,14 @@ defmodule ExplorerWeb.ViewingAddressesTest do end test "viewing new transactions via live update", %{addresses: addresses, session: session} do - session = session - |> AddressPage.visit_page(addresses.lincoln) - |> assert_has(AddressPage.balance()) + session = + session + |> AddressPage.visit_page(addresses.lincoln) + |> assert_has(AddressPage.balance()) transaction = :transaction - |> insert(from_address_hash: addresses.lincoln.hash) + |> insert(from_address: addresses.lincoln) |> with_block() |> Repo.preload([:block, :from_address, :to_address]) diff --git a/apps/explorer_web/test/support/channel_case.ex b/apps/explorer_web/test/support/channel_case.ex new file mode 100644 index 0000000000..9e644a4d7f --- /dev/null +++ b/apps/explorer_web/test/support/channel_case.ex @@ -0,0 +1,41 @@ +defmodule ExplorerWeb.ChannelCase do + @moduledoc """ + This module defines the test case to be used by + channel tests. + + Such tests rely on `Phoenix.ChannelTest` and also + import other functionality to make it easier + to build common datastructures and query the data layer. + + Finally, if the test case interacts with the database, + it cannot be async. For this reason, every test runs + inside a transaction which is reset at the beginning + of the test unless the test case is marked as async. + """ + + use ExUnit.CaseTemplate + + using do + quote do + # Import conveniences for testing with channels + use Phoenix.ChannelTest + + # The default endpoint for testing + @endpoint ExplorerWeb.Endpoint + + import Explorer.Factory + end + end + + @dialyzer {:nowarn_function, __ex_unit_setup_0: 1} + setup tags do + :ok = Ecto.Adapters.SQL.Sandbox.checkout(Explorer.Repo) + + unless tags[:async] do + Ecto.Adapters.SQL.Sandbox.mode(Explorer.Repo, {:shared, self()}) + end + + :ok + # {k:ok, conn: %Plug.Conn{} |> Plug.Conn.put_private(:phoenix_endpoint, ExplorerWeb.Endpoint)} + end +end