feat(intake): structured notification-recipient resolver (emails/users/roles/everyone)
parseRecipientConfig (backward-compat: legacy string[] -> emails) + resolveRecipientEmails (expands userIds/roleIds/everyone-with-interests.view into deduped addresses) + resolveNotificationRecipients (load setting, fallback to inquiry_contact_email). Wired into the website-intake email path so berth/contact/residential staff alerts honor the richer recipients. TDD: parseRecipientConfig unit tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
47
tests/unit/notification-recipients.test.ts
Normal file
47
tests/unit/notification-recipients.test.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
|
||||
import { parseRecipientConfig } from '@/lib/services/notification-recipients';
|
||||
|
||||
describe('parseRecipientConfig', () => {
|
||||
it('treats a legacy string[] as explicit emails (backward-compat)', () => {
|
||||
expect(parseRecipientConfig(['a@x.com', 'b@x.com'])).toEqual({
|
||||
emails: ['a@x.com', 'b@x.com'],
|
||||
userIds: [],
|
||||
roleIds: [],
|
||||
everyone: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('reads the structured object shape', () => {
|
||||
expect(
|
||||
parseRecipientConfig({
|
||||
emails: ['a@x.com'],
|
||||
userIds: ['u1', 'u2'],
|
||||
roleIds: ['r1'],
|
||||
everyone: true,
|
||||
}),
|
||||
).toEqual({
|
||||
emails: ['a@x.com'],
|
||||
userIds: ['u1', 'u2'],
|
||||
roleIds: ['r1'],
|
||||
everyone: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('filters non-string / empty entries and coerces everyone defensively', () => {
|
||||
expect(
|
||||
parseRecipientConfig({
|
||||
emails: ['a@x.com', 2, '', null],
|
||||
userIds: 'nope',
|
||||
everyone: 'yes',
|
||||
}),
|
||||
).toEqual({ emails: ['a@x.com'], userIds: [], roleIds: [], everyone: false });
|
||||
});
|
||||
|
||||
it('returns empty for null / garbage', () => {
|
||||
const empty = { emails: [], userIds: [], roleIds: [], everyone: false };
|
||||
expect(parseRecipientConfig(null)).toEqual(empty);
|
||||
expect(parseRecipientConfig('nope')).toEqual(empty);
|
||||
expect(parseRecipientConfig(42)).toEqual(empty);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user