mirror of
https://github.com/documenso/documenso.git
synced 2026-08-22 22:32:22 +10:00
feat: unify settings (#3128)
This commit is contained in:
@@ -15,11 +15,11 @@ test('[ENVELOPE_EXPIRATION]: set custom expiration period at organisation level'
|
||||
await apiSignin({
|
||||
page,
|
||||
email: user.email,
|
||||
redirectPath: `/o/${organisation.url}/settings/document`,
|
||||
redirectPath: `/o/${organisation.url}/settings/reminders`,
|
||||
});
|
||||
|
||||
// Wait for the form to load.
|
||||
await expect(page.getByTestId('document-language-trigger')).toBeVisible();
|
||||
await expect(page.getByTestId('envelope-expiration-mode')).toBeVisible();
|
||||
|
||||
// Change the amount to 2.
|
||||
const amountInput = page.getByTestId('envelope-expiration-amount');
|
||||
@@ -36,7 +36,7 @@ test('[ENVELOPE_EXPIRATION]: set custom expiration period at organisation level'
|
||||
await page.getByRole('option', { name: 'Weeks' }).click();
|
||||
|
||||
await page.getByRole('button', { name: 'Save changes' }).first().click();
|
||||
await expect(page.getByText('Your document preferences have been updated').first()).toBeVisible();
|
||||
await expect(page.getByText('Your reminder preferences have been updated').first()).toBeVisible();
|
||||
|
||||
// Verify via database.
|
||||
const orgSettings = await prisma.organisationGlobalSettings.findUniqueOrThrow({
|
||||
@@ -54,18 +54,18 @@ test('[ENVELOPE_EXPIRATION]: disable expiration at organisation level', async ({
|
||||
await apiSignin({
|
||||
page,
|
||||
email: user.email,
|
||||
redirectPath: `/o/${organisation.url}/settings/document`,
|
||||
redirectPath: `/o/${organisation.url}/settings/reminders`,
|
||||
});
|
||||
|
||||
await expect(page.getByTestId('document-language-trigger')).toBeVisible();
|
||||
|
||||
// Find the mode select (shows "Custom duration") and change to "Never expires".
|
||||
const modeTrigger = page.getByTestId('envelope-expiration-mode');
|
||||
await expect(modeTrigger).toBeVisible();
|
||||
|
||||
await modeTrigger.click();
|
||||
await page.getByRole('option', { name: 'Never expires' }).click();
|
||||
|
||||
await page.getByRole('button', { name: 'Save changes' }).first().click();
|
||||
await expect(page.getByText('Your document preferences have been updated').first()).toBeVisible();
|
||||
await expect(page.getByText('Your reminder preferences have been updated').first()).toBeVisible();
|
||||
|
||||
// Verify via database.
|
||||
const orgSettings = await prisma.organisationGlobalSettings.findUniqueOrThrow({
|
||||
@@ -106,11 +106,9 @@ test('[ENVELOPE_EXPIRATION]: team overrides organisation expiration', async ({ p
|
||||
await apiSignin({
|
||||
page,
|
||||
email: user.email,
|
||||
redirectPath: `/t/${team.url}/settings/document`,
|
||||
redirectPath: `/t/${team.url}/settings/reminders`,
|
||||
});
|
||||
|
||||
await expect(page.getByTestId('document-language-trigger')).toBeVisible();
|
||||
|
||||
// The expiration picker mode select should show "Inherit from organisation" by default.
|
||||
const modeTrigger = page.getByTestId('envelope-expiration-mode');
|
||||
await expect(modeTrigger).toBeVisible();
|
||||
@@ -129,7 +127,7 @@ test('[ENVELOPE_EXPIRATION]: team overrides organisation expiration', async ({ p
|
||||
await page.getByRole('option', { name: 'Days' }).click();
|
||||
|
||||
await page.getByRole('button', { name: 'Save changes' }).first().click();
|
||||
await expect(page.getByText('Your document preferences have been updated').first()).toBeVisible();
|
||||
await expect(page.getByText('Your reminder preferences have been updated').first()).toBeVisible();
|
||||
|
||||
// Verify team setting is overridden.
|
||||
const teamSettings = await getTeamSettings({ teamId: team.id });
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { NEXT_PUBLIC_WEBAPP_URL } from '@documenso/lib/constants/app';
|
||||
import { prisma } from '@documenso/prisma';
|
||||
import { FieldType } from '@documenso/prisma/client';
|
||||
import { seedPendingDocumentWithFullFields } from '@documenso/prisma/seed/documents';
|
||||
import { seedUser } from '@documenso/prisma/seed/users';
|
||||
import { expect, test } from '@playwright/test';
|
||||
import { type APIRequestContext, expect, test } from '@playwright/test';
|
||||
|
||||
import { apiSeedPendingDocument } from '../fixtures/api-seeds';
|
||||
import { apiSignin } from '../fixtures/authentication';
|
||||
import { signSignaturePad } from '../fixtures/signature';
|
||||
|
||||
@@ -128,3 +130,82 @@ test('[ENVELOPE_EXPIRATION]: expired recipient cannot complete signing', async (
|
||||
}).toPass({ timeout: 10_000 });
|
||||
}
|
||||
});
|
||||
|
||||
const trpcMutation = async (request: APIRequestContext, procedure: string, input: Record<string, unknown>) => {
|
||||
return await request.post(`${NEXT_PUBLIC_WEBAPP_URL()}/api/trpc/${procedure}`, {
|
||||
headers: { 'content-type': 'application/json' },
|
||||
data: JSON.stringify({ json: input }),
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* The signing page loader only redirects expired recipients, which a direct API call
|
||||
* bypasses. The tests above exercise the V1 signing path; this covers the V2 route
|
||||
* (`envelope.field.sign`), which must reject on the server regardless of the UI.
|
||||
*/
|
||||
test('[ENVELOPE_EXPIRATION]: expired recipient cannot sign a field via the V2 API', async ({ request }) => {
|
||||
const { envelope, distributeResult } = await apiSeedPendingDocument(request, {
|
||||
title: '[TEST] Expired recipient V2 signing',
|
||||
recipients: [
|
||||
{
|
||||
email: `expired-v2-${Date.now()}@test.documenso.com`,
|
||||
name: 'Expired Signer',
|
||||
role: 'SIGNER',
|
||||
signingOrder: 1,
|
||||
},
|
||||
],
|
||||
fieldsPerRecipient: [
|
||||
[
|
||||
{ type: FieldType.SIGNATURE, page: 1, positionX: 5, positionY: 5, width: 5, height: 5 },
|
||||
{ type: FieldType.TEXT, page: 1, positionX: 5, positionY: 15, width: 5, height: 5 },
|
||||
],
|
||||
],
|
||||
});
|
||||
|
||||
const recipient = distributeResult.recipients[0];
|
||||
|
||||
const seededEnvelope = await prisma.envelope.findUniqueOrThrow({
|
||||
where: { id: envelope.id },
|
||||
include: { fields: true },
|
||||
});
|
||||
|
||||
const textField = seededEnvelope.fields.find((field) => field.type === FieldType.TEXT);
|
||||
|
||||
if (!textField) {
|
||||
throw new Error('TEXT field not found on the seeded envelope');
|
||||
}
|
||||
|
||||
// Sanity check: the recipient can sign while the signing window is open.
|
||||
const beforeExpiry = await trpcMutation(request, 'envelope.field.sign', {
|
||||
token: recipient.token,
|
||||
fieldId: textField.id,
|
||||
fieldValue: { type: FieldType.TEXT, value: 'before' },
|
||||
});
|
||||
|
||||
expect(beforeExpiry.ok()).toBeTruthy();
|
||||
|
||||
await prisma.field.update({
|
||||
where: { id: textField.id },
|
||||
data: { inserted: false, customText: '' },
|
||||
});
|
||||
|
||||
await prisma.recipient.update({
|
||||
where: { id: recipient.id },
|
||||
data: { expiresAt: new Date(Date.now() - 60_000) },
|
||||
});
|
||||
|
||||
const afterExpiry = await trpcMutation(request, 'envelope.field.sign', {
|
||||
token: recipient.token,
|
||||
fieldId: textField.id,
|
||||
fieldValue: { type: FieldType.TEXT, value: 'after' },
|
||||
});
|
||||
|
||||
expect(afterExpiry.ok()).toBeFalsy();
|
||||
|
||||
const fieldAfter = await prisma.field.findUniqueOrThrow({
|
||||
where: { id: textField.id },
|
||||
});
|
||||
|
||||
expect(fieldAfter.inserted).toBe(false);
|
||||
expect(fieldAfter.customText).toBe('');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user