diff --git a/lib/phoenix_live_view.ex b/lib/phoenix_live_view.ex index 0d8578a469..ff77ea9e74 100644 --- a/lib/phoenix_live_view.ex +++ b/lib/phoenix_live_view.ex @@ -2245,8 +2245,8 @@ defmodule Phoenix.LiveView do an `Phoenix.LiveView.AsyncResult` struct holding the status of the operation and the result when the function completes. - The function must return either a map or a keyword list with the assigns - to merge into the socket. + The function must return either `{:ok, assigns}` or `{:error, reason}`, + where `assigns` is a map with the keys passed to `assign_async/3`. The task is only started when the socket is connected. diff --git a/lib/phoenix_live_view/async.ex b/lib/phoenix_live_view/async.ex index 64653c342a..ff4c107eff 100644 --- a/lib/phoenix_live_view/async.ex +++ b/lib/phoenix_live_view/async.ex @@ -363,7 +363,7 @@ defmodule Phoenix.LiveView.Async do defp handle_kind(socket, _maybe_component, :assign, keys, result) do case result do - {:ok, {:ok, assigns}} when is_map(assigns) or is_list(assigns) -> + {:ok, {:ok, assigns}} when is_map(assigns) -> new_assigns = for {key, val} <- assigns do {key, AsyncResult.ok(get_current_async!(socket, key), val)} diff --git a/test/phoenix_live_view/integrations/assign_async_test.exs b/test/phoenix_live_view/integrations/assign_async_test.exs index 7e16d89e03..226346b786 100644 --- a/test/phoenix_live_view/integrations/assign_async_test.exs +++ b/test/phoenix_live_view/integrations/assign_async_test.exs @@ -32,6 +32,15 @@ defmodule Phoenix.LiveView.AssignAsyncTest do assert render(lv) end + test "keyword list return", %{conn: conn} do + {:ok, lv, _html} = live(conn, "/assign_async?test=bad_keyword") + + assert render_async(lv) =~ + "expected assign_async to return {:ok, map} of\\nassigns for [:data] or {:error, reason}, got: {:ok, [data: 123]}" + + assert render(lv) + end + test "valid return", %{conn: conn} do {:ok, lv, _html} = live(conn, "/assign_async?test=ok") assert render_async(lv) =~ "data: 123" @@ -222,7 +231,9 @@ defmodule Phoenix.LiveView.AssignAsyncTest do test "valid return", %{conn: conn} do {:ok, lv, _html} = live(conn, "/assign_async?test=sup_ok") - assert render_async(lv) =~ "data: 123" + html = render_async(lv) + assert html =~ "data: 123" + refute html =~ "expected assign_async to return" end test "raise during execution", %{conn: conn} do diff --git a/test/support/live_views/assign_async.ex b/test/support/live_views/assign_async.ex index 95153b654c..69e55ce476 100644 --- a/test/support/live_views/assign_async.ex +++ b/test/support/live_views/assign_async.ex @@ -40,13 +40,17 @@ defmodule Phoenix.LiveViewTest.Support.AssignAsyncLive do {:ok, assign_async(socket, :data, fn -> {:ok, %{bad: 123}} end)} end + def mount(%{"test" => "bad_keyword"}, _session, socket) do + {:ok, assign_async(socket, :data, fn -> {:ok, data: 123} end)} + end + def mount(%{"test" => "ok"}, _session, socket) do {:ok, assign_async(socket, :data, fn -> {:ok, %{data: 123}} end)} end def mount(%{"test" => "sup_ok"}, _session, socket) do {:ok, - assign_async(socket, :data, fn -> {:ok, data: 123} end, supervisor: TestAsyncSupervisor)} + assign_async(socket, :data, fn -> {:ok, %{data: 123}} end, supervisor: TestAsyncSupervisor)} end def mount(%{"test" => "raise"}, _session, socket) do