Here is a simple subcomponent that reveals an answer
to a question when the button is clicked:
const Question = ({ question, answer }) => {
const [showAnswer, setShowAnswer] = useState(false)
return (
<>
<article>
<header>
<h2 data-testid="question">{question}</h2>
<button onClick={() => setShowAnswer(!showAnswer)}>
{
!showAnswer ? <FiPlusCircle /> : <FiMinusCircle />
}
</button>
</header>
{
showAnswer && <p data-testid="answer">{answer}</p>
}
</article>
</>
)
}
export default Question;
I am trying to test that when the button
is clicked, the onClick
attached is called once and the a <p>
element appears on the screen:
const onClick = jest.fn()
test('clicking the button toggles an answer on/off', () => {
render(<Question />);
const button = screen.getByRole('button')
fireEvent.click(button)
expect(onClick).toHaveBeenCalledTimes(1);
expect(screen.getByTestId('answer')).toBeInTheDocument()
fireEvent.click(button)
expect(screen.getByTestId('answer')).not.toBeInTheDocument()
screen.debug()
})
RTL says that onClick
is not called at all (in the UI it is, as the result is as expected)
Also, if I want to test that this button really toggles the answer
element (message should come on and off) how would I test for that?
If I add another fireEvent.click()
to the test (simulating the second click on the button which should trigger the answer
element off), and add
expect(screen.getByTestId('answer')).not.toBeInTheDocument()
RTL will just not find that element (which is good, I guess, it means it has been really toggled off the DOM). What assertion would you use for this test to pass for that case?