44 lines
1.7 KiB
TypeScript
44 lines
1.7 KiB
TypeScript
import { render, screen } from '@testing-library/react';
|
|
import userEvent from '@testing-library/user-event';
|
|
import { ThemeProvider } from '../../theme';
|
|
import RatingInput, { RatingInputProps } from './RatingInput';
|
|
|
|
function renderRating(props: Partial<RatingInputProps> = {}) {
|
|
const onChange = jest.fn();
|
|
const utils = render(
|
|
<ThemeProvider>
|
|
<RatingInput value={0} onChange={onChange} {...props} />
|
|
</ThemeProvider>,
|
|
);
|
|
return { ...utils, onChange };
|
|
}
|
|
|
|
describe('<RatingInput/> component', () => {
|
|
it('renders max stars and exposes the current value', () => {
|
|
const { container } = renderRating({ value: 3 });
|
|
expect(container.querySelector('[data-rating="3"]')).toBeInTheDocument();
|
|
expect(container.querySelectorAll('[data-star]')).toHaveLength(5);
|
|
});
|
|
|
|
it('calls onChange with the clicked star value', async () => {
|
|
const user = userEvent.setup();
|
|
const { onChange } = renderRating({ value: 0 });
|
|
await user.click(screen.getByRole('radio', { name: '4' }));
|
|
expect(onChange).toHaveBeenCalledWith(4);
|
|
});
|
|
|
|
it('reflects the chosen value on the matching star', () => {
|
|
renderRating({ value: 2 });
|
|
expect(screen.getByRole('radio', { name: '2' })).toHaveAttribute('aria-checked', 'true');
|
|
expect(screen.getByRole('radio', { name: '3' })).toHaveAttribute('aria-checked', 'false');
|
|
});
|
|
|
|
it('is a non-interactive display with no radios when readOnly', () => {
|
|
const { container, onChange } = renderRating({ value: 5, readOnly: true });
|
|
expect(container.querySelector('[data-rating="5"]')).toBeInTheDocument();
|
|
expect(container.querySelectorAll('[data-star]')).toHaveLength(0);
|
|
expect(screen.queryByRole('radio')).not.toBeInTheDocument();
|
|
expect(onChange).not.toHaveBeenCalled();
|
|
});
|
|
});
|