Friday, May 17, 2024
 Popular · Latest · Hot · Upcoming
150
rated 0 times [  156] [ 6]  / answers: 1 / hits: 9133  / 4 Years ago, sat, july 4, 2020, 12:00:00

I'm testing a connected functional component in ReactJS using jest and the react-testing-library.


The component renders some input fields and a button. Here's a simplified version of it, in which I decided to leave the full structure of GridContainer and GridItem components (from Material-UI) as they might play a role in this issue:


export function Letter(props) {
const [letter, setLetter] = useState({
// not relevant
});

return (
<GridContainer>
<GridItem md={6} sm={6}>
<GridContainer>
<GridItem>
<LetterImageUpload />
</GridItem>
<GridItem>
<LetterText />
</GridItem>
</GridContainer>
</GridItem>
<GridItem md={6} sm={6}>
<LetterAddress />
<GridContainer>
<Button
data-testid="AddToStoreButton"
onClick={() => {
props.addToStore(letter);
}}
>
Add to Store
</Button>
</GridContainer>
</GridItem>
</GridContainer>
);
}

function mapDispatchToProps(dispatch) {
return {
addToStore: letter => {
dispatch({ type: "ADD_TO_STORE", payload: letter });
}
};
}

export default connect(
null,
mapDispatchToProps
)(Letter);

As you can see I export both the dumb component and the connected component (the latter via export default), so that I can just import { Letter } in my tests and not bother about the redux store (is this the right way?).


The accompanying test goes like this:


import { Letter } from "components/Letter/Letter.js";

let container = null;
beforeEach(() => {
container = document.createElement("div");
document.body.appendChild(container);
});

afterEach(() => {
unmountComponentAtNode(container);
container.remove();
container = null;
});

test("Letter", () => {
act(() => {
render(<Letter addToStore={jest.fn()} />, container);
});
// FIXME: querySelector returns null
container.querySelector('[data-testid="AddToStoreButton"]').simulate("click");
// assert
});

In a debugger I can see that querySelector returns null regardless of the selector I used.
For instance, I tried the following in the live debugger:


> container.querySelector('[data-testid="AddToCartButton"]')
null
> container.querySelector("button")
null
> container.querySelector("div")
null

I'm clearly doing something spectacularly wrong. Can anyone spot it?


More From » reactjs

 Answers
10

Following the tip by Anthony, it turned out I was using render from the react testing library, but actually using as it were the one exported by the "react-dom" library.


The complete solution, using the react testing library looks like this:


import { fireEvent, render } from "@testing-library/react";

test("Letter", () => {
const { getByTestId } = render(<Letter addToStore={() => {}} />);
fireEvent.click(getByTestId("AddToStoreButton"));
// assert
});

Just to add a bit of more context, if you follow the approach shown in the Testing Recipes on ReactJS.org, you'll need to import { render } from "react-dom", instead.


[#3290] Wednesday, July 1, 2020, 4 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
tayla

Total Points: 681
Total Questions: 102
Total Answers: 108

Location: Marshall Islands
Member since Tue, Sep 21, 2021
3 Years ago
tayla questions
Fri, Mar 5, 21, 00:00, 3 Years ago
Wed, Oct 28, 20, 00:00, 4 Years ago
Thu, Apr 9, 20, 00:00, 4 Years ago
Mon, Dec 9, 19, 00:00, 5 Years ago
;