Files
accounted/lib/invoices/__tests__/email-recipients.test.ts
T
Mattsson 466e55a015 Fix/invoice delivery and payment accounts (#1116)
* fix: reconcile annual reports with final closing entries

* test: cover annual report depreciation and VAT balances

* Merge remote-tracking branch 'origin/main' into fix/usr-fdbck-ch

* fix: show exact invoice delivery details

* fix: use currency account in invoice emails

* fix: address invoice delivery review feedback

* fix: harden invoice delivery and payment accounts

* test: assert RLS-denied zero-row updates

* fix: close remaining invoice compliance gaps

* fix: harden invoice archive authorization

* fix: close invoice delivery review findings

* fix: verify delivery finalization results

* fix: cap combined invoice email recipients

* fix: close final invoice compliance findings

* fix: prevent stale payment account saves

* test: prove invoice delivery isolation

* fix: close invoice privacy review findings

* test: normalize delivery retention dates
2026-07-23 09:54:02 +02:00

88 lines
3.1 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import {
exceedsInvoiceEmailRecipientLimit,
findAdditionalInvoiceRecipientCollisions,
invoiceEmailRecipientCount,
parseInvoiceRecipientText,
resolveInvoiceEmailRecipients,
} from '@/lib/invoices/email-recipients'
describe('resolveInvoiceEmailRecipients', () => {
it('uses the legacy copy only while the company list is unconfigured', () => {
expect(resolveInvoiceEmailRecipients({
to: 'customer@example.test',
configuredCc: null,
legacyCc: 'billing@example.test',
}).cc).toEqual(['billing@example.test'])
expect(resolveInvoiceEmailRecipients({
to: 'customer@example.test',
configuredCc: [],
legacyCc: 'billing@example.test',
}).cc).toEqual([])
})
it('merges fixed and per-send recipients with deterministic precedence', () => {
expect(resolveInvoiceEmailRecipients({
to: 'customer@example.test',
configuredCc: ['finance@example.test', 'CUSTOMER@example.test'],
configuredBcc: ['archive@example.test', 'finance@example.test'],
additionalCc: ['handler@example.test', 'Finance@example.test'],
additionalBcc: ['director@example.test', 'archive@example.test'],
})).toEqual({
to: ['customer@example.test'],
cc: ['finance@example.test', 'handler@example.test'],
bcc: ['archive@example.test', 'director@example.test'],
})
})
it('counts the final de-duplicated To, CC, and BCC recipients', () => {
const atLimit = resolveInvoiceEmailRecipients({
to: 'customer@example.test',
configuredCc: Array.from({ length: 19 }, (_, index) => `copy-${index}@example.test`),
})
expect(invoiceEmailRecipientCount(atLimit)).toBe(20)
expect(exceedsInvoiceEmailRecipientLimit(atLimit)).toBe(false)
const overLimit = resolveInvoiceEmailRecipients({
to: 'customer@example.test',
configuredCc: atLimit.cc,
additionalBcc: ['archive@example.test'],
})
expect(invoiceEmailRecipientCount(overLimit)).toBe(21)
expect(exceedsInvoiceEmailRecipientLimit(overLimit)).toBe(true)
})
it('trims and de-duplicates address text', () => {
expect(parseInvoiceRecipientText(
' finance@example.test,\nDIRECTOR@example.test; finance@example.test ',
)).toEqual(['finance@example.test', 'DIRECTOR@example.test'])
})
it('reports per-send collisions instead of silently changing recipient precedence', () => {
expect(findAdditionalInvoiceRecipientCollisions({
to: 'customer@example.test',
configuredCc: ['finance@example.test'],
configuredBcc: ['archive@example.test'],
additionalCc: ['CUSTOMER@example.test', 'case-owner@example.test'],
additionalBcc: ['finance@example.test', 'case-owner@example.test'],
})).toEqual([
{
address: 'CUSTOMER@example.test',
field: 'additional_cc',
conflicts_with: 'to',
},
{
address: 'finance@example.test',
field: 'additional_bcc',
conflicts_with: 'configured_cc',
},
{
address: 'case-owner@example.test',
field: 'additional_bcc',
conflicts_with: 'additional_cc',
},
])
})
})