diff --git a/src/apps/opportunities/src/components/ChallengeDetailHeader.spec.tsx b/src/apps/opportunities/src/components/ChallengeDetailHeader.spec.tsx
index e6f38df13..ab8ae2403 100644
--- a/src/apps/opportunities/src/components/ChallengeDetailHeader.spec.tsx
+++ b/src/apps/opportunities/src/components/ChallengeDetailHeader.spec.tsx
@@ -672,22 +672,116 @@ describe('ChallengeDetailHeader actions and presentation', () => {
})
})
- it('retains a future Iterative Review deadline in a Task timeline', () => {
+ it.each([
+ {
+ challengeEnd: '2026-08-31T17:44:00.000Z',
+ challengeStart: '2026-08-10T17:44:00.000Z',
+ isOpen: true,
+ phaseEnd: '2026-08-15T17:44:00.000Z',
+ phaseStart: '2026-08-13T17:44:00.000Z',
+ state: 'current',
+ },
+ {
+ challengeEnd: '2999-08-31T17:44:00.000Z',
+ challengeStart: '2999-08-10T17:44:00.000Z',
+ isOpen: false,
+ phaseEnd: '2999-08-21T17:44:00.000Z',
+ phaseStart: '2999-08-20T17:44:00.000Z',
+ state: 'future',
+ },
+ ])('omits a $state Iterative Review phase from a Task timeline', ({
+ challengeEnd,
+ challengeStart,
+ isOpen,
+ phaseEnd,
+ phaseStart,
+ }: {
+ challengeEnd: string
+ challengeStart: string
+ isOpen: boolean
+ phaseEnd: string
+ phaseStart: string
+ }) => {
+ const { container }: RenderResult = render(
+
+
+ ,
+ )
+
+ fireEvent.click(screen.getByRole('button', { name: 'Show full timeline' }))
+ const timeline = screen.getByRole('region', { name: 'Challenge timeline' })
+ const itemLabels = within(timeline)
+ .getAllByRole('listitem')
+ .map(item => item.querySelector('strong')?.textContent)
+ expect(itemLabels)
+ .toEqual(['Launch', 'Registration', 'Submission', 'Winners'])
+ expect(within(timeline)
+ .queryByText('Iterative Review'))
+ .not.toBeInTheDocument()
+ expect(container.querySelector('.timelineItems'))
+ .toHaveStyle({
+ gridTemplateColumns: '88px minmax(0, 1fr) minmax(0, 1fr) 88px',
+ })
+ })
+
+ it('retains Iterative Review for non-Task challenge timelines', () => {
render(
{
- const phaseKey = challengeCatalogKey(item.name)
- if (!taskChallenge || !phaseKey.includes('iterativereview')) return true
- const phaseEnd = timelineTimestamp(item.actualEndDate ?? item.scheduledEndDate)
- return phaseEnd !== undefined && phaseEnd > now
- })
+ const authoredPhases = (challenge.phases ?? []).filter(item => (
+ !taskChallenge || !challengeCatalogKey(item.name)
+ .includes('iterativereview')
+ ))
const phases = authoredPhases
.map((item, index) => ({ index, item }))
.sort((left: IndexedChallengePhase, right: IndexedChallengePhase) => {