The idea of "testing what the user sees" makes a lot of sense to.
There's a conversation going on about how to test the order of elements. At this point it's inconclusive. I think users would benefit from some guidance around testing order of elements and how to reconcile this concern with the guiding principles.
It is possible that I am completely on the wrong track here. Any input is appreciated.
Hey Max. Just a thought, I鈥檇 consider not testing from this angle. It seems like an implementation detail.
To me what seems to matter most in your example from the chat is that given a list of data, your component successfully renders it. It shouldn鈥檛 crash, and you should see all of the content in a list item that you expect to see. If you know that the list renders and that an item displays what you expect it to, I struggle to see what confidence you鈥檇 get from knowing that it renders them in the order of the provided data.
Alternatively, get creative! Do something like give each of your list item wrappers a dynamic aria label, then queryByLabelText(/item-.*/). This will give you a list of your items that you can loop over and assert on.
Again, I don鈥檛 think it鈥檚 necessary, but it鈥檚 an approach you could consider if you really feel you need to test it. Good luck!
I'd recommend something like putting a testid or aria-label on the list items, then asserting by verifying the items returned by queryAllBy... are in the right order. But as someone pointed out in Spectrum it is possible to reverse a list of nodes in CSS, so bear that in mind.
thanks @bcarroll22 @alexkrolick
Another way to do this is to use the underlying dom testing lib to search in specific elements. The following example gets all table rows and checks then for specific text in each row.
````
import { getByText as domGetByText } from "@testing-library/dom"
describe("StockTable", () => {
it("renders countries in correct order by country code", async () => {
const { getAllByTestId } = render(
const tableRows = getAllByTestId("table-row")
domGetByText(tableRows[0], /Denmark/)
domGetByText(tableRows[1], /Spain/)
domGetByText(tableRows[2], /France/)
})
})
```
Hello Max. I had a similar issue. I've solved as shown below, without breaking [the guiding principles], I hope. As someone said CSS could make a difference for the user. But anyway, for my case the below works (tweaked for your use-case):
import { render } from '@testing-library/react';
import React from 'react';
const Hello = ({ names }) => (
<div>
{names.map((name, index) => (
<p key={index}>{name}</p>
))}
</div>
);
it('<Hello /> displays names in order', () => {
const { queryAllByText } = render(
<Hello names={['test-name-1', 'test-name-2', 'test-name-3']} />,
);
const names = queryAllByText(/test-name-[1-3]/);
expect(names).toHaveLength(3);
expect(names[0]).toHaveTextContent('test-name-1');
expect(names[1]).toHaveTextContent('test-name-2');
expect(names[2]).toHaveTextContent('test-name-3');
});
Most helpful comment
Hello Max. I had a similar issue. I've solved as shown below, without breaking [the guiding principles], I hope. As someone said CSS could make a difference for the user. But anyway, for my case the below works (tweaked for your use-case):