elixir-wallaby/wallaby

Cannot assert text exists if it is across multiple elements such as spans

tony-rowan opened this issue · 3 comments

Issue

Cannot assert with Query.text if some of the asserted text is within a <span> tag.

Details

Elixir: 1.13.0
Erlang: 23.1.4
OS: MacOS Monterey 12.3.1
Webdriver: chromedriver
Browser: Chrome
Local or CI: Locally

Test Code & HTML

<h1>Welcome to <span>My</span> New App!</h1>

<p>There is some more content here</p>
  feature "Can see the title", %{session: session} do
    session
    |> visit("/")
    |> assert_has(Query.text("There is some more content here"))
    |> assert_has(Query.text("Welcome to My New App!"))
  end

Project that reproduces the bug

https://github.com/tony-rowan/wallaby-query-text-bug-demo

This isn't really a bug and more a limitation of how querying HTML works.

If you really wanted to accomplish this as you have, you could get the innerHTML attribute of the h1 tag and then use something like Floki.

If your app uses liveview there is a chance you already have Floki installed.

    session
    |> visit("/")
    |> find(Query.css("h1"), fn header ->
      assert "Welcome to My New App!" ==
               header
               |> Element.attr("innerHTML")
               |> Floki.parse_document!()
               |> Floki.text()
    end)

Thanks for getting back so quickly and for the workaround. I wanted to avoid having to tie the tests to the exact HTML structure though, since this is not something that the users would be able to see.

The (very minimal) workaround I have at the moment is to check the text I'm looking for against the plain text on the page.

  def assert_has_text(session, text) do
    page_text = session |> Browser.text()
    assert page_text =~ text
    session
  end

The big drawback with this is that it doesn't include the automatic wait time for the assertion to become true. Is there a part of the API I'm missing that I can use to include this?

I actually was not remembering how the Browser.text/1 and Element.text/1 functions work.

The following is what you should do

    assert "Welcome to My New App!" ==
             session
             |> visit("/")
             |> find(Query.css("h1"))
             |> Element.text()

I think it is okay to query for the container of your text in your test.