Skip to content

Commit

Permalink
Support custom reloader in Phoenix.LiveView.Channel (#3247)
Browse files Browse the repository at this point in the history
  • Loading branch information
wojtekmach committed May 14, 2024
1 parent 376fea7 commit 6648f77
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 67 deletions.
19 changes: 15 additions & 4 deletions lib/phoenix_live_view/channel.ex
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,8 @@ defmodule Phoenix.LiveView.Channel do
end

def handle_info({:phoenix_live_reload, _topic, _changed_file}, %{socket: socket} = state) do
Phoenix.CodeReloader.reload(socket.endpoint)
{mod, fun, args} = socket.private.phoenix_reloader
apply(mod, fun, [socket.endpoint | args])

new_socket =
Enum.reduce(socket.assigns, socket, fn {key, val}, socket ->
Expand Down Expand Up @@ -1310,7 +1311,13 @@ defmodule Phoenix.LiveView.Channel do
{:noreply, post_verified_mount(new_state)}

{:ok, diff, {:live_patch, opts}, new_state} ->
reply = put_container(session, route, %{rendered: diff, live_patch: opts, liveview_version: lv_vsn})
reply =
put_container(session, route, %{
rendered: diff,
live_patch: opts,
liveview_version: lv_vsn
})

GenServer.reply(from, {:ok, reply})
{:noreply, post_verified_mount(new_state)}

Expand Down Expand Up @@ -1522,9 +1529,13 @@ defmodule Phoenix.LiveView.Channel do

if live_reload_config[:notify][:live_view] do
state.socket.endpoint.subscribe("live_view")
end

{:noreply, state}
reloader = live_reload_config[:reloader] || {Phoenix.CodeReloader, :reload, []}
state = put_in(state.socket.private[:phoenix_reloader], reloader)
{:noreply, state}
else
{:noreply, state}
end
end

defp maybe_subscribe_to_live_reload(response), do: response
Expand Down
89 changes: 68 additions & 21 deletions test/phoenix_live_view/integrations/live_reload_test.exs
Original file line number Diff line number Diff line change
@@ -1,38 +1,60 @@
defmodule Phoenix.LiveView.LiveReloadTest do
use ExUnit.Case, async: true

defmodule Endpoint do
use Phoenix.Endpoint, otp_app: :phoenix_live_view

socket "/live", Phoenix.LiveView.Socket
socket "/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket
plug Phoenix.CodeReloader
plug Phoenix.LiveViewTest.Router
end

import Phoenix.ConnTest
import Phoenix.ChannelTest
import Phoenix.LiveViewTest

alias Phoenix.LiveReloader
alias Phoenix.LiveReloader.Channel
@endpoint Endpoint
@pubsub PubSub

@endpoint Phoenix.LiveView.LiveReloadTestHelpers.Endpoint
@pubsub Phoenix.LiveView.PubSub
@live_reload_config [
url: "ws://localhost:4004",
patterns: [
~r"priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$"
],
notify: [
live_view: [
~r"lib/test_auth_web/live/.*(ex)$"
]
]
]

setup_all do
ExUnit.CaptureLog.capture_log(fn ->
start_supervised!(@endpoint)
start_supervised!(Phoenix.PubSub.child_spec(name: @pubsub))
end)
test "LiveView renders again when the phoenix_live_reload is received" do
%{conn: conn, socket: socket} = start(@live_reload_config)

:ok
end
Application.put_env(:phoenix_live_view, :vsn, 1)
{:ok, lv, _html} = live(conn, "/live-reload")
assert render(lv) =~ "<div>Version 1</div>"

setup config do
{:ok, _, socket} =
LiveReloader.Socket |> socket() |> subscribe_and_join(Channel, "phoenix:live_reload", %{})
send(
socket.channel_pid,
{:file_event, self(), {"lib/test_auth_web/live/user_live.ex", :created}}
)

Application.put_env(:phoenix_live_view, :vsn, 2)

conn = Plug.Test.init_test_session(build_conn(), config[:session] || %{})
{:ok, conn: conn, socket: socket}
assert_receive {:phoenix_live_reload, :live_view, "lib/test_auth_web/live/user_live.ex"}
assert render(lv) =~ "<div>Version 2</div>"
end

test "LiveView renders again when the phoenix_live_reload is received", %{
conn: conn,
socket: socket
} do
Phoenix.PubSub.subscribe(@pubsub, "live_view")
def reload(endpoint, caller) do
Phoenix.CodeReloader.reload(endpoint)
send(caller, :reloaded)
end

test "custom reloader" do
reloader = {__MODULE__, :reload, [self()]}
%{conn: conn, socket: socket} = start([reloader: reloader] ++ @live_reload_config)

Application.put_env(:phoenix_live_view, :vsn, 1)
{:ok, lv, _html} = live(conn, "/live-reload")
Expand All @@ -46,6 +68,31 @@ defmodule Phoenix.LiveView.LiveReloadTest do
Application.put_env(:phoenix_live_view, :vsn, 2)

assert_receive {:phoenix_live_reload, :live_view, "lib/test_auth_web/live/user_live.ex"}
assert_receive :reloaded, 1000
assert render(lv) =~ "<div>Version 2</div>"
end

def start(live_reload_config) do
start_supervised!(
{@endpoint,
secret_key_base: String.duplicate("1", 50),
live_view: [signing_salt: "0123456789"],
pubsub_server: @pubsub,
live_reload: live_reload_config}
)

conn = Plug.Test.init_test_session(build_conn(), %{})
start_supervised!({Phoenix.PubSub, name: @pubsub})
Phoenix.PubSub.subscribe(@pubsub, "live_view")

{:ok, _, socket} =
subscribe_and_join(
socket(Phoenix.LiveReloader.Socket),
Phoenix.LiveReloader.Channel,
"phoenix:live_reload",
%{}
)

%{conn: conn, socket: socket}
end
end
9 changes: 5 additions & 4 deletions test/support/endpoint.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ defmodule Phoenix.LiveViewTest.EndpointOverridable do
defmacro __before_compile__(_env) do
quote do
@parsers Plug.Parsers.init(
parsers: [:urlencoded, :multipart, :json],
pass: ["*/*"],
json_decoder: Phoenix.json_library()
)
parsers: [:urlencoded, :multipart, :json],
pass: ["*/*"],
json_decoder: Phoenix.json_library()
)

defoverridable call: 2

def call(conn, _) do
%{conn | secret_key_base: config(:secret_key_base)}
|> Plug.Parsers.call(@parsers)
Expand Down
38 changes: 0 additions & 38 deletions test/support/live_reload_test_helpers.ex

This file was deleted.

0 comments on commit 6648f77

Please sign in to comment.