mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-11-14 00:01:03 +00:00
fix(planner): a refresh of the trip no longer wipes an open transport or booking form
The transport form re-seeded itself whenever the trip's costs arrived as a new array, and the booking form whenever days, places or stays did. A socket reconnect re-reads the whole trip, so behind a proxy that drops idle sockets every 15 to 30 seconds everything typed so far was wiped. Both forms now re-seed only for what opens a different form; the data is read when the form is seeded, as before. Fixes #3069
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
// FE-PLANNER-RESMODAL-001 to FE-PLANNER-RESMODAL-109
|
||||
// FE-PLANNER-RESMODAL-001 to FE-PLANNER-RESMODAL-110
|
||||
import { render, screen, waitFor, fireEvent, within, act } from '../../../tests/helpers/render';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { http, HttpResponse } from 'msw';
|
||||
@@ -1829,4 +1829,13 @@ describe('ReservationModal', () => {
|
||||
expect(onSave.mock.calls[0][0].confirmation_number).toBe('PNR-NEW');
|
||||
});
|
||||
});
|
||||
|
||||
it('FE-PLANNER-RESMODAL-110: a refresh of the trip while the dialog is open keeps what the user typed (#3069)', async () => {
|
||||
const { rerender } = render(<ReservationModal {...defaultProps} />);
|
||||
const title = screen.getByPlaceholderText(/e\.g\. Lufthansa/i) as HTMLInputElement;
|
||||
await userEvent.type(title, 'Le Jules Verne');
|
||||
// A socket reconnect re-reads the trip: days, places and stays arrive as new arrays.
|
||||
rerender(<ReservationModal {...defaultProps} days={[]} places={[]} accommodations={[]} />);
|
||||
expect(title).toHaveValue('Le Jules Verne');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -132,8 +132,12 @@ export function ReservationModal({ isOpen, onClose, onSave, reservation, days, p
|
||||
setForm({ ...EMPTY_FORM, assignment_id: defaultAssignmentId ?? '' })
|
||||
setPendingFiles([])
|
||||
}
|
||||
// Keyed only on what opens a different form. Days, places and stays are read
|
||||
// when the form is seeded; a refresh of the trip while the dialog is open (a
|
||||
// socket reconnect re-reads it) hands in new arrays of the same data and must
|
||||
// not reseed it and wipe what the user is typing (#3069).
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [reservation, prefill, isOpen, selectedDayId, defaultAssignmentId, days, places, accommodations])
|
||||
}, [reservation, prefill, isOpen, selectedDayId, defaultAssignmentId])
|
||||
|
||||
const handleSubmit = async (e?: { preventDefault?: () => void }) => {
|
||||
e?.preventDefault?.()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// FE-PLANNER-TRANSMODAL-001 to FE-PLANNER-TRANSMODAL-083
|
||||
// FE-PLANNER-TRANSMODAL-001 to FE-PLANNER-TRANSMODAL-085
|
||||
import { render, screen, waitFor, fireEvent, within, act } from '../../../tests/helpers/render';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { http, HttpResponse } from 'msw';
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
buildAssignment,
|
||||
buildReservation,
|
||||
buildTripFile,
|
||||
buildBudgetItem,
|
||||
} from '../../../tests/helpers/factories';
|
||||
import { TransportModal } from './TransportModal';
|
||||
import type { Day, Reservation } from '../../types';
|
||||
@@ -1725,4 +1726,22 @@ describe('TransportModal', () => {
|
||||
const legs = onSave.mock.calls[0][0].metadata.legs as { confirmation_number?: string }[];
|
||||
expect(legs.map(l => l.confirmation_number ?? null)).toEqual([null, 'SEG-TWO']);
|
||||
});
|
||||
|
||||
it('FE-PLANNER-TRANSMODAL-084: a store refresh while the dialog is open keeps what the user typed (#3069)', async () => {
|
||||
render(<TransportModal {...defaultProps} />);
|
||||
const title = screen.getByPlaceholderText(/e\.g\. Lufthansa/i) as HTMLInputElement;
|
||||
await userEvent.type(title, 'LH 400');
|
||||
// A socket reconnect re-reads the trip: the costs arrive as a new array.
|
||||
act(() => { useTripStore.setState({ budgetItems: [buildBudgetItem()] }); });
|
||||
expect(title).toHaveValue('LH 400');
|
||||
});
|
||||
|
||||
it('FE-PLANNER-TRANSMODAL-085: opening a different transport still fills the form with it', () => {
|
||||
const first = buildReservation({ title: 'First flight', type: 'flight' });
|
||||
const second = buildReservation({ title: 'Second flight', type: 'flight' });
|
||||
const { rerender } = render(<TransportModal {...defaultProps} reservation={first} />);
|
||||
expect(screen.getByDisplayValue('First flight')).toBeInTheDocument();
|
||||
rerender(<TransportModal {...defaultProps} reservation={second} />);
|
||||
expect(screen.getByDisplayValue('Second flight')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -135,7 +135,10 @@ export function TransportModal({ isOpen, onClose, onSave, reservation, days, sel
|
||||
meta_seat: meta.seat || '',
|
||||
}),
|
||||
})
|
||||
}, [isOpen, reservation, prefill, selectedDayId, budgetItems])
|
||||
// Keyed only on what opens a different form. A store refresh while the dialog
|
||||
// is open (a socket reconnect re-reads the trip, a fellow traveller's cost) must
|
||||
// not reseed it and wipe what the user is typing (#3069).
|
||||
}, [isOpen, reservation, prefill, selectedDayId])
|
||||
|
||||
const handleSubmit = async (e?: React.FormEvent) => {
|
||||
e?.preventDefault()
|
||||
|
||||
Reference in New Issue
Block a user