Skip to content

Commit

Permalink
fix(releases): hiding calendar on release picker dialog when not sche…
Browse files Browse the repository at this point in the history
…duled release type (#8137)
  • Loading branch information
jordanl17 authored Dec 24, 2024
1 parent be255dc commit cd2d8ac
Show file tree
Hide file tree
Showing 3 changed files with 210 additions and 16 deletions.
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')
})
})
})

0 comments on commit cd2d8ac

Please sign in to comment.