I need to test that I can create a post having one category (chosen from an async loaded list) on my admin site.
I have a LiveComponent for a select which uses Tom Select JS with a phx-hook like this:
~H"""
<.field_wrapper errors={@errors} name={@name} class={@wrapper_class}>
<div
id={"#{@id}"}
phx-hook="ComboBox"
>
<div id={"#{@id}_wrapper"} phx-update="ignore">
<.field_label required={@required} for={@id} class={@label_class}>
<%= @label %>
</.field_label>
<div class="combo-box-wrapper">
<select
class={["combo-box", @class]}
multiple={@multiple}
name={@name}
required={@required}
{@rest}
>
<option :for={{value, label} <- @value} selected value={value}><%= label %></option>
</select>
</div>
</div>
</div>
</.field_wrapper>
Here’s the JS Hook:
Hooks.ComboBox = {
mounted() {
this.init(this.el)
},
init: async function (el) {
const settings = {
preload: 'focus',
load: (query, callback) => {
const params = {query: query}
this.pushEventTo(el, 'fetch_association', params, (data) => callback(data.results))
}
}
new TomSelect(el.querySelector('select.combo-box'), settings)
},
}
The <option>
s for the <select>
are loaded when the input is focused.
Before focusing, the select only has the options which are already associated to the post (which are empty in tests).
My test:
@create_attrs %{
category_id: "123",
title: "some title"
}
...
test "saves new post", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/posts/new")
assert view
|> form("#post-form", post: @create_attrs)
|> render_submit()
assert_patch(view, ~p"/posts")
end
I’m getting this error:
value for select "post[category_id]" must be one of [], got: "123"
I’m guessing that this is because the <option>
list is empty and Phoenix checks for a list of possible values?
How can I test this since the <option>
s are filled by the JS hook? I see that render_hook exists, but of course it doesn’t run the JS part.
I guess I can also avoid testing the JS hook itself by injecting a list of <option>
s for this test’s purpose, but I’m not sure how.
Thank you!