elm-explorations / test

Write unit and fuzz tests for Elm code.
https://package.elm-lang.org/packages/elm-explorations/test/latest
BSD 3-Clause "New" or "Revised" License
236 stars 40 forks source link

Query.has [Selector.text] does not match exact text #197

Closed khrynczenko closed 1 year ago

khrynczenko commented 1 year ago

Hello, Lately while writing some tests where I wanted to make sure that the text inside an html element is exactly the same as what I want I found something unexpected (at least to me). It seems that using Query.has together with Selector.text is not powerful enough to make proper tests that should check for exact match of a text inside. Instead what actually happens is it checks whether the content contains a text provided in an argument.

Example: We want to make sure that the numbers inside our Html msg are rounded to 2 decimal places. Let's say that Query.fromHtml returns a value representing following html.

        <span class="s1">
            <span class="s3">
                11,22
            </span>
        </span>

We pass that into Query.has [ Selector.text "11,22" ]. Everything works fine so far but let's say that the logic changes for some reason and the following is returned.

        <span class="s1">
            <span class="s3">
                11,222
            </span>
        </span>

The same test will not fail and we will not even notice the problem until we find about it during runtime. Is there a way to write this test better? Maybe there should something like Selector.textExact :thinking: ? I hope I explained my self well, if you need some clarification, let me know.

Janiczek commented 1 year ago

Hey there @khrynczenko! Sorry for the radio silence, I was mistakenly assuming a specific person was "in charge" of Html.* modules in this library. That was incorrect, so I'll discuss this with you :wave:

Is my understanding correct that you want to keep Selector.text behaviour the same and want to add Selector.textExact where Query.has [ Selector.textExact "11,22" ] would fail for <span class="s3"> 11,222 </span>?

khrynczenko commented 1 year ago

Thanks for the response @Janiczek. That is exactly what I had in mind.

Janiczek commented 1 year ago

How should it behave wrt. the whitespace?

<span class="s1">
  <span class="s3">
    11,22
  </span>
</span>

does have whitespace around the 11,22, so the exact string to match is something like

"\n    11,22\n  "

In other words, if we don't deal with trimming, Selector.textExact "11,22" would fail for the above example. The following test would pass:

        , test "No trimming is happening" <|
            \() ->
                Html.div [] [ Html.text """
                    We like whitespace
                """ ]
                    |> Query.fromHtml
                    |> Query.hasNot [ textExactly "We like whitespace" ]
--                              ^^^

Do you agree with that, or should the text be implicitly trimmed before compared to the argument of textExact? (Followup: should the argument also be trimmed?)

khrynczenko commented 1 year ago

To be honest I am not sure, maybe it would be best do allow regular expression as an argument which would give users the most freedom? :thinking: For my particular use case trimming is fine, but I wonder what others users might want. What do you think?

Janiczek commented 1 year ago

So far you're the only user (calling for this function) 🙂 I see three options:

I can't think of examples of any other variants that would warrant the fully generic regex case. Maybe we just need three functions instead of two?

khrynczenko commented 1 year ago

Exact match with trimming is what I would go for to add. I don't see myself using exact match without trimming since I want to test the content that would be actually rendered to the user anyway.

khrynczenko commented 1 year ago

@Janiczek Let me scratch that actually because I got confused it seems. When we would call Query.has [textExactly "whatever"]. It matches against what we provided to the text function. So if my code is something like:

    span [ class "price" ] [ text "11.22 EUR" ]

I don't need any trimming. So in the end I think this function should not trim am I right? I am very sorry, I got confused.

khrynczenko commented 1 year ago

Just make this more clear. When I have a code like below.

   span [ class "price" ] [ text "11.22" ]

If I call

Query.has [ Selector.text  "11.22" ]

It will match against this.

   span [ class "price" ] [ text "11.22" ]

And the following.

   span [ class "price" ] [ text "11.222" ]

What I want is to match only against the first case which is this and only this.

   span [ class "price" ] [ text "11.22" ]

No trimming is necessary or anything like that. Does this makes sense?

Janiczek commented 1 year ago

Yes. That's without trimming, it's essentially <span class="price">11.22</span>, with no whitespace. Alright! I guess since we're testing Elm views, there won't be a lot of whitespace around that would normally be the case with hand-written / pretty-printed HTML. Makes sense, I'll update the PR.

Janiczek commented 1 year ago

Published in 2.1.0, let me know how it goes!

khrynczenko commented 1 year ago

It works smoothly. Thanks :)