React Testing Library (RTL): test a responsive design
TLDR; You will not be able to test media-queries with current setup (jest-dom).
After debugging and going through github repository of jest-dom, it seems it will be pretty hard to test what responsive design.
There are couple of issue with the way, jest-dom (which uses jsdom) library renders component and calculates style.
To begin with, it doesn't attach/compute styles from attached stylesheet. This came with surprise to me as I am used to test UI with Angular setup. As mentioned in the attached link, you can try to overcome this issue by manually creating style element
const style = document.createElement('style')
style.innerHTML = `
@media screen and (min-width: 500px) {
.title .adjectives {
display: none;
color: red;
}
}
`;
document.body.appendChild(style)
or use helper function to do that as suggested in this bug.
After this change, I assumed it would work but to my surprise, it FAILED!, I checked with non-media query style and it was attaching style perfectly and that's when I discovered this TODO comment in jsdom, which makes sense as media-query styles are not working.
To conclude, it will not be possible to test media-query at the moment with react-testing-library. I haven't checked if it is working with enzyme setup, but it might who knows!
on you can use end to end testing framework such as Cypress.
React Testing Library - Failing to test Window Resize React Hook
I think there are a few things you have to change to make your test working again:
- You haven't waited to your debounce function work which is the main problem. So you can use either mock the timer or wait until your debounce function getting called.
// Make your test as `async` in case of wanting to wait
test("should return new values on window resize", async () => {
// If you go for mocking timer, uncomment this & below advance the timer
// jest.useFakeTimers();
const { result } = renderHook(() => useViewportSize());
act(() => {
window.resizeTo(500, 500);
//fireEvent(window, new Event("resize"));
});
// jest.advanceTimersByTime(251) // you can also use this way
await mockDelay(debounceDelay); // `await` 300ms to make sure the function callback run
expect(result.current.width).toBe(500);
expect(result.current.height).toBe(500);
});
- You might refine your implementation code by changing to use your mock value instead:
const debouncedHandleResize = debounce(() => {
setViewportSize({
// using your mock values
width: window.innerWidth,
height: window.innerHeight
});
}, debounceTime);
PS: I also edited your codesandbox based on the async way: https://codesandbox.io/s/useviewportsize-forked-pvnc1?file=/src/use-viewport-size.test.tsx
ant design v4 breaks react testing library tests for Select and Autocomplete
After losing 2 days on this, here is the problem and solution:
Problem
In antd v3 it used to be possible to open a Select by doing selectHtmlElement.click()
. You can test in the chrome dev tools console. In v4 this does not work.
This means that RTL which uses JSDOM under the hood will have the same behaviour. When you do fireEvent.click(selectElement);
nothing happens !
Solution
This put me on the right track: https://github.com/ant-design/ant-design/issues/22074
The event you need to trigger is not a click()
but a mouseDown()
on the first child of the select.
const elt = getByTestId('your-select-test-id').firstElementChild;
fireEvent.mouseDown(elt); // THIS WILL OPEN THE SELECT !
Now at this point you probably want to select an option from the list but there is an animation going on so the following code (that used to work in v3) will also fail.
expect(getByText('Option from Select')).toBeVisible(); // FAILS !
You have 2 options, use toBeInTheDocument()
or wait for the animation to be over by using waitFor(...)
Option 1: Faster but not totally accurate, I prefer to use this for simple use cases as it makes the tests faster and synchronous
expect(getByText('Option from Select')).toBeInTheDocument(); // WORKS !
Option 2: Slower as you need to wait for the animation to finish but more accurate for complex cases
await waitFor(() => expect(getByText('Option from Select')).toBeVisible()); // WORKS !
react-testing-library - Screen vs Render queries
The latest recommended option by the react-testing-library
author Kent C. Dodds himself is to use screen
.
The benefit of using
screen
is you no longer need to keep therender
call destructure up-to-date as you add/remove the queries you need. You only need to typescreen.
and let your editor's magic autocomplete take care of the rest.The only exception to this is if you're setting the
container
orbaseElement
which you probably should avoid doing (I honestly can't think of a legitimate use case for those options anymore and they only exist for historical reasons at this point).
Source: https://kentcdodds.com/blog/common-mistakes-with-react-testing-library#not-using-screen
Related Topics
<Style> and <Script> Tags Are Displayed Physically on Page
Firefox Displaying Table-Cell Incorrectly (Chrome Working Good)
Is The CSS3 Transform Translate Percentage Values Relative to Its Width And/Or Height
Word-Wrap Not Working in Internet Explorer
What to Use Instead of Contains() in CSS3
CSS3 Box-Shadow for Overlapping-Like Divs
Firefox Select Element Doubles Text-Indent Value
Translate3D Between 0% and Negative % in Ie10
Applying CSS Rules Based on Input Checkbox Status
How to Enable SASS Line Numbers in CSS Output
CSS3 Background-Size: Cover Doesn't Make Image Cover Vertically
CSS: :Before: :After Pseudo-Element of Class Not Working
Bootstrap Modal Restores Button Focus on Close
HTML5 Video with Fixed Height, But Scale Width to 100%
Flex-Flow: Column Wrap. How to Set Container's Width Equal to Content
How to Restore The "Auto" Values for List-Style-Type in Nested Unordered Lists