diff --git a/job-tracker-ui/scripts/verify-job-date-widgets.mjs b/job-tracker-ui/scripts/verify-job-date-widgets.mjs index aec37c88..19b02859 100644 --- a/job-tracker-ui/scripts/verify-job-date-widgets.mjs +++ b/job-tracker-ui/scripts/verify-job-date-widgets.mjs @@ -140,6 +140,18 @@ try { await expect(add).toBeHidden(); assert.equal(writes.length, 2); assert.equal(writes[1].body.dateApplied, '2026-11-24'); assert.equal(writes[1].body.deadline, '2026-11-24'); + job.status = 'Saved'; job.dateApplied = null; + await page.getByRole('button', { name: `${copy.jobTableActions}: Teacher`, exact: true }).click(); + await page.getByRole('menuitem', { name: copy.jobTableEdit, exact: true }).click(); + const unapplied = page.getByRole('dialog', { name: copy.editJobTitle, exact: true }); + await expect(unapplied.getByRole('group', { name: copy.editJobAppliedOn, exact: true }).locator('input')).toHaveValue(''); + await unapplied.getByRole('textbox', { name: copy.editJobJobTitle, exact: true }).fill('Retain unapplied teacher'); + await capture('unapplied'); + await unapplied.getByRole('button', { name: copy.save, exact: true }).click(); + await expect(unapplied).toBeHidden(); + assert.equal(writes.length, 3); + assert.equal(writes[2].body.dateApplied, null); assert.equal(writes[2].body.status, 'Saved'); + assert.equal(writes[2].body.expectedVersion, 7); assert.equal(writes[2].body.jobTitle, 'Retain unapplied teacher'); report.journeys.push({ zone, language, width, touch: mobile, theme, sevenCalendarSelections: 'PASS', localeDraftRetention: 'PASS', localToday: today, fixtureSaveCreate: 'PASS' }); await context.close(); } diff --git a/job-tracker-ui/src/components/EditJobDialog.tsx b/job-tracker-ui/src/components/EditJobDialog.tsx index 49b5382f..0d934b13 100644 --- a/job-tracker-ui/src/components/EditJobDialog.tsx +++ b/job-tracker-ui/src/components/EditJobDialog.tsx @@ -38,9 +38,9 @@ const FIELD_SX = { "& .MuiInputBase-root": { minHeight: 56 } }; const PICKER_TEXT_FIELD_PROPS = { fullWidth: true, sx: FIELD_SX }; function toDateInputValue(isoLike?: string): string { - if (!isoLike) return new Date().toISOString().slice(0, 10); + if (!isoLike) return ""; const d = new Date(isoLike); - if (Number.isNaN(+d)) return new Date().toISOString().slice(0, 10); + if (Number.isNaN(+d)) return ""; return d.toISOString().slice(0, 10); } diff --git a/job-tracker-ui/src/job-date-picker-calendar.test.tsx b/job-tracker-ui/src/job-date-picker-calendar.test.tsx index 6517aae2..b8beb3bd 100644 --- a/job-tracker-ui/src/job-date-picker-calendar.test.tsx +++ b/job-tracker-ui/src/job-date-picker-calendar.test.tsx @@ -34,6 +34,18 @@ beforeEach(() => { }); afterEach(() => { jest.useRealTimers(); }); +test.each([null, "", "not-a-date"])("Edit preserves an absent or invalid application date (%s) instead of inventing today", async dateApplied => { + client.get.mockResolvedValue({ data: { ...job, status: "Saved", dateApplied } } as any); + render(wrap()); + await screen.findByDisplayValue("Teacher"); + expect(screen.getByLabelText(translations.en.editJobAppliedOn)).toBeEmptyDOMElement(); + fireEvent.change(screen.getByLabelText(translations.en.editJobJobTitle), { target: { value: "Saved teacher opportunity" } }); + fireEvent.click(screen.getByRole("button", { name: translations.en.save })); + await waitFor(() => expect(client.put).toHaveBeenCalledWith("/jobapplications/1", expect.objectContaining({ + expectedVersion: 7, status: "Saved", dateApplied: null, jobTitle: "Saved teacher opportunity", + }))); +}); + test.each(["2026-11-23T00:30:00Z", "2026-11-23T23:30:00Z"])("Add defaults and successful reset use local today at %s", async clock => { jest.useFakeTimers(); jest.setSystemTime(new Date(clock));