diff --git a/packages/app-tests/e2e/envelope-editor-v2/envelope-email-attachments.spec.ts b/packages/app-tests/e2e/envelope-editor-v2/envelope-email-attachments.spec.ts deleted file mode 100644 index 73a5a8370..000000000 --- a/packages/app-tests/e2e/envelope-editor-v2/envelope-email-attachments.spec.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { nanoid } from '@documenso/lib/universal/id'; -import { prisma } from '@documenso/prisma'; -import { expect, test } from '@playwright/test'; - -import { - addEnvelopeItemPdf, - getEnvelopeEditorSettingsTrigger, - openDocumentEnvelopeEditor, - openEmbeddedEnvelopeEditor, - openTemplateEnvelopeEditor, - persistEmbeddedEnvelope, - setRecipientEmail, - type TEnvelopeEditorSurface, -} from '../fixtures/envelope-editor'; -import { expectToastTextToBeVisible } from '../fixtures/generic'; - -const runAttachmentSettingsFlow = async (surface: TEnvelopeEditorSurface) => { - const { root, isEmbedded } = surface; - const externalId = `e2e-email-attachments-${nanoid()}`; - - if (isEmbedded && !surface.envelopeId) { - await addEnvelopeItemPdf(root); - await setRecipientEmail(root, 0, 'signer@example.com'); - } - - for (const attachDocument of [false, true, false]) { - await getEnvelopeEditorSettingsTrigger(root).click(); - await root.locator('input[name="externalId"]').fill(externalId); - await root.getByRole('button', { name: 'Notifications' }).click(); - const attachmentControl = root.getByRole('checkbox', { name: 'Attach completed document PDFs to emails' }); - await expect(attachmentControl).toBeChecked({ checked: !attachDocument }); - await attachmentControl.setChecked(attachDocument); - await expect(root.locator('#documentCompleted')).toBeChecked(); - await expect(root.locator('#ownerDocumentCompleted')).toBeChecked(); - await root.getByRole('button', { name: 'Update', exact: true }).click(); - - if (!isEmbedded) { - await expectToastTextToBeVisible(root, 'Envelope updated'); - const meta = await prisma.envelope.findUniqueOrThrow({ - where: { id: surface.envelopeId }, - include: { documentMeta: true }, - }); - expect(meta.documentMeta.emailSettings).toMatchObject({ attachDocument }); - await root.reload(); - } - } - - if (isEmbedded) { - await persistEmbeddedEnvelope(surface); - } - - const envelope = await prisma.envelope.findFirstOrThrow({ - where: { externalId, userId: surface.userId, teamId: surface.teamId, type: surface.envelopeType }, - include: { documentMeta: true }, - }); - expect(envelope.documentMeta.emailSettings).toMatchObject({ - attachDocument: false, - documentCompleted: true, - ownerDocumentCompleted: true, - }); -}; - -test.describe('document editor', () => { - test('save email attachment opt-out and toggle back', async ({ page }) => { - await runAttachmentSettingsFlow(await openDocumentEnvelopeEditor(page)); - }); -}); - -test.describe('template editor', () => { - test('save email attachment opt-out and toggle back', async ({ page }) => { - await runAttachmentSettingsFlow(await openTemplateEnvelopeEditor(page)); - }); -}); - -test.describe('embedded create', () => { - test('save email attachment opt-out and toggle back', async ({ page }) => { - await runAttachmentSettingsFlow(await openEmbeddedEnvelopeEditor(page, { envelopeType: 'DOCUMENT' })); - }); -}); - -test.describe('embedded edit', () => { - test('save email attachment opt-out and toggle back', async ({ page }) => { - await runAttachmentSettingsFlow(await openEmbeddedEnvelopeEditor(page, { envelopeType: 'TEMPLATE', mode: 'edit' })); - }); -}); diff --git a/packages/app-tests/e2e/organisations/organisation-team-preferences.spec.ts b/packages/app-tests/e2e/organisations/organisation-team-preferences.spec.ts index cf15bb702..895b0c5aa 100644 --- a/packages/app-tests/e2e/organisations/organisation-team-preferences.spec.ts +++ b/packages/app-tests/e2e/organisations/organisation-team-preferences.spec.ts @@ -215,8 +215,6 @@ test('[ORGANISATIONS]: manage email preferences', async ({ page }) => { await page.getByRole('textbox', { name: 'Reply to email' }).click(); await page.getByRole('textbox', { name: 'Reply to email' }).fill('organisation@documenso.com'); - await page.getByRole('checkbox', { name: 'Attach completed document PDFs to emails' }).uncheck(); - // Update email document settings by enabling/disabling some checkboxes await page.getByRole('checkbox', { name: 'Email the owner when a recipient signs' }).uncheck(); await page.getByRole('checkbox', { name: 'Email the signer if the document is still pending' }).uncheck(); @@ -232,7 +230,6 @@ test('[ORGANISATIONS]: manage email preferences', async ({ page }) => { // Check that the team settings have inherited these values. expect(teamSettings.emailReplyTo).toEqual('organisation@documenso.com'); expect(teamSettings.emailDocumentSettings).toEqual({ - attachDocument: false, recipientSigningRequest: true, recipientRemoved: true, recipientSigned: false, // unchecked @@ -276,7 +273,6 @@ test('[ORGANISATIONS]: manage email preferences', async ({ page }) => { // Check that the team settings have overridden the organisation values. expect(updatedTeamSettings.emailReplyTo).toEqual('team@example.com'); expect(updatedTeamSettings.emailDocumentSettings).toEqual({ - attachDocument: true, recipientSigned: true, recipientSigningRequest: false, recipientRemoved: true, @@ -299,7 +295,6 @@ test('[ORGANISATIONS]: manage email preferences', async ({ page }) => { expect(teamOverrideDocumentMeta.emailReplyTo).toEqual('team@example.com'); expect(teamOverrideDocumentMeta.emailSettings).toEqual({ - attachDocument: true, recipientSigned: true, recipientSigningRequest: false, recipientRemoved: true, @@ -327,7 +322,6 @@ test('[ORGANISATIONS]: manage email preferences', async ({ page }) => { // Check that the team settings now inherit from organisation again. expect(inheritedTeamSettings.emailReplyTo).toEqual('organisation@documenso.com'); expect(inheritedTeamSettings.emailDocumentSettings).toEqual({ - attachDocument: false, recipientSigningRequest: true, recipientRemoved: true, recipientSigned: false, @@ -350,7 +344,6 @@ test('[ORGANISATIONS]: manage email preferences', async ({ page }) => { expect(documentMeta.emailReplyTo).toEqual('organisation@documenso.com'); expect(documentMeta.emailSettings).toEqual({ - attachDocument: false, recipientSigningRequest: true, recipientRemoved: true, recipientSigned: false, @@ -361,22 +354,4 @@ test('[ORGANISATIONS]: manage email preferences', async ({ page }) => { ownerDocumentCompleted: true, ownerDocumentCreated: true, }); - - // Re-enable attachments and verify that inherited defaults change only for new documents. - await page.goto(`/o/${organisation.url}/settings/email`); - const attachmentControl = page.getByRole('checkbox', { name: 'Attach completed document PDFs to emails' }); - await expect(attachmentControl).not.toBeChecked(); - await attachmentControl.check(); - await page.getByRole('button', { name: 'Save changes' }).first().click(); - await expect(page.getByText('Your email preferences have been updated').first()).toBeVisible(); - await page.reload(); - await expect(attachmentControl).toBeChecked(); - - const restoredSettings = await getTeamSettings({ teamId: team.id }); - expect(restoredSettings.emailDocumentSettings.attachDocument).toBe(true); - const newDocument = await seedTeamDocumentWithMeta(team); - const newMeta = await prisma.documentMeta.findUniqueOrThrow({ where: { id: newDocument.documentMetaId } }); - expect(newMeta.emailSettings?.attachDocument).toBe(true); - const existingMeta = await prisma.documentMeta.findUniqueOrThrow({ where: { id: document.documentMetaId } }); - expect(existingMeta.emailSettings?.attachDocument).toBe(false); }); diff --git a/packages/lib/jobs/definitions/emails/send-document-completed-emails.handler.test.ts b/packages/lib/jobs/definitions/emails/send-document-completed-emails.handler.test.ts deleted file mode 100644 index 40c0fa801..000000000 --- a/packages/lib/jobs/definitions/emails/send-document-completed-emails.handler.test.ts +++ /dev/null @@ -1,190 +0,0 @@ -import { DocumentDistributionMethod, DocumentSource, RecipientRole } from '@prisma/client'; -import type { ReactElement } from 'react'; -import { beforeEach, describe, expect, it, vi } from 'vitest'; - -import { DEFAULT_DOCUMENT_EMAIL_SETTINGS } from '../../../types/document-email'; -import type { JobRunIO } from '../../client/_internal/job'; -import { run } from './send-document-completed-emails.handler'; - -const mocks = vi.hoisted(() => ({ - findEnvelope: vi.fn(), - createAuditLog: vi.fn(), - findEnvelopeItems: vi.fn(), - getEmailContext: vi.fn(), - getFile: vi.fn(), - sendMail: vi.fn(), - checkLimits: vi.fn(), -})); - -vi.mock('@documenso/prisma', () => ({ - prisma: { - envelope: { findUnique: mocks.findEnvelope }, - envelopeItem: { findMany: mocks.findEnvelopeItems }, - documentAuditLog: { create: mocks.createAuditLog }, - }, -})); -vi.mock('@documenso/email/templates/document-completed', () => ({ - DocumentCompletedEmailTemplate: () => null, -})); -vi.mock('../../../client-only/providers/i18n-server', () => ({ - getI18nInstance: async () => ({ _: () => 'Signing Complete!' }), -})); -vi.mock('../../../constants/app', () => ({ NEXT_PUBLIC_WEBAPP_URL: () => 'http://localhost:3000' })); -vi.mock('../../../server-only/email/get-email-context', () => ({ getEmailContext: mocks.getEmailContext })); -vi.mock('../../../server-only/rate-limit/assert-organisation-rates-and-limits', () => ({ - assertOrganisationRatesAndLimits: mocks.checkLimits, -})); -vi.mock('../../../universal/upload/get-file.server', () => ({ getFileServerSide: mocks.getFile })); -vi.mock('../../../utils/document-audit-logs', () => ({ createDocumentAuditLogData: (data: unknown) => data })); -vi.mock('../../../utils/teams', () => ({ formatDocumentsPath: () => '/t/test-team/documents' })); -vi.mock('../../../utils/render-email-with-i18n', () => ({ - renderEmailWithI18N: async (template: ReactElement<{ downloadLink: string }>) => template.props.downloadLink, -})); - -const createEnvelope = (distributionMethod: DocumentDistributionMethod = DocumentDistributionMethod.EMAIL) => ({ - id: 'envelope_test', - secondaryId: 'document_1', - teamId: 1, - internalVersion: 2, - title: 'Confidential document', - source: DocumentSource.DOCUMENT, - team: { id: 1, url: 'test-team' }, - user: { id: 1, name: 'Owner', email: 'owner@example.com', disabled: false }, - documentMeta: { - distributionMethod, - emailSettings: { ...DEFAULT_DOCUMENT_EMAIL_SETTINGS }, - }, - envelopeItems: [ - { title: 'First document', documentData: { id: 'file_1', type: 'S3', data: 'file_1' } }, - { title: 'Second document', documentData: { id: 'file_2', type: 'BYTES', data: 'file_2' } }, - ], - recipients: [ - { id: 2, name: 'Signer', email: 'signer@example.com', role: RecipientRole.SIGNER, token: 'signer-token' }, - { id: 3, name: 'CC', email: 'cc@example.com', role: RecipientRole.CC, token: 'cc-token' }, - ], -}); - -let envelope = createEnvelope(); -const io = { logger: { warn: vi.fn() } } as unknown as JobRunIO; -const runJob = () => run({ payload: { envelopeId: envelope.id }, io }); - -beforeEach(() => { - vi.clearAllMocks(); - envelope = createEnvelope(); - mocks.findEnvelope.mockImplementation(async () => envelope); - mocks.findEnvelopeItems.mockImplementation(async () => envelope.envelopeItems); - mocks.getFile.mockResolvedValue(new Uint8Array([1, 2, 3])); - mocks.getEmailContext.mockResolvedValue({ - branding: {}, - emailLanguage: 'en', - senderEmail: 'sender@example.com', - replyToEmail: 'reply@example.com', - organisationId: 'org_test', - claims: {}, - emailsDisabled: false, - emailTransport: { sendMail: mocks.sendMail }, - }); -}); - -describe('completion email document attachments', () => { - it('keeps email content, links, audit logs, and CC metering when PDFs are disabled', async () => { - envelope.documentMeta.emailSettings.attachDocument = false; - // Loading a PDF would fail: link-only email must still succeed. - mocks.getFile.mockRejectedValue(new Error('PDF storage unavailable')); - - await runJob(); - - expect(mocks.findEnvelopeItems).not.toHaveBeenCalled(); - expect(mocks.getFile).not.toHaveBeenCalled(); - expect(mocks.sendMail).toHaveBeenCalledTimes(3); - const emails = mocks.sendMail.mock.calls.map(([email]) => email); - expect(emails.map((email) => email.to[0].address)).toEqual([ - 'owner@example.com', - 'signer@example.com', - 'cc@example.com', - ]); - for (const email of emails) { - expect(email).toMatchObject({ attachments: [], subject: 'Signing Complete!' }); - expect(email.html).toBe(email.text); - } - expect(emails[0].html).toBe('http://localhost:3000/t/test-team/documents/envelope_test'); - expect(emails[1].html).toBe('http://localhost:3000/sign/signer-token/complete'); - expect(emails[2].html).toBe('http://localhost:3000/sign/cc-token/complete'); - expect(mocks.createAuditLog).toHaveBeenCalledTimes(3); - expect(mocks.checkLimits).toHaveBeenCalledOnce(); - }); - - it.each([true, undefined])('attaches all PDFs by default and when enabled (%s)', async (attachDocument) => { - mocks.findEnvelope.mockResolvedValue({ - ...envelope, - documentMeta: { ...envelope.documentMeta, emailSettings: { attachDocument } }, - }); - - await runJob(); - - expect(mocks.getFile).toHaveBeenCalledTimes(2); - expect(mocks.sendMail).toHaveBeenCalledTimes(3); - for (const [email] of mocks.sendMail.mock.calls) { - expect(email.attachments).toEqual([ - { filename: 'First document.pdf', content: Buffer.from([1, 2, 3]), contentType: 'application/pdf' }, - { filename: 'Second document.pdf', content: Buffer.from([1, 2, 3]), contentType: 'application/pdf' }, - ]); - } - }); - - it('retains legacy single-document filenames', async () => { - envelope.internalVersion = 1; - envelope.envelopeItems = [envelope.envelopeItems[0]]; - await runJob(); - expect(mocks.sendMail.mock.calls[0][0].attachments[0].filename).toBe('Confidential document.pdf'); - }); - - it('sends link-only owner emails when recipient emails are disabled', async () => { - envelope.documentMeta.emailSettings.attachDocument = false; - envelope.documentMeta.emailSettings.documentCompleted = false; - await runJob(); - expect(mocks.findEnvelopeItems).not.toHaveBeenCalled(); - expect(mocks.getFile).not.toHaveBeenCalled(); - expect(mocks.sendMail).toHaveBeenCalledOnce(); - expect(mocks.sendMail.mock.calls[0][0].to[0].address).toBe('owner@example.com'); - }); - - it('sends link-only recipient emails when owner emails are disabled', async () => { - envelope.documentMeta.emailSettings.attachDocument = false; - envelope.documentMeta.emailSettings.ownerDocumentCompleted = false; - await runJob(); - expect(mocks.findEnvelopeItems).not.toHaveBeenCalled(); - expect(mocks.getFile).not.toHaveBeenCalled(); - expect(mocks.sendMail).toHaveBeenCalledTimes(2); - }); - - it('sends a single link-only completion email when the owner is also a recipient', async () => { - envelope.documentMeta.emailSettings.attachDocument = false; - envelope.recipients[0].email = envelope.user.email; - await runJob(); - expect(mocks.sendMail).toHaveBeenCalledTimes(2); - expect(mocks.sendMail.mock.calls[0][0]).toMatchObject({ - to: [{ address: 'owner@example.com' }], - attachments: [], - html: 'http://localhost:3000/t/test-team/documents/envelope_test', - }); - }); - - it('preserves owner-only link emails when distribution is NONE', async () => { - envelope.documentMeta.distributionMethod = DocumentDistributionMethod.NONE; - envelope.documentMeta.emailSettings.attachDocument = false; - await runJob(); - expect(mocks.findEnvelopeItems).not.toHaveBeenCalled(); - expect(mocks.getFile).not.toHaveBeenCalled(); - expect(mocks.sendMail).toHaveBeenCalledOnce(); - }); - - it('does not load PDFs or send mail when both completion emails are disabled', async () => { - envelope.documentMeta.emailSettings.documentCompleted = false; - envelope.documentMeta.emailSettings.ownerDocumentCompleted = false; - await runJob(); - expect(mocks.findEnvelopeItems).not.toHaveBeenCalled(); - expect(mocks.getFile).not.toHaveBeenCalled(); - expect(mocks.sendMail).not.toHaveBeenCalled(); - }); -}); diff --git a/packages/lib/types/document-email-api.test.ts b/packages/lib/types/document-email-api.test.ts deleted file mode 100644 index 2f56a2dd9..000000000 --- a/packages/lib/types/document-email-api.test.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { describe, expect, it } from 'vitest'; -import { ZCreateDocumentMutationSchema, ZGenerateDocumentFromTemplateMutationSchema } from '../../api/v1/schema'; -import { ZCreateDocumentPayloadSchema } from '../../trpc/server/document-router/create-document.types'; -import { ZCreateEnvelopePayloadSchema } from '../../trpc/server/envelope-router/create-envelope.types'; -import { ZUpdateEnvelopeRequestSchema } from '../../trpc/server/envelope-router/update-envelope.types'; -import { ZUseEnvelopePayloadSchema } from '../../trpc/server/envelope-router/use-envelope.types'; -import { ZUpdateOrganisationSettingsRequestSchema } from '../../trpc/server/organisation-router/update-organisation-settings.types'; -import { ZUpdateTeamSettingsRequestSchema } from '../../trpc/server/team-router/update-team-settings.types'; -import { - ZCreateDocumentFromTemplateRequestSchema, - ZCreateTemplateV2RequestSchema, -} from '../../trpc/server/template-router/schema'; - -const requestCases = [ - { - name: 'v1 document creation', - schema: ZCreateDocumentMutationSchema, - body: { title: 'Document', recipients: [] }, - field: 'meta', - }, - { - name: 'v1 template use', - schema: ZGenerateDocumentFromTemplateMutationSchema, - body: { recipients: [] }, - field: 'meta', - }, - { name: 'document creation', schema: ZCreateDocumentPayloadSchema, body: { title: 'Document' }, field: 'meta' }, - { - name: 'envelope creation', - schema: ZCreateEnvelopePayloadSchema, - body: { title: 'Document', type: 'DOCUMENT' }, - field: 'meta', - }, - { - name: 'envelope update', - schema: ZUpdateEnvelopeRequestSchema, - body: { envelopeId: 'envelope_test' }, - field: 'meta', - }, - { - name: 'envelope template use', - schema: ZUseEnvelopePayloadSchema, - body: { envelopeId: 'envelope_test' }, - field: 'override', - }, - { name: 'template creation', schema: ZCreateTemplateV2RequestSchema, body: { title: 'Template' }, field: 'meta' }, - { - name: 'document from template', - schema: ZCreateDocumentFromTemplateRequestSchema, - body: { templateId: 1, recipients: [] }, - field: 'override', - }, -] as const; - -describe.each(requestCases)('$name email settings API', ({ schema, body, field }) => { - it.each([true, false])('accepts and retains attachDocument=%s', (attachDocument) => { - const request = { ...body, [field]: { emailSettings: { attachDocument } } }; - const result = schema.parse(request); - expect(result).toMatchObject({ [field]: { emailSettings: { attachDocument } } }); - }); - - it('rejects non-boolean attachment controls instead of enabling attachments', () => { - const request = { ...body, [field]: { emailSettings: { attachDocument: 'false' } } }; - expect(schema.safeParse(request).success).toBe(false); - }); -}); - -describe('default email settings API', () => { - it.each([true, false])('retains organisation and team attachment defaults (%s)', (attachDocument) => { - expect( - ZUpdateOrganisationSettingsRequestSchema.parse({ - organisationId: 'org_test', - data: { emailDocumentSettings: { attachDocument } }, - }), - ).toMatchObject({ data: { emailDocumentSettings: { attachDocument } } }); - expect( - ZUpdateTeamSettingsRequestSchema.parse({ teamId: 1, data: { emailDocumentSettings: { attachDocument } } }), - ).toMatchObject({ data: { emailDocumentSettings: { attachDocument } } }); - }); - - it('rejects malformed organisation and team defaults', () => { - expect( - ZUpdateOrganisationSettingsRequestSchema.safeParse({ - organisationId: 'org_test', - data: { emailDocumentSettings: { attachDocument: 'false' } }, - }).success, - ).toBe(false); - expect( - ZUpdateTeamSettingsRequestSchema.safeParse({ - teamId: 1, - data: { emailDocumentSettings: { attachDocument: 'false' } }, - }).success, - ).toBe(false); - }); - - it('retains null as the team inheritance control', () => { - expect(ZUpdateTeamSettingsRequestSchema.parse({ teamId: 1, data: { emailDocumentSettings: null } })).toMatchObject({ - data: { emailDocumentSettings: null }, - }); - }); -}); diff --git a/packages/lib/types/document-email.test.ts b/packages/lib/types/document-email.test.ts deleted file mode 100644 index ab95f89f9..000000000 --- a/packages/lib/types/document-email.test.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { DocumentDistributionMethod, type DocumentMeta } from '@prisma/client'; -import { describe, expect, it } from 'vitest'; - -import { extractDerivedDocumentMeta } from '../utils/document'; -import { generateDefaultOrganisationSettings } from '../utils/organisations'; -import { extractDerivedTeamSettings, generateDefaultTeamSettings } from '../utils/teams'; -import { - DEFAULT_DOCUMENT_EMAIL_SETTINGS, - extractDerivedDocumentEmailSettings, - ZDocumentEmailSettingsInputSchema, - ZDocumentEmailSettingsSchema, -} from './document-email'; -import { ZDocumentMetaCreateSchema, ZDocumentMetaUpdateSchema } from './document-meta'; - -describe('document email attachments', () => { - it('keeps attachments enabled for absent and legacy settings', () => { - expect(extractDerivedDocumentEmailSettings().attachDocument).toBe(true); - expect(ZDocumentEmailSettingsSchema.parse(null).attachDocument).toBe(true); - expect(ZDocumentEmailSettingsInputSchema.parse({ documentCompleted: false })).toMatchObject({ - attachDocument: true, - documentCompleted: false, - }); - }); - - it('disables attachments independently of notification events', () => { - expect(ZDocumentEmailSettingsInputSchema.parse({ attachDocument: false })).toEqual({ - ...DEFAULT_DOCUMENT_EMAIL_SETTINGS, - attachDocument: false, - }); - }); - - it.each(['false', 0, null, [], {}])('rejects invalid attachment values: %j', (attachDocument) => { - expect(ZDocumentEmailSettingsInputSchema.safeParse({ attachDocument }).success).toBe(false); - expect(ZDocumentMetaCreateSchema.safeParse({ emailSettings: { attachDocument } }).success).toBe(false); - expect(ZDocumentMetaUpdateSchema.safeParse({ emailSettings: { attachDocument } }).success).toBe(false); - }); - - it('does not replace an explicit opt-out with defaults when another input is invalid', () => { - expect( - ZDocumentMetaCreateSchema.safeParse({ - emailSettings: { attachDocument: false, documentCompleted: 'true' }, - }).success, - ).toBe(false); - }); - - it('preserves the owner attachment setting when email distribution is disabled', () => { - const settings = extractDerivedDocumentEmailSettings({ - distributionMethod: DocumentDistributionMethod.NONE, - emailSettings: { ...DEFAULT_DOCUMENT_EMAIL_SETTINGS, attachDocument: false }, - } as DocumentMeta); - - expect(settings).toMatchObject({ - attachDocument: false, - documentCompleted: false, - ownerDocumentCompleted: true, - }); - }); - - it('inherits organisation defaults, allows team overrides, and restores inheritance', () => { - const organisationSettings = generateDefaultOrganisationSettings(); - organisationSettings.emailDocumentSettings = { ...DEFAULT_DOCUMENT_EMAIL_SETTINGS, attachDocument: false }; - const teamSettings = generateDefaultTeamSettings(); - - const inherited = extractDerivedTeamSettings(organisationSettings, teamSettings); - expect(extractDerivedDocumentMeta(inherited, undefined).emailSettings.attachDocument).toBe(false); - - teamSettings.emailDocumentSettings = { ...DEFAULT_DOCUMENT_EMAIL_SETTINGS, attachDocument: true }; - const overridden = extractDerivedTeamSettings(organisationSettings, teamSettings); - expect(extractDerivedDocumentMeta(overridden, undefined).emailSettings.attachDocument).toBe(true); - - teamSettings.emailDocumentSettings = null; - expect( - extractDerivedDocumentMeta(extractDerivedTeamSettings(organisationSettings, teamSettings), undefined) - .emailSettings.attachDocument, - ).toBe(false); - }); - - it('allows a document or template to override inherited attachment defaults in either direction', () => { - const settings = generateDefaultOrganisationSettings(); - - expect( - extractDerivedDocumentMeta(settings, { - emailSettings: { ...DEFAULT_DOCUMENT_EMAIL_SETTINGS, attachDocument: false }, - }).emailSettings.attachDocument, - ).toBe(false); - - settings.emailDocumentSettings = { ...DEFAULT_DOCUMENT_EMAIL_SETTINGS, attachDocument: false }; - expect( - extractDerivedDocumentMeta(settings, { - emailSettings: { ...DEFAULT_DOCUMENT_EMAIL_SETTINGS, attachDocument: true }, - }).emailSettings.attachDocument, - ).toBe(true); - }); -});