feat: add envelopes (#2025)

This PR is handles the changes required to support envelopes. The new
envelope editor/signing page will be hidden during release.

The core changes here is to migrate the documents and templates model to
a centralized envelopes model.

Even though Documents and Templates are removed, from the user
perspective they will still exist as we remap envelopes to documents and
templates.
This commit is contained in:
David Nguyen
2025-10-14 21:56:36 +11:00
committed by GitHub
parent 7b17156e56
commit 7f09ba72f4
447 changed files with 33467 additions and 9622 deletions

View File

@ -2,6 +2,7 @@ import { expect, test } from '@playwright/test';
import { NEXT_PUBLIC_WEBAPP_URL } from '@documenso/lib/constants/app';
import { createApiToken } from '@documenso/lib/server-only/public-api/create-api-token';
import { mapSecondaryIdToDocumentId } from '@documenso/lib/utils/envelope';
import { prisma } from '@documenso/prisma';
import { seedPendingDocumentWithFullFields } from '@documenso/prisma/seed/documents';
import { seedUser } from '@documenso/prisma/seed/users';
@ -25,7 +26,7 @@ test.describe('Document API', () => {
// Test with sendCompletionEmails: false
const response = await request.post(
`${NEXT_PUBLIC_WEBAPP_URL()}/api/v1/documents/${document.id}/send`,
`${NEXT_PUBLIC_WEBAPP_URL()}/api/v1/documents/${mapSecondaryIdToDocumentId(document.secondaryId)}/send`,
{
headers: {
Authorization: `Bearer ${token}`,
@ -41,7 +42,7 @@ test.describe('Document API', () => {
expect(response.status()).toBe(200);
// Verify email settings were updated
const updatedDocument = await prisma.document.findUnique({
const updatedDocument = await prisma.envelope.findUnique({
where: { id: document.id },
include: { documentMeta: true },
});
@ -53,7 +54,7 @@ test.describe('Document API', () => {
// Test with sendCompletionEmails: true
const response2 = await request.post(
`${NEXT_PUBLIC_WEBAPP_URL()}/api/v1/documents/${document.id}/send`,
`${NEXT_PUBLIC_WEBAPP_URL()}/api/v1/documents/${mapSecondaryIdToDocumentId(document.secondaryId)}/send`,
{
headers: {
Authorization: `Bearer ${token}`,
@ -69,7 +70,7 @@ test.describe('Document API', () => {
expect(response2.status()).toBe(200);
// Verify email settings were updated
const updatedDocument2 = await prisma.document.findUnique({
const updatedDocument2 = await prisma.envelope.findUnique({
where: { id: document.id },
include: { documentMeta: true },
});
@ -93,16 +94,16 @@ test.describe('Document API', () => {
// Set initial email settings
await prisma.documentMeta.upsert({
where: { documentId: document.id },
where: { id: document.documentMetaId },
create: {
documentId: document.id,
id: document.documentMetaId,
emailSettings: {
documentCompleted: true,
ownerDocumentCompleted: false,
},
},
update: {
documentId: document.id,
id: document.documentMetaId,
emailSettings: {
documentCompleted: true,
ownerDocumentCompleted: false,
@ -118,7 +119,7 @@ test.describe('Document API', () => {
});
const response = await request.post(
`${NEXT_PUBLIC_WEBAPP_URL()}/api/v1/documents/${document.id}/send`,
`${NEXT_PUBLIC_WEBAPP_URL()}/api/v1/documents/${mapSecondaryIdToDocumentId(document.secondaryId)}/send`,
{
headers: {
Authorization: `Bearer ${token}`,
@ -134,7 +135,7 @@ test.describe('Document API', () => {
expect(response.status()).toBe(200);
// Verify email settings were not modified
const updatedDocument = await prisma.document.findUnique({
const updatedDocument = await prisma.envelope.findUnique({
where: { id: document.id },
include: { documentMeta: true },
});

View File

@ -3,6 +3,11 @@ import { expect, test } from '@playwright/test';
import { NEXT_PUBLIC_WEBAPP_URL } from '@documenso/lib/constants/app';
import { createApiToken } from '@documenso/lib/server-only/public-api/create-api-token';
import type { TCheckboxFieldMeta, TRadioFieldMeta } from '@documenso/lib/types/field-meta';
import {
mapDocumentIdToSecondaryId,
mapSecondaryIdToDocumentId,
mapSecondaryIdToTemplateId,
} from '@documenso/lib/utils/envelope';
import { prisma } from '@documenso/prisma';
import { FieldType, RecipientRole } from '@documenso/prisma/client';
import { seedBlankTemplate } from '@documenso/prisma/seed/templates';
@ -35,10 +40,12 @@ test.describe('Template Field Prefill API v1', () => {
},
});
const firstEnvelopeItem = template.envelopeItems[0];
// 4. Create a recipient for the template
const recipient = await prisma.recipient.create({
data: {
templateId: template.id,
envelopeId: template.id,
email: 'recipient@example.com',
name: 'Test Recipient',
role: RecipientRole.SIGNER,
@ -53,7 +60,8 @@ test.describe('Template Field Prefill API v1', () => {
// Add TEXT field
const textField = await prisma.field.create({
data: {
templateId: template.id,
envelopeId: template.id,
envelopeItemId: firstEnvelopeItem.id,
recipientId: recipient.id,
type: FieldType.TEXT,
page: 1,
@ -73,7 +81,8 @@ test.describe('Template Field Prefill API v1', () => {
// Add NUMBER field
const numberField = await prisma.field.create({
data: {
templateId: template.id,
envelopeId: template.id,
envelopeItemId: firstEnvelopeItem.id,
recipientId: recipient.id,
type: FieldType.NUMBER,
page: 1,
@ -93,7 +102,8 @@ test.describe('Template Field Prefill API v1', () => {
// Add RADIO field
const radioField = await prisma.field.create({
data: {
templateId: template.id,
envelopeId: template.id,
envelopeItemId: firstEnvelopeItem.id,
recipientId: recipient.id,
type: FieldType.RADIO,
page: 1,
@ -117,7 +127,8 @@ test.describe('Template Field Prefill API v1', () => {
// Add CHECKBOX field
const checkboxField = await prisma.field.create({
data: {
templateId: template.id,
envelopeId: template.id,
envelopeItemId: firstEnvelopeItem.id,
recipientId: recipient.id,
type: FieldType.CHECKBOX,
page: 1,
@ -141,7 +152,8 @@ test.describe('Template Field Prefill API v1', () => {
// Add DROPDOWN field
const dropdownField = await prisma.field.create({
data: {
templateId: template.id,
envelopeId: template.id,
envelopeItemId: firstEnvelopeItem.id,
recipientId: recipient.id,
type: FieldType.DROPDOWN,
page: 1,
@ -166,11 +178,13 @@ test.describe('Template Field Prefill API v1', () => {
});
// 7. Navigate to the template
await page.goto(`${WEBAPP_BASE_URL}/templates/${template.id}`);
await page.goto(
`${WEBAPP_BASE_URL}/templates/${mapSecondaryIdToTemplateId(template.secondaryId)}`,
);
// 8. Create a document from the template with prefilled fields
const response = await request.post(
`${WEBAPP_BASE_URL}/api/v1/templates/${template.id}/generate-document`,
`${WEBAPP_BASE_URL}/api/v1/templates/${mapSecondaryIdToTemplateId(template.secondaryId)}/generate-document`,
{
headers: {
Authorization: `Bearer ${token}`,
@ -229,9 +243,9 @@ test.describe('Template Field Prefill API v1', () => {
expect(responseData.documentId).toBeDefined();
// 9. Verify the document was created with prefilled fields
const document = await prisma.document.findUnique({
const document = await prisma.envelope.findUnique({
where: {
id: responseData.documentId,
secondaryId: mapDocumentIdToSecondaryId(responseData.documentId),
},
include: {
fields: true,
@ -240,6 +254,10 @@ test.describe('Template Field Prefill API v1', () => {
expect(document).not.toBeNull();
if (!document) {
throw new Error('Document not found');
}
// 10. Verify each field has the correct prefilled values
const documentTextField = document?.fields.find(
(field) => field.type === FieldType.TEXT && field.fieldMeta?.type === 'text',
@ -297,14 +315,14 @@ test.describe('Template Field Prefill API v1', () => {
// 11. Sign in as the recipient and verify the prefilled fields are visible
const documentRecipient = await prisma.recipient.findFirst({
where: {
documentId: document?.id,
envelopeId: document?.id,
email: 'recipient@example.com',
},
});
// Send the document to the recipient
const sendResponse = await request.post(
`${WEBAPP_BASE_URL}/api/v1/documents/${document?.id}/send`,
`${WEBAPP_BASE_URL}/api/v1/documents/${mapSecondaryIdToDocumentId(document.secondaryId)}/send`,
{
headers: {
Authorization: `Bearer ${token}`,
@ -367,10 +385,12 @@ test.describe('Template Field Prefill API v1', () => {
},
});
const firstEnvelopeItem = template.envelopeItems[0];
// 4. Create a recipient for the template
const recipient = await prisma.recipient.create({
data: {
templateId: template.id,
envelopeId: template.id,
email: 'recipient@example.com',
name: 'Test Recipient',
role: RecipientRole.SIGNER,
@ -385,7 +405,8 @@ test.describe('Template Field Prefill API v1', () => {
// Add TEXT field
await prisma.field.create({
data: {
templateId: template.id,
envelopeId: template.id,
envelopeItemId: firstEnvelopeItem.id,
recipientId: recipient.id,
type: FieldType.TEXT,
page: 1,
@ -405,7 +426,8 @@ test.describe('Template Field Prefill API v1', () => {
// Add NUMBER field
await prisma.field.create({
data: {
templateId: template.id,
envelopeId: template.id,
envelopeItemId: firstEnvelopeItem.id,
recipientId: recipient.id,
type: FieldType.NUMBER,
page: 1,
@ -429,11 +451,13 @@ test.describe('Template Field Prefill API v1', () => {
});
// 7. Navigate to the template
await page.goto(`${WEBAPP_BASE_URL}/templates/${template.id}`);
await page.goto(
`${WEBAPP_BASE_URL}/templates/${mapSecondaryIdToTemplateId(template.secondaryId)}`,
);
// 8. Create a document from the template without prefilled fields
const response = await request.post(
`${WEBAPP_BASE_URL}/api/v1/templates/${template.id}/generate-document`,
`${WEBAPP_BASE_URL}/api/v1/templates/${mapSecondaryIdToTemplateId(template.secondaryId)}/generate-document`,
{
headers: {
Authorization: `Bearer ${token}`,
@ -461,9 +485,9 @@ test.describe('Template Field Prefill API v1', () => {
expect(responseData.documentId).toBeDefined();
// 9. Verify the document was created with default fields
const document = await prisma.document.findUnique({
const document = await prisma.envelope.findUnique({
where: {
id: responseData.documentId,
secondaryId: mapDocumentIdToSecondaryId(responseData.documentId),
},
include: {
fields: true,
@ -472,6 +496,10 @@ test.describe('Template Field Prefill API v1', () => {
expect(document).not.toBeNull();
if (!document) {
throw new Error('Document not found');
}
// 10. Verify fields have their default values
const documentTextField = document?.fields.find((field) => field.type === FieldType.TEXT);
expect(documentTextField?.fieldMeta).toMatchObject({
@ -488,7 +516,7 @@ test.describe('Template Field Prefill API v1', () => {
// 11. Sign in as the recipient and verify the default fields are visible
const documentRecipient = await prisma.recipient.findFirst({
where: {
documentId: document?.id,
envelopeId: document?.id,
email: 'recipient@example.com',
},
});
@ -496,7 +524,7 @@ test.describe('Template Field Prefill API v1', () => {
expect(documentRecipient).not.toBeNull();
const sendResponse = await request.post(
`${WEBAPP_BASE_URL}/api/v1/documents/${document?.id}/send`,
`${WEBAPP_BASE_URL}/api/v1/documents/${mapSecondaryIdToDocumentId(document.secondaryId)}/send`,
{
headers: {
Authorization: `Bearer ${token}`,
@ -539,10 +567,12 @@ test.describe('Template Field Prefill API v1', () => {
},
});
const firstEnvelopeItem = template.envelopeItems[0];
// 4. Create a recipient for the template
const recipient = await prisma.recipient.create({
data: {
templateId: template.id,
envelopeId: template.id,
email: 'recipient@example.com',
name: 'Test Recipient',
role: RecipientRole.SIGNER,
@ -556,7 +586,8 @@ test.describe('Template Field Prefill API v1', () => {
// 5. Add a field to the template
const field = await prisma.field.create({
data: {
templateId: template.id,
envelopeId: template.id,
envelopeItemId: firstEnvelopeItem.id,
recipientId: recipient.id,
type: FieldType.RADIO,
page: 1,
@ -579,7 +610,7 @@ test.describe('Template Field Prefill API v1', () => {
// 6. Try to create a document with invalid prefill value
const response = await request.post(
`${WEBAPP_BASE_URL}/api/v1/templates/${template.id}/generate-document`,
`${WEBAPP_BASE_URL}/api/v1/templates/${mapSecondaryIdToTemplateId(template.secondaryId)}/generate-document`,
{
headers: {
Authorization: `Bearer ${token}`,

View File

@ -3,6 +3,11 @@ import { expect, test } from '@playwright/test';
import { NEXT_PUBLIC_WEBAPP_URL } from '@documenso/lib/constants/app';
import { createApiToken } from '@documenso/lib/server-only/public-api/create-api-token';
import type { TCheckboxFieldMeta, TRadioFieldMeta } from '@documenso/lib/types/field-meta';
import {
mapDocumentIdToSecondaryId,
mapSecondaryIdToDocumentId,
mapSecondaryIdToTemplateId,
} from '@documenso/lib/utils/envelope';
import { prisma } from '@documenso/prisma';
import { FieldType, RecipientRole } from '@documenso/prisma/client';
import { seedBlankTemplate } from '@documenso/prisma/seed/templates';
@ -35,10 +40,12 @@ test.describe('Template Field Prefill API v2', () => {
},
});
const firstEnvelopeItem = template.envelopeItems[0];
// 4. Create a recipient for the template
const recipient = await prisma.recipient.create({
data: {
templateId: template.id,
envelopeId: template.id,
email: 'recipient@example.com',
name: 'Test Recipient',
role: RecipientRole.SIGNER,
@ -53,7 +60,8 @@ test.describe('Template Field Prefill API v2', () => {
// Add TEXT field
const textField = await prisma.field.create({
data: {
templateId: template.id,
envelopeId: template.id,
envelopeItemId: firstEnvelopeItem.id,
recipientId: recipient.id,
type: FieldType.TEXT,
page: 1,
@ -73,7 +81,8 @@ test.describe('Template Field Prefill API v2', () => {
// Add NUMBER field
const numberField = await prisma.field.create({
data: {
templateId: template.id,
envelopeId: template.id,
envelopeItemId: firstEnvelopeItem.id,
recipientId: recipient.id,
type: FieldType.NUMBER,
page: 1,
@ -93,7 +102,8 @@ test.describe('Template Field Prefill API v2', () => {
// Add RADIO field
const radioField = await prisma.field.create({
data: {
templateId: template.id,
envelopeId: template.id,
envelopeItemId: firstEnvelopeItem.id,
recipientId: recipient.id,
type: FieldType.RADIO,
page: 1,
@ -117,7 +127,8 @@ test.describe('Template Field Prefill API v2', () => {
// Add CHECKBOX field
const checkboxField = await prisma.field.create({
data: {
templateId: template.id,
envelopeId: template.id,
envelopeItemId: firstEnvelopeItem.id,
recipientId: recipient.id,
type: FieldType.CHECKBOX,
page: 1,
@ -141,7 +152,8 @@ test.describe('Template Field Prefill API v2', () => {
// Add DROPDOWN field
const dropdownField = await prisma.field.create({
data: {
templateId: template.id,
envelopeId: template.id,
envelopeItemId: firstEnvelopeItem.id,
recipientId: recipient.id,
type: FieldType.DROPDOWN,
page: 1,
@ -166,7 +178,9 @@ test.describe('Template Field Prefill API v2', () => {
});
// 7. Navigate to the template
await page.goto(`${WEBAPP_BASE_URL}/templates/${template.id}`);
await page.goto(
`${WEBAPP_BASE_URL}/templates/${mapSecondaryIdToTemplateId(template.secondaryId)}`,
);
// 8. Create a document from the template with prefilled fields using v2 API
const response = await request.post(`${WEBAPP_BASE_URL}/api/v2-beta/template/use`, {
@ -175,7 +189,7 @@ test.describe('Template Field Prefill API v2', () => {
'Content-Type': 'application/json',
},
data: {
templateId: template.id,
templateId: mapSecondaryIdToTemplateId(template.secondaryId),
recipients: [
{
id: recipient.id,
@ -226,9 +240,9 @@ test.describe('Template Field Prefill API v2', () => {
expect(responseData.id).toBeDefined();
// 9. Verify the document was created with prefilled fields
const document = await prisma.document.findUnique({
const document = await prisma.envelope.findUnique({
where: {
id: responseData.id,
secondaryId: mapDocumentIdToSecondaryId(responseData.id),
},
include: {
fields: true,
@ -237,6 +251,10 @@ test.describe('Template Field Prefill API v2', () => {
expect(document).not.toBeNull();
if (!document) {
throw new Error('Document not found');
}
// 10. Verify each field has the correct prefilled values
const documentTextField = document?.fields.find(
(field) => field.type === FieldType.TEXT && field.fieldMeta?.type === 'text',
@ -297,7 +315,7 @@ test.describe('Template Field Prefill API v2', () => {
'Content-Type': 'application/json',
},
data: {
documentId: document?.id,
documentId: mapSecondaryIdToDocumentId(document?.secondaryId),
meta: {
subject: 'Test Subject',
message: 'Test Message',
@ -311,7 +329,7 @@ test.describe('Template Field Prefill API v2', () => {
// 11. Sign in as the recipient and verify the prefilled fields are visible
const documentRecipient = await prisma.recipient.findFirst({
where: {
documentId: document?.id,
envelopeId: document?.id,
email: 'recipient@example.com',
},
});
@ -364,10 +382,12 @@ test.describe('Template Field Prefill API v2', () => {
},
});
const firstEnvelopeItem = template.envelopeItems[0];
// 4. Create a recipient for the template
const recipient = await prisma.recipient.create({
data: {
templateId: template.id,
envelopeId: template.id,
email: 'recipient@example.com',
name: 'Test Recipient',
role: RecipientRole.SIGNER,
@ -382,7 +402,8 @@ test.describe('Template Field Prefill API v2', () => {
// Add TEXT field
await prisma.field.create({
data: {
templateId: template.id,
envelopeId: template.id,
envelopeItemId: firstEnvelopeItem.id,
recipientId: recipient.id,
type: FieldType.TEXT,
page: 1,
@ -402,7 +423,8 @@ test.describe('Template Field Prefill API v2', () => {
// Add NUMBER field
await prisma.field.create({
data: {
templateId: template.id,
envelopeId: template.id,
envelopeItemId: firstEnvelopeItem.id,
recipientId: recipient.id,
type: FieldType.NUMBER,
page: 1,
@ -426,7 +448,9 @@ test.describe('Template Field Prefill API v2', () => {
});
// 7. Navigate to the template
await page.goto(`${WEBAPP_BASE_URL}/templates/${template.id}`);
await page.goto(
`${WEBAPP_BASE_URL}/templates/${mapSecondaryIdToTemplateId(template.secondaryId)}`,
);
// 8. Create a document from the template without prefilled fields using v2 API
const response = await request.post(`${WEBAPP_BASE_URL}/api/v2-beta/template/use`, {
@ -435,7 +459,7 @@ test.describe('Template Field Prefill API v2', () => {
'Content-Type': 'application/json',
},
data: {
templateId: template.id,
templateId: mapSecondaryIdToTemplateId(template.secondaryId),
recipients: [
{
id: recipient.id,
@ -454,9 +478,9 @@ test.describe('Template Field Prefill API v2', () => {
expect(responseData.id).toBeDefined();
// 9. Verify the document was created with default fields
const document = await prisma.document.findUnique({
const document = await prisma.envelope.findUnique({
where: {
id: responseData.id,
secondaryId: mapDocumentIdToSecondaryId(responseData.id),
},
include: {
fields: true,
@ -465,6 +489,10 @@ test.describe('Template Field Prefill API v2', () => {
expect(document).not.toBeNull();
if (!document) {
throw new Error('Document not found');
}
// 10. Verify fields have their default values
const documentTextField = document?.fields.find((field) => field.type === FieldType.TEXT);
expect(documentTextField?.fieldMeta).toMatchObject({
@ -484,7 +512,7 @@ test.describe('Template Field Prefill API v2', () => {
'Content-Type': 'application/json',
},
data: {
documentId: document?.id,
documentId: mapSecondaryIdToDocumentId(document?.secondaryId),
meta: {
subject: 'Test Subject',
message: 'Test Message',
@ -498,7 +526,7 @@ test.describe('Template Field Prefill API v2', () => {
// 11. Sign in as the recipient and verify the default fields are visible
const documentRecipient = await prisma.recipient.findFirst({
where: {
documentId: document?.id,
envelopeId: document?.id,
email: 'recipient@example.com',
},
});
@ -531,10 +559,12 @@ test.describe('Template Field Prefill API v2', () => {
},
});
const firstEnvelopeItem = template.envelopeItems[0];
// 4. Create a recipient for the template
const recipient = await prisma.recipient.create({
data: {
templateId: template.id,
envelopeId: template.id,
email: 'recipient@example.com',
name: 'Test Recipient',
role: RecipientRole.SIGNER,
@ -548,7 +578,8 @@ test.describe('Template Field Prefill API v2', () => {
// 5. Add a field to the template
const field = await prisma.field.create({
data: {
templateId: template.id,
envelopeId: template.id,
envelopeItemId: firstEnvelopeItem.id,
recipientId: recipient.id,
type: FieldType.RADIO,
page: 1,
@ -576,7 +607,7 @@ test.describe('Template Field Prefill API v2', () => {
'Content-Type': 'application/json',
},
data: {
templateId: template.id,
templateId: mapSecondaryIdToTemplateId(template.secondaryId),
recipients: [
{
id: recipient.id,

View File

@ -19,7 +19,7 @@ test('[DOCUMENT_AUTH]: should grant access when not required', async ({ page })
const recipients = await prisma.recipient.findMany({
where: {
documentId: document.id,
envelopeId: document.id,
},
});
@ -52,7 +52,7 @@ test('[DOCUMENT_AUTH]: should allow or deny access when required', async ({ page
const recipients = await prisma.recipient.findMany({
where: {
documentId: document.id,
envelopeId: document.id,
},
});

View File

@ -85,7 +85,7 @@ test('[NEXT_RECIPIENT_DICTATION]: should allow updating next recipient when dict
await page.waitForURL(`${signUrl}/complete`);
// Verify document and recipient states
const updatedDocument = await prisma.document.findUniqueOrThrow({
const updatedDocument = await prisma.envelope.findUniqueOrThrow({
where: { id: document.id },
include: {
recipients: {
@ -172,7 +172,7 @@ test('[NEXT_RECIPIENT_DICTATION]: should not show dictation UI when disabled', a
// Verify document and recipient states
const updatedDocument = await prisma.document.findUniqueOrThrow({
const updatedDocument = await prisma.envelope.findUniqueOrThrow({
where: { id: document.id },
include: {
recipients: {
@ -259,7 +259,7 @@ test('[NEXT_RECIPIENT_DICTATION]: should work with parallel signing flow', async
// Verify final document and recipient states
await expect(async () => {
const updatedDocument = await prisma.document.findUniqueOrThrow({
const updatedDocument = await prisma.envelope.findUniqueOrThrow({
where: { id: document.id },
include: {
recipients: {
@ -295,19 +295,13 @@ test('[NEXT_RECIPIENT_DICTATION]: should allow assistant to dictate next signer'
{ signingOrder: 2, role: RecipientRole.SIGNER },
{ signingOrder: 3, role: RecipientRole.SIGNER },
],
updateDocumentOptions: {
documentMeta: {
upsert: {
create: {
allowDictateNextSigner: true,
signingOrder: DocumentSigningOrder.SEQUENTIAL,
},
update: {
allowDictateNextSigner: true,
signingOrder: DocumentSigningOrder.SEQUENTIAL,
},
},
},
});
await prisma.documentMeta.update({
where: { id: document.documentMetaId },
data: {
allowDictateNextSigner: true,
signingOrder: DocumentSigningOrder.SEQUENTIAL,
},
});
@ -362,7 +356,7 @@ test('[NEXT_RECIPIENT_DICTATION]: should allow assistant to dictate next signer'
// Verify document and recipient states
await expect(async () => {
const updatedDocument = await prisma.document.findUniqueOrThrow({
const updatedDocument = await prisma.envelope.findUniqueOrThrow({
where: { id: document.id },
include: {
recipients: {

View File

@ -1,7 +1,7 @@
import type { Page } from '@playwright/test';
import { expect, test } from '@playwright/test';
import { getFieldsForDocument } from '@documenso/lib/server-only/field/get-fields-for-document';
import { prisma } from '@documenso/prisma';
import { seedBlankDocument } from '@documenso/prisma/seed/documents';
import { seedUser } from '@documenso/prisma/seed/users';
@ -14,7 +14,7 @@ const setupDocumentAndNavigateToFieldsStep = async (page: Page) => {
await apiSignin({
page,
email: user.email,
redirectPath: `/documents/${document.id}/edit`,
redirectPath: `/t/${team.url}/documents/${document.id}/edit`,
});
await page.getByRole('button', { name: 'Continue' }).click();
@ -84,10 +84,8 @@ test.describe('AutoSave Fields Step', () => {
await triggerAutosave(page);
await expect(async () => {
const retrievedFields = await getFieldsForDocument({
documentId: document.id,
userId: user.id,
teamId: team.id,
const retrievedFields = await getFieldsForEnvelope({
envelopeId: document.id,
});
expect(retrievedFields.length).toBe(3);
@ -149,10 +147,8 @@ test.describe('AutoSave Fields Step', () => {
await triggerAutosave(page);
await expect(async () => {
const retrievedFields = await getFieldsForDocument({
documentId: document.id,
userId: user.id,
teamId: team.id,
const retrievedFields = await getFieldsForEnvelope({
envelopeId: document.id,
});
expect(retrievedFields.length).toBe(2);
@ -213,10 +209,8 @@ test.describe('AutoSave Fields Step', () => {
await triggerAutosave(page);
await expect(async () => {
const retrievedFields = await getFieldsForDocument({
documentId: document.id,
userId: user.id,
teamId: team.id,
const retrievedFields = await getFieldsForEnvelope({
envelopeId: document.id,
});
expect(retrievedFields.length).toBe(4);
@ -260,10 +254,8 @@ test.describe('AutoSave Fields Step', () => {
await triggerAutosave(page);
await expect(async () => {
const retrievedFields = await getFieldsForDocument({
documentId: document.id,
userId: user.id,
teamId: team.id,
const retrievedFields = await getFieldsForEnvelope({
envelopeId: document.id,
});
expect(retrievedFields.length).toBe(2);
@ -291,3 +283,28 @@ test.describe('AutoSave Fields Step', () => {
}).toPass();
});
});
const getFieldsForEnvelope = async ({ envelopeId }: { envelopeId: string }) => {
const fields = await prisma.field.findMany({
where: {
envelope: {
id: envelopeId,
},
},
include: {
signature: true,
recipient: {
select: {
name: true,
email: true,
signingStatus: true,
},
},
},
orderBy: {
id: 'asc',
},
});
return fields;
};

View File

@ -1,7 +1,8 @@
import type { Page } from '@playwright/test';
import { expect, test } from '@playwright/test';
import { EnvelopeType } from '@prisma/client';
import { getDocumentById } from '@documenso/lib/server-only/document/get-document-by-id';
import { getEnvelopeById } from '@documenso/lib/server-only/envelope/get-envelope-by-id';
import { seedBlankDocument } from '@documenso/prisma/seed/documents';
import { seedUser } from '@documenso/prisma/seed/users';
@ -17,7 +18,7 @@ const setupDocument = async (page: Page) => {
await apiSignin({
page,
email: user.email,
redirectPath: `/documents/${document.id}/edit`,
redirectPath: `/t/${team.url}/documents/${document.id}/edit`,
});
return { user, team, document };
@ -41,8 +42,12 @@ test.describe('AutoSave Settings Step', () => {
await triggerAutosave(page);
await expect(async () => {
const retrieved = await getDocumentById({
documentId: document.id,
const retrieved = await getEnvelopeById({
id: {
type: 'envelopeId',
id: document.id,
},
type: EnvelopeType.DOCUMENT,
userId: user.id,
teamId: team.id,
});
@ -63,8 +68,12 @@ test.describe('AutoSave Settings Step', () => {
await triggerAutosave(page);
await expect(async () => {
const retrieved = await getDocumentById({
documentId: document.id,
const retrieved = await getEnvelopeById({
id: {
type: 'envelopeId',
id: document.id,
},
type: EnvelopeType.DOCUMENT,
userId: user.id,
teamId: team.id,
});
@ -85,8 +94,12 @@ test.describe('AutoSave Settings Step', () => {
await triggerAutosave(page);
await expect(async () => {
const retrieved = await getDocumentById({
documentId: document.id,
const retrieved = await getEnvelopeById({
id: {
type: 'envelopeId',
id: document.id,
},
type: EnvelopeType.DOCUMENT,
userId: user.id,
teamId: team.id,
});
@ -107,8 +120,12 @@ test.describe('AutoSave Settings Step', () => {
await triggerAutosave(page);
await expect(async () => {
const retrieved = await getDocumentById({
documentId: document.id,
const retrieved = await getEnvelopeById({
id: {
type: 'envelopeId',
id: document.id,
},
type: EnvelopeType.DOCUMENT,
userId: user.id,
teamId: team.id,
});
@ -129,8 +146,12 @@ test.describe('AutoSave Settings Step', () => {
await triggerAutosave(page);
await expect(async () => {
const retrieved = await getDocumentById({
documentId: document.id,
const retrieved = await getEnvelopeById({
id: {
type: 'envelopeId',
id: document.id,
},
type: EnvelopeType.DOCUMENT,
userId: user.id,
teamId: team.id,
});
@ -152,8 +173,12 @@ test.describe('AutoSave Settings Step', () => {
await triggerAutosave(page);
await expect(async () => {
const retrieved = await getDocumentById({
documentId: document.id,
const retrieved = await getEnvelopeById({
id: {
type: 'envelopeId',
id: document.id,
},
type: EnvelopeType.DOCUMENT,
userId: user.id,
teamId: team.id,
});
@ -173,8 +198,12 @@ test.describe('AutoSave Settings Step', () => {
await triggerAutosave(page);
await expect(async () => {
const retrieved = await getDocumentById({
documentId: document.id,
const retrieved = await getEnvelopeById({
id: {
type: 'envelopeId',
id: document.id,
},
type: EnvelopeType.DOCUMENT,
userId: user.id,
teamId: team.id,
});
@ -195,8 +224,12 @@ test.describe('AutoSave Settings Step', () => {
await triggerAutosave(page);
await expect(async () => {
const retrieved = await getDocumentById({
documentId: document.id,
const retrieved = await getEnvelopeById({
id: {
type: 'envelopeId',
id: document.id,
},
type: EnvelopeType.DOCUMENT,
userId: user.id,
teamId: team.id,
});
@ -227,8 +260,12 @@ test.describe('AutoSave Settings Step', () => {
await triggerAutosave(page);
await expect(async () => {
const retrieved = await getDocumentById({
documentId: document.id,
const retrieved = await getEnvelopeById({
id: {
type: 'envelopeId',
id: document.id,
},
type: EnvelopeType.DOCUMENT,
userId: user.id,
teamId: team.id,
});

View File

@ -1,8 +1,10 @@
import type { Page } from '@playwright/test';
import { expect, test } from '@playwright/test';
import { EnvelopeType } from '@prisma/client';
import { getDocumentById } from '@documenso/lib/server-only/document/get-document-by-id';
import { getEnvelopeById } from '@documenso/lib/server-only/envelope/get-envelope-by-id';
import { getRecipientsForDocument } from '@documenso/lib/server-only/recipient/get-recipients-for-document';
import { mapSecondaryIdToDocumentId } from '@documenso/lib/utils/envelope';
import { seedBlankDocument } from '@documenso/prisma/seed/documents';
import { seedUser } from '@documenso/prisma/seed/users';
@ -17,7 +19,7 @@ const setupDocumentAndNavigateToSignersStep = async (page: Page) => {
await apiSignin({
page,
email: user.email,
redirectPath: `/documents/${document.id}/edit`,
redirectPath: `/t/${team.url}/documents/${document.id}/edit`,
});
await page.getByRole('button', { name: 'Continue' }).click();
@ -47,7 +49,7 @@ test.describe('AutoSave Signers Step', () => {
await expect(async () => {
const retrievedRecipients = await getRecipientsForDocument({
documentId: document.id,
documentId: mapSecondaryIdToDocumentId(document.secondaryId),
userId: user.id,
teamId: team.id,
});
@ -71,7 +73,7 @@ test.describe('AutoSave Signers Step', () => {
await expect(async () => {
const retrievedRecipients = await getRecipientsForDocument({
documentId: document.id,
documentId: mapSecondaryIdToDocumentId(document.secondaryId),
userId: user.id,
teamId: team.id,
});
@ -99,7 +101,7 @@ test.describe('AutoSave Signers Step', () => {
await expect(async () => {
const retrievedRecipients = await getRecipientsForDocument({
documentId: document.id,
documentId: mapSecondaryIdToDocumentId(document.secondaryId),
userId: user.id,
teamId: team.id,
});
@ -145,14 +147,18 @@ test.describe('AutoSave Signers Step', () => {
await triggerAutosave(page);
await expect(async () => {
const retrievedDocumentData = await getDocumentById({
documentId: document.id,
const retrievedDocumentData = await getEnvelopeById({
id: {
type: 'envelopeId',
id: document.id,
},
type: EnvelopeType.DOCUMENT,
userId: user.id,
teamId: team.id,
});
const retrievedRecipients = await getRecipientsForDocument({
documentId: document.id,
documentId: mapSecondaryIdToDocumentId(document.secondaryId),
userId: user.id,
teamId: team.id,
});

View File

@ -1,7 +1,8 @@
import type { Page } from '@playwright/test';
import { expect, test } from '@playwright/test';
import { EnvelopeType } from '@prisma/client';
import { getDocumentById } from '@documenso/lib/server-only/document/get-document-by-id';
import { getEnvelopeById } from '@documenso/lib/server-only/envelope/get-envelope-by-id';
import { seedBlankDocument } from '@documenso/prisma/seed/documents';
import { seedUser } from '@documenso/prisma/seed/users';
@ -16,7 +17,7 @@ export const setupDocumentAndNavigateToSubjectStep = async (page: Page) => {
await apiSignin({
page,
email: user.email,
redirectPath: `/documents/${document.id}/edit`,
redirectPath: `/t/${team.url}/documents/${document.id}/edit`,
});
await page.getByRole('button', { name: 'Continue' }).click();
@ -59,8 +60,12 @@ test.describe('AutoSave Subject Step', () => {
await triggerAutosave(page);
await expect(async () => {
const retrievedDocumentData = await getDocumentById({
documentId: document.id,
const retrievedDocumentData = await getEnvelopeById({
id: {
type: 'envelopeId',
id: document.id,
},
type: EnvelopeType.DOCUMENT,
userId: user.id,
teamId: team.id,
});
@ -81,8 +86,12 @@ test.describe('AutoSave Subject Step', () => {
await triggerAutosave(page);
await expect(async () => {
const retrievedDocumentData = await getDocumentById({
documentId: document.id,
const retrievedDocumentData = await getEnvelopeById({
id: {
type: 'envelopeId',
id: document.id,
},
type: EnvelopeType.DOCUMENT,
userId: user.id,
teamId: team.id,
});
@ -105,8 +114,12 @@ test.describe('AutoSave Subject Step', () => {
await triggerAutosave(page);
await expect(async () => {
const retrievedDocumentData = await getDocumentById({
documentId: document.id,
const retrievedDocumentData = await getEnvelopeById({
id: {
type: 'envelopeId',
id: document.id,
},
type: EnvelopeType.DOCUMENT,
userId: user.id,
teamId: team.id,
});
@ -156,8 +169,12 @@ test.describe('AutoSave Subject Step', () => {
await triggerAutosave(page);
await expect(async () => {
const retrievedDocumentData = await getDocumentById({
documentId: document.id,
const retrievedDocumentData = await getEnvelopeById({
id: {
type: 'envelopeId',
id: document.id,
},
type: EnvelopeType.DOCUMENT,
userId: user.id,
teamId: team.id,
});

View File

@ -50,7 +50,7 @@ test('[DOCUMENT_FLOW]: Simple duplicate recipients test', async ({ page }) => {
await page.waitForTimeout(2500);
await page.getByRole('button', { name: 'Send' }).click();
await page.waitForURL(new RegExp(`/t/${team.url}/documents/\\d+`));
await page.waitForURL(new RegExp(`/t/${team.url}/documents/envelope_.*`));
await expect(page.getByRole('link', { name: document.title })).toBeVisible();
});

View File

@ -69,7 +69,7 @@ const completeDocumentFlowWithDuplicateRecipients = async (options: {
await page.getByRole('button', { name: 'Send' }).click();
// Wait for send confirmation
await page.waitForURL(new RegExp(`/t/${team.url}/documents/\\d+`));
await page.waitForURL(`/t/${team.url}/documents`);
await expect(page.getByRole('link', { name: document.title })).toBeVisible();
};
@ -157,7 +157,7 @@ test.describe('[DOCUMENT_FLOW]: Duplicate Recipients', () => {
await page.waitForTimeout(2500);
await page.getByRole('button', { name: 'Send' }).click();
await page.waitForURL(new RegExp(`/t/${team.url}/documents/\\d+`));
await page.waitForURL(new RegExp(`/t/${team.url}/documents/envelope_.*`));
await expect(page.getByRole('link', { name: document.title })).toBeVisible();
});
@ -188,7 +188,7 @@ test.describe('[DOCUMENT_FLOW]: Duplicate Recipients', () => {
const recipients = await prisma.recipient.findMany({
where: {
documentId: document.id,
envelopeId: document.id,
},
});
@ -286,7 +286,7 @@ test.describe('[DOCUMENT_FLOW]: Duplicate Recipients', () => {
await page.getByRole('button', { name: 'Send' }).click();
await page.waitForURL(new RegExp(`/t/${team.url}/documents/\\d+`));
await page.waitForURL(new RegExp(`/t/${team.url}/documents/envelope_.*`));
await expect(page.getByRole('link', { name: document.title })).toBeVisible();
});
@ -348,7 +348,7 @@ test.describe('[DOCUMENT_FLOW]: Duplicate Recipients', () => {
await page.waitForTimeout(2500);
await page.getByRole('button', { name: 'Send' }).click();
await page.waitForURL(new RegExp(`/t/${team.url}/documents/\\d+`));
await page.waitForURL(new RegExp(`/t/${team.url}/documents/envelope_.*`));
await expect(page.getByRole('link', { name: document.title })).toBeVisible();
});

View File

@ -9,7 +9,6 @@ import {
import { DateTime } from 'luxon';
import path from 'node:path';
import { getRecipientByEmail } from '@documenso/lib/server-only/recipient/get-recipient-by-email';
import { prisma } from '@documenso/prisma';
import {
seedBlankDocument,
@ -23,7 +22,7 @@ import { signSignaturePad } from '../fixtures/signature';
// Can't use the function in server-only/document due to it indirectly using
// require imports.
const getDocumentByToken = async (token: string) => {
return await prisma.document.findFirstOrThrow({
return await prisma.envelope.findFirstOrThrow({
where: {
recipients: {
some: {
@ -59,7 +58,7 @@ test('[DOCUMENT_FLOW]: should be able to upload a PDF document', async ({ page }
await fileChooser.setFiles(path.join(__dirname, '../../../../assets/example.pdf'));
// Wait to be redirected to the edit page.
await page.waitForURL(new RegExp(`/t/${team.url}/documents/\\d+`));
await page.waitForURL(new RegExp(`/t/${team.url}/documents/envelope_.*`));
});
test('[DOCUMENT_FLOW]: should be able to create a document', async ({ page }) => {
@ -115,7 +114,7 @@ test('[DOCUMENT_FLOW]: should be able to create a document', async ({ page }) =>
await page.waitForTimeout(2500);
await page.getByRole('button', { name: 'Send' }).click();
await page.waitForURL(new RegExp(`/t/${team.url}/documents/\\d+`));
await page.waitForURL(new RegExp(`/t/${team.url}/documents/envelope_.*`));
// Assert document was created
await expect(page.getByRole('link', { name: documentTitle })).toBeVisible();
@ -200,7 +199,7 @@ test('[DOCUMENT_FLOW]: should be able to create a document with multiple recipie
await page.waitForTimeout(2500);
await page.getByRole('button', { name: 'Send' }).click();
await page.waitForURL(new RegExp(`/t/${team.url}/documents/\\d+`));
await page.waitForURL(new RegExp(`/t/${team.url}/documents/envelope_.*`));
// Assert document was created
await expect(page.getByRole('link', { name: documentTitle })).toBeVisible();
@ -298,7 +297,7 @@ test('[DOCUMENT_FLOW]: should be able to create a document with multiple recipie
await page.waitForTimeout(2500);
await page.getByRole('button', { name: 'Send' }).click();
await page.waitForURL(new RegExp(`/t/${team.url}/documents/\\d+`));
await page.waitForURL(new RegExp(`/t/${team.url}/documents/envelope_.*`));
// Assert document was created
await expect(page.getByRole('link', { name: 'Test Title' })).toBeVisible();
@ -437,14 +436,18 @@ test('[DOCUMENT_FLOW]: should be able to create, send with redirect url, sign a
// Assert document was created
await expect(page.getByRole('link', { name: documentTitle })).toBeVisible();
await page.getByRole('link', { name: documentTitle }).click();
await page.waitForURL(new RegExp(`/t/${team.url}/documents/\\d+`));
await page.waitForURL(new RegExp(`/t/${team.url}/documents/envelope_.*`));
const url = page.url().split('/');
const documentId = url[url.length - 1];
const { token } = await getRecipientByEmail({
email: 'user1@example.com',
documentId: Number(documentId),
const { token } = await prisma.recipient.findFirstOrThrow({
where: {
envelope: {
id: documentId,
},
email: 'user1@example.com',
},
});
await page.goto(`/sign/${token}`);
@ -500,7 +503,7 @@ test('[DOCUMENT_FLOW]: should be able to sign a document with custom date', asyn
recipient: {
email: 'user1@example.com',
},
documentId: Number(document.id),
envelopeId: document.id,
},
});
@ -583,11 +586,11 @@ test('[DOCUMENT_FLOW]: should be able to create and sign a document with 3 recip
await page.waitForTimeout(2500);
await page.getByRole('button', { name: 'Send' }).click();
await page.waitForURL(new RegExp(`/t/${team.url}/documents/\\d+`));
await page.waitForURL(new RegExp(`/t/${team.url}/documents/envelope_.*`));
await expect(page.getByRole('link', { name: documentTitle })).toBeVisible();
const createdDocument = await prisma.document.findFirst({
const createdDocument = await prisma.envelope.findFirst({
where: { title: documentTitle },
include: { recipients: true },
});
@ -602,13 +605,13 @@ test('[DOCUMENT_FLOW]: should be able to create and sign a document with 3 recip
expect(recipient).not.toBeNull();
const fields = await prisma.field.findMany({
where: { recipientId: recipient?.id, documentId: createdDocument?.id },
where: { recipientId: recipient?.id, envelopeId: createdDocument?.id },
});
const recipientField = fields[0];
if (i > 0) {
const previousRecipient = await prisma.recipient.findFirst({
where: { email: `user${i}@example.com`, documentId: createdDocument?.id },
where: { email: `user${i}@example.com`, envelopeId: createdDocument?.id },
});
expect(previousRecipient?.signingStatus).toBe(SigningStatus.SIGNED);
@ -636,7 +639,7 @@ test('[DOCUMENT_FLOW]: should be able to create and sign a document with 3 recip
// Wait for the document to be signed.
await page.waitForTimeout(10000);
const finalDocument = await prisma.document.findFirst({
const finalDocument = await prisma.envelope.findFirst({
where: { id: createdDocument?.id },
});
@ -648,18 +651,20 @@ test('[DOCUMENT_FLOW]: should prevent out-of-order signing in sequential mode',
}) => {
const { user, team } = await seedUser();
const { recipients } = await seedPendingDocumentWithFullFields({
const { document, recipients } = await seedPendingDocumentWithFullFields({
teamId: team.id,
owner: user,
recipients: ['user1@example.com', 'user2@example.com', 'user3@example.com'],
fields: [FieldType.SIGNATURE],
recipientsCreateOptions: [{ signingOrder: 1 }, { signingOrder: 2 }, { signingOrder: 3 }],
updateDocumentOptions: {
documentMeta: {
create: {
signingOrder: DocumentSigningOrder.SEQUENTIAL,
},
},
});
await prisma.documentMeta.update({
where: {
id: document.documentMetaId,
},
data: {
signingOrder: DocumentSigningOrder.SEQUENTIAL,
},
});

View File

@ -28,7 +28,7 @@ test.describe('Unauthorized Access to Documents', () => {
});
await page.goto(`${NEXT_PUBLIC_WEBAPP_URL()}/t/${team.url}/documents/${document.id}`);
await expect(page.getByRole('heading', { name: 'Oops! Something went wrong.' })).toBeVisible();
await expect(page.getByRole('heading', { name: 'Team not found' })).toBeVisible();
});
test('should block unauthorized access to the draft document edit page', async ({ page }) => {
@ -44,7 +44,7 @@ test.describe('Unauthorized Access to Documents', () => {
});
await page.goto(`${NEXT_PUBLIC_WEBAPP_URL()}/t/${team.url}/documents/${document.id}/edit`);
await expect(page.getByRole('heading', { name: 'Oops! Something went wrong.' })).toBeVisible();
await expect(page.getByRole('heading', { name: 'Team not found' })).toBeVisible();
});
test('should block unauthorized access to the pending document page', async ({ page }) => {
@ -61,7 +61,7 @@ test.describe('Unauthorized Access to Documents', () => {
});
await page.goto(`${NEXT_PUBLIC_WEBAPP_URL()}/t/${team.url}/documents/${document.id}`);
await expect(page.getByRole('heading', { name: 'Oops! Something went wrong.' })).toBeVisible();
await expect(page.getByRole('heading', { name: 'Team not found' })).toBeVisible();
});
test('should block unauthorized access to pending document edit page', async ({ page }) => {
@ -78,7 +78,7 @@ test.describe('Unauthorized Access to Documents', () => {
});
await page.goto(`${NEXT_PUBLIC_WEBAPP_URL()}/t/${team.url}/documents/${document.id}/edit`);
await expect(page.getByRole('heading', { name: 'Oops! Something went wrong.' })).toBeVisible();
await expect(page.getByRole('heading', { name: 'Team not found' })).toBeVisible();
});
test('should block unauthorized access to completed document page', async ({ page }) => {
@ -95,6 +95,6 @@ test.describe('Unauthorized Access to Documents', () => {
});
await page.goto(`${NEXT_PUBLIC_WEBAPP_URL()}/t/${team.url}/documents/${document.id}`);
await expect(page.getByRole('heading', { name: 'Oops! Something went wrong.' })).toBeVisible();
await expect(page.getByRole('heading', { name: 'Team not found' })).toBeVisible();
});
});

View File

@ -1,6 +1,6 @@
import { PDFDocument } from '@cantoo/pdf-lib';
import { expect, test } from '@playwright/test';
import { DocumentStatus, FieldType } from '@prisma/client';
import { PDFDocument } from 'pdf-lib';
import { getDocumentByToken } from '@documenso/lib/server-only/document/get-document-by-token';
import { getFile } from '@documenso/lib/universal/upload/get-file';
@ -28,7 +28,9 @@ test.describe('Signing Certificate Tests', () => {
const documentData = await prisma.documentData
.findFirstOrThrow({
where: {
id: document.documentDataId,
envelopeItem: {
envelopeId: document.id,
},
},
})
.then(async (data) => getFile(data));
@ -65,12 +67,21 @@ test.describe('Signing Certificate Tests', () => {
await page.waitForTimeout(2500);
// Get the completed document
const completedDocument = await prisma.document.findFirstOrThrow({
const completedDocument = await prisma.envelope.findFirstOrThrow({
where: { id: document.id },
include: { documentData: true },
include: {
envelopeItems: {
include: {
documentData: true,
},
},
},
});
const completedDocumentData = await getFile(completedDocument.documentData);
// Todo: Envelopes
const firstDocumentData = completedDocument.envelopeItems[0].documentData;
const completedDocumentData = await getFile(firstDocumentData);
// Load the PDF and check number of pages
const pdfDoc = await PDFDocument.load(completedDocumentData);
@ -110,7 +121,9 @@ test.describe('Signing Certificate Tests', () => {
const documentData = await prisma.documentData
.findFirstOrThrow({
where: {
id: document.documentDataId,
envelopeItem: {
envelopeId: document.id,
},
},
})
.then(async (data) => getFile(data));
@ -145,12 +158,21 @@ test.describe('Signing Certificate Tests', () => {
await page.waitForTimeout(2500);
// Get the completed document
const completedDocument = await prisma.document.findFirstOrThrow({
const completedDocument = await prisma.envelope.findFirstOrThrow({
where: { id: document.id },
include: { documentData: true },
include: {
envelopeItems: {
include: {
documentData: true,
},
},
},
});
const completedDocumentData = await getFile(completedDocument.documentData);
// Todo: Envelopes
const firstDocumentData = completedDocument.envelopeItems[0].documentData;
const completedDocumentData = await getFile(firstDocumentData);
// Load the PDF and check number of pages
const completedPdf = await PDFDocument.load(completedDocumentData);
@ -190,7 +212,9 @@ test.describe('Signing Certificate Tests', () => {
const documentData = await prisma.documentData
.findFirstOrThrow({
where: {
id: document.documentDataId,
envelopeItem: {
envelopeId: document.id,
},
},
})
.then(async (data) => getFile(data));
@ -225,12 +249,18 @@ test.describe('Signing Certificate Tests', () => {
await page.waitForTimeout(2500);
// Get the completed document
const completedDocument = await prisma.document.findFirstOrThrow({
const completedDocument = await prisma.envelope.findFirstOrThrow({
where: { id: document.id },
include: { documentData: true },
include: {
envelopeItems: {
include: {
documentData: true,
},
},
},
});
const completedDocumentData = await getFile(completedDocument.documentData);
const completedDocumentData = await getFile(completedDocument.envelopeItems[0].documentData);
// Load the PDF and check number of pages
const completedPdf = await PDFDocument.load(completedDocumentData);

View File

@ -44,12 +44,6 @@ test('[TEAMS]: can create document folder', async ({ page }) => {
test('[TEAMS]: can create document subfolder within a document folder', async ({ page }) => {
const { team, teamOwner } = await seedTeamDocuments();
await apiSignin({
page,
email: teamOwner.email,
redirectPath: `/t/${team.url}`,
});
const teamFolder = await seedBlankFolder(teamOwner, team.id, {
createFolderOptions: {
name: 'Team Folder',
@ -57,7 +51,11 @@ test('[TEAMS]: can create document subfolder within a document folder', async ({
},
});
await page.goto(`/t/${team.url}/documents/f/${teamFolder.id}`);
await apiSignin({
page,
email: teamOwner.email,
redirectPath: `/t/${team.url}/documents/f/${teamFolder.id}`,
});
await page.getByTestId('folder-create-button').click();
@ -383,12 +381,10 @@ test('[TEAMS]: can create a template inside a template folder', async ({ page })
await page.waitForTimeout(3000);
await page.getByRole('button', { name: 'Create' }).click();
await page.waitForTimeout(1000);
// Expect redirect.
await expect(page.getByText('documenso-supporter-pledge.pdf')).toBeVisible();
// Return to folder and verify file is visible.
await page.goto(`/t/${team.url}/templates/f/${folder.id}`);
await expect(page.getByText('documenso-supporter-pledge.pdf')).toBeVisible();
});

View File

@ -96,7 +96,7 @@ test('[ORGANISATIONS]: manage document preferences', async ({ page }) => {
const documentMeta = await prisma.documentMeta.findFirstOrThrow({
where: {
documentId: document.id,
id: document.documentMetaId,
},
});
@ -272,7 +272,7 @@ test('[ORGANISATIONS]: manage email preferences', async ({ page }) => {
const teamOverrideDocumentMeta = await prisma.documentMeta.findFirstOrThrow({
where: {
documentId: teamOverrideDocument.id,
id: teamOverrideDocument.documentMetaId,
},
});
@ -317,7 +317,7 @@ test('[ORGANISATIONS]: manage email preferences', async ({ page }) => {
const documentMeta = await prisma.documentMeta.findFirstOrThrow({
where: {
documentId: document.id,
id: document.documentMetaId,
},
});

View File

@ -146,6 +146,7 @@ test('[TEAMS]: search does not reveal documents from other teams', async ({ page
redirectPath: `/t/${teamA.url}/documents`,
});
await page.waitForTimeout(100);
await page.getByPlaceholder('Search documents...').fill('Unique');
await page.waitForURL(/query=Unique/);

View File

@ -1,5 +1,9 @@
import { expect, test } from '@playwright/test';
import {
mapSecondaryIdToDocumentId,
mapSecondaryIdToTemplateId,
} from '@documenso/lib/utils/envelope';
import { prisma } from '@documenso/prisma';
import {
seedTeamDocumentWithMeta,
@ -21,7 +25,9 @@ test('[TEAMS]: check that default team signature settings are all enabled', asyn
const document = await seedTeamDocumentWithMeta(team);
// Create a document and check the settings
await page.goto(`/t/${team.url}/documents/${document.id}/edit`);
await page.goto(
`/t/${team.url}/documents/${mapSecondaryIdToDocumentId(document.secondaryId)}/edit`,
);
// Verify that the settings match
await page.getByRole('button', { name: 'Advanced Options' }).click();
@ -154,7 +160,7 @@ test('[TEAMS]: check signature modes work for templates', async ({ page }) => {
const template = await seedTeamTemplateWithMeta(team);
await page.goto(`/t/${team.url}/templates/${template.id}`);
await page.goto(`/t/${team.url}/templates/${mapSecondaryIdToTemplateId(template.secondaryId)}`);
await page.getByRole('button', { name: 'Use' }).click();
// Check the send document checkbox to true
@ -162,9 +168,10 @@ test('[TEAMS]: check signature modes work for templates', async ({ page }) => {
await page.getByRole('button', { name: 'Create and send' }).click();
await page.waitForTimeout(1000);
const document = await prisma.document.findFirst({
const document = await prisma.envelope.findFirst({
where: {
templateId: template.id,
// Created from template
templateId: mapSecondaryIdToTemplateId(template.secondaryId),
},
include: {
documentMeta: true,

View File

@ -1,5 +1,5 @@
import { type Page, expect, test } from '@playwright/test';
import type { Team, Template } from '@prisma/client';
import type { Envelope, Team } from '@prisma/client';
import { PDF_VIEWER_PAGE_SELECTOR } from '@documenso/lib/constants/pdf-viewer';
import { prisma } from '@documenso/prisma';
@ -14,7 +14,7 @@ import { apiSignin } from '../fixtures/authentication';
const completeTemplateFlowWithDuplicateRecipients = async (options: {
page: Page;
team: Team;
template: Template;
template: Envelope;
}) => {
const { page, team, template } = options;
// Step 1: Settings - Continue with defaults
@ -131,20 +131,20 @@ test.describe('[TEMPLATE_FLOW]: Duplicate Recipients', () => {
// Create document
await page.getByRole('button', { name: 'Create and send' }).click();
await page.waitForURL(new RegExp(`/t/${team.url}/documents/\\d+`));
await page.waitForURL(new RegExp(`/t/${team.url}/documents/envelope_.*`));
// Get the document ID from URL for database queries
const url = page.url();
const documentIdMatch = url.match(/\/documents\/(\d+)/);
const documentIdMatch = url.match(/\/documents\/envelope_(.*)/);
const documentId = documentIdMatch ? parseInt(documentIdMatch[1]) : null;
const envelopeId = documentIdMatch ? documentIdMatch[1] : null;
expect(documentId).not.toBeNull();
expect(envelopeId).not.toBeNull();
// Get recipients directly from database
const recipients = await prisma.recipient.findMany({
where: {
documentId: documentId!,
envelopeId: `envelope_${envelopeId}`,
},
});

View File

@ -2,6 +2,7 @@ import type { Page } from '@playwright/test';
import { expect, test } from '@playwright/test';
import { getTemplateById } from '@documenso/lib/server-only/template/get-template-by-id';
import { mapSecondaryIdToTemplateId } from '@documenso/lib/utils/envelope';
import { seedBlankTemplate } from '@documenso/prisma/seed/templates';
import { seedUser } from '@documenso/prisma/seed/users';
@ -14,7 +15,7 @@ const setupTemplateAndNavigateToFieldsStep = async (page: Page) => {
await apiSignin({
page,
email: user.email,
redirectPath: `/templates/${template.id}/edit`,
redirectPath: `/t/${team.url}/templates/${mapSecondaryIdToTemplateId(template.secondaryId)}/edit`,
});
await page.getByRole('button', { name: 'Continue' }).click();
@ -85,7 +86,10 @@ test.describe('AutoSave Fields Step', () => {
await expect(async () => {
const retrievedFields = await getTemplateById({
id: template.id,
id: {
type: 'envelopeId',
id: template.id,
},
userId: user.id,
teamId: team.id,
});
@ -152,7 +156,10 @@ test.describe('AutoSave Fields Step', () => {
await expect(async () => {
const retrievedFields = await getTemplateById({
id: template.id,
id: {
type: 'envelopeId',
id: template.id,
},
userId: user.id,
teamId: team.id,
});
@ -218,7 +225,11 @@ test.describe('AutoSave Fields Step', () => {
await expect(async () => {
const retrievedFields = await getTemplateById({
id: template.id,
id: {
type: 'envelopeId',
id: template.id,
},
userId: user.id,
teamId: team.id,
});
@ -270,7 +281,10 @@ test.describe('AutoSave Fields Step', () => {
await expect(async () => {
const retrievedTemplate = await getTemplateById({
id: template.id,
id: {
type: 'envelopeId',
id: template.id,
},
userId: user.id,
teamId: team.id,
});

View File

@ -2,6 +2,7 @@ import type { Page } from '@playwright/test';
import { expect, test } from '@playwright/test';
import { getTemplateById } from '@documenso/lib/server-only/template/get-template-by-id';
import { mapSecondaryIdToTemplateId } from '@documenso/lib/utils/envelope';
import { seedBlankTemplate } from '@documenso/prisma/seed/templates';
import { seedUser } from '@documenso/prisma/seed/users';
@ -16,7 +17,7 @@ const setupTemplate = async (page: Page) => {
await apiSignin({
page,
email: user.email,
redirectPath: `/templates/${template.id}/edit`,
redirectPath: `/t/${team.url}/templates/${mapSecondaryIdToTemplateId(template.secondaryId)}/edit`,
});
return { user, team, template };
@ -41,7 +42,10 @@ test.describe('AutoSave Settings Step - Templates', () => {
await expect(async () => {
const retrievedTemplate = await getTemplateById({
id: template.id,
id: {
type: 'envelopeId',
id: template.id,
},
userId: user.id,
teamId: team.id,
});
@ -65,7 +69,10 @@ test.describe('AutoSave Settings Step - Templates', () => {
await expect(async () => {
const retrievedTemplate = await getTemplateById({
id: template.id,
id: {
type: 'envelopeId',
id: template.id,
},
userId: user.id,
teamId: team.id,
});
@ -87,7 +94,10 @@ test.describe('AutoSave Settings Step - Templates', () => {
await expect(async () => {
const retrievedTemplate = await getTemplateById({
id: template.id,
id: {
type: 'envelopeId',
id: template.id,
},
userId: user.id,
teamId: team.id,
});
@ -109,7 +119,10 @@ test.describe('AutoSave Settings Step - Templates', () => {
await expect(async () => {
const retrievedTemplate = await getTemplateById({
id: template.id,
id: {
type: 'envelopeId',
id: template.id,
},
userId: user.id,
teamId: team.id,
});
@ -131,7 +144,10 @@ test.describe('AutoSave Settings Step - Templates', () => {
await expect(async () => {
const retrievedTemplate = await getTemplateById({
id: template.id,
id: {
type: 'envelopeId',
id: template.id,
},
userId: user.id,
teamId: team.id,
});
@ -154,7 +170,10 @@ test.describe('AutoSave Settings Step - Templates', () => {
await expect(async () => {
const retrievedTemplate = await getTemplateById({
id: template.id,
id: {
type: 'envelopeId',
id: template.id,
},
userId: user.id,
teamId: team.id,
});
@ -175,7 +194,10 @@ test.describe('AutoSave Settings Step - Templates', () => {
await expect(async () => {
const retrievedTemplate = await getTemplateById({
id: template.id,
id: {
type: 'envelopeId',
id: template.id,
},
userId: user.id,
teamId: team.id,
});
@ -197,7 +219,10 @@ test.describe('AutoSave Settings Step - Templates', () => {
await expect(async () => {
const retrievedTemplate = await getTemplateById({
id: template.id,
id: {
type: 'envelopeId',
id: template.id,
},
userId: user.id,
teamId: team.id,
});
@ -229,7 +254,10 @@ test.describe('AutoSave Settings Step - Templates', () => {
await expect(async () => {
const retrievedTemplate = await getTemplateById({
id: template.id,
id: {
type: 'envelopeId',
id: template.id,
},
userId: user.id,
teamId: team.id,
});

View File

@ -1,8 +1,11 @@
import type { Page } from '@playwright/test';
import { expect, test } from '@playwright/test';
import { EnvelopeType } from '@prisma/client';
import { getRecipientsForTemplate } from '@documenso/lib/server-only/recipient/get-recipients-for-template';
import { getEnvelopeWhereInput } from '@documenso/lib/server-only/envelope/get-envelope-by-id';
import { getTemplateById } from '@documenso/lib/server-only/template/get-template-by-id';
import { mapSecondaryIdToTemplateId } from '@documenso/lib/utils/envelope';
import { prisma } from '@documenso/prisma';
import { seedBlankTemplate } from '@documenso/prisma/seed/templates';
import { seedUser } from '@documenso/prisma/seed/users';
@ -17,7 +20,7 @@ const setupTemplateAndNavigateToSignersStep = async (page: Page) => {
await apiSignin({
page,
email: user.email,
redirectPath: `/templates/${template.id}/edit`,
redirectPath: `/t/${team.url}/templates/${mapSecondaryIdToTemplateId(template.secondaryId)}/edit`,
});
await page.getByRole('button', { name: 'Continue' }).click();
@ -47,7 +50,7 @@ test.describe('AutoSave Signers Step - Templates', () => {
await expect(async () => {
const retrievedRecipients = await getRecipientsForTemplate({
templateId: template.id,
templateId: mapSecondaryIdToTemplateId(template.secondaryId),
userId: user.id,
teamId: team.id,
});
@ -71,7 +74,7 @@ test.describe('AutoSave Signers Step - Templates', () => {
await expect(async () => {
const retrievedRecipients = await getRecipientsForTemplate({
templateId: template.id,
templateId: mapSecondaryIdToTemplateId(template.secondaryId),
userId: user.id,
teamId: team.id,
});
@ -99,7 +102,7 @@ test.describe('AutoSave Signers Step - Templates', () => {
await expect(async () => {
const retrievedRecipients = await getRecipientsForTemplate({
templateId: template.id,
templateId: mapSecondaryIdToTemplateId(template.secondaryId),
userId: user.id,
teamId: team.id,
});
@ -152,13 +155,16 @@ test.describe('AutoSave Signers Step - Templates', () => {
await expect(async () => {
const retrievedTemplate = await getTemplateById({
id: template.id,
id: {
type: 'envelopeId',
id: template.id,
},
userId: user.id,
teamId: team.id,
});
const retrievedRecipients = await getRecipientsForTemplate({
templateId: template.id,
templateId: mapSecondaryIdToTemplateId(template.secondaryId),
userId: user.id,
teamId: team.id,
});
@ -172,3 +178,36 @@ test.describe('AutoSave Signers Step - Templates', () => {
}).toPass();
});
});
export interface GetRecipientsForTemplateOptions {
templateId: number;
userId: number;
teamId: number;
}
const getRecipientsForTemplate = async ({
templateId,
userId,
teamId,
}: GetRecipientsForTemplateOptions) => {
const { envelopeWhereInput } = await getEnvelopeWhereInput({
id: {
type: 'templateId',
id: templateId,
},
type: EnvelopeType.TEMPLATE,
userId,
teamId,
});
const recipients = await prisma.recipient.findMany({
where: {
envelope: envelopeWhereInput,
},
orderBy: {
id: 'asc',
},
});
return recipients;
};

View File

@ -1,6 +1,7 @@
import { expect, test } from '@playwright/test';
import { TeamMemberRole } from '@prisma/client';
import { mapSecondaryIdToTemplateId } from '@documenso/lib/utils/envelope';
import { seedTeam, seedTeamMember } from '@documenso/prisma/seed/teams';
import { seedBlankTemplate } from '@documenso/prisma/seed/templates';
import { seedUser } from '@documenso/prisma/seed/users';
@ -118,8 +119,10 @@ test('[TEMPLATE_FLOW] team member visibility permissions', async ({ page }) => {
redirectPath: `/t/${team.url}/templates/${template.id}/edit`,
});
// Regular member should not be able to modify visibility when set to managers and above
await expect(page.getByTestId('documentVisibilitySelectValue')).toBeDisabled();
// A regular member should not be able to see the template.
// They should be redirected to the templates page.
await expect(page.getByText('Not Found').first()).toBeVisible();
await page.goto(`/t/${team.url}/templates`);
// Create a new template with 'everyone' visibility
const everyoneTemplate = await seedBlankTemplate(owner, team.id, {
@ -130,7 +133,9 @@ test('[TEMPLATE_FLOW] team member visibility permissions', async ({ page }) => {
});
// Navigate to the new template
await page.goto(`/t/${team.url}/templates/${everyoneTemplate.id}/edit`);
await page.goto(
`/t/${team.url}/templates/${mapSecondaryIdToTemplateId(everyoneTemplate.secondaryId)}/edit`,
);
// Regular member should be able to see but not modify visibility
await expect(page.getByTestId('documentVisibilitySelectValue')).toBeDisabled();

View File

@ -29,7 +29,7 @@ import { apiSignin } from '../fixtures/authentication';
// await apiSignin({
// page,
// email: user.email,
// redirectPath: `/templates/${template.id}/edit`,
// redirectPath: `/templates/${mapSecondaryIdToTemplateId(template.secondaryId)}/edit`,
// });
// // Save the settings by going to the next step.

View File

@ -75,11 +75,11 @@ test('[TEMPLATE]: should create a document from a template', async ({ page }) =>
await page.getByRole('button', { name: 'Create as draft' }).click();
// Review that the document was created with the correct values.
await page.waitForURL(new RegExp(`/t/${team.url}/documents/\\d+`));
await page.waitForURL(new RegExp(`/t/${team.url}/documents/envelope_.*`));
const documentId = Number(page.url().split('/').pop());
const documentId = page.url().split('/').pop();
const document = await prisma.document.findFirstOrThrow({
const document = await prisma.envelope.findFirstOrThrow({
where: {
id: documentId,
},
@ -178,11 +178,11 @@ test('[TEMPLATE]: should create a team document from a team template', async ({
await page.getByRole('button', { name: 'Create as draft' }).click();
// Review that the document was created with the correct values.
await page.waitForURL(new RegExp(`/t/${team.url}/documents/\\d+`));
await page.waitForURL(new RegExp(`/t/${team.url}/documents/envelope_.*`));
const documentId = Number(page.url().split('/').pop());
const documentId = page.url().split('/').pop();
const document = await prisma.document.findFirstOrThrow({
const document = await prisma.envelope.findFirstOrThrow({
where: {
id: documentId,
},
@ -284,34 +284,40 @@ test('[TEMPLATE]: should create a document from a template with custom document'
await page.getByRole('button', { name: 'Create as draft' }).click();
// Review that the document was created with the custom document data
await page.waitForURL(new RegExp(`/t/${team.url}/documents/\\d+`));
await page.waitForURL(new RegExp(`/t/${team.url}/documents/envelope_.*`));
const documentId = Number(page.url().split('/').pop());
const documentId = page.url().split('/').pop();
const document = await prisma.document.findFirstOrThrow({
const document = await prisma.envelope.findFirstOrThrow({
where: {
id: documentId,
},
include: {
documentData: true,
envelopeItems: {
include: {
documentData: true,
},
},
},
});
const firstDocumentData = document.envelopeItems[0].documentData;
const expectedDocumentDataType =
process.env.NEXT_PUBLIC_UPLOAD_TRANSPORT === 's3'
? DocumentDataType.S3_PATH
: DocumentDataType.BYTES_64;
expect(document.title).toEqual('TEMPLATE_WITH_CUSTOM_DOC');
expect(document.documentData.type).toEqual(expectedDocumentDataType);
expect(firstDocumentData.type).toEqual(expectedDocumentDataType);
if (expectedDocumentDataType === DocumentDataType.BYTES_64) {
expect(document.documentData.data).toEqual(pdfContent);
expect(document.documentData.initialData).toEqual(pdfContent);
expect(firstDocumentData.data).toEqual(pdfContent);
expect(firstDocumentData.initialData).toEqual(pdfContent);
} else {
// For S3, we expect the data/initialData to be the S3 path (non-empty string)
expect(document.documentData.data).toBeTruthy();
expect(document.documentData.initialData).toBeTruthy();
expect(firstDocumentData.data).toBeTruthy();
expect(firstDocumentData.initialData).toBeTruthy();
}
});
@ -377,16 +383,20 @@ test('[TEMPLATE]: should create a team document from a template with custom docu
await page.getByRole('button', { name: 'Create as draft' }).click();
// Review that the document was created with the custom document data
await page.waitForURL(new RegExp(`/t/${team.url}/documents/\\d+`));
await page.waitForURL(new RegExp(`/t/${team.url}/documents/envelope_.*`));
const documentId = Number(page.url().split('/').pop());
const documentId = page.url().split('/').pop();
const document = await prisma.document.findFirstOrThrow({
const document = await prisma.envelope.findFirstOrThrow({
where: {
id: documentId,
},
include: {
documentData: true,
envelopeItems: {
include: {
documentData: true,
},
},
},
});
@ -395,17 +405,19 @@ test('[TEMPLATE]: should create a team document from a template with custom docu
? DocumentDataType.S3_PATH
: DocumentDataType.BYTES_64;
const firstDocumentData = document.envelopeItems[0].documentData;
expect(document.teamId).toEqual(team.id);
expect(document.title).toEqual('TEAM_TEMPLATE_WITH_CUSTOM_DOC');
expect(document.documentData.type).toEqual(expectedDocumentDataType);
expect(firstDocumentData.type).toEqual(expectedDocumentDataType);
if (expectedDocumentDataType === DocumentDataType.BYTES_64) {
expect(document.documentData.data).toEqual(pdfContent);
expect(document.documentData.initialData).toEqual(pdfContent);
expect(firstDocumentData.data).toEqual(pdfContent);
expect(firstDocumentData.initialData).toEqual(pdfContent);
} else {
// For S3, we expect the data/initialData to be the S3 path (non-empty string)
expect(document.documentData.data).toBeTruthy();
expect(document.documentData.initialData).toBeTruthy();
expect(firstDocumentData.data).toBeTruthy();
expect(firstDocumentData.initialData).toBeTruthy();
}
});
@ -451,34 +463,44 @@ test('[TEMPLATE]: should create a document from a template using template docume
await page.getByRole('button', { name: 'Create as draft' }).click();
// Review that the document was created with the template's document data
await page.waitForURL(new RegExp(`/t/${team.url}/documents/\\d+`));
await page.waitForURL(new RegExp(`/t/${team.url}/documents/envelope_.*`));
const documentId = Number(page.url().split('/').pop());
const documentId = page.url().split('/').pop();
const document = await prisma.document.findFirstOrThrow({
const document = await prisma.envelope.findFirstOrThrow({
where: {
id: documentId,
},
include: {
documentData: true,
envelopeItems: {
include: {
documentData: true,
},
},
},
});
const templateWithData = await prisma.template.findFirstOrThrow({
const firstDocumentData = document.envelopeItems[0].documentData;
const templateWithData = await prisma.envelope.findFirstOrThrow({
where: {
id: template.id,
},
include: {
templateDocumentData: true,
envelopeItems: {
include: {
documentData: true,
},
},
},
});
expect(document.title).toEqual('TEMPLATE_WITH_ORIGINAL_DOC');
expect(document.documentData.data).toEqual(templateWithData.templateDocumentData.data);
expect(document.documentData.initialData).toEqual(
templateWithData.templateDocumentData.initialData,
expect(firstDocumentData.data).toEqual(templateWithData.envelopeItems[0].documentData.data);
expect(firstDocumentData.initialData).toEqual(
templateWithData.envelopeItems[0].documentData.initialData,
);
expect(document.documentData.type).toEqual(templateWithData.templateDocumentData.type);
expect(firstDocumentData.type).toEqual(templateWithData.envelopeItems[0].documentData.type);
});
test('[TEMPLATE]: should persist document visibility when creating from template', async ({
@ -532,14 +554,21 @@ test('[TEMPLATE]: should persist document visibility when creating from template
await page.getByRole('button', { name: 'Create as draft' }).click();
// Review that the document was created with the correct visibility
await page.waitForURL(new RegExp(`/t/${team.url}/documents/\\d+`));
await page.waitForURL(new RegExp(`/t/${team.url}/documents/envelope_.*`));
const documentId = Number(page.url().split('/').pop());
const documentId = page.url().split('/').pop();
const document = await prisma.document.findFirstOrThrow({
const document = await prisma.envelope.findFirstOrThrow({
where: {
id: documentId,
},
include: {
envelopeItems: {
include: {
documentData: true,
},
},
},
});
expect(document.title).toEqual('TEMPLATE_WITH_VISIBILITY');

View File

@ -77,7 +77,7 @@ test('[DIRECT_TEMPLATES]: toggle direct template link', async ({ page }) => {
// Navigate to template settings and disable access.
await page.goto(`${NEXT_PUBLIC_WEBAPP_URL()}${formatTemplatesPath(template.team?.url)}`);
await page.getByRole('cell', { name: 'Use Template' }).getByRole('button').nth(1).click();
await page.getByRole('menuitem', { name: 'Direct link' }).click();
await page.getByTestId('template-direct-link').click();
await page.getByRole('switch').click();
await page.getByRole('button', { name: 'Save' }).click();
await expect(page.getByText('Direct link signing has been').first()).toBeVisible();
@ -111,7 +111,7 @@ test('[DIRECT_TEMPLATES]: delete direct template link', async ({ page }) => {
// Navigate to template settings and delete the access.
await page.goto(`${NEXT_PUBLIC_WEBAPP_URL()}${formatTemplatesPath(template.team?.url)}`);
await page.getByRole('cell', { name: 'Use Template' }).getByRole('button').nth(1).click();
await page.getByRole('menuitem', { name: 'Direct link' }).click();
await page.getByTestId('template-direct-link').click();
await page.getByRole('button', { name: 'Remove' }).click();
await page.getByRole('button', { name: 'Confirm' }).click();
await expect(page.getByText('Direct template link deleted').first()).toBeVisible();
@ -171,6 +171,7 @@ test('[DIRECT_TEMPLATES]: use direct template link with 1 recipient', async ({ p
await page.goto(formatDirectTemplatePath(template.directLink?.token || ''));
await expect(page.getByRole('heading', { name: 'General' })).toBeVisible();
await page.waitForTimeout(100);
await page.getByPlaceholder('recipient@documenso.com').fill(seedTestEmail());
await page.getByRole('button', { name: 'Continue' }).click();

View File

@ -24,7 +24,7 @@ test.describe('Unauthorized Access to Templates', () => {
});
await page.goto(`${NEXT_PUBLIC_WEBAPP_URL()}/t/${team.url}/templates/${template.id}`);
await expect(page.getByRole('heading', { name: 'Oops! Something went wrong.' })).toBeVisible();
await expect(page.getByRole('heading', { name: 'Team not found' })).toBeVisible();
});
test('should block unauthorized access to the template edit page', async ({ page }) => {
@ -40,6 +40,6 @@ test.describe('Unauthorized Access to Templates', () => {
});
await page.goto(`${NEXT_PUBLIC_WEBAPP_URL()}/t/${team.url}/templates/${template.id}/edit`);
await expect(page.getByRole('heading', { name: 'Oops! Something went wrong.' })).toBeVisible();
await expect(page.getByRole('heading', { name: 'Team not found' })).toBeVisible();
});
});

View File

@ -12,13 +12,12 @@
"keywords": [],
"author": "",
"devDependencies": {
"@playwright/test": "1.52.0",
"@types/node": "^20",
"@documenso/lib": "*",
"@documenso/prisma": "*",
"pdf-lib": "^1.17.1"
"@playwright/test": "1.52.0",
"@types/node": "^20"
},
"dependencies": {
"start-server-and-test": "^2.0.12"
}
}
}