diff --git a/frontend/src/components/modals/PlannedDayModal.test.tsx b/frontend/src/components/modals/PlannedDayModal.test.tsx index e5115ca..9458c9d 100644 --- a/frontend/src/components/modals/PlannedDayModal.test.tsx +++ b/frontend/src/components/modals/PlannedDayModal.test.tsx @@ -2,7 +2,7 @@ import { describe, it, expect, vi, beforeEach } from 'vitest' import { render, screen, waitFor } from '@testing-library/react' import userEvent from '@testing-library/user-event' import { PlannedDayModal } from './PlannedDayModal' -import type { PlannedLeaveDay } from '@/types' +import { makePlannedLeaveDay } from '@/../tests/fixtures' describe('PlannedDayModal', () => { const mockOnClose = vi.fn() @@ -49,17 +49,10 @@ describe('PlannedDayModal', () => { }) it('shows "Redigera planerad dag" title when editing existing day', () => { - const existingDay: PlannedLeaveDay = { + const existingDay = makePlannedLeaveDay({ id: 'day-1', - workspaceId: 'ws-1', - childId: 'c-1', parentPersonalDataUuid: 'p1', - date: '2026-06-15', - dayType: 'vacation', - isDubbeldag: false, - createdAt: '2026-01-01T00:00:00Z', - updatedAt: '2026-01-01T00:00:00Z', - } + }) render() expect(screen.getByTestId('modal-title')).toHaveTextContent('Redigera planerad dag') }) @@ -430,17 +423,10 @@ describe('PlannedDayModal', () => { }) it('displays local error after delete failure', async () => { - const existingDay: PlannedLeaveDay = { + const existingDay = makePlannedLeaveDay({ id: 'day-1', - workspaceId: 'ws-1', - childId: 'c-1', parentPersonalDataUuid: 'p1', - date: '2026-06-15', - dayType: 'vacation', - isDubbeldag: false, - createdAt: '2026-01-01T00:00:00Z', - updatedAt: '2026-01-01T00:00:00Z', - } + }) mockOnDelete.mockRejectedValue(new Error('Delete failed')) // Mock the confirm dialog @@ -464,17 +450,10 @@ describe('PlannedDayModal', () => { }) it('displays a generic error message for non-Error thrown in delete', async () => { - const existingDay: PlannedLeaveDay = { + const existingDay = makePlannedLeaveDay({ id: 'day-1', - workspaceId: 'ws-1', - childId: 'c-1', parentPersonalDataUuid: 'p1', - date: '2026-06-15', - dayType: 'vacation', - isDubbeldag: false, - createdAt: '2026-01-01T00:00:00Z', - updatedAt: '2026-01-01T00:00:00Z', - } + }) mockOnDelete.mockRejectedValue('Some error') vi.spyOn(window, 'confirm').mockReturnValue(true) @@ -521,17 +500,12 @@ describe('PlannedDayModal', () => { describe('existing day initialization', () => { it('initializes day type from existing day', async () => { - const existingDay: PlannedLeaveDay = { + const existingDay = makePlannedLeaveDay({ id: 'day-1', - workspaceId: 'ws-1', - childId: 'c-1', parentPersonalDataUuid: 'p2', - date: '2026-06-15', dayType: 'sjukpenning', isDubbeldag: true, - createdAt: '2026-01-01T00:00:00Z', - updatedAt: '2026-01-01T00:00:00Z', - } + }) render( { }) it('initializes parent from existing day', async () => { - const existingDay: PlannedLeaveDay = { + const existingDay = makePlannedLeaveDay({ id: 'day-1', - workspaceId: 'ws-1', - childId: 'c-1', parentPersonalDataUuid: 'p2', - date: '2026-06-15', dayType: 'sjukpenning', - isDubbeldag: false, - createdAt: '2026-01-01T00:00:00Z', - updatedAt: '2026-01-01T00:00:00Z', - } + }) render( { }) it('shows correct title when editing existing day', () => { - const existingDay: PlannedLeaveDay = { + const existingDay = makePlannedLeaveDay({ id: 'day-1', - workspaceId: 'ws-1', - childId: 'c-1', parentPersonalDataUuid: 'p1', - date: '2026-06-15', - dayType: 'vacation', - isDubbeldag: false, - createdAt: '2026-01-01T00:00:00Z', - updatedAt: '2026-01-01T00:00:00Z', - } + }) render( { }) it('reinitializes when existingDay changes', async () => { - const firstDay: PlannedLeaveDay = { + const firstDay = makePlannedLeaveDay({ id: 'day-1', - workspaceId: 'ws-1', - childId: 'c-1', parentPersonalDataUuid: 'p1', - date: '2026-06-15', - dayType: 'vacation', - isDubbeldag: false, - createdAt: '2026-01-01T00:00:00Z', - updatedAt: '2026-01-01T00:00:00Z', - } + }) - const secondDay: PlannedLeaveDay = { + const secondDay = makePlannedLeaveDay({ id: 'day-2', - workspaceId: 'ws-1', - childId: 'c-1', parentPersonalDataUuid: 'p1', - date: '2026-06-15', dayType: 'lagsta', isDubbeldag: true, - createdAt: '2026-01-01T00:00:00Z', - updatedAt: '2026-01-01T00:00:00Z', - } + }) const { rerender } = render( { describe('delete button functionality', () => { it('does not render delete button when onDelete not provided', () => { - const existingDay: PlannedLeaveDay = { + const existingDay = makePlannedLeaveDay({ id: 'day-1', - workspaceId: 'ws-1', - childId: 'c-1', parentPersonalDataUuid: 'p1', - date: '2026-06-15', - dayType: 'vacation', - isDubbeldag: false, - createdAt: '2026-01-01T00:00:00Z', - updatedAt: '2026-01-01T00:00:00Z', - } + }) render( { }) it('does not render delete button in range mode', () => { - const existingDay: PlannedLeaveDay = { + const existingDay = makePlannedLeaveDay({ id: 'day-1', - workspaceId: 'ws-1', - childId: 'c-1', parentPersonalDataUuid: 'p1', - date: '2026-06-15', - dayType: 'vacation', - isDubbeldag: false, - createdAt: '2026-01-01T00:00:00Z', - updatedAt: '2026-01-01T00:00:00Z', - } + }) render( { }) it('renders delete button when editing existing day with delete handler', () => { - const existingDay: PlannedLeaveDay = { + const existingDay = makePlannedLeaveDay({ id: 'day-1', - workspaceId: 'ws-1', - childId: 'c-1', parentPersonalDataUuid: 'p1', - date: '2026-06-15', - dayType: 'vacation', - isDubbeldag: false, - createdAt: '2026-01-01T00:00:00Z', - updatedAt: '2026-01-01T00:00:00Z', - } + }) render( { }) it('shows confirmation dialog before deleting', async () => { - const existingDay: PlannedLeaveDay = { + const existingDay = makePlannedLeaveDay({ id: 'day-1', - workspaceId: 'ws-1', - childId: 'c-1', parentPersonalDataUuid: 'p1', - date: '2026-06-15', - dayType: 'vacation', - isDubbeldag: false, - createdAt: '2026-01-01T00:00:00Z', - updatedAt: '2026-01-01T00:00:00Z', - } + }) const confirmSpy = vi.spyOn(window, 'confirm').mockReturnValue(true) mockOnDelete.mockResolvedValue(undefined) @@ -816,17 +737,10 @@ describe('PlannedDayModal', () => { }) it('does not call onDelete if confirmation is cancelled', async () => { - const existingDay: PlannedLeaveDay = { + const existingDay = makePlannedLeaveDay({ id: 'day-1', - workspaceId: 'ws-1', - childId: 'c-1', parentPersonalDataUuid: 'p1', - date: '2026-06-15', - dayType: 'vacation', - isDubbeldag: false, - createdAt: '2026-01-01T00:00:00Z', - updatedAt: '2026-01-01T00:00:00Z', - } + }) const confirmSpy = vi.spyOn(window, 'confirm').mockReturnValue(false) mockOnDelete.mockResolvedValue(undefined) @@ -848,17 +762,10 @@ describe('PlannedDayModal', () => { }) it('calls onDelete if confirmation is accepted', async () => { - const existingDay: PlannedLeaveDay = { + const existingDay = makePlannedLeaveDay({ id: 'day-1', - workspaceId: 'ws-1', - childId: 'c-1', parentPersonalDataUuid: 'p1', - date: '2026-06-15', - dayType: 'vacation', - isDubbeldag: false, - createdAt: '2026-01-01T00:00:00Z', - updatedAt: '2026-01-01T00:00:00Z', - } + }) const confirmSpy = vi.spyOn(window, 'confirm').mockReturnValue(true) mockOnDelete.mockResolvedValue(undefined) @@ -882,17 +789,10 @@ describe('PlannedDayModal', () => { }) it('disables delete button when saving', () => { - const existingDay: PlannedLeaveDay = { + const existingDay = makePlannedLeaveDay({ id: 'day-1', - workspaceId: 'ws-1', - childId: 'c-1', parentPersonalDataUuid: 'p1', - date: '2026-06-15', - dayType: 'vacation', - isDubbeldag: false, - createdAt: '2026-01-01T00:00:00Z', - updatedAt: '2026-01-01T00:00:00Z', - } + }) render( { }) it('shows loading text on delete button when saving', () => { - const existingDay: PlannedLeaveDay = { + const existingDay = makePlannedLeaveDay({ id: 'day-1', - workspaceId: 'ws-1', - childId: 'c-1', parentPersonalDataUuid: 'p1', - date: '2026-06-15', - dayType: 'vacation', - isDubbeldag: false, - createdAt: '2026-01-01T00:00:00Z', - updatedAt: '2026-01-01T00:00:00Z', - } + }) render( { vi.mocked(usePlannedDays).mockReturnValue( makePlannedDaysResult({ data: [ - { + makePlannedLeaveDay({ id: 'pd-1', - workspaceId: 'ws-1', - childId: 'child-1', parentPersonalDataUuid: 'person-1', date: clickedDate, - dayType: 'vacation', - isDubbeldag: false, - createdAt: '2026-01-01', - updatedAt: '2026-01-01', - }, + }), ], }) ) diff --git a/frontend/src/pages/Dashboard.test.tsx b/frontend/src/pages/Dashboard.test.tsx index bca59d1..c5a4740 100644 --- a/frontend/src/pages/Dashboard.test.tsx +++ b/frontend/src/pages/Dashboard.test.tsx @@ -13,6 +13,7 @@ import { makePlannedDaysResult, makeScraperFetchResult, makeWorkspaceMembersResult, + makePlannedLeaveDay, } from '../../tests/fixtures' vi.mock('@/hooks') @@ -88,8 +89,8 @@ describe('Dashboard', () => { vi.mocked(hooks.usePlannedDays).mockReturnValue( makePlannedDaysResult({ data: [ - { id: '1', workspaceId: 'ws-1', childId: 'c-1', parentPersonalDataUuid: 'pd-1', date: '2026-06-15', dayType: 'vacation', isDubbeldag: false, createdAt: '', updatedAt: '' }, - { id: '2', workspaceId: 'ws-1', childId: 'c-1', parentPersonalDataUuid: 'pd-1', date: '2026-06-16', dayType: 'sjukpenning', isDubbeldag: false, createdAt: '', updatedAt: '' }, + makePlannedLeaveDay({ id: '1', date: '2026-06-15' }), + makePlannedLeaveDay({ id: '2', date: '2026-06-16', dayType: 'sjukpenning' }), ], }) ) @@ -445,9 +446,9 @@ describe('Dashboard', () => { vi.mocked(hooks.usePlannedDays).mockReturnValue( makePlannedDaysResult({ data: [ - { id: '1', workspaceId: 'ws-1', childId: 'c-1', parentPersonalDataUuid: 'pd-1', date: '2026-06-15', dayType: 'vacation', isDubbeldag: false, createdAt: '', updatedAt: '' }, - { id: '2', workspaceId: 'ws-1', childId: 'c-1', parentPersonalDataUuid: 'pd-1', date: '2026-06-16', dayType: 'sjukpenning', isDubbeldag: false, createdAt: '', updatedAt: '' }, - { id: '3', workspaceId: 'ws-1', childId: 'c-1', parentPersonalDataUuid: 'pd-1', date: '2026-06-17', dayType: 'lagsta', isDubbeldag: false, createdAt: '', updatedAt: '' }, + makePlannedLeaveDay({ id: '1', date: '2026-06-15' }), + makePlannedLeaveDay({ id: '2', date: '2026-06-16', dayType: 'sjukpenning' }), + makePlannedLeaveDay({ id: '3', date: '2026-06-17', dayType: 'lagsta' }), ], }) ) diff --git a/frontend/src/types/entities.ts b/frontend/src/types/entities.ts index 07a66ee..bdcef1b 100644 --- a/frontend/src/types/entities.ts +++ b/frontend/src/types/entities.ts @@ -105,13 +105,10 @@ export interface PlannedLeaveDay { dayType: 'sjukpenning' | 'lagsta' | 'vacation' isDubbeldag: boolean // Which `LeaveWish` produced this day; null/omitted means ad-hoc (not tied to a wish). - // Optional (rather than required) so existing object literals elsewhere in the - // codebase that predate this field keep type-checking; `toPlannedLeaveDay` in - // services/api.ts always populates it from the wire response. - wishId?: string | null + // `toPlannedLeaveDay` in services/api.ts always populates it from the wire response. + wishId: string | null // True when the user hand-edited this day's type — the planner must not retype it. - // Optional for the same reason as `wishId` above. - isPinned?: boolean + isPinned: boolean createdAt: string updatedAt: string }