feat(notifications): add channel routing matrix, daily summary, and task watch button
This commit is contained in:
1 parent
6795edbf4b
commit
d2afcf49df
7 files changed
+461
-32
No files matched your search
@@ -0,0 +1,106 @@
|
||||
import React from 'react';
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
||||
import { UserSettingsView } from '../UserSettingsView';
|
||||
import { api } from '../../../lib/api';
|
||||
import { User } from '../../../lib/types';
|
||||
|
||||
vi.mock('../../../lib/api', async () => {
|
||||
const actual = await vi.importActual<typeof import('../../../lib/api')>('../../../lib/api');
|
||||
return {
|
||||
...actual,
|
||||
api: {
|
||||
...actual.api,
|
||||
getMe: vi.fn(async () => ({ isLastAdmin: false })),
|
||||
getAuthStatus: vi.fn(async () => ({ demoMode: false })),
|
||||
updateSettings: vi.fn(async (patch) => ({ ...baseUser, ...patch })),
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
const baseUser: User = {
|
||||
id: 'u1',
|
||||
email: 'anna@example.com',
|
||||
displayName: 'Anna',
|
||||
role: 'member',
|
||||
isActive: true,
|
||||
alarmChannels: ['email'],
|
||||
createdAt: '2026-10-30T00:00:00Z',
|
||||
};
|
||||
|
||||
describe('UserSettingsView notification matrix', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it('derives events.due from alarmChannels, disables Discord without webhook, and saves the exact notificationSettings object', async () => {
|
||||
const onUserUpdated = vi.fn();
|
||||
render(
|
||||
<UserSettingsView
|
||||
currentUser={baseUser}
|
||||
activeTheme="dark"
|
||||
themes={[]}
|
||||
customThemes={[]}
|
||||
onThemeChange={() => {}}
|
||||
onCustomThemesChange={() => {}}
|
||||
onUserUpdated={onUserUpdated}
|
||||
onBack={() => {}}
|
||||
/>
|
||||
);
|
||||
|
||||
// Open "Alarme" section
|
||||
fireEvent.click(screen.getByText('Alarme'));
|
||||
|
||||
// Without Discord webhook, Discord switches are disabled and hint is visible
|
||||
const discordSwitches = screen.getAllByTitle('Bitte zuerst unten eine Discord Webhook URL eintragen');
|
||||
expect(discordSwitches.length).toBe(5);
|
||||
expect((discordSwitches[0] as HTMLButtonElement).disabled).toBe(true);
|
||||
expect(screen.getByText(/Discord-Schalter sind deaktiviert/)).toBeTruthy();
|
||||
|
||||
// Enter a Discord Webhook URL to enable the Discord column
|
||||
fireEvent.change(screen.getByPlaceholderText(/https:\/\/discord\.com\/api\/webhooks/), {
|
||||
target: { value: 'https://discord.com/api/webhooks/123/abc' },
|
||||
});
|
||||
|
||||
// Derive check: alarmChannels=['email'] -> due.email=true, due.discord=false
|
||||
expect(screen.getByTitle('Fällige Aufgaben (sofort) – E-Mail').getAttribute('aria-checked')).toBe('true');
|
||||
expect(screen.getByTitle('Fällige Aufgaben (sofort) – Discord').getAttribute('aria-checked')).toBe('false');
|
||||
|
||||
// Toggle settings in the matrix, daily summary, and global switches
|
||||
fireEvent.click(screen.getByTitle('Fällige Aufgaben (sofort) – Discord'));
|
||||
fireEvent.click(screen.getByTitle('Geteilte Aufgabe erledigt – E-Mail'));
|
||||
fireEvent.click(screen.getByTitle('Beobachtete Aufgaben – Discord'));
|
||||
fireEvent.click(screen.getByTitle('Alle Benachrichtigungen pausieren'));
|
||||
fireEvent.click(screen.getByTitle('Auch eigene Änderungen an beobachteten Aufgaben melden'));
|
||||
fireEvent.click(screen.getByTitle('Tageszusammenfassung'));
|
||||
fireEvent.change(screen.getByLabelText('Uhrzeit der Tageszusammenfassung'), {
|
||||
target: { value: '08:30' },
|
||||
});
|
||||
fireEvent.click(screen.getByTitle('Tageszusammenfassung – Discord'));
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Alarm-Einstellungen speichern' }));
|
||||
|
||||
await waitFor(() => expect(api.updateSettings).toHaveBeenCalledTimes(1));
|
||||
expect(api.updateSettings).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
discordWebhookUrl: 'https://discord.com/api/webhooks/123/abc',
|
||||
notificationSettings: {
|
||||
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 },
|
||||
},
|
||||
dailySummary: {
|
||||
enabled: true,
|
||||
time: '08:30',
|
||||
email: true,
|
||||
discord: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user