Skip to content

Commit

Permalink
fix(sanity): prevent unexpected release type picker mutation (#8701)
Browse files Browse the repository at this point in the history
  • Loading branch information
juice49 authored Feb 20, 2025
1 parent 400cebd commit 2693a76
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const activeScheduledRelease: ReleaseDocument = {
metadata: {
title: 'active Release',
releaseType: 'scheduled',
intendedPublishAt: '2023-10-10T10:00:00Z',
intendedPublishAt: '2023-10-10T10:00:00.000Z',
description: 'active Release description',
},
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,15 @@ export function ReleaseTypePicker(props: {release: NotArchivedRelease}): React.J
if (open && !dialog) {
const newRelease = {
...release,
metadata: {...release.metadata, intendedPublishAt: updatedDate, releaseType},
metadata: {
...release.metadata,
releaseType,
...(typeof updatedDate === 'undefined'
? {}
: {
intendedPublishAt: updatedDate,
}),
},
}

if (!isEqual(newRelease, release)) {
Expand Down Expand Up @@ -127,12 +135,18 @@ export function ReleaseTypePicker(props: {release: NotArchivedRelease}): React.J
return <ReleaseTime release={release} />
}, [getReleaseTime, isPublishDateInPast, publishDate, release, tRelease])

const handleButtonReleaseTypeChange = useCallback((pickedReleaseType: ReleaseType) => {
setReleaseType(pickedReleaseType)
const nextPublishAt = pickedReleaseType === 'scheduled' ? startOfMinute(new Date()) : undefined
setIntendedPublishAt(nextPublishAt)
setIsIntendedScheduleDateInPast(true)
}, [])
const handleButtonReleaseTypeChange = useCallback(
(pickedReleaseType: ReleaseType) => {
setReleaseType(pickedReleaseType)
const nextPublishAt =
pickedReleaseType === 'scheduled'
? (publishDate ?? startOfMinute(new Date()))
: (publishDate ?? undefined)
setIntendedPublishAt(nextPublishAt)
setIsIntendedScheduleDateInPast(true)
},
[publishDate],
)

const handlePublishAtCalendarChange = useCallback(
(date: Date | null) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,13 +183,78 @@ describe('ReleaseTypePicker', () => {
...activeASAPRelease,
metadata: expect.objectContaining({
...activeASAPRelease.metadata,
intendedPublishAt: undefined,
releaseType: 'undecided',
}),
})
})
})

describe('noops if the release type is unchanged when the picker is closed', () => {
it('after returning to "ASAP" from "undecided"', async () => {
await renderComponent()

const pickerButton = screen.getByRole('button')
fireEvent.click(pickerButton)

const undecidedTab = within(screen.getByRole('tablist')).getByText('Undecided')
fireEvent.click(undecidedTab)

const asapTab = within(screen.getByRole('tablist')).getByText('ASAP')
fireEvent.click(asapTab)

fireEvent.click(screen.getByTestId('release-type-picker'))
fireEvent.click(pickerButton)

expect(mockUpdateRelease).not.toHaveBeenCalled()
})

it('after returning to "ASAP" from "at time"', async () => {
await renderComponent()

const pickerButton = screen.getByRole('button')
fireEvent.click(pickerButton)

const atTimeTab = within(screen.getByRole('tablist')).getByText('At time')
fireEvent.click(atTimeTab)

const asapTab = within(screen.getByRole('tablist')).getByText('ASAP')
fireEvent.click(asapTab)

fireEvent.click(screen.getByTestId('release-type-picker'))
fireEvent.click(pickerButton)

expect(mockUpdateRelease).not.toHaveBeenCalled()
})

it('after returning to "at time" from "ASAP" after the system time has incremented', async () => {
vi.useFakeTimers({shouldAdvanceTime: true})

const intendedPublishAt = new Date(activeScheduledRelease.metadata.intendedPublishAt ?? 0)

// 24 hours before `intendedPublishAt`.
vi.setSystemTime(new Date(intendedPublishAt.getTime() - 3_600 * 1_000 * 24))

await renderComponent(activeScheduledRelease)

const pickerButton = screen.getByRole('button')
fireEvent.click(pickerButton)

const asapTab = within(screen.getByRole('tablist')).getByText('ASAP')
fireEvent.click(asapTab)

// 23 hours before `intendedPublishAt` (one hour after picker opened).
vi.setSystemTime(new Date(intendedPublishAt.getTime() - 3_600 * 1_000 * 23))

const atTimeTab = within(screen.getByRole('tablist')).getByText('At time')
fireEvent.click(atTimeTab)

fireEvent.click(pickerButton)

expect(mockUpdateRelease).not.toHaveBeenCalled()
vi.useRealTimers()
})
})

describe('picker behavior based on release state', () => {
it('does not show button for picker when release is published state', async () => {
await renderComponent(publishedASAPRelease)
Expand Down

0 comments on commit 2693a76

Please sign in to comment.