feat(notify): own webhook as a full notification channel
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m59s

The custom webhook could be entered but never switched on since the
notification matrix replaced the old alarm channels. It is now a third
column next to e-mail and Discord for every event and the daily summary;
bundles go out as JSON (event "digest").

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
sandrodachandClaude Opus 5.5 committed 2026-10-30 19:02:46 +01:00
1 parent 6c154af251
commit 261579f0f2
10 files changed
+202 -56

No files matched your search

@@ -88,19 +88,53 @@ describe('UserSettingsView notification matrix', () => {
paused: true,
includeOwnWatched: true,
events: {
due: { email: true, discord: true },
shared: { email: true, discord: false },
taskDone: { email: true, discord: false },
watched: { email: true, discord: false },
due: { email: true, discord: true, webhook: false },
shared: { email: true, discord: false, webhook: false },
taskDone: { email: true, discord: false, webhook: false },
watched: { email: true, discord: false, webhook: false },
},
dailySummary: {
enabled: true,
time: '08:30',
email: true,
discord: true,
webhook: false,
},
},
})
);
});
it('enables the webhook column once an own webhook URL is entered and saves it as due channel', async () => {
render(
<UserSettingsView
currentUser={baseUser}
activeTheme="dark"
themes={[]}
customThemes={[]}
onThemeChange={() => {}}
onCustomThemesChange={() => {}}
onUserUpdated={() => {}}
onBack={() => {}}
/>
);
fireEvent.click(screen.getByText('Alarme'));
const off = screen.getAllByTitle('Bitte zuerst unten eine eigene Webhook URL eintragen');
expect(off.length).toBe(5);
expect((off[0] as HTMLButtonElement).disabled).toBe(true);
fireEvent.change(screen.getByPlaceholderText(/dein-server\.local/), {
target: { value: 'https://hooks.example.com/mindsift' },
});
fireEvent.click(screen.getByTitle('Fällige Aufgaben (sofort) – Webhook'));
fireEvent.click(screen.getByTitle('Freigabe erhalten – Webhook'));
fireEvent.click(screen.getByRole('button', { name: 'Alarm-Einstellungen speichern' }));
await waitFor(() => expect(api.updateSettings).toHaveBeenCalledTimes(1));
const patch = vi.mocked(api.updateSettings).mock.calls[0][0];
expect(patch.customWebhookUrl).toBe('https://hooks.example.com/mindsift');
expect(patch.alarmChannels).toEqual(['email', 'webhook']);
expect(patch.notificationSettings?.events.due.webhook).toBe(true);
expect(patch.notificationSettings?.events.shared.webhook).toBe(true);
});
});