Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(releases): hiding calendar on release picker dialog when not scheduled release type #8137

Merged
merged 2 commits into from
Dec 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,7 @@ export function ReleaseTypePicker(props: {release: ReleaseDocument}): JSX.Elemen
}, [inputValue, isPublishDateInPast, publishDate, release.publishAt, releaseType, t, tRelease])

const handleButtonReleaseTypeChange = useCallback((pickedReleaseType: ReleaseType) => {
if (pickedReleaseType === 'scheduled') {
setDateInputOpen(true)
}
setDateInputOpen(pickedReleaseType === 'scheduled')

setReleaseType(pickedReleaseType)
const nextPublishAt = pickedReleaseType === 'scheduled' ? new Date() : undefined
Expand All @@ -136,6 +134,11 @@ export function ReleaseTypePicker(props: {release: ReleaseDocument}): JSX.Elemen
}
}, [])

const handleOnPickerClick = () => {
if (open) close()
else setOpen(true)
}

const PopoverContent = () => {
return (
<Stack space={1}>
Expand Down Expand Up @@ -199,7 +202,7 @@ export function ReleaseTypePicker(props: {release: ReleaseDocument}): JSX.Elemen
isReleaseScheduled || release.state === 'archived' || release.state === 'published'
}
mode="bleed"
onClick={() => setOpen(!open)}
onClick={handleOnPickerClick}
padding={2}
ref={buttonRef}
tooltipProps={{
Expand All @@ -209,10 +212,11 @@ export function ReleaseTypePicker(props: {release: ReleaseDocument}): JSX.Elemen
selected={open}
tone={getReleaseTone({...release, metadata: {...release.metadata, releaseType}})}
style={{borderRadius: '999px'}}
data-testid="release-type-picker"
>
<Flex flex={1} gap={2}>
{isUpdating ? (
<Spinner size={1} />
<Spinner size={1} data-testid="updating-release-spinner" />
) : (
<ReleaseAvatar
tone={getReleaseTone({...release, metadata: {...release.metadata, releaseType}})}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,6 @@ describe('ReleaseDetail', () => {

describe('after releases have loaded', () => {
describe('with unpublished release', () => {
const currentDate = new Date().toISOString()
beforeEach(async () => {
vi.clearAllMocks()
})
Expand All @@ -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', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -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(<ReleaseTypePicker release={release} />, {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')
})
})
})
Loading