Files
documenso/packages/app-tests/e2e/envelope-editor-v2/envelope-recipient-groups.spec.ts
2026-08-05 14:13:22 +10:00

138 lines
4.4 KiB
TypeScript

import { prisma } from '@documenso/prisma';
import { expect, test } from '@playwright/test';
import {
clickAddSignerButton,
dragGroupCardOntoCard,
dragRecipientRowToGap,
getRecipientEmailInputs,
getRecipientStepCards,
moveGroupCardUp,
openDocumentEnvelopeEditor,
openTemplateEnvelopeEditor,
setRecipientEmail,
setRecipientName,
type TEnvelopeEditorSurface,
toggleSigningOrder,
} from '../fixtures/envelope-editor';
const expectRecipientOrders = async (surface: TEnvelopeEditorSurface, expected: Array<[string, number]>) => {
const { envelopeId } = surface;
if (!envelopeId) {
throw new Error('Expected surface to have an envelope ID');
}
await expect
.poll(
async () => {
const recipients = await prisma.recipient.findMany({
where: { envelopeId },
});
return recipients.map((r) => [r.email, r.signingOrder] as const).sort((a, b) => a[0].localeCompare(b[0]));
},
{ timeout: 15_000 },
)
.toEqual([...expected].sort((a, b) => a[0].localeCompare(b[0])));
};
const runGroupingFlow = async (surface: TEnvelopeEditorSurface) => {
const { root } = surface;
await setRecipientEmail(root, 0, 'alice@example.com');
await setRecipientName(root, 0, 'Alice');
await clickAddSignerButton(root);
await setRecipientEmail(root, 1, 'bob@example.com');
await clickAddSignerButton(root);
await setRecipientEmail(root, 2, 'carol@example.com');
await toggleSigningOrder(root, true);
// Three standalone groups.
await expect(root.getByText('Group 1', { exact: true })).toBeVisible();
await expect(root.getByText('Group 3', { exact: true })).toBeVisible();
// Drag carol's card onto bob's card to merge them into one group.
await dragGroupCardOntoCard(root, 2, 1);
await expect(root.getByText('2 recipients · any order')).toBeVisible();
await expect(root.getByTestId('ungroup-step-button')).toBeVisible();
await expect(root.getByText('Group 3', { exact: true })).not.toBeVisible();
await expectRecipientOrders(surface, [
['alice@example.com', 1],
['bob@example.com', 2],
['carol@example.com', 2],
]);
// Groups survive a reload (grouped normalization on load).
await root.reload();
await expect(root.getByText('2 recipients · any order')).toBeVisible();
// Ungroup dissolves back into sequential groups.
await root.getByTestId('ungroup-step-button').click();
await expect(root.getByText('2 recipients · any order')).not.toBeVisible();
await expect(root.getByText('Group 3', { exact: true })).toBeVisible();
await expectRecipientOrders(surface, [
['alice@example.com', 1],
['bob@example.com', 2],
['carol@example.com', 3],
]);
// Drag bob's row into the gap after the last group, moving him to the end.
await dragRecipientRowToGap(root, 1, 3);
await expectRecipientOrders(surface, [
['alice@example.com', 1],
['bob@example.com', 3],
['carol@example.com', 2],
]);
};
test.describe('document editor', () => {
test('documents: group recipients via drag and drop and ungroup', async ({ page }) => {
const surface = await openDocumentEnvelopeEditor(page);
await runGroupingFlow(surface);
});
test('documents: reordered group cards can still be dragged', async ({ page }) => {
const surface = await openDocumentEnvelopeEditor(page);
const { root } = surface;
await setRecipientEmail(root, 0, 'alice@example.com');
await clickAddSignerButton(root);
await setRecipientEmail(root, 1, 'bob@example.com');
await toggleSigningOrder(root, true);
await expect(getRecipientStepCards(root)).toHaveCount(2);
// Move bob's card into position 1.
await moveGroupCardUp(root, 1);
await expect(getRecipientEmailInputs(root).nth(0)).toHaveValue('bob@example.com');
await expect(getRecipientEmailInputs(root).nth(1)).toHaveValue('alice@example.com');
// Regression: after a reorder, the card moved into position 2 must still
// be draggable — positional drag-and-drop ids used to go stale on mounted
// cards, silently killing their drag handles. Prove it by completing a
// merge with the repositioned card.
await dragGroupCardOntoCard(root, 1, 0);
await expect(root.getByText('2 recipients · any order')).toBeVisible();
});
});
test.describe('template editor', () => {
test('templates: group recipients via drag and drop and ungroup', async ({ page }) => {
const surface = await openTemplateEnvelopeEditor(page);
await runGroupingFlow(surface);
});
});