Files
documenso/packages/lib/server-only/signature-level/assert-compatible-recipient-grouping.test.ts
T
2026-08-26 12:10:29 +10:00

81 lines
3.0 KiB
TypeScript

import { RecipientRole } from '@prisma/client';
import { describe, expect, it } from 'vitest';
import { SignatureLevel } from '../../types/signature-level';
import { assertCompatibleRecipientGrouping } from './assert-compatible-recipient-grouping';
const signer = (signingOrder: number | null) => ({ role: RecipientRole.SIGNER, signingOrder });
const cc = (signingOrder: number | null) => ({ role: RecipientRole.CC, signingOrder });
const expectRejected = (
signatureLevel: string,
recipients: Array<{ role: RecipientRole; signingOrder: number | null }>,
) => {
expect(() => assertCompatibleRecipientGrouping({ signatureLevel, recipients })).toThrow(
/signing group|same signing step/i,
);
};
const expectAccepted = (
signatureLevel: string,
recipients: Array<{ role: RecipientRole; signingOrder: number | null }>,
) => {
expect(() => assertCompatibleRecipientGrouping({ signatureLevel, recipients })).not.toThrow();
};
describe('assertCompatibleRecipientGrouping', () => {
describe('AES/QES envelopes', () => {
for (const signatureLevel of [SignatureLevel.AES, SignatureLevel.QES]) {
it(`rejects two signers sharing a signing order (${signatureLevel})`, () => {
expectRejected(signatureLevel, [signer(1), signer(2), signer(2)]);
});
it(`accepts distinct signing orders (${signatureLevel})`, () => {
expectAccepted(signatureLevel, [signer(1), signer(2), signer(3)]);
});
}
// Every null order collapses into the same tail step, so two of them sign
// in parallel exactly as a duplicate order would.
it('rejects two signers without a signing order', () => {
expectRejected(SignatureLevel.AES, [signer(null), signer(null)]);
});
it('rejects a signer without an order alongside an ordered signer', () => {
// The unordered recipient shares the tail step with the other null.
expectRejected(SignatureLevel.AES, [signer(1), signer(null), signer(null)]);
});
it('accepts a single signer without a signing order', () => {
expectAccepted(SignatureLevel.AES, [signer(null)]);
});
it('accepts one ordered signer and one unordered signer', () => {
expectAccepted(SignatureLevel.AES, [signer(1), signer(null)]);
});
// CC recipients never sign, so their order carries no meaning.
it('ignores CC recipients sharing an order with a signer', () => {
expectAccepted(SignatureLevel.AES, [signer(1), cc(1)]);
});
it('ignores several CC recipients sharing an order with each other', () => {
expectAccepted(SignatureLevel.AES, [signer(1), cc(2), cc(2), cc(null), cc(null)]);
});
it('accepts an empty recipient list', () => {
expectAccepted(SignatureLevel.AES, []);
});
});
describe('SES envelopes', () => {
it('permits signing groups', () => {
expectAccepted(SignatureLevel.SES, [signer(1), signer(2), signer(2)]);
});
it('permits multiple unordered signers', () => {
expectAccepted(SignatureLevel.SES, [signer(null), signer(null)]);
});
});
});