phoenixframework / phoenix_live_view

Rich, real-time user experiences with server-rendered HTML
https://hex.pm/packages/phoenix_live_view
MIT License
6.22k stars 931 forks source link

LiveViewTest failing on empty `textarea` when using the `fast_html` engine with Floki #2457

Closed Kuret closed 1 year ago

Kuret commented 1 year ago

Environment

Actual behavior

When using the fast_html engine configured for Floki, tests with (for example) render_change fail when testing a form that includes a textarea with no inner value.

For example, in our view we have a textarea, bound to a form with an empty changeset (so no initial value)

Our test contains:

      {:ok, view, _initial_html} = live_isolated(conn, FormLive, session: ...)

      html =
        view
        |> element("form")
        |> render_change(%{"param_name" => %{"field_name" => "field_value"}})

Produces an error:

** (FunctionClauseError) no function clause matching in Phoenix.LiveViewTest.ClientProxy.form_defaults/3

This happens because for the default mochiweb parser Floki uses, a textarea always gets (incorrectly) parsed with an empty string value:

iex> :mochiweb_html.parse("<textarea></textarea>")
{"textarea", [], [""]}

In contrast, fast_html does not return an empty value (correctly so imo):

iex()> :fast_html.decode_fragment("<textarea></textarea>")           
{:ok, [{"textarea", [], []}]}

This in turn causes a FunctionClauseError in LiveViewTest's ClientProxy module, because this textarea has no value:

  # lib/phoenix_live_view/test/client_proxy.ex:1132

  defp form_defaults({"textarea", _, [value]}, name, acc) do
    Plug.Conn.Query.decode_pair({name, String.replace_prefix(value, "\n", "")}, acc)
  end

Expected behavior

render_change does not fail on empty textareas regardless of which HTML Engine is used.

We use fast_html for (for example) parsing some returned html from external API calls and markdown-y parsing/previews so we need the tests to be able to use the same engine.

josevalim commented 1 year ago

Please do send a PR!

Kuret commented 1 year ago

Hi,

I'm not too familiar with this code. I see that these form_defaults functions are also there for other elements, where there is no specific match on a [value].

Is there a specific reason this is only done this way for textarea's or can I just assume a default of [""]?

Kuret commented 1 year ago

After playing around with the codebase, I couldn't find any side effect of assuming a default of [""] (Floki's default parsing already sets that when the node is empty anyways), so I made a PR for this.

josevalim commented 1 year ago

Closing in favor of the PR!