New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add an assertion helper for checking an element's children #27
Comments
Hey @PJUllrich. Good to hear from you! Thanks for giving PhoenixTest a try an opening an issue. Right now, all the functions are working with CSS selectors because I find that to be very flexible because -- since it allows us to specify anything with CSS selectors. But I'd be interested to hear more about what you're looking for. Are you saying you'd be looking for something like one of these? Or do you have some other type of assertion in your mind? |> assert_has?(within("#mytable"), "tr", "My second row")
# or
|> within("#mytable", fn session ->
assert_has?(session, "tr", "My second row")
end)
# or
assert_has?(child("#mytable", "tr"), "My second row") |
hey hey, so I'm just dreaming here and am not sure whether it's feasible to implement this, but what would be great if I could "step" through the children of an element in general. So, imagine I have the following HTML: <table id="mytable">
<tr data-id="row-1">
<td>Hello World</td>
</tr>
<tr data-id="row-2">
<td>Good bye</td>
</tr>
</table> Now, common test cases that I have to write for such HTML are:
I guess, in pseudo code, this could be: row = nth_child("#mytable", "tr", 1)
assert_has_attribute(row, "data-id", "row-1")
assert_contains(row, "Hello World") This test would get the table and its first I don't think this could be done with CSS, but I'm unsure. Maybe Floki woudl be a better option here? That parses the HTML, so it might be easier to navigate through the children of an element. |
I have a The In a LiveViewTest I've always done it like this: build(:foo, name: "Bender", position: 3)
build(:foo, name: "Fry", position: 2)
build(:foo, name: "Leela", position: 1)
build(:foo, name: "Amy", position: 4)
# ...
assert lv
|> element("ul.my-list")
|> render() =~ ~r/Leela.*Fry.*Bender.*Amy/s It would be great to be able to do something like:
Just spitballing on the syntax there (though I am personally a fan of that closure version). I'm not certain if it's a goal of this lib to be able to use completely in place of LiveViewTest, but oh boy it was a little painful having to bring it in just for that :) (Nothing against LVT, of course, this lib is just so nice!) |
So I threw together a quick prototype and I realized that it really doesn't buy all that much since this is all possible with CSS. If you're interested it's here but all it does is provide the |> within("ul.my-list", fn element ->
element
|> assert_has("li:nth-child(1)", "Leela")
|> assert_has("li:nth-child(2)", "Fry")
|> assert_has("li:nth-child(3)", "Bender")
end) As soon as I got this far I was like, "Waitammit, this is all already possible albeit slightly more verbose": |> assert_has("ul.my-list li:nth-child(1)", "Leela")
|> assert_has("ul.my-list li:nth-child(2)", "Fry")
|> assert_has("ul.my-list li:nth-child(3)", "Bender") @PJUllrich your example should be achievable like so: assert_has("#my-table tr[data-id=row-1]:nth-child(1)", "Hello world") I think this is somewhat of the same thought process I went through implementing my own within but I was never using Floki directly so I didn't quite reach this far. In any event, perhaps something like this would still be desirable for people who are CSS-adverse. Asserting on order is also pretty common so maybe a helper that does that would be in ahem order. Something like:
The first arg would be the selector to add |
While this is getting a bit off topic, I did a quick prototype of def assert_order(session, child_selector, texts) when is_list(texts) do
texts
|> Enum.with_index()
|> Enum.each(fn {text, index} ->
assert_has(session, "#{child_selector}:nth-child(#{index + 1})", text)
end)
end assert_order(session, "ul li", ~w(Leela Fry Bender)) I could be made a little more efficient but that would require more intrusive changes and not sure it would make that big of a difference. Not sure the function is even worth it but was getting into thinking about all of this so I thought I'd try it out. |
Love the discussion here! 馃コ I think for now, I'm hesitant to introduce a lot more assertion helpers like And even though I like the ergonomics of But I feel your pain. I've had to assert against lists before, and there's always a desire to make it easy to say "assert that the second element has text I think having CSS selector helpers could be an interesting idea because we keep the flexibility of CSS, keep the existing workflow, and make them an optional layer that we can put on top of the existing library. What if we were to translate your CSS into something that feels easier to user? # before
assert has_element?(view, ~s(table#my-table > tr:nth-of-type\(2\)), "My second row")
# after
session
|> assert_has(nth_child("#my-table", "tr", n: 2), "My second row") |
I actually wasn't really suggesting
assert_has("#my-table tr", "My second row", nth_child: 2) or, sort of taking inspiration from Wallaby assert_has("#my-table tr", "My second row", css: [nth_child: 2]) Of course all of these ideas (including your function idea) could be a slippery slope of people asking for all of CSS as options. |
Sooooo now that I think more about this, a helper more like what you most recently suggested @germsvel could actually be pretty dang nice. I'm not 100% on a name but I'm thinking a simple 2-arity function that constructs an |> assert_has(nth_child("#my-table tr", 2), "My second row") It feels gratuitous to have have an extra parameter to drill down into children when it's literally just a space in CSS. The value I'm starting to see in this function is NOT to hide CSS from people, but simply to have cleaner, more expressive tests. Other possibilities for names could be:
WDYT? |
@sodapopcan yeah, if we go down the route of what I'm going to call CSS selector aliases (thin wrappers around CSS selectors), the questions then become:
Off the top of my head:
I think that would cover most of my use cases. At least, I think it would. And since the helpers just render text, we could theoretically combine them: assert_has(within(id("user"), class("post")), "User's post") |
I think this hits the problem I mentioned above where this becomes a slippery slop. For me there is zero value in providing a function just to do |
Sorry for my absence here. I just wanted to chime in that I like this suggestion by @sodapopcan the best:
However, the parameters of the
Something like that. For the general discussion, I don't think CSS helpers are super important right now. The topic of this issue was more: "How can we extend the library to better test tables?". So, rather topical than general. |
Yeah, I agree that the At that point, I might want to add something like For the sake of this discussion, I think it could be interesting to add |
@germsvel I think so. Let's give it a try. |
Just want to throw in that it would be nice to have |
@PJUllrich @sodapopcan curious what you think of the approach in #46 |
@PJUllrich I ended up going a different route for this, but I think the solution would fit your problems.
For example, if you want to assert that the second assert_has(session, "table#my-table tr", at: 2, text: "My second row") It hasn't been released yet, but it should be available in |
Hey German 馃憢
First of all, thank you very much for this great library! 馃殌
I have a feature request: I work a lot with lists and tables and have to assert often that e.g. the first row in a table contains a certain text. Until now, I write custom CSS selectors like e.g.:
Do you think we could maybe add a helper that makes this easier to the library?
The text was updated successfully, but these errors were encountered: