Open tangway opened 6 months ago
"test": "jest"
jest.config.cjs
file in root directoryran pnpm install --save-dev @testing-library/react @testing-library/jest-dom jest jest-environment-jsdom @babel/preset-env @babel/preset-react babel-jest
made jest.config.cjs
in root folder
module.exports = {
testEnvironment: 'jsdom',
verbose: true,
transform: {
'^.+\\.[t|j]sx?$': 'babel-jest',
},
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
};
made .babelrc
in root folder
{
"presets": ["@babel/preset-env", "@babel/preset-react"]
}
added jest to package.json
scripts to run
"scripts": {
"test": "jest"
},
added import React from 'react';
to all react components and this test passed
App.test.jsx:
import React from 'react';
import { render, fireEvent } from '@testing-library/react';
import App from '../src/App';
import questions from '../src/questions';
test('should set correct state to true when correct answer is selected', () => {
const { getByText } = render(<App />);
const correctAnswerButton = getByText(questions[0].answer);
// Check if the correct state is now true
fireEvent.click(correctAnswerButton);
});
realized that the above test does not check for state of correct
is set to true
and that it's not advisable to check for change via useState.
would need a visual change in the UI instead to test upon
found the right way to test for changed state from RTL recommended tutorial https://www.robinwieruch.de/react-testing-library/ under the chapter "When to use findBy?".
The findBy search variant is used for asynchronous elements which will be there eventually.
wrote up a test:
test('should display CORRECT when correct answer is selected', async () => {
const { getByText } = render(<App />);
const correctAnswerButton = getByText(questions[0].answer);
fireEvent.click(correctAnswerButton);
expect(await screen.findByText(/CORRECT/)).toBeInTheDocument();
});
problem that got me stuck for awhile:
somehow the result of fireEvent.click(correctAnswerButton)
made getStatus()
display "WRONG" even though it is clicking on the correct answer.
it took me some time to realize it was due to the fact that i had placed setCorrectAnswer
inside of the checkAnswer
function and since setState
functions are async it doesnt update immediately and when it checks if (userSelection === correctAnswer)
it would not be true
the offending code:
const checkAnswer = userSelection => {
setCorrectAnswer(questions[0].answer)
if (userSelection === correctAnswer) {
setCorrect(true);
} else {
setCorrect(false);
}
};
so the fix is to declare the state outside of the scope of the function:
const [correctAnswer, setCorrectAnswer] = useState(questions[0].answer);
and with that solved it was easy to write the other test case where the answer is wrong. this is what App.test.jsx
looks like now:
import React from 'react';
import { render, fireEvent, screen } from '@testing-library/react';
import { test, expect } from 'jest';
import '@testing-library/jest-dom';
import App from '../src/App';
import questions from '../src/questions';
test('should display CORRECT when correct answer is selected', async () => {
const { getByText } = render(<App />);
const correctAnswerButton = getByText(questions[0].answer);
fireEvent.click(correctAnswerButton);
expect(await screen.findByText(/CORRECT/)).toBeInTheDocument();
});
test('should display WRONG when wrong answer is selected', async () => {
const { getByText } = render(<App />);
const correctAnswerButton = getByText('Belize');
fireEvent.click(correctAnswerButton);
expect(await screen.findByText(/WRONG/)).toBeInTheDocument();
});
tests can be difficult to setup but working on a large scale application with many other people it has these advantages: