Scrum4Me/__tests__/components/backlog/new-sprint-trigger.test.tsx
Janpeter Visser 3d5c22382c
feat(PBI-91): expliciete schermstaat + draft-zichtbaarheid PB-page (#210)
* docs(ST-1369): plan PBI-91 — expliciete schermstaat + draft-zichtbaarheid

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(ST-1369): screen-state module — ScreenState + deriveScreenState()

Pure afleidingslaag die de verspreide schermstaat-derivatie van de Product
Backlog page consolideert tot één testbaar ScreenState-model. Nog geen
consumers — die volgen in T-1035/T-1036.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test(ST-1369): unit-tests voor deriveScreenState()

Dekt alle vier de kinds (NO_SPRINT, DRAFT, ACTIVE, EDITING), de building-flag
en de draft-voorrang boven een actieve sprint.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(ST-1369): SprintSwitcher op deriveScreenState + draft op trigger (G5)

De trigger-knop toont nu de concept-sprint zodra er een sprint-draft loopt,
niet langer alleen de (disabled) dropdown-regel. Schermstaat-afleiding loopt
via de pure deriveScreenState() i.p.v. losse flags.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(ST-1369): NewSprintTrigger achter isActiveProduct-gate (G6)

De "Nieuwe sprint"-knop rendert niet langer op een niet-actief product —
een sprint-draft starten daar was verwarrend. page.tsx geeft de bestaande
isActiveProduct-flag door.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test(ST-1369): component-tests voor draft-op-trigger (G5) en isActiveProduct-gate (G6)

sprint-switcher: trigger toont concept-sprint bij een pending draft, en geen
concept-label zonder draft. new-sprint-trigger: nieuw testbestand — rendert
niet op een niet-actief product, wel op een actief product zonder draft.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 01:45:35 +02:00

57 lines
1.8 KiB
TypeScript

// @vitest-environment jsdom
import { describe, it, expect, beforeEach, vi } from 'vitest'
import { render, screen } from '@testing-library/react'
import '@testing-library/jest-dom'
import type { ReactNode } from 'react'
const workflowMock: {
value: { pendingSprintDraft?: Record<string, unknown> } | undefined
} = { value: undefined }
vi.mock('@/stores/user-settings/store', () => ({
useUserSettingsStore: (
selector: (s: {
entities: {
settings: {
workflow: { pendingSprintDraft?: Record<string, unknown> } | undefined
}
}
}) => unknown,
) => selector({ entities: { settings: { workflow: workflowMock.value } } }),
}))
vi.mock('./new-sprint-metadata-dialog', () => ({
NewSprintMetadataDialog: () => null,
}))
vi.mock('@/components/shared/demo-tooltip', () => ({
DemoTooltip: ({ children }: { children: ReactNode }) => children,
}))
import { NewSprintTrigger } from '@/components/backlog/new-sprint-trigger'
beforeEach(() => {
workflowMock.value = undefined
})
describe('NewSprintTrigger', () => {
it('renders the button on an active product without a draft', () => {
render(<NewSprintTrigger productId="p1" isDemo={false} isActiveProduct={true} />)
expect(screen.getByText('Nieuwe sprint')).toBeInTheDocument()
})
it('renders nothing on a non-active product (G6)', () => {
const { container } = render(
<NewSprintTrigger productId="p1" isDemo={false} isActiveProduct={false} />,
)
expect(container).toBeEmptyDOMElement()
})
it('renders nothing when a sprint draft is pending', () => {
workflowMock.value = { pendingSprintDraft: { p1: { goal: 'X' } } }
const { container } = render(
<NewSprintTrigger productId="p1" isDemo={false} isActiveProduct={true} />,
)
expect(container).toBeEmptyDOMElement()
})
})