Testing GreetLive
We’ll test that we can find some text rendered by a LiveView.
If you look at our router, you’ll see we’re mounting a new LiveView in /greet.
# lib/ranger_web/router.ex
live "/greet", GreetLive
Here’s our code found in lib/ranger_web/live/greet_live.ex:
defmodule RangerWeb.GreetLive do
use RangerWeb, :live_view
def render(assigns) do
~H"""
<%= if @live do %>
<h1 class="text-4xl font-bold tracking-tight sm:text-center sm:text-6xl">
Welcome to Testing LiveView
</h1>
<% else %>
<h1 class="text-4xl font-bold tracking-tight sm:text-center sm:text-6xl">
Welcome to stateless HTTP
</h1>
<% end %>
"""
end
def mount(_, _, socket) do
if connected?(socket) do
{:ok, assign(socket, :live, true)}
else
{:ok, assign(socket, :live, false)}
end
end
end
GreetLive conditionally renders text on the screen based on whether or not the LiveView is connected.
LiveView’s life-cycle first makes a stateless HTTP request. Then, it upgrades the connection to a websocket. We’ll see how we can test both scenarios.
Testing GreetLive
Open the corresponding test file located in test/ranger_web/live/greet_live_test.exs.
Since this is our first test, let’s talk about the setup.
Setup required for LiveView tests
# test/ranger_web/live/greet_live_test.exs
defmodule RangerWeb.GreetLiveTest do
use RangerWeb.ConnCase
import Phoenix.LiveViewTest
end
- We use
RangerWeb.ConnCasejust like we do in controller tests because we need a connection struct in every test to mount the live view. - We then import
Phoenix.LiveViewTestto get all the helpers we’ll need to mount the live view, interact with it, and assert things about it.
Testing stateless HTTP rendering
This test will check the disconnected state of the LiveView.
test "rendering disconnected state", %{conn: conn} do
disconnected = conn |> get(~p"/greet")
assert html_response(disconnected, 200) =~ "Welcome to stateless HTTP"
end
We assert that the HTML string returned has the text "Welcome to stateless HTTP" somewhere in the HTML.
We can run the test with mix test path/to/test/file:
mix test test/ranger_web/live/greet_live_test.exs
.
Finished in 0.1 seconds
1 tests, 0 failures, 0 excluded
Excellent. As you can see, our test found the text our LiveView renders when it is not connected.
Upgrade connection with live/2
LiveViewTest has a live/2 helper that can upgrade the connection. Let’s use that:
test "upgrading to connected state", %{conn: conn} do
disconnected = conn |> get(~p"/greet")
{:ok, _view, html} = live(disconnected)
assert html =~ "Welcome to Testing LiveView"
end
Let’s break the test down:
- The
live/2helper comes fromPhoenix.LiveViewTest. We only pass one argument tolive/2and leave the second as the default (which isnil). That returns a three tuple,{:ok, view, html}. - We’ll ignore the
viewfor now. We’ll talk about that in a second. - The
htmlreturned is the HTML returned from the connected state. - We make a similar assertion to the one we made with the disconnected state. In this case we assert that the
"Welcome to Testing LiveView"string is somewhere in the HTML blob.
Run the test, and it works!
mix test test/ranger_web/live/greet_live_test.exs
.
Finished in 0.1 seconds
1 tests, 0 failures, 0 excluded
We’re now testing the text that comes from the connected LiveView.
Passing the path to live/2
Typically, we don’t need to test the stateless HTTP request and response.
We can simplify our test by using live/2 and passing the path as the second argument.
live/2 performs the stateless request for us behind the scenes, upgrades the connection, and returns the connected HTML as the third element of the tuple.
test "rendering connected state", %{conn: conn} do
{:ok, _view, html} = live(conn, ~p"/greet")
assert html =~ "Welcome to Testing LiveView"
end
Run the test to confirm it works as expected:
mix test test/ranger_web/live/greet_live_test.exs
.
Finished in 0.1 seconds
1 tests, 0 failures, 0 excluded
Using view
Thus far, we’ve only looked at the html portion of the live/2 helper.
But the helper returns a view as a second argument. That view is a struct full of information that will allow us to interact with the LiveView.
We’ll do more of that in future videos, but for now, you will see that view has some information like:
- the module we’re testing, and
- the process ID of the LiveView.
But, most importantly, we can pass that view to render functions to render the HTML on the page:
test "rendering with the view", %{conn: conn} do
{:ok, view, _html} = live(conn, "/greet")
assert view.module == RangerWeb.GreetLive
assert is_pid(view.pid)
assert render(view) =~ "Welcome to Testing LiveView"
end
You might not see much difference between the html rendered and what we get from render(view), but in future lessons, we’ll see how we can interact with the page and re-render the resulting HTML.
For now, you can see the live/2 helper is the key to accessing the world of LiveView testing.