mirror of
https://github.com/documenso/documenso.git
synced 2026-07-22 16:03:39 +10:00
268 lines
8.6 KiB
TypeScript
268 lines
8.6 KiB
TypeScript
import { nanoid } from '@documenso/lib/universal/id';
|
|
import { prisma } from '@documenso/prisma';
|
|
import { expect, type Page, test } from '@playwright/test';
|
|
import { DocumentSigningOrder, RecipientRole } from '@prisma/client';
|
|
|
|
import {
|
|
addEnvelopeItemPdf,
|
|
assertRecipientRole,
|
|
clickAddMyselfButton,
|
|
clickAddSignerButton,
|
|
clickEnvelopeEditorStep,
|
|
getEnvelopeEditorSettingsTrigger,
|
|
getRecipientEmailInputs,
|
|
getRecipientNameInputs,
|
|
getRecipientRemoveButtons,
|
|
getSigningOrderInputs,
|
|
openDocumentEnvelopeEditor,
|
|
openEmbeddedEnvelopeEditor,
|
|
openTemplateEnvelopeEditor,
|
|
persistEmbeddedEnvelope,
|
|
setRecipientEmail,
|
|
setRecipientName,
|
|
setRecipientRole,
|
|
setSigningOrderValue,
|
|
type TEnvelopeEditorSurface,
|
|
toggleAllowDictateSigners,
|
|
toggleSigningOrder,
|
|
} from '../fixtures/envelope-editor';
|
|
import { expectToastTextToBeVisible } from '../fixtures/generic';
|
|
|
|
type RecipientFlowResult = {
|
|
externalId: string;
|
|
expectedRecipientsBySigningOrder: Array<{
|
|
email: string;
|
|
name: string;
|
|
role: RecipientRole;
|
|
signingOrder: number;
|
|
}>;
|
|
removedRecipientEmail: string;
|
|
};
|
|
|
|
const TEST_RECIPIENT_VALUES = {
|
|
secondRecipient: {
|
|
email: 'recipient-two@example.com',
|
|
name: 'Recipient Two',
|
|
},
|
|
thirdRecipient: {
|
|
email: 'recipient-three@example.com',
|
|
name: 'Recipient Three',
|
|
},
|
|
embeddedPrimaryRecipient: {
|
|
email: 'embedded-primary@example.com',
|
|
name: 'Embedded Primary',
|
|
},
|
|
};
|
|
|
|
const openSettingsDialog = async (root: Page) => {
|
|
await getEnvelopeEditorSettingsTrigger(root).click();
|
|
await expect(root.getByRole('heading', { name: 'Document Settings' })).toBeVisible();
|
|
};
|
|
|
|
const updateExternalId = async (surface: TEnvelopeEditorSurface, externalId: string) => {
|
|
await openSettingsDialog(surface.root);
|
|
await surface.root.locator('input[name="externalId"]').fill(externalId);
|
|
await surface.root.getByRole('button', { name: 'Update' }).click();
|
|
|
|
if (!surface.isEmbedded) {
|
|
await expectToastTextToBeVisible(surface.root, 'Envelope updated');
|
|
}
|
|
};
|
|
|
|
const navigateToAddFieldsAndBack = async (root: Page) => {
|
|
await clickEnvelopeEditorStep(root, 'addFields');
|
|
await expect(root.getByText('Selected Recipient')).toBeVisible();
|
|
|
|
await clickEnvelopeEditorStep(root, 'upload');
|
|
await expect(root.getByRole('heading', { name: 'Recipients' })).toBeVisible();
|
|
};
|
|
|
|
const runRecipientFlow = async (surface: TEnvelopeEditorSurface): Promise<RecipientFlowResult> => {
|
|
const externalId = `e2e-recipients-${nanoid()}`;
|
|
|
|
await updateExternalId(surface, externalId);
|
|
|
|
let primaryRecipient = TEST_RECIPIENT_VALUES.embeddedPrimaryRecipient;
|
|
|
|
if (surface.isEmbedded) {
|
|
await expect(surface.root.getByRole('button', { name: 'Add Myself' })).toHaveCount(0);
|
|
await setRecipientEmail(surface.root, 0, primaryRecipient.email);
|
|
await setRecipientName(surface.root, 0, primaryRecipient.name);
|
|
} else {
|
|
await expect(surface.root.getByRole('button', { name: 'Add Myself' })).toBeVisible();
|
|
await clickAddMyselfButton(surface.root);
|
|
|
|
primaryRecipient = {
|
|
email: surface.userEmail,
|
|
name: surface.userName,
|
|
};
|
|
|
|
await expect(getRecipientEmailInputs(surface.root).nth(0)).toHaveValue(surface.userEmail);
|
|
}
|
|
|
|
await clickAddSignerButton(surface.root);
|
|
await clickAddSignerButton(surface.root);
|
|
|
|
await setRecipientEmail(surface.root, 1, TEST_RECIPIENT_VALUES.secondRecipient.email);
|
|
await setRecipientName(surface.root, 1, TEST_RECIPIENT_VALUES.secondRecipient.name);
|
|
|
|
await setRecipientEmail(surface.root, 2, TEST_RECIPIENT_VALUES.thirdRecipient.email);
|
|
await setRecipientName(surface.root, 2, TEST_RECIPIENT_VALUES.thirdRecipient.name);
|
|
|
|
await setRecipientRole(surface.root, 1, 'Needs to approve');
|
|
await setRecipientRole(surface.root, 2, 'Receives copy');
|
|
|
|
await getRecipientRemoveButtons(surface.root).nth(2).click();
|
|
await expect(getRecipientEmailInputs(surface.root)).toHaveCount(2);
|
|
|
|
await toggleSigningOrder(surface.root, true);
|
|
await expect(getSigningOrderInputs(surface.root)).toHaveCount(2);
|
|
await setSigningOrderValue(surface.root, 0, 2);
|
|
|
|
await toggleAllowDictateSigners(surface.root, true);
|
|
|
|
await navigateToAddFieldsAndBack(surface.root);
|
|
|
|
await expect(getRecipientEmailInputs(surface.root)).toHaveCount(2);
|
|
await expect(getRecipientEmailInputs(surface.root).nth(0)).toHaveValue(TEST_RECIPIENT_VALUES.secondRecipient.email);
|
|
await expect(getRecipientEmailInputs(surface.root).nth(1)).toHaveValue(primaryRecipient.email);
|
|
|
|
await expect(getRecipientNameInputs(surface.root).nth(0)).toHaveValue(TEST_RECIPIENT_VALUES.secondRecipient.name);
|
|
await expect(getRecipientNameInputs(surface.root).nth(1)).toHaveValue(primaryRecipient.name);
|
|
|
|
await assertRecipientRole(surface.root, 0, 'Needs to approve');
|
|
await assertRecipientRole(surface.root, 1, 'Needs to sign');
|
|
|
|
await expect(surface.root.locator('#signingOrder')).toHaveAttribute('aria-checked', 'true');
|
|
await expect(surface.root.locator('#allowDictateNextSigner')).toHaveAttribute('aria-checked', 'true');
|
|
await expect(getSigningOrderInputs(surface.root).nth(0)).toHaveValue('1');
|
|
await expect(getSigningOrderInputs(surface.root).nth(1)).toHaveValue('2');
|
|
|
|
return {
|
|
externalId,
|
|
removedRecipientEmail: TEST_RECIPIENT_VALUES.thirdRecipient.email,
|
|
expectedRecipientsBySigningOrder: [
|
|
{
|
|
email: TEST_RECIPIENT_VALUES.secondRecipient.email,
|
|
name: TEST_RECIPIENT_VALUES.secondRecipient.name,
|
|
role: RecipientRole.APPROVER,
|
|
signingOrder: 1,
|
|
},
|
|
{
|
|
email: primaryRecipient.email,
|
|
name: primaryRecipient.name,
|
|
role: RecipientRole.SIGNER,
|
|
signingOrder: 2,
|
|
},
|
|
],
|
|
};
|
|
};
|
|
|
|
const assertRecipientsPersistedInDatabase = async ({
|
|
surface,
|
|
externalId,
|
|
expectedRecipientsBySigningOrder,
|
|
removedRecipientEmail,
|
|
}: {
|
|
surface: TEnvelopeEditorSurface;
|
|
externalId: string;
|
|
expectedRecipientsBySigningOrder: RecipientFlowResult['expectedRecipientsBySigningOrder'];
|
|
removedRecipientEmail: string;
|
|
}) => {
|
|
const envelope = await prisma.envelope.findFirstOrThrow({
|
|
where: {
|
|
externalId,
|
|
userId: surface.userId,
|
|
teamId: surface.teamId,
|
|
type: surface.envelopeType,
|
|
},
|
|
include: {
|
|
documentMeta: true,
|
|
recipients: {
|
|
orderBy: {
|
|
signingOrder: 'asc',
|
|
},
|
|
},
|
|
},
|
|
orderBy: {
|
|
createdAt: 'desc',
|
|
},
|
|
});
|
|
|
|
expect(envelope.recipients).toHaveLength(expectedRecipientsBySigningOrder.length);
|
|
expect(envelope.documentMeta.signingOrder).toBe(DocumentSigningOrder.SEQUENTIAL);
|
|
expect(envelope.documentMeta.allowDictateNextSigner).toBe(true);
|
|
|
|
expectedRecipientsBySigningOrder.forEach((expectedRecipient, index) => {
|
|
const recipient = envelope.recipients[index];
|
|
|
|
expect(recipient.email).toBe(expectedRecipient.email);
|
|
expect(recipient.name).toBe(expectedRecipient.name);
|
|
expect(recipient.role).toBe(expectedRecipient.role);
|
|
expect(recipient.signingOrder).toBe(expectedRecipient.signingOrder);
|
|
});
|
|
|
|
expect(envelope.recipients.some((recipient) => recipient.email === removedRecipientEmail)).toBe(false);
|
|
};
|
|
|
|
test.describe('document editor', () => {
|
|
test('add myself, CRUD, roles, signing order and dictate signers', async ({ page }) => {
|
|
const surface = await openDocumentEnvelopeEditor(page);
|
|
const result = await runRecipientFlow(surface);
|
|
|
|
await assertRecipientsPersistedInDatabase({
|
|
surface,
|
|
...result,
|
|
});
|
|
});
|
|
});
|
|
|
|
test.describe('template editor', () => {
|
|
test('add myself, CRUD, roles, signing order and dictate signers', async ({ page }) => {
|
|
const surface = await openTemplateEnvelopeEditor(page);
|
|
const result = await runRecipientFlow(surface);
|
|
|
|
await assertRecipientsPersistedInDatabase({
|
|
surface,
|
|
...result,
|
|
});
|
|
});
|
|
});
|
|
|
|
test.describe('embedded create', () => {
|
|
test('CRUD, roles, signing order and dictate signers', async ({ page }) => {
|
|
const surface = await openEmbeddedEnvelopeEditor(page, {
|
|
envelopeType: 'DOCUMENT',
|
|
tokenNamePrefix: 'e2e-embed-recipients',
|
|
});
|
|
|
|
await addEnvelopeItemPdf(surface.root, 'embedded-document-recipients.pdf');
|
|
|
|
const result = await runRecipientFlow(surface);
|
|
await persistEmbeddedEnvelope(surface);
|
|
|
|
await assertRecipientsPersistedInDatabase({
|
|
surface,
|
|
...result,
|
|
});
|
|
});
|
|
});
|
|
|
|
test.describe('embedded edit', () => {
|
|
test('CRUD, roles, signing order and dictate signers', async ({ page }) => {
|
|
const surface = await openEmbeddedEnvelopeEditor(page, {
|
|
envelopeType: 'TEMPLATE',
|
|
mode: 'edit',
|
|
tokenNamePrefix: 'e2e-embed-recipients',
|
|
});
|
|
|
|
const result = await runRecipientFlow(surface);
|
|
await persistEmbeddedEnvelope(surface);
|
|
|
|
await assertRecipientsPersistedInDatabase({
|
|
surface,
|
|
...result,
|
|
});
|
|
});
|
|
});
|