I have a LiveView that starts a GenServer on mount. This GenServer loads data and at some point broadcasts a message to a topic that the LiveView is subscribed to.
How to write tests for this?
test "displays company name", %{conn: conn} do
{:ok, view, html} =
live_isolated(conn, MyLiveView, session: %{"customer_id" => "5013"})
assert html =~ "Company Name"
end
Company Name is rendered after the PubSub message is received. But the live_isolated in the test gives me the html right after mount. So how can I get the new html in the test?
I ran into this same problem and wanted to try your solution, but the funciton wait_until does not seem to be a liveview function… I get an undefined function error.
Thanks for this for others who come across this thread, here’s a helper I wrote which uses this function specifically for rendering LiveViews:
@doc """
Wait for a LiveView html-based assertion to pass.
Accepts a LiveView from Phoenix.LiveViewTest.live/2, and a function
of arity 1, which gets passed html from the rendered LiveView.
Returns the rendered html which passed the assertion.
## Examples
iex> {:ok, lv, _html} = live(conn, ~p"/rooms/4")
iex> html = render_until(lv, fn html -> assert html =~ "Loading finished!" end)
"""
def render_until(lv, fun) do
wrapped_fun = fn ->
html = Phoenix.LiveViewTest.render(lv)
fun.(html)
html
end
MyApp.TimeHelper.wait_until(wrapped_fun)
end
A better way to test this is to (if you’re using PubSub) subscribe your test process to the topic and then assert_receive on the message from PubSub in your test pid.
Then you can render your LiveView and the html will be there and you don’t need busy waiting loops in test
Funnily I actually came to this thread because that exact solution to my problem didn’t work. There’s still a race condition because the test process can receive the message before the LiveView process does. My tests tend to fail very rarely on local, but very commonly on CI (via GitHub Actions, not sure exactly what the deal with that is). There are some different solutions proposed in this thread: Testing LiveViews that rely on PubSub for updates, I haven’t tried the :sys.get_state/1 solution but maybe I’ll try writing a different helper with that and see if it’s reliable.