目前如何用JEST + React测试回调函数?



我想测试这个组件:

  1. onClick={() => onConfirmVote(number)}接收到的参数
  2. getVoteText
  3. 返回值

我的代码:

function CandidateList({ data }: IProps) {
const { convertToCurrency, convertToPercentage } = useNumberConversion();
const getVoteText = useCallback(
(total: number, percentage: number) => `${convertToCurrency(total)} (${convertToPercentage(percentage)})`,
[convertToCurrency, convertToPercentage]
);
return (
<ListGroup data-testid='candidate-list-component'>
{data.map(({ onConfirmVote, avatar, number, votesConfirmed, hasVoted }) => (
<ListGroup.Item key={`${number}`} as='li' className='d-flex flex-wrap gap-2 align-items-center'>
<div className='d-flex justify-content-between align-items-center w-100'>
<div className='d-flex flex-wrap align-items-center gap-2'>
<Avatar alt={`Candidate #${number}`} src={avatar} />
<h5 className='fw-bold mb-0'>#{number}</h5>
</div>
<div className='mt-1 d-flex flex-wrap align-items-center gap-2'>
<span className='mb-1'>Votes:</span>
<Badge bg='primary' pill style={{ width: '155px' }} data-testid='badge-vote-value-component'>
{getVoteText(votesConfirmed.total, votesConfirmed.totalPercentage)}
</Badge>
</div>
</div>
<Button className='w-100' variant='success' onClick={() => onConfirmVote(number)} disabled={hasVoted}>
CONFIRM
</Button>
</ListGroup.Item>
))}
</ListGroup>
);
}

MY TESTE CODE:

describe('[CANDIDATE LIST] - Testing Confirm Vote Button Component', () => {
test('Should be work on click to Confirm Vote!', () => {
render(<CandidateList data={MOCKED_DATA} />);
const confirmVoteButton = screen.getAllByRole('button');
confirmVoteButton.forEach(button => {
console.log(button);
expect(fireEvent.click(button)).toBe(true);
});
});
});

我已经简化了你的组件,你可以尝试这样做:

  • 组件
import React from "react";
const ManyButtons = ({ data }) => {
const getVoteText = (total, percentage) => `${total} (${percentage})`;
return (
<div>
{data.map(({ onConfirmVote, number, votesConfirmed: { total, totalPercentage } }, index) => (
<div key={index}>
<div>{getVoteText(total, totalPercentage)}</div>
<button onClick={() => onConfirmVote(number)}>
CONFIRM
</button>
</div>
))}
</div>
);
};
export default ManyButtons;

测试:

import { screen, render, fireEvent } from "@testing-library/react";
import ManyButtons from "../ManyButton";
const mockOnConfirmVote = jest.fn();
const mockedData = [
{ onConfirmVote: mockOnConfirmVote, number: 1, votesConfirmed: { total: 1, totalPercentage: 1 } },
{ onConfirmVote: mockOnConfirmVote, number: 2, votesConfirmed: { total: 2, totalPercentage: 2 } },
{ onConfirmVote: mockOnConfirmVote, number: 3, votesConfirmed: { total: 3, totalPercentage: 3 } },
]
describe('it should work', () => {
it('should work', () => {
render(<ManyButtons data={mockedData} />);
const buttons = screen.getAllByRole('button', { name: /confirm/i });
expect(buttons).toHaveLength(mockedData.length);
buttons.forEach(btn => fireEvent.click(btn))
expect(mockOnConfirmVote).toHaveBeenCalledTimes(buttons.length);
mockedData.forEach(({ number, votesConfirmed: { total, totalPercentage }}) => {
expect(mockOnConfirmVote).toHaveBeenCalledWith(number);
expect(screen.getByText(`${total} (${totalPercentage})`)).toBeInTheDocument();
})
})
})

最新更新