diff --git a/frontend/src/components/settings/NotificationSuppressionSection.tsx b/frontend/src/components/settings/NotificationSuppressionSection.tsx index ecc9bb65..67ee170c 100644 --- a/frontend/src/components/settings/NotificationSuppressionSection.tsx +++ b/frontend/src/components/settings/NotificationSuppressionSection.tsx @@ -282,7 +282,7 @@ export function NotificationSuppressionSection({ if (!formName.trim()) { toast.error('Name is required.'); return; } if (formScheduleInvalid && !formScheduleTouched) { toast.error( - "This rule's stored weekly window could not be read. Turn the weekly window on to set a new schedule, or toggle it off then on to confirm clearing it.", + "This rule's stored weekly window could not be read. Turn the weekly window on to set a new schedule, or toggle it on then off to confirm clearing it.", ); return; } diff --git a/frontend/src/components/settings/__tests__/NotificationSuppressionSection.test.tsx b/frontend/src/components/settings/__tests__/NotificationSuppressionSection.test.tsx index c5b88f4d..d52875cc 100644 --- a/frontend/src/components/settings/__tests__/NotificationSuppressionSection.test.tsx +++ b/frontend/src/components/settings/__tests__/NotificationSuppressionSection.test.tsx @@ -368,4 +368,29 @@ describe('NotificationSuppressionSection', () => { }); }); }); + + it('does not carry the invalid-schedule save gate over to a later edit of a different, valid rule', async () => { + mockListRules([corruptScheduleRule, scheduledRule]); + render(); + await waitFor(() => expect(screen.getByText('Corrupt window')).toBeInTheDocument()); + + const editButtons = screen.getAllByTitle('Edit'); + await userEvent.click(editButtons[0]); + await waitFor(() => expect(screen.getByRole('dialog', { name: /Edit mute rule/i })).toBeInTheDocument()); + await userEvent.click(screen.getByRole('button', { name: 'Cancel' })); + await waitFor(() => expect(screen.queryByRole('dialog')).not.toBeInTheDocument()); + + await userEvent.click(screen.getAllByTitle('Edit')[1]); + await waitFor(() => expect(screen.getByRole('dialog', { name: /Edit mute rule/i })).toBeInTheDocument()); + await userEvent.click(screen.getByRole('button', { name: /Create|Update/i })); + + await waitFor(() => { + const put = mockedFetch.mock.calls.find( + ([url, opts]) => + url === '/notification-suppression-rules/42' && (opts as { method?: string })?.method === 'PUT', + ); + expect(put).toBeTruthy(); + }); + expect(toast.error).not.toHaveBeenCalledWith(expect.stringContaining('could not be read')); + }); });