mirror of
https://github.com/documenso/documenso.git
synced 2026-07-14 06:47:10 +10:00
415 lines
13 KiB
TypeScript
415 lines
13 KiB
TypeScript
import * as fs from 'node:fs';
|
|
import * as path from 'node:path';
|
|
import { NEXT_PUBLIC_WEBAPP_URL } from '@documenso/lib/constants/app';
|
|
import { createApiToken } from '@documenso/lib/server-only/public-api/create-api-token';
|
|
import { prisma } from '@documenso/prisma';
|
|
import { EnvelopeType, RecipientRole } from '@documenso/prisma/client';
|
|
import { seedTeam } from '@documenso/prisma/seed/teams';
|
|
import { seedBlankTemplate } from '@documenso/prisma/seed/templates';
|
|
import type {
|
|
TCreateEnvelopePayload,
|
|
TCreateEnvelopeResponse,
|
|
} from '@documenso/trpc/server/envelope-router/create-envelope.types';
|
|
import { expect, test } from '@playwright/test';
|
|
|
|
import { apiSignin } from '../fixtures/authentication';
|
|
|
|
const WEBAPP_BASE_URL = NEXT_PUBLIC_WEBAPP_URL();
|
|
const baseUrl = `${WEBAPP_BASE_URL}/api/v2-beta`;
|
|
|
|
test.describe.configure({ mode: 'parallel' });
|
|
|
|
/**
|
|
* Helper function to set default recipients for a team
|
|
*/
|
|
const setTeamDefaultRecipients = async (
|
|
teamId: number,
|
|
defaultRecipients: Array<{ email: string; name: string; role: RecipientRole }>,
|
|
) => {
|
|
const teamSettings = await prisma.teamGlobalSettings.findFirstOrThrow({
|
|
where: {
|
|
team: {
|
|
id: teamId,
|
|
},
|
|
},
|
|
});
|
|
|
|
await prisma.teamGlobalSettings.update({
|
|
where: {
|
|
id: teamSettings.id,
|
|
},
|
|
data: {
|
|
defaultRecipients,
|
|
},
|
|
});
|
|
};
|
|
|
|
test.describe('Default Recipients', () => {
|
|
test('[DEFAULT_RECIPIENTS]: default recipients are added to documents created via UI', async ({ page }) => {
|
|
const { team, owner } = await seedTeam({
|
|
createTeamMembers: 2,
|
|
});
|
|
|
|
// Get a team member to set as default recipient
|
|
const teamMembers = await prisma.organisationMember.findMany({
|
|
where: {
|
|
organisationId: team.organisationId,
|
|
userId: {
|
|
not: owner.id,
|
|
},
|
|
},
|
|
include: {
|
|
user: true,
|
|
},
|
|
});
|
|
|
|
const defaultRecipientUser = teamMembers[0].user;
|
|
|
|
// Set up default recipients for the team
|
|
await setTeamDefaultRecipients(team.id, [
|
|
{
|
|
email: defaultRecipientUser.email,
|
|
name: defaultRecipientUser.name || defaultRecipientUser.email,
|
|
role: RecipientRole.CC,
|
|
},
|
|
]);
|
|
|
|
await apiSignin({
|
|
page,
|
|
email: owner.email,
|
|
redirectPath: `/t/${team.url}/documents`,
|
|
});
|
|
|
|
// Upload document via UI - this triggers document creation with default recipients
|
|
const [fileChooser] = await Promise.all([
|
|
page.waitForEvent('filechooser'),
|
|
page
|
|
.locator('input[type=file]')
|
|
.nth(1)
|
|
.evaluate((e) => {
|
|
if (e instanceof HTMLInputElement) {
|
|
e.click();
|
|
}
|
|
}),
|
|
]);
|
|
|
|
await fileChooser.setFiles(path.join(__dirname, '../../../../assets/example.pdf'));
|
|
|
|
// Wait to be redirected to the edit page (v2 envelope editor)
|
|
await page.waitForURL(new RegExp(`/t/${team.url}/documents/envelope_.*`));
|
|
|
|
// Extract document ID from URL
|
|
const urlParts = page.url().split('/');
|
|
const documentId = urlParts.find((part) => part.startsWith('envelope_'));
|
|
|
|
// Wait for the Recipients card to be visible (v2 envelope editor)
|
|
await expect(page.getByRole('heading', { name: 'Recipients' })).toBeVisible();
|
|
|
|
await expect(page.getByTestId('signer-email-input').first()).not.toBeEmpty();
|
|
|
|
await page.getByRole('button', { name: 'Add Signer' }).click();
|
|
|
|
// Add a regular signer using the v2 editor
|
|
await page.getByTestId('signer-email-input').last().fill('regular-signer@documenso.com');
|
|
await page
|
|
.getByPlaceholder(/Recipient/)
|
|
.first()
|
|
.fill('Regular Signer');
|
|
|
|
// Wait for autosave to complete
|
|
await page.waitForTimeout(3000);
|
|
|
|
// Verify that default recipient is present in the database
|
|
await expect(async () => {
|
|
const envelope = await prisma.envelope.findFirstOrThrow({
|
|
where: {
|
|
id: documentId,
|
|
},
|
|
include: {
|
|
recipients: true,
|
|
},
|
|
});
|
|
|
|
// Should have 2 recipients: the regular signer + the default recipient
|
|
expect(envelope.recipients.length).toBe(2);
|
|
|
|
const defaultRecipient = envelope.recipients.find(
|
|
(r) => r.email.toLowerCase() === defaultRecipientUser.email.toLowerCase(),
|
|
);
|
|
expect(defaultRecipient).toBeDefined();
|
|
expect(defaultRecipient?.role).toBe(RecipientRole.CC);
|
|
|
|
const regularSigner = envelope.recipients.find((r) => r.email === 'regular-signer@documenso.com');
|
|
expect(regularSigner).toBeDefined();
|
|
}).toPass();
|
|
});
|
|
|
|
// TODO: Are we intending to allow default recipients to be removed from a document?
|
|
test.skip('[DEFAULT_RECIPIENTS]: default recipients cannot be removed from a document', async ({ page }) => {
|
|
const { team, owner } = await seedTeam({
|
|
createTeamMembers: 2,
|
|
});
|
|
|
|
// Get a team member to set as default recipient
|
|
const teamMembers = await prisma.organisationMember.findMany({
|
|
where: {
|
|
organisationId: team.organisationId,
|
|
userId: {
|
|
not: owner.id,
|
|
},
|
|
},
|
|
include: {
|
|
user: true,
|
|
},
|
|
});
|
|
|
|
const defaultRecipientUser = teamMembers[0].user;
|
|
|
|
// Set up default recipients for the team
|
|
await setTeamDefaultRecipients(team.id, [
|
|
{
|
|
email: defaultRecipientUser.email,
|
|
name: defaultRecipientUser.name || defaultRecipientUser.email,
|
|
role: RecipientRole.CC,
|
|
},
|
|
]);
|
|
|
|
await apiSignin({
|
|
page,
|
|
email: owner.email,
|
|
redirectPath: `/t/${team.url}/documents`,
|
|
});
|
|
|
|
// Upload document via UI - this triggers document creation with default recipients
|
|
const [fileChooser] = await Promise.all([
|
|
page.waitForEvent('filechooser'),
|
|
page
|
|
.locator('input[type=file]')
|
|
.nth(1)
|
|
.evaluate((e) => {
|
|
if (e instanceof HTMLInputElement) {
|
|
e.click();
|
|
}
|
|
}),
|
|
]);
|
|
|
|
await fileChooser.setFiles(path.join(__dirname, '../../../../assets/example.pdf'));
|
|
|
|
// Wait to be redirected to the edit page (v2 envelope editor)
|
|
await page.waitForURL(new RegExp(`/t/${team.url}/documents/envelope_.*`));
|
|
|
|
// Extract document ID from URL
|
|
const urlParts = page.url().split('/');
|
|
const documentId = urlParts.find((part) => part.startsWith('envelope_'));
|
|
|
|
// Replace the default recipient with a regular signer
|
|
await page.getByTestId('signer-email-input').first().fill('regular-signer@documenso.com');
|
|
await page
|
|
.getByPlaceholder(/Recipient/)
|
|
.first()
|
|
.fill('Regular Signer');
|
|
|
|
// Wait for autosave to complete
|
|
await page.waitForTimeout(3000);
|
|
|
|
// Wait for recipients to be saved
|
|
await expect(async () => {
|
|
const envelope = await prisma.envelope.findFirstOrThrow({
|
|
where: {
|
|
id: documentId,
|
|
},
|
|
include: {
|
|
recipients: true,
|
|
},
|
|
});
|
|
expect(envelope.recipients.length).toBe(2);
|
|
}).toPass();
|
|
|
|
// Verify that the default recipient's remove button is disabled
|
|
// In the v2 editor, default recipients should have a disabled remove button
|
|
// Find the fieldset containing the default recipient's email and check if its remove button is disabled
|
|
const defaultRecipientRow = page.locator('fieldset').filter({
|
|
hasText: defaultRecipientUser.email,
|
|
});
|
|
|
|
// The default recipient row should exist and have a disabled remove button
|
|
await expect(defaultRecipientRow).toHaveCount(1);
|
|
const removeButton = defaultRecipientRow.getByTestId('remove-signer-button');
|
|
await expect(removeButton).toBeDisabled();
|
|
});
|
|
|
|
test('[DEFAULT_RECIPIENTS]: documents created via API have default recipients', async ({ request }) => {
|
|
const { team, owner } = await seedTeam({
|
|
createTeamMembers: 2,
|
|
});
|
|
|
|
// Get a team member to set as default recipient
|
|
const teamMembers = await prisma.organisationMember.findMany({
|
|
where: {
|
|
organisationId: team.organisationId,
|
|
userId: {
|
|
not: owner.id,
|
|
},
|
|
},
|
|
include: {
|
|
user: true,
|
|
},
|
|
});
|
|
|
|
const defaultRecipientUser = teamMembers[0].user;
|
|
|
|
// Set up default recipients for the team
|
|
await setTeamDefaultRecipients(team.id, [
|
|
{
|
|
email: defaultRecipientUser.email,
|
|
name: defaultRecipientUser.name || defaultRecipientUser.email,
|
|
role: RecipientRole.CC,
|
|
},
|
|
]);
|
|
|
|
// Create API token
|
|
const { token } = await createApiToken({
|
|
userId: owner.id,
|
|
teamId: team.id,
|
|
tokenName: 'test-token',
|
|
expiresIn: null,
|
|
});
|
|
|
|
// Create envelope via API
|
|
const payload: TCreateEnvelopePayload = {
|
|
type: EnvelopeType.DOCUMENT,
|
|
title: 'Test Document with Default Recipients',
|
|
recipients: [
|
|
{
|
|
email: 'api-recipient@documenso.com',
|
|
name: 'API Recipient',
|
|
role: RecipientRole.SIGNER,
|
|
},
|
|
],
|
|
};
|
|
|
|
const formData = new FormData();
|
|
formData.append('payload', JSON.stringify(payload));
|
|
|
|
const pdfData = fs.readFileSync(path.join(__dirname, '../../../../assets/example.pdf'));
|
|
formData.append('files', new File([pdfData], 'test.pdf', { type: 'application/pdf' }));
|
|
|
|
const res = await request.post(`${baseUrl}/envelope/create`, {
|
|
headers: { Authorization: `Bearer ${token}` },
|
|
multipart: formData,
|
|
});
|
|
|
|
expect(res.ok()).toBeTruthy();
|
|
expect(res.status()).toBe(200);
|
|
|
|
const response = (await res.json()) as TCreateEnvelopeResponse;
|
|
|
|
// Verify the envelope has both the API recipient and the default recipient
|
|
const envelope = await prisma.envelope.findUniqueOrThrow({
|
|
where: {
|
|
id: response.id,
|
|
},
|
|
include: {
|
|
recipients: true,
|
|
},
|
|
});
|
|
|
|
expect(envelope.recipients.length).toBe(2);
|
|
|
|
const apiRecipient = envelope.recipients.find((r) => r.email === 'api-recipient@documenso.com');
|
|
expect(apiRecipient).toBeDefined();
|
|
expect(apiRecipient?.role).toBe(RecipientRole.SIGNER);
|
|
|
|
const defaultRecipient = envelope.recipients.find(
|
|
(r) => r.email.toLowerCase() === defaultRecipientUser.email.toLowerCase(),
|
|
);
|
|
expect(defaultRecipient).toBeDefined();
|
|
expect(defaultRecipient?.role).toBe(RecipientRole.CC);
|
|
});
|
|
|
|
test('[DEFAULT_RECIPIENTS]: documents created from template have default recipients', async ({ page }) => {
|
|
const { team, owner } = await seedTeam({
|
|
createTeamMembers: 2,
|
|
});
|
|
|
|
// Get a team member to set as default recipient
|
|
const teamMembers = await prisma.organisationMember.findMany({
|
|
where: {
|
|
organisationId: team.organisationId,
|
|
userId: {
|
|
not: owner.id,
|
|
},
|
|
},
|
|
include: {
|
|
user: true,
|
|
},
|
|
});
|
|
|
|
const defaultRecipientUser = teamMembers[0].user;
|
|
|
|
// Set up default recipients for the team
|
|
await setTeamDefaultRecipients(team.id, [
|
|
{
|
|
email: defaultRecipientUser.email,
|
|
name: defaultRecipientUser.name || defaultRecipientUser.email,
|
|
role: RecipientRole.CC,
|
|
},
|
|
]);
|
|
|
|
// Create a template
|
|
const template = await seedBlankTemplate(owner, team.id);
|
|
|
|
await apiSignin({
|
|
page,
|
|
email: owner.email,
|
|
redirectPath: `/t/${team.url}/templates/${template.id}/edit`,
|
|
});
|
|
|
|
// Set template title
|
|
await page.getByLabel('Title').fill('Template with Default Recipients');
|
|
|
|
await page.getByRole('button', { name: 'Continue' }).click();
|
|
await expect(page.getByRole('heading', { name: 'Add Placeholder' })).toBeVisible();
|
|
|
|
// Add a template recipient
|
|
await page.getByPlaceholder('Email').fill('template-recipient@documenso.com');
|
|
await page.getByPlaceholder('Name').fill('Template Recipient');
|
|
|
|
await page.getByRole('button', { name: 'Continue' }).click();
|
|
await expect(page.getByRole('heading', { name: 'Add Fields' })).toBeVisible();
|
|
|
|
await page.getByRole('button', { name: 'Save template' }).click();
|
|
|
|
// Use template to create document
|
|
await page.waitForURL(`/t/${team.url}/templates`);
|
|
await page.getByRole('button', { name: 'Use Template' }).click();
|
|
await page.getByRole('button', { name: 'Create as draft' }).click();
|
|
|
|
// Wait for document to be created
|
|
await page.waitForURL(new RegExp(`/t/${team.url}/documents/envelope_.*`));
|
|
|
|
const documentId = page.url().split('/').pop();
|
|
|
|
// Verify the document has both the template recipient and the default recipient
|
|
const document = await prisma.envelope.findFirstOrThrow({
|
|
where: {
|
|
id: documentId,
|
|
},
|
|
include: {
|
|
recipients: true,
|
|
},
|
|
});
|
|
|
|
expect(document.recipients.length).toBe(2);
|
|
|
|
const templateRecipient = document.recipients.find((r) => r.email === 'template-recipient@documenso.com');
|
|
expect(templateRecipient).toBeDefined();
|
|
|
|
const defaultRecipient = document.recipients.find(
|
|
(r) => r.email.toLowerCase() === defaultRecipientUser.email.toLowerCase(),
|
|
);
|
|
expect(defaultRecipient).toBeDefined();
|
|
expect(defaultRecipient?.role).toBe(RecipientRole.CC);
|
|
});
|
|
});
|