mirror of
https://github.com/documenso/documenso.git
synced 2025-11-13 00:03:33 +10:00
409 lines
14 KiB
TypeScript
409 lines
14 KiB
TypeScript
import { expect, test } from '@playwright/test';
|
|
import { DocumentSigningOrder, RecipientRole } from '@prisma/client';
|
|
import { customAlphabet } from 'nanoid';
|
|
|
|
import { NEXT_PUBLIC_WEBAPP_URL } from '@documenso/lib/constants/app';
|
|
import { createDocumentAuthOptions } from '@documenso/lib/utils/document-auth';
|
|
import { mapSecondaryIdToTemplateId } from '@documenso/lib/utils/envelope';
|
|
import { formatDirectTemplatePath } from '@documenso/lib/utils/templates';
|
|
import { prisma } from '@documenso/prisma';
|
|
import { seedTeam } from '@documenso/prisma/seed/teams';
|
|
import { seedDirectTemplate, seedTemplate } from '@documenso/prisma/seed/templates';
|
|
import { seedTestEmail, seedUser } from '@documenso/prisma/seed/users';
|
|
|
|
import { apiSignin } from '../fixtures/authentication';
|
|
|
|
// Duped from `packages/lib/utils/teams.ts` due to errors when importing that file.
|
|
const formatDocumentsPath = (teamUrl: string) => `/t/${teamUrl}/documents`;
|
|
const formatTemplatesPath = (teamUrl: string) => `/t/${teamUrl}/templates`;
|
|
|
|
const nanoid = customAlphabet('1234567890abcdef', 10);
|
|
|
|
test('[DIRECT_TEMPLATES]: create direct link for template', async ({ page }) => {
|
|
const { team, owner, organisation } = await seedTeam({
|
|
createTeamMembers: 1,
|
|
});
|
|
|
|
// Should be visible to team members.
|
|
const teamTemplate = await seedTemplate({
|
|
title: 'Team template 1',
|
|
userId: owner.id,
|
|
teamId: team.id,
|
|
});
|
|
|
|
await apiSignin({
|
|
page,
|
|
email: owner.email,
|
|
redirectPath: `/t/${team.url}/templates`,
|
|
});
|
|
|
|
const url = `${NEXT_PUBLIC_WEBAPP_URL()}/t/${team.url}/templates/${teamTemplate.id}`;
|
|
|
|
// Owner should see list of templates with no direct link badge.
|
|
await page.goto(url);
|
|
await expect(page.getByRole('button', { name: 'direct link' })).toHaveCount(1);
|
|
|
|
// Create direct link.
|
|
await page.getByRole('button', { name: 'Create Direct Link' }).click();
|
|
await page.getByRole('button', { name: 'Enable direct link signing' }).click();
|
|
await page.getByRole('button', { name: 'Create one automatically' }).click();
|
|
await expect(page.getByRole('heading', { name: 'Direct Link Signing' })).toBeVisible();
|
|
|
|
await page.waitForTimeout(1000);
|
|
await page.getByTestId('btn-dialog-close').click();
|
|
|
|
// Expect badge to appear.
|
|
await expect(page.getByRole('button', { name: 'direct link' })).toHaveCount(2);
|
|
});
|
|
|
|
test('[DIRECT_TEMPLATES]: toggle direct template link', async ({ page }) => {
|
|
const { team, owner, organisation } = await seedTeam({
|
|
createTeamMembers: 1,
|
|
});
|
|
|
|
// Should be visible to team members.
|
|
const template = await seedDirectTemplate({
|
|
title: 'Team direct template link 1',
|
|
userId: owner.id,
|
|
teamId: team.id,
|
|
});
|
|
|
|
await apiSignin({
|
|
page,
|
|
email: owner.email,
|
|
});
|
|
|
|
// Check that the direct template link is accessible.
|
|
await page.goto(formatDirectTemplatePath(template.directLink?.token || ''));
|
|
await expect(page.getByRole('heading', { name: 'General' })).toBeVisible();
|
|
|
|
// 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.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();
|
|
|
|
// Check that the direct template link is no longer accessible.
|
|
await page.goto(formatDirectTemplatePath(template.directLink?.token || '123'));
|
|
await expect(page.getByText('404 not found')).toBeVisible();
|
|
});
|
|
|
|
test('[DIRECT_TEMPLATES]: delete direct template link', async ({ page }) => {
|
|
const { team, owner, organisation } = await seedTeam({
|
|
createTeamMembers: 1,
|
|
});
|
|
|
|
// Should be visible to team members.
|
|
const template = await seedDirectTemplate({
|
|
title: 'Team direct template link 1',
|
|
userId: owner.id,
|
|
teamId: team.id,
|
|
});
|
|
|
|
await apiSignin({
|
|
page,
|
|
email: owner.email,
|
|
});
|
|
|
|
// Check that the direct template link is accessible.
|
|
await page.goto(formatDirectTemplatePath(template.directLink?.token || ''));
|
|
await expect(page.getByRole('heading', { name: 'General' })).toBeVisible();
|
|
|
|
// 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.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();
|
|
|
|
// Check that the direct template link is no longer accessible.
|
|
await page.goto(formatDirectTemplatePath(template.directLink?.token || ''));
|
|
await expect(page.getByText('404 not found')).toBeVisible();
|
|
});
|
|
|
|
test('[DIRECT_TEMPLATES]: V1 direct template link auth access', async ({ page }) => {
|
|
const { user, team } = await seedUser();
|
|
|
|
const directTemplateWithAuth = await seedDirectTemplate({
|
|
title: 'Personal direct template link',
|
|
userId: user.id,
|
|
teamId: team.id,
|
|
createTemplateOptions: {
|
|
authOptions: createDocumentAuthOptions({
|
|
globalAccessAuth: ['ACCOUNT'],
|
|
globalActionAuth: [],
|
|
}),
|
|
},
|
|
});
|
|
|
|
const directTemplatePath = formatDirectTemplatePath(
|
|
directTemplateWithAuth.directLink?.token || '',
|
|
);
|
|
|
|
await page.goto(directTemplatePath);
|
|
|
|
await expect(page.getByText('Authentication required')).toBeVisible();
|
|
|
|
await apiSignin({
|
|
page,
|
|
email: user.email,
|
|
});
|
|
|
|
await page.goto(directTemplatePath);
|
|
|
|
await expect(page.getByRole('heading', { name: 'General' })).toBeVisible();
|
|
await expect(page.getByLabel('Email')).toBeDisabled();
|
|
|
|
await page.getByRole('button', { name: 'Continue' }).click();
|
|
await page.getByRole('button', { name: 'Complete' }).click();
|
|
|
|
await page.getByRole('button', { name: 'Sign' }).click();
|
|
await page.waitForURL(/\/sign/);
|
|
await expect(page.getByRole('heading', { name: 'Document Signed' })).toBeVisible();
|
|
});
|
|
|
|
test('[DIRECT_TEMPLATES]: V2 direct template link auth access', async ({ page }) => {
|
|
const { user, team } = await seedUser();
|
|
|
|
const directTemplateWithAuth = await seedDirectTemplate({
|
|
title: 'Personal direct template link',
|
|
userId: user.id,
|
|
teamId: team.id,
|
|
internalVersion: 2,
|
|
createTemplateOptions: {
|
|
authOptions: createDocumentAuthOptions({
|
|
globalAccessAuth: ['ACCOUNT'],
|
|
globalActionAuth: [],
|
|
}),
|
|
},
|
|
});
|
|
|
|
const directTemplatePath = formatDirectTemplatePath(
|
|
directTemplateWithAuth.directLink?.token || '',
|
|
);
|
|
|
|
await page.goto(directTemplatePath);
|
|
|
|
await expect(page.getByText('Authentication required')).toBeVisible();
|
|
|
|
await apiSignin({
|
|
page,
|
|
email: user.email,
|
|
});
|
|
|
|
await page.goto(directTemplatePath);
|
|
|
|
await expect(page.getByRole('heading', { name: 'Personal direct template link' })).toBeVisible();
|
|
await page.getByRole('button', { name: 'Complete' }).click();
|
|
await expect(page.getByLabel('Your Email')).not.toBeVisible();
|
|
|
|
await page.getByRole('button', { name: 'Sign' }).click();
|
|
await page.waitForURL(/\/sign/);
|
|
await expect(page.getByRole('heading', { name: 'Document Signed' })).toBeVisible();
|
|
});
|
|
|
|
test('[DIRECT_TEMPLATES]: use direct template link with 1 recipient', async ({ page }) => {
|
|
const { team, owner, organisation } = await seedTeam({
|
|
createTeamMembers: 1,
|
|
});
|
|
|
|
// Should be visible to team members.
|
|
const template = await seedDirectTemplate({
|
|
title: 'Team direct template link 1',
|
|
userId: owner.id,
|
|
teamId: team.id,
|
|
});
|
|
|
|
// Check that the direct template link is accessible.
|
|
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();
|
|
|
|
await expect(page.getByText('Next Recipient Name')).not.toBeVisible();
|
|
|
|
await page.getByRole('button', { name: 'Complete' }).click();
|
|
await page.getByRole('button', { name: 'Sign' }).click();
|
|
await page.waitForURL(/\/sign/);
|
|
await expect(page.getByRole('heading', { name: 'Document Signed' })).toBeVisible();
|
|
|
|
// Add a longer waiting period to ensure document status is updated
|
|
await page.waitForTimeout(3000);
|
|
});
|
|
|
|
test('[DIRECT_TEMPLATES]: V1 use direct template link with 2 recipients with next signer dictation', async ({
|
|
page,
|
|
}) => {
|
|
const { team, owner, organisation } = await seedTeam({
|
|
createTeamMembers: 1,
|
|
});
|
|
|
|
// Should be visible to team members.
|
|
const template = await seedDirectTemplate({
|
|
title: 'Team direct template link 1',
|
|
userId: owner.id,
|
|
teamId: team.id,
|
|
});
|
|
|
|
await prisma.documentMeta.update({
|
|
where: {
|
|
id: template.documentMetaId,
|
|
},
|
|
data: {
|
|
allowDictateNextSigner: true,
|
|
signingOrder: DocumentSigningOrder.SEQUENTIAL,
|
|
},
|
|
});
|
|
|
|
const originalName = 'Signer 2';
|
|
const originalSecondSignerEmail = seedTestEmail();
|
|
|
|
// Add another signer
|
|
await prisma.recipient.create({
|
|
data: {
|
|
signingOrder: 2,
|
|
envelopeId: template.id,
|
|
email: originalSecondSignerEmail,
|
|
name: originalName,
|
|
token: Math.random().toString().slice(2, 7),
|
|
role: RecipientRole.SIGNER,
|
|
},
|
|
});
|
|
|
|
// Check that the direct template link is accessible.
|
|
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();
|
|
await page.getByRole('button', { name: 'Complete' }).click();
|
|
|
|
await expect(page.getByText('Next Recipient Name')).toBeVisible();
|
|
|
|
const nextRecipientNameInputValue = await page.getByLabel('Next Recipient Name').inputValue();
|
|
expect(nextRecipientNameInputValue).toBe(originalName);
|
|
|
|
const nextRecipientEmailInputValue = await page.getByLabel('Next Recipient Email').inputValue();
|
|
expect(nextRecipientEmailInputValue).toBe(originalSecondSignerEmail);
|
|
|
|
const newName = 'Hello';
|
|
const newSecondSignerEmail = seedTestEmail();
|
|
|
|
await page.getByLabel('Next Recipient Email').fill(newSecondSignerEmail);
|
|
await page.getByLabel('Next Recipient Name').fill(newName);
|
|
|
|
await page.getByRole('button', { name: 'Sign' }).click();
|
|
await page.waitForURL(/\/sign/);
|
|
await expect(page.getByRole('heading', { name: 'Document Signed' })).toBeVisible();
|
|
|
|
const createdEnvelopeRecipients = await prisma.recipient.findMany({
|
|
where: {
|
|
envelope: {
|
|
templateId: mapSecondaryIdToTemplateId(template.secondaryId),
|
|
},
|
|
},
|
|
});
|
|
|
|
const updatedSecondRecipient = createdEnvelopeRecipients.find(
|
|
(recipient) => recipient.signingOrder === 2,
|
|
);
|
|
|
|
expect(updatedSecondRecipient?.name).toBe(newName);
|
|
expect(updatedSecondRecipient?.email).toBe(newSecondSignerEmail);
|
|
});
|
|
|
|
test('[DIRECT_TEMPLATES]: V2 use direct template link with 2 recipients with next signer dictation', async ({
|
|
page,
|
|
}) => {
|
|
const { team, owner, organisation } = await seedTeam({
|
|
createTeamMembers: 1,
|
|
});
|
|
|
|
// Should be visible to team members.
|
|
const template = await seedDirectTemplate({
|
|
title: 'Team direct template link 1',
|
|
userId: owner.id,
|
|
teamId: team.id,
|
|
internalVersion: 2,
|
|
});
|
|
|
|
await prisma.documentMeta.update({
|
|
where: {
|
|
id: template.documentMetaId,
|
|
},
|
|
data: {
|
|
allowDictateNextSigner: true,
|
|
signingOrder: DocumentSigningOrder.SEQUENTIAL,
|
|
},
|
|
});
|
|
|
|
const originalName = 'Signer 2';
|
|
const originalSecondSignerEmail = seedTestEmail();
|
|
|
|
// Add another signer
|
|
await prisma.recipient.create({
|
|
data: {
|
|
signingOrder: 2,
|
|
envelopeId: template.id,
|
|
email: originalSecondSignerEmail,
|
|
name: originalName,
|
|
token: Math.random().toString().slice(2, 7),
|
|
role: RecipientRole.SIGNER,
|
|
},
|
|
});
|
|
|
|
// Check that the direct template link is accessible.
|
|
await page.goto(formatDirectTemplatePath(template.directLink?.token || ''));
|
|
await expect(page.getByRole('heading', { name: 'Team direct template link 1' })).toBeVisible();
|
|
await page.waitForTimeout(100);
|
|
|
|
await page.getByRole('button', { name: 'Complete' }).click();
|
|
|
|
const currentName = 'John Doe';
|
|
const currentEmail = seedTestEmail();
|
|
|
|
await page.getByPlaceholder('Enter Your Name').fill(currentName);
|
|
await page.getByPlaceholder('Enter Your Email').fill(currentEmail);
|
|
|
|
await expect(page.getByText('Next Recipient Name')).toBeVisible();
|
|
|
|
const nextRecipientNameInputValue = await page.getByLabel('Next Recipient Name').inputValue();
|
|
expect(nextRecipientNameInputValue).toBe(originalName);
|
|
|
|
const nextRecipientEmailInputValue = await page.getByLabel('Next Recipient Email').inputValue();
|
|
expect(nextRecipientEmailInputValue).toBe(originalSecondSignerEmail);
|
|
|
|
const newName = 'Hello';
|
|
const newSecondSignerEmail = seedTestEmail();
|
|
|
|
await page.getByLabel('Next Recipient Email').fill(newSecondSignerEmail);
|
|
await page.getByLabel('Next Recipient Name').fill(newName);
|
|
|
|
await page.getByRole('button', { name: 'Sign' }).click();
|
|
await page.waitForURL(/\/sign/);
|
|
await expect(page.getByRole('heading', { name: 'Document Signed' })).toBeVisible();
|
|
|
|
const createdEnvelopeRecipients = await prisma.recipient.findMany({
|
|
where: {
|
|
envelope: {
|
|
templateId: mapSecondaryIdToTemplateId(template.secondaryId),
|
|
},
|
|
},
|
|
});
|
|
|
|
const updatedSecondRecipient = createdEnvelopeRecipients.find(
|
|
(recipient) => recipient.signingOrder === 2,
|
|
);
|
|
|
|
expect(updatedSecondRecipient?.name).toBe(newName);
|
|
expect(updatedSecondRecipient?.email).toBe(newSecondSignerEmail);
|
|
});
|