mirror of
https://github.com/documenso/documenso.git
synced 2025-11-17 10:11:35 +10:00
feat: add envelope editor
This commit is contained in:
@ -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}`,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@ -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,
|
||||
});
|
||||
|
||||
@ -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,
|
||||
});
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
@ -15,7 +15,7 @@ test('[TEMPLATE_FLOW]: add settings', async ({ page }) => {
|
||||
await apiSignin({
|
||||
page,
|
||||
email: user.email,
|
||||
redirectPath: `/t/${team.url}/templates/${mapSecondaryIdToTemplateId(template.secondaryId)}/edit`,
|
||||
redirectPath: `/t/${team.url}/templates/${template.id}/edit`,
|
||||
});
|
||||
|
||||
// Set title.
|
||||
@ -49,7 +49,7 @@ test('[TEMPLATE_FLOW] add document visibility settings', async ({ page }) => {
|
||||
await apiSignin({
|
||||
page,
|
||||
email: user.email,
|
||||
redirectPath: `/t/${team.url}/templates/${mapSecondaryIdToTemplateId(template.secondaryId)}/edit`,
|
||||
redirectPath: `/t/${team.url}/templates/${template.id}/edit`,
|
||||
});
|
||||
|
||||
// Set document visibility.
|
||||
@ -64,9 +64,7 @@ test('[TEMPLATE_FLOW] add document visibility settings', async ({ page }) => {
|
||||
await expect(page.getByRole('heading', { name: 'Add Placeholders' })).toBeVisible();
|
||||
|
||||
// Navigate back to the edit page to check that the settings are saved correctly.
|
||||
await page.goto(
|
||||
`/t/${team.url}/templates/${mapSecondaryIdToTemplateId(template.secondaryId)}/edit`,
|
||||
);
|
||||
await page.goto(`/t/${team.url}/templates/${template.id}/edit`);
|
||||
|
||||
await expect(page.getByRole('heading', { name: 'General' })).toBeVisible();
|
||||
await expect(page.getByTestId('documentVisibilitySelectValue')).toContainText(
|
||||
@ -99,7 +97,7 @@ test('[TEMPLATE_FLOW] team member visibility permissions', async ({ page }) => {
|
||||
await apiSignin({
|
||||
page,
|
||||
email: managerUser.email,
|
||||
redirectPath: `/t/${team.url}/templates/${mapSecondaryIdToTemplateId(template.secondaryId)}/edit`,
|
||||
redirectPath: `/t/${team.url}/templates/${template.id}/edit`,
|
||||
});
|
||||
|
||||
// Manager should be able to set visibility to managers and above
|
||||
@ -118,12 +116,13 @@ test('[TEMPLATE_FLOW] team member visibility permissions', async ({ page }) => {
|
||||
await apiSignin({
|
||||
page,
|
||||
email: memberUser.email,
|
||||
redirectPath: `/t/${team.url}/templates/${mapSecondaryIdToTemplateId(template.secondaryId)}/edit`,
|
||||
redirectPath: `/t/${team.url}/templates/${template.id}/edit`,
|
||||
});
|
||||
|
||||
// A regular member should not be able to see the template.
|
||||
// They should be redirected to the templates page.
|
||||
expect(new URL(page.url()).pathname).toBe(`/t/${team.url}/templates`);
|
||||
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, {
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { expect, test } from '@playwright/test';
|
||||
|
||||
import { mapSecondaryIdToTemplateId } from '@documenso/lib/utils/envelope';
|
||||
import { seedBlankTemplate } from '@documenso/prisma/seed/templates';
|
||||
import { seedUser } from '@documenso/prisma/seed/users';
|
||||
|
||||
@ -80,7 +79,7 @@ test('[TEMPLATE_FLOW]: add placeholder', async ({ page }) => {
|
||||
await apiSignin({
|
||||
page,
|
||||
email: user.email,
|
||||
redirectPath: `/t/${team.url}/templates/${mapSecondaryIdToTemplateId(template.secondaryId)}/edit`,
|
||||
redirectPath: `/t/${team.url}/templates/${template.id}/edit`,
|
||||
});
|
||||
|
||||
// Save the settings by going to the next step.
|
||||
|
||||
Reference in New Issue
Block a user