How do we write a test for a function component that is a button with a logo?

I have a function component button that takes an optional slot ‘icon’ between which if an icon is passed, it will render it along with the button label

I’ve also added an option to render the icon either left or right of the button label. This is accomplished by passing an icon_position parameter to the button.

How do we write a test to verify if the icon appears on the left/right side of the button label? Here’s my code-

<.link href={@to} class={get_button_classes(assigns)}>
          <%= if @icon && @icon_position == "left" do %>
            <%= render_slot(@icon) %>
          <% end %>
          <%= render_slot(@inner_block) %>
          <%= if @icon && @icon_position == "right" do %>
            <%= render_slot(@icon) %>
          <% end %>
        </.link>

Thanks in advance

Using HtmlQuery, I’d do this:

<.link href={@to} class={get_button_classes(assigns)} test-role="nav">
  <div :if={@icon && @icon_position == "left"} test-role="icon-left">
    <%= render_slot(@icon) %>
  </div>
  <%= render_slot(@inner_block) %>
  <div :if={@icon && @icon_position == "right"} test-role="icon-right" %>
    <%= render_slot(@icon) %>
  </div>
</.link>
assert HtmlQuery.find(html, "[test-role=nav] [test-role=icon-left]")
refute HtmlQuery.find(html, "[test-role=nav] [test-role=icon-right]")

I might also test that the icon exists; if it’s an SVG, a test might look like this:

assert HtmlQuery.find(html, "[test-role=nav] [test-role=icon-left] svg")

or even:

assert HtmlQuery.find(html, "[test-role=nav] [test-role=icon-left] svg[test-role=logo]")

I don’t remember exactly what that looks like using the built-in LiveViewTest stuff; probably something like:

assert html |> element("[test-role=nav] [test-role=icon-left]") |> render()
1 Like

If you don’t want to bring in another dependency, something like the following might work:

test "icon is rendered on the left side correctly" do
  markup = rendered_to_string(~H"""
    <.link icon_position="left">
      <:icon>...</:icon>
    </.link>
  """)

  assert markup =~ ~s(data-role="icon-left")
  refute markup =~ ~s(data-role="icon-right")
end
1 Like

Could also split by the content and see where the icon is.

test "icon is rendered on the left side correctly" do
  markup = rendered_to_string(~H"""
    <.link icon_position="left">
      <:icon>icon</:icon>
      content
    </.link>
  """)

  [left_of_content, right_of_content] = String.split(markup, "content")
  assert left_of_content =~ "icon"
  refute right_of_content =~ "icon"
end
2 Likes

We are just assigning an attribute icon_position to the component. How will Phoenix know to take it as a data-role?

Thanks! This fixed the test!