Skip to content

LiveviewTest render_upload: key :root_pid not found in: %Phoenix.LiveViewTest.ClientProxy #3732

@Aratramba

Description

@Aratramba

Environment

  • Elixir version (elixir -v): Elixir 1.18.1
  • Phoenix version (mix deps): 1.7.20
  • Phoenix LiveView version (mix deps): 1.0.7
  • Operating system: OSX Sonoma
  • Browsers you attempted to reproduce this bug on (the more the merrier): Chrome
  • Does the problem persist after removing "assets/node_modules" and trying again? Yes/no: Yes

Actual behavior

I have a Liveview with a live_render'ed View inside it. The nested view has a form with an upload field. This used to work until we upgraded from Liveview 1.0.4 to 1.0.7

I think it must be related to changes from #3676

I attached two test single app files: one with Liveview 1.0.4 and the one with 1.0.7. The former passes, the latter crashes.

upload_test_case_lv1.0.4.exs.txt
upload_test_case_lv1.0.7.exs.txt

Error

This is the error:

key :root_pid not found in: %Phoenix.LiveViewTest.ClientProxy
** (exit) exited in: GenServer.call(#PID<0.478.0>, {:sync_with_root, "lv:upload-debug-nested"}, 5000)
         ** (EXIT) an exception was raised:
             ** (KeyError) key :root_pid not found in: %Phoenix.LiveViewTest.ClientProxy{
       session_token: "SFMyNTY.g2gDaAJhBnQAAAAHdwJpZG0AAAATdXBsb2FkLWRlYnVnLW5lc3RlZHcHc2Vzc2lvbnQAAAAAdwR2aWV3dyRFbGl4aXIuRXhhbXBsZS5VcGxvYWREZWJ1Z05lc3RlZExpdmV3CnBhcmVudF9waWRYdw1ub25vZGVAbm9ob3N0AAAB3wAAAAAAAAAAdwlyb290X3ZpZXd3F0VsaXhpci5FeGFtcGxlLkhvbWVMaXZldwZyb3V0ZXJ3FUVsaXhpci5FeGFtcGxlLlJvdXRlcncIcm9vdF9waWRYdw1ub25vZGVAbm9ob3N0AAAB3wAAAAAAAAAAbgYAA4mv0pUBYgABUYA.SDO68nteWqaaJXld2gjkVjjYsrnvvxBaR8Onhk7RjkM",
       static_token: "SFMyNTY.g2gDaAJhBnQAAAADdwJpZG0AAAATdXBsb2FkLWRlYnVnLW5lc3RlZHcKYXNzaWduX25ld2p3BWZsYXNodAAAAABuBgDriK_SlQFiAAFRgA.Q_2uXqoM_sUVtFC_5sjbeTYDrl5dVnfl1SHkT9gEOl0",
       module: Example.UploadDebugNestedLive,
       endpoint: Example.Endpoint,
       router: nil,
       pid: #PID<0.480.0>,
       proxy: #PID<0.478.0>,
       topic: "lv:upload-debug-nested",
       ref: #Reference<0.2560702666.3450339331.178198>,
       rendered: %{
         0 => %{
           0 => " id=\"phx-GDBeDvR2_M0ciRMj\"",
           1 => " name=\"avatar\"",
           2 => " accept=\".jpg,.jpeg,.png\"",
           3 => " data-phx-upload-ref=\"phx-GDBeDvR2_M0ciRMj\"",
           4 => " data-phx-active-refs=\"4932\"",
           5 => " data-phx-done-refs=\"4932\"",
           6 => " data-phx-preflighted-refs=\"4932\"",
           7 => "",
           8 => " multiple",
           :s => ["<input", " type=\"file\"", "",
            " data-phx-hook=\"Phoenix.LiveFileUpload\" data-phx-update=\"ignore\"",
            "", "", "", "", "", ">"],
           :r => 1
         },
         :s => ["<form id=\"upload-form\" phx-submit=\"save\" phx-change=\"validate\">\n  ",
          "\n  <button type=\"submit\">Upload</button>\n</form>"],
         :r => 1,
         :streams => []
       },
       children: [],
       child_statics: %{},
       id: "upload-debug-nested",
       uri: nil,
       connect_params: %{},
       connect_info: %{},
       on_error: :warn
     }
                 (phoenix_live_view 1.0.7) lib/phoenix_live_view/test/client_proxy.ex:609: anonymous fn/2 in Phoenix.LiveViewTest.ClientProxy.handle_call/3
                 (stdlib 6.0) gen_server.erl:2209: :gen_server.try_handle_call/4
                 (stdlib 6.0) gen_server.erl:2238: :gen_server.handle_msg/6
                 (stdlib 6.0) proc_lib.erl:329: :proc_lib.init_p_do_apply/3

Reduced test case:

See the attached file for a single file app.

defmodule LiveviewSandboxWeb.UploadDebugLive do
  use LiveviewSandboxWeb, :live_view

  def mount(_params, _session, socket) do
    {:ok, socket}
  end

  def render(assigns) do
    ~H"""
    {live_render(@socket, LiveviewSandboxWeb.UploadDebugNestedLive,
      id: "upload-debug-nested",
      session: %{}
    )}
    """
  end
end
defmodule LiveviewSandboxWeb.UploadDebugNestedLive do
  use LiveviewSandboxWeb, :live_view

  @impl Phoenix.LiveView
  def mount(_params, _session, socket) do
    {:ok,
     socket
     |> assign(:uploaded_files, [])
     |> allow_upload(:avatar, accept: ~w(.jpg .jpeg .png), max_entries: 2)}
  end

  @impl Phoenix.LiveView
  def render(assigns) do
    ~H"""
    <form id="upload-form" phx-submit="save" phx-change="validate">
      <.live_file_input upload={@uploads.avatar} />
      <button type="submit">Upload</button>
    </form>
    """
  end

  @impl Phoenix.LiveView
  def handle_event("validate", _params, socket) do
    {:noreply, socket}
  end

  @impl Phoenix.LiveView
  def handle_event("cancel-upload", %{"ref" => ref}, socket) do
    {:noreply, cancel_upload(socket, :avatar, ref)}
  end

  @impl Phoenix.LiveView
  def handle_event("save", _params, socket) do
    uploaded_files =
      consume_uploaded_entries(socket, :avatar, fn %{path: path}, _entry ->
        dest =
          Path.join([:code.priv_dir(:liveview_sandbox), "static", "uploads", Path.basename(path)])

        File.cp!(path, dest)
        {:ok, "/uploads/#{Path.basename(dest)}"}
      end)

    {:noreply, update(socket, :uploaded_files, &(&1 ++ uploaded_files))}
  end
end
defmodule LiveviewSandboxWeb.UploadDebugNestedLiveTest do
  use LiveviewSandboxWeb.ConnCase, async: false
  import Phoenix.LiveViewTest

  test "uploading a file", %{conn: conn} do
    {:ok, view, _html} = live(conn, "/upload-debug")

    [nested_view] = live_children(view)

    avatar =
      file_input(nested_view, "#upload-form", :avatar, [
        %{
          name: "red-dot.png",
          content: File.read!("test/data/red-dot.png"),
          type: "image/png"
        }
      ])

    render_upload(avatar, "red-dot.png")
  end
end

Expected behavior

I expect the test not to crash.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions