How to ignore whitespace when asserting in ExUnit?


I am currently trying to write tests for some components I have been writing for Phoenix. I generally feel like I understand the testing story quite well, but one annoying thing about having HTML templates is the whitespace and assert html ~= ~S(rendered template) requiring the exact whitespace including all tabs. This results into me having to try around to find the exact tab levels.

In particular, something like

def render(_assigns) do
    <div class="bg-white shadow sm:rounded-lg">

requires a test assert like

    assert html =~ ~S(  <div class="bg-white shadow sm:rounded-lg">
    This is the card content.

That is, well, not ideal.

I have looked through the docs trying to find a sigil or function that strips all tabs and newlines from a string, but only found String.trim/1 that only works on leading and trailing whitespace.

Is there any way to accomplish this? I have looked at the Surface library tests too and they have whitespace all over the place as well.

Any help and pointer would be much appreciated!


Why don’t you just remove the whitespace before asserting equality ?

Something like:

def no_ws(str) do
  String.replace(str, ~r/\s/, "")


assert no_ws(expected) == no_ws(render(...))
# or just
assert "thisstringhasnowhitespace" == no_ws(render(...))
1 Like

You’d likely need a proper html parser to remove whitespaces in html correctly. But then you could likely use more high level api to assert the contents. LiveView uses floki for that.


A full parser like Floki is certainly the ideal.

In a pinch, something like String.replace(html, ~r(\s+), " ") will squash whitespace in a reasonable imitation of HTML’s display behavior:

squished_html = String.replace(html, ~r(\s+), " ")
assert squished_html =~ ~S(<div class="bg-white shadow sm:rounded-lg"> This is the card content. </div>)

but having typed that, I can 100% guarantee I’d wind up forgetting the spaces right next to > and < when working fast :frowning: