diff --git a/packages/sanity/src/core/releases/tool/detail/__tests__/ReleaseDetail.test.tsx b/packages/sanity/src/core/releases/tool/detail/__tests__/ReleaseDetail.test.tsx index 10a32c2fdc6..1f6ac051bf6 100644 --- a/packages/sanity/src/core/releases/tool/detail/__tests__/ReleaseDetail.test.tsx +++ b/packages/sanity/src/core/releases/tool/detail/__tests__/ReleaseDetail.test.tsx @@ -157,7 +157,6 @@ describe('ReleaseDetail', () => { describe('after releases have loaded', () => { describe('with unpublished release', () => { - const currentDate = new Date().toISOString() beforeEach(async () => { vi.clearAllMocks() }) @@ -167,16 +166,6 @@ describe('after releases have loaded', () => { fireEvent.click(screen.getByTestId('release-menu-button')) screen.getByTestId('archive-release-menu-item') }) - - // eslint-disable-next-line no-warning-comments - // TODO: unsure if this will work this way in the future - /*it('should navigate to release review changes screen', () => { - expect(screen.getByTestId('review-button').closest('button')).not.toBeDisabled() - fireEvent.click(screen.getByTestId('review-button')) - expect(mockRouterNavigate).toHaveBeenCalledWith({ - path: '/test-release-id?screen=review', - }) - })*/ } describe('with pending document validation', () => { diff --git a/packages/sanity/src/core/releases/tool/detail/__tests__/ReleaseTypePicker.test.tsx b/packages/sanity/src/core/releases/tool/detail/__tests__/ReleaseTypePicker.test.tsx new file mode 100644 index 00000000000..739c86487fa --- /dev/null +++ b/packages/sanity/src/core/releases/tool/detail/__tests__/ReleaseTypePicker.test.tsx @@ -0,0 +1,201 @@ +import {fireEvent, render, screen, waitFor, within} from '@testing-library/react' +import {beforeEach, describe, expect, it, vi} from 'vitest' + +import {getByDataUi, queryByDataUi} from '../../../../../../test/setup/customQueries' +import {createTestProvider} from '../../../../../../test/testUtils/TestProvider' +import {useTimeZoneMockReturn} from '../../../../scheduledPublishing/hooks/__tests__/__mocks__/useTimeZone.mock' +import { + activeASAPRelease, + activeScheduledRelease, + activeUndecidedRelease, + publishedASAPRelease, +} from '../../../__fixtures__/release.fixture' +import {releasesUsEnglishLocaleBundle} from '../../../i18n' +import { + mockUseReleaseOperations, + useReleaseOperationsMockReturn, +} from '../../../store/__tests__/__mocks/useReleaseOperations.mock' +import {ReleaseTypePicker} from '../ReleaseTypePicker' + +vi.mock('../../../store/useReleaseOperations', () => ({ + useReleaseOperations: vi.fn(() => useReleaseOperationsMockReturn), +})) + +vi.mock('../../../../scheduledPublishing/hooks/useTimeZone', async (importOriginal) => ({ + ...(await importOriginal()), + useTimeZone: vi.fn(() => useTimeZoneMockReturn), +})) + +const renderComponent = async (release = activeASAPRelease) => { + const wrapper = await createTestProvider({ + resources: [releasesUsEnglishLocaleBundle], + }) + + render(, {wrapper}) + + await waitFor(() => { + expect(screen.getByTestId('release-type-picker')).toBeInTheDocument() + }) +} + +const mockUpdateRelease = vi.fn() + +describe('ReleaseTypePicker', () => { + beforeEach(() => { + vi.clearAllMocks() + mockUseReleaseOperations.mockReturnValue({ + ...useReleaseOperationsMockReturn, + updateRelease: mockUpdateRelease.mockResolvedValue({}), + }) + }) + + describe('renders the label for different release types', () => { + it('renders the button and displays for ASAP release', async () => { + await renderComponent() + + expect(screen.getByText('ASAP')).toBeInTheDocument() + }) + + it('renders the button and displays for undecided release', async () => { + await renderComponent(activeUndecidedRelease) + + expect(screen.getByText('Undecided')).toBeInTheDocument() + }) + + it('renders the button and displays the date for scheduled release', async () => { + await renderComponent(activeScheduledRelease) + + expect(screen.getByText('Oct 10, 2023', {exact: false})).toBeInTheDocument() + }) + }) + + describe('interacting with the popup content', () => { + it('opens the popover when the button is clicked', async () => { + await renderComponent() + + const pickerButton = screen.getByRole('button') + fireEvent.click(pickerButton) + getByDataUi(document.body, 'Popover') + }) + + it('does not show calendar for ASAP and undecided releases', async () => { + await renderComponent() + + const pickerButton = screen.getByRole('button') + fireEvent.click(pickerButton) + expect(screen.queryByTestId('date-input')).not.toBeInTheDocument() + expect(queryByDataUi(document.body, 'Calendar')).not.toBeInTheDocument() + + const scheduledTab = screen.getByText('Undecided') + fireEvent.click(scheduledTab) + expect(screen.queryByTestId('date-input')).not.toBeInTheDocument() + expect(queryByDataUi(document.body, 'Calendar')).not.toBeInTheDocument() + }) + + it('switches to "Scheduled" release type and displays the date input', async () => { + await renderComponent() + + const pickerButton = screen.getByRole('button') + fireEvent.click(pickerButton) + const scheduledTab = screen.getByText('At time') + fireEvent.click(scheduledTab) + expect(screen.getByTestId('date-input')).toBeInTheDocument() + expect(getByDataUi(document.body, 'Calendar')).toBeInTheDocument() + }) + + it('hides calendar when moving back from scheduled option', async () => { + await renderComponent() + + const pickerButton = screen.getByRole('button') + fireEvent.click(pickerButton) + const scheduledTab = screen.getByText('At time') + fireEvent.click(scheduledTab) + const asapTab = screen.getByText('ASAP') + fireEvent.click(asapTab) + + expect(screen.queryByTestId('date-input')).not.toBeInTheDocument() + expect(queryByDataUi(document.body, 'Calendar')).not.toBeInTheDocument() + }) + + it('sets the selected scheduled time when popup closed', async () => { + await renderComponent() + + const pickerButton = screen.getByRole('button') + fireEvent.click(pickerButton) + const scheduledTab = screen.getByText('At time') + fireEvent.click(scheduledTab) + + const Calendar = getByDataUi(document.body, 'CalendarMonth') + + // Select the 10th day in the calendar + fireEvent.click(within(Calendar).getByText('10')) + expect(mockUpdateRelease).not.toHaveBeenCalled() + + // Close the popup and check if the release is updated + fireEvent.click(screen.getByTestId('release-type-picker')) + expect(mockUpdateRelease).toHaveBeenCalledTimes(1) + expect(mockUpdateRelease).toHaveBeenCalledWith({ + ...activeASAPRelease, + metadata: expect.objectContaining({ + ...activeASAPRelease.metadata, + releaseType: 'scheduled', + intendedPublishAt: expect.stringMatching(/^\d{4}-\d{2}-10T\d{2}:\d{2}:\d{2}\.\d{3}Z$/), + }), + }) + }) + + it('sets the release type to undecided when undecided is selected', async () => { + await renderComponent() + + const pickerButton = screen.getByRole('button') + fireEvent.click(pickerButton) + const undecidedTab = screen.getByText('Undecided') + fireEvent.click(undecidedTab) + fireEvent.click(screen.getByTestId('release-type-picker')) + expect(mockUpdateRelease).toHaveBeenCalledTimes(1) + expect(mockUpdateRelease).toHaveBeenCalledWith({ + ...activeASAPRelease, + metadata: expect.objectContaining({ + ...activeASAPRelease.metadata, + intendedPublishAt: undefined, + releaseType: 'undecided', + }), + }) + }) + }) + + describe('picker behavior based on release state', () => { + it('disables the picker for archived releases', async () => { + await renderComponent({...activeASAPRelease, state: 'archived'}) + + const pickerButton = screen.getByRole('button') + expect(pickerButton).toBeDisabled() + }) + + it('disables the picker for published releases', async () => { + await renderComponent(publishedASAPRelease) + + const pickerButton = screen.getByRole('button') + expect(pickerButton).toBeDisabled() + }) + + it('shows a spinner when updating the release', async () => { + // keep promise pending + mockUseReleaseOperations.mockReturnValue({ + ...useReleaseOperationsMockReturn, + updateRelease: vi.fn().mockImplementation(() => { + return new Promise(() => {}) + }), + }) + await renderComponent() + + const pickerButton = screen.getByRole('button') + fireEvent.click(pickerButton) + fireEvent.click(screen.getByText('Undecided')) + fireEvent.click(screen.getByTestId('release-type-picker')) + + // Check if the spinner is displayed while updating + screen.getByTestId('updating-release-spinner') + }) + }) +})