import {render, screen, waitFor} from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import {describe, expect, it, vi} from 'vitest';
import PlantingRating from './PlantingRating';
const planting = {id: 7, url: '/plantings/7'};
function stubFetch(ok) {
const fetch = vi.fn(async () => ({ok, status: ok ? 200 : 500, json: async () => ({})}));
vi.stubGlobal('fetch', fetch);
return fetch;
}
const star = (number) => screen.getByLabelText(`${number} of 5`, {exact: false, selector: 'input'});
describe('PlantingRating', () => {
it('shows the current rating', () => {
stubFetch(true);
render();
expect(star(4)).toBeChecked();
});
it('shows no rating when there is none', () => {
stubFetch(true);
render();
expect(screen.getByText('Not rated')).toBeInTheDocument();
});
describe('when a star is clicked', () => {
it('patches the planting with the rating', async () => {
const fetch = stubFetch(true);
render();
await userEvent.click(star(5));
expect(fetch).toHaveBeenCalledWith('/plantings/7', expect.objectContaining({
method: 'PATCH',
body: JSON.stringify({planting: {overall_rating: 5}}),
}));
});
it('shows the new rating', async () => {
stubFetch(true);
render();
await userEvent.click(star(5));
expect(star(5)).toBeChecked();
});
});
describe('when the save fails', () => {
it('goes back to the old rating', async () => {
stubFetch(false);
render();
await userEvent.click(star(5));
await waitFor(() => expect(star(2)).toBeChecked());
});
it('says the rating did not save', async () => {
stubFetch(false);
render();
await userEvent.click(star(5));
expect(await screen.findByRole('alert')).toHaveTextContent('didn’t save');
});
});
});