diff --git a/client/src/components/Planner/ReservationModal.test.tsx b/client/src/components/Planner/ReservationModal.test.tsx index b9d6a7922..a051bfb7c 100644 --- a/client/src/components/Planner/ReservationModal.test.tsx +++ b/client/src/components/Planner/ReservationModal.test.tsx @@ -1,4 +1,4 @@ -// FE-PLANNER-RESMODAL-001 to FE-PLANNER-RESMODAL-105 +// FE-PLANNER-RESMODAL-001 to FE-PLANNER-RESMODAL-106 import { render, screen, waitFor, fireEvent, within, act } from '../../../tests/helpers/render'; import userEvent from '@testing-library/user-event'; import { http, HttpResponse } from 'msw'; @@ -1409,6 +1409,38 @@ describe('ReservationModal', () => { expect(onSave.mock.calls[0][0].create_budget_entry).toEqual({ total_price: 50, category: 'accommodation' }); }); + it('FE-PLANNER-RESMODAL-106: an import with source files but no upload handler still saves and opens the expense editor', async () => { + // Without onFileUpload the pending source files cannot go anywhere; the save + // used to call the missing handler, reject, and never reach the expense step. + budgetEnabled(); + const onSave = vi.fn().mockResolvedValue({ id: 84 }); + const onOpenExpense = vi.fn(); + const prefill = hotelPrefill({ + type: 'restaurant', + metadata: {}, + _accommodation: undefined, + _sourceFiles: [new File(['pdf'], 'voucher.pdf', { type: 'application/pdf' })], + }); + render( + + ); + + await userEvent.click(screen.getByRole('button', { name: /Create expense/i })); + await waitFor(() => expect(onSave).toHaveBeenCalled()); + await waitFor(() => + expect(onOpenExpense).toHaveBeenCalledWith( + expect.objectContaining({ prefill: expect.objectContaining({ reservationId: 84 }) }) + ) + ); + }); + // ── File error paths ──────────────────────────────────────────────────────── it('FE-PLANNER-RESMODAL-077: a cancelled file dialog changes nothing', () => { diff --git a/client/src/components/Planner/bookingFormModel.test.ts b/client/src/components/Planner/bookingFormModel.test.ts index c6be97fc7..014d5c6b0 100644 --- a/client/src/components/Planner/bookingFormModel.test.ts +++ b/client/src/components/Planner/bookingFormModel.test.ts @@ -1,4 +1,4 @@ -// FE-PLANNER-BOOKINGFORM-001 to -007: the travellers, picked files, attached files +// FE-PLANNER-BOOKINGFORM-001 to -008: the travellers, picked files, attached files // and expense requests of the transport and booking forms, desktop and phone alike. import { typeToCostCategory } from '@trek/shared'; import { describe, expect, it, vi } from 'vitest'; @@ -60,6 +60,10 @@ describe('bookingFormModel', () => { expect(upload).not.toHaveBeenCalled(); }); + it('FE-PLANNER-BOOKINGFORM-008: without an upload handler the picked files are skipped and the save is not rejected', async () => { + await expect(uploadBookingFiles(undefined, 42, [new File(['a'], 'a.pdf')], 'Hotel stay')).resolves.toBeUndefined(); + }); + it('FE-PLANNER-BOOKINGFORM-005: an expense wish opens the editor for the saved booking, nothing else does', () => { const booking = { title: 'Hotel Adlon', type: 'hotel' }; const item = buildBudgetItem({ id: 7 }); diff --git a/client/src/components/Planner/bookingFormModel.ts b/client/src/components/Planner/bookingFormModel.ts index eab9b82b2..71a952afe 100644 --- a/client/src/components/Planner/bookingFormModel.ts +++ b/client/src/components/Planner/bookingFormModel.ts @@ -34,13 +34,16 @@ export function travelersChanged(reservation: Pick | n * the other, each described with the booking's title. Callers run it after both a * create and an edit: the form only holds files the user just picked, so nothing is * uploaded twice, and skipping the edit dropped them without a word (#2534). + * Without an upload handler (a dialog opened with no file support) there is + * nowhere to send them, so nothing is uploaded and the save carries on. */ export async function uploadBookingFiles( - upload: (fd: FormData) => Promise, + upload: ((fd: FormData) => Promise) | undefined, savedId: number, files: File[], description: string ): Promise { + if (!upload) return; for (const file of files) { const fd = new FormData(); fd.append('file', file);