Today I put together one technique I find useful for writing test. That is to use data attributes for finding DOM elements in test. The same idea can apply to JavaScripting, but I focus mainly on Phoenix LiveView testing here because that is the one I have been working on.
TL;DR
As of writing, I prefer to take advantage of data attributes over using commonly used Id selectors. Particularly, I love the flexibility and explicitness of the custom data-role
attribute.
Given that we have this HTML document
defmodule MnishiguchiWeb.AlchemistsLive do
use MnishiguchiWeb, :live_view
alias Mnishiguchi.Alchemists
@impl Phoenix.LiveView
def mount(_params, _session, socket) do
{:ok, assign(socket, alchemists: Alchemists.list_alchemists())}
end
@impl Phoenix.LiveView
def render(assigns) do
~L"""
<div class="row">
<%= for alchemist <- @alchemists do %>
<div class="card mb-3" data-role="alchemist-card" data-id="<%= alchemist.id %>">
<div class="card-body">
<h5 class="card-title"><%= alchemist.name %></h5>
</div>
<div>
<% end %>
</div>
"""
end
end
In test code, we can find a given DOM element by data-role
.
defmodule MnishiguchiWeb.AlchemistsLiveTest do
use MnishiguchiWeb.ConnCase, async: true
import Phoenix.LiveViewTest
@path "/alchemists"
test "displays alchemists", %{conn: conn} do
alchemist1 = create_alchemist(name: "Taro Yamada")
{:ok, view, _disconnected_html} = live(conn, @path)
assert has_alchemist_card?(view, "Taro Yamada")
refute has_alchemist_card?(view, "Jiro Yamada")
end
defp has_alchemist_card?(view, name) do
has_element?(view, "[data-role=alchemist-card]", name)
end
end
In case we want to pinpoint a specific list item for example, we could use both data-role
and data-id
attributes.
defp has_alchemist_card?(view, id, name) do
has_element?(view, "[data-role=alchemist-card][data-id=#{id}]", name)
end
Phoenix.LiveViewTest is so awesome that it allows us to test our dynamic pages easily without the need of a headless browser.
Alternative approaches
Of course, we can use other CSS selectors as well. Here are some commonly-used selectors.
The data-test-id
is similar to data-role
but the difference is to me data-test-id
is less descriptive because it is test specific as opposed to data-role
defining semantics of the DOM element itself.
While data-role
is just a custom data attribute, ARIA roles are more formal standard or specifications and as of writing, details of many roles are to be determined.
Advantages of using data attributes
To me, some advantages of using data attributes are:
- minimize the risk of accidentally breaking test code when styling pages
- enable us to describe what the element is flexibly
- make the DOM self explanatory
Disadvantages of using data attributes
I am aware of some disadvantages, but they are no big deal.
- a little verbose
- many examples out there might use DOM Id or class for finding an element
That's it!
Top comments (0)