Repository: phoenixframework/phoenix_html
Pull request #201 (2018-02-22 03:41:11)

input_name should return a String when passed an unnamed form.
- This bug shows up when using multiple_select with an unnamed form.
- Function spec indicates that input_name returns a String.


Patch:
diff --git a/lib/phoenix_html/form.ex b/lib/phoenix_html/form.ex
index b8ea17f..cdcef52 100644
--- a/lib/phoenix_html/form.ex
+++ b/lib/phoenix_html/form.ex
@@ -361,7 +361,7 @@ defmodule Phoenix.HTML.Form do
   """
   @spec input_name(t | atom, field) :: String.t
   def input_name(%{name: nil}, field),
-    do: field
+    do: to_string(field)
   def input_name(%{name: name}, field) when is_atom(field) or is_binary(field),
     do: "#{name}[#{field}]"
   def input_name(name, field) when is_atom(name) and is_atom(field) or is_binary(field),


Test patch:
diff --git a/test/phoenix_html/form_test.exs b/test/phoenix_html/form_test.exs
index b90ec11..908b6b6 100644
--- a/test/phoenix_html/form_test.exs
+++ b/test/phoenix_html/form_test.exs
@@ -9,11 +9,11 @@ defmodule Phoenix.HTML.FormTest do
   A function that executes `form_for/4` and
   extracts its inner contents for assertion.
   """
-  def safe_form(fun, opts \\ []) do
+  def safe_form(fun, opts \\ [as: :search]) do
     mark = "--PLACEHOLDER--"
 
     contents =
-      safe_to_string form_for(conn(), "/", [as: :search] ++ opts, fn f ->
+      safe_to_string form_for(conn(), "/", opts, fn f ->
         html_escape [mark, fun.(f), mark]
       end)
 
@@ -238,7 +238,7 @@ defmodule Phoenix.HTML.FormTest do
       safe_form(&file_input(&1, :key))
     end
 
-    assert safe_form(&file_input(&1, :key), multipart: true) ==
+    assert safe_form(&file_input(&1, :key), multipart: true, as: :search) ==
           ~s(<input id="search_key" name="search[key]" type="file">)
   end
 
@@ -700,6 +700,39 @@ defmodule Phoenix.HTML.FormTest do
           ~s(</select>)
   end
 
+  test "multiple_select/4 with unnamed form" do
+    assert safe_form(&multiple_select(&1, :key, [{"foo", 1}, {"bar", 2}], value: [1], selected: [2]), []) ==
+           ~s(<select multiple="" name="key[]">) <>
+           ~s(<option value="1" selected>foo</option>) <>
+           ~s(<option value="2">bar</option>) <>
+           ~s(</select>)
+
+    assert safe_form(&multiple_select(&1, :other, [{"foo", 1}, {"bar", 2}], selected: [2]), []) ==
+           ~s(<select multiple="" name="other[]">) <>
+           ~s(<option value="1">foo</option>) <>
+           ~s(<option value="2" selected>bar</option>) <>
+           ~s(</select>)
+
+    assert safe_form(&multiple_select(&1, :key, [{"foo", 1}, {"bar", 2}], value: [2]), []) ==
+           ~s(<select multiple="" name="key[]">) <>
+           ~s(<option value="1">foo</option>) <>
+           ~s(<option value="2" selected>bar</option>) <>
+           ~s(</select>)
+
+    assert safe_form(&multiple_select(&1, :key, ~w(value novalue), value: ["novalue"]), []) ==
+           ~s(<select multiple="" name="key[]">) <>
+           ~s(<option value="value">value</option>) <>
+           ~s(<option value="novalue" selected>novalue</option>) <>
+           ~s(</select>)
+
+    assert safe_form(&multiple_select(put_in(&1.params["key"], ["3"]), :key, [{"foo", 1}, {"bar", 2}, {"goo", 3}], selected: [2]), []) ==
+          ~s(<select multiple="" name="key[]">) <>
+          ~s(<option value="1">foo</option>) <>
+          ~s(<option value="2">bar</option>) <>
+          ~s(<option value="3" selected>goo</option>) <>
+          ~s(</select>)
+  end
+
   # date_select/4
 
   test "date_select/4" do