mirror of
https://github.com/documenso/documenso.git
synced 2026-07-24 17:04:12 +10:00
feat: signing reminders (#1749)
This commit is contained in:
@@ -31,6 +31,12 @@ const TEST_SETTINGS_VALUES = {
|
||||
expirationMode: 'Custom duration',
|
||||
expirationAmount: 5,
|
||||
expirationUnit: 'Weeks',
|
||||
reminderMode: 'Enabled',
|
||||
reminderSendAfterAmount: 3,
|
||||
reminderSendAfterUnit: 'Days',
|
||||
reminderRepeatMode: 'Custom interval',
|
||||
reminderRepeatAmount: 7,
|
||||
reminderRepeatUnit: 'Days',
|
||||
accessAuth: 'Require account',
|
||||
actionAuth: 'Require password',
|
||||
visibility: 'Managers and above',
|
||||
@@ -42,6 +48,10 @@ const DB_EXPECTED_VALUES = {
|
||||
timezone: 'Europe/London',
|
||||
distributionMethod: DocumentDistributionMethod.NONE,
|
||||
envelopeExpirationPeriod: { unit: 'week', amount: 5 },
|
||||
reminderSettings: {
|
||||
sendAfter: { unit: 'day', amount: 3 },
|
||||
repeatEvery: { unit: 'day', amount: 7 },
|
||||
},
|
||||
visibility: DocumentVisibility.MANAGER_AND_ABOVE,
|
||||
globalAccessAuth: ['ACCOUNT'],
|
||||
globalActionAuth: ['PASSWORD'],
|
||||
@@ -130,6 +140,66 @@ const runSettingsFlow = async (
|
||||
await root.getByRole('option', { name: TEST_SETTINGS_VALUES.expirationUnit }).click();
|
||||
await clickSettingsDialogHeader(root);
|
||||
|
||||
// Configure reminder settings.
|
||||
await root.getByRole('button', { name: 'Reminders' }).click();
|
||||
|
||||
await root.locator('[data-testid="reminder-mode-select"]').click();
|
||||
await root.getByRole('option', { name: TEST_SETTINGS_VALUES.reminderMode }).click();
|
||||
await clickSettingsDialogHeader(root);
|
||||
|
||||
await root.locator('[data-testid="reminder-send-after-amount"]').clear();
|
||||
await root
|
||||
.locator('[data-testid="reminder-send-after-amount"]')
|
||||
.fill(String(TEST_SETTINGS_VALUES.reminderSendAfterAmount));
|
||||
|
||||
await root.locator('[data-testid="reminder-send-after-unit"]').click();
|
||||
await root.getByRole('option', { name: TEST_SETTINGS_VALUES.reminderSendAfterUnit }).click();
|
||||
await clickSettingsDialogHeader(root);
|
||||
|
||||
await root.locator('[data-testid="reminder-repeat-mode-select"]').click();
|
||||
await root.getByRole('option', { name: TEST_SETTINGS_VALUES.reminderRepeatMode }).click();
|
||||
await clickSettingsDialogHeader(root);
|
||||
|
||||
await root.locator('[data-testid="reminder-repeat-amount"]').clear();
|
||||
await root
|
||||
.locator('[data-testid="reminder-repeat-amount"]')
|
||||
.fill(String(TEST_SETTINGS_VALUES.reminderRepeatAmount));
|
||||
|
||||
await root.locator('[data-testid="reminder-repeat-unit"]').click();
|
||||
await root.getByRole('option', { name: TEST_SETTINGS_VALUES.reminderRepeatUnit }).click();
|
||||
await clickSettingsDialogHeader(root);
|
||||
|
||||
const spinbuttons = root.getByRole('spinbutton');
|
||||
await spinbuttons.first().clear();
|
||||
await spinbuttons.first().fill(String(TEST_SETTINGS_VALUES.reminderSendAfterAmount));
|
||||
|
||||
const sendAfterUnitTrigger = root
|
||||
.locator('button[role="combobox"]')
|
||||
.filter({ hasText: /Days|Weeks|Months/ })
|
||||
.first();
|
||||
await sendAfterUnitTrigger.click();
|
||||
await root.getByRole('option', { name: TEST_SETTINGS_VALUES.reminderSendAfterUnit }).click();
|
||||
await clickSettingsDialogHeader(root);
|
||||
|
||||
const repeatModeSelect = root
|
||||
.locator('button[role="combobox"]')
|
||||
.filter({ hasText: /Custom interval|Don't repeat/ })
|
||||
.first();
|
||||
await repeatModeSelect.click();
|
||||
await root.getByRole('option', { name: TEST_SETTINGS_VALUES.reminderRepeatMode }).click();
|
||||
await clickSettingsDialogHeader(root);
|
||||
|
||||
await spinbuttons.last().clear();
|
||||
await spinbuttons.last().fill(String(TEST_SETTINGS_VALUES.reminderRepeatAmount));
|
||||
|
||||
const repeatUnitTrigger = root
|
||||
.locator('button[role="combobox"]')
|
||||
.filter({ hasText: /Days|Weeks|Months/ })
|
||||
.last();
|
||||
await repeatUnitTrigger.click();
|
||||
await root.getByRole('option', { name: TEST_SETTINGS_VALUES.reminderRepeatUnit }).click();
|
||||
await clickSettingsDialogHeader(root);
|
||||
|
||||
await root.getByRole('button', { name: 'Email' }).click();
|
||||
await root.locator('#recipientSigned').click();
|
||||
await root.locator('#recipientSigningRequest').click();
|
||||
@@ -200,6 +270,27 @@ const runSettingsFlow = async (
|
||||
.first(),
|
||||
).toBeVisible();
|
||||
|
||||
// Verify reminder settings persisted in UI.
|
||||
await root.getByRole('button', { name: 'Reminders' }).click();
|
||||
await expect(root.locator('[data-testid="reminder-mode-select"]')).toContainText(
|
||||
TEST_SETTINGS_VALUES.reminderMode,
|
||||
);
|
||||
await expect(root.locator('[data-testid="reminder-send-after-amount"]')).toHaveValue(
|
||||
String(TEST_SETTINGS_VALUES.reminderSendAfterAmount),
|
||||
);
|
||||
await expect(root.locator('[data-testid="reminder-send-after-unit"]')).toContainText(
|
||||
TEST_SETTINGS_VALUES.reminderSendAfterUnit,
|
||||
);
|
||||
await expect(root.locator('[data-testid="reminder-repeat-mode-select"]')).toContainText(
|
||||
TEST_SETTINGS_VALUES.reminderRepeatMode,
|
||||
);
|
||||
await expect(root.locator('[data-testid="reminder-repeat-amount"]')).toHaveValue(
|
||||
String(TEST_SETTINGS_VALUES.reminderRepeatAmount),
|
||||
);
|
||||
await expect(root.locator('[data-testid="reminder-repeat-unit"]')).toContainText(
|
||||
TEST_SETTINGS_VALUES.reminderRepeatUnit,
|
||||
);
|
||||
|
||||
await root.getByRole('button', { name: 'Email' }).click();
|
||||
await expect(root.locator('#recipientSigned')).toHaveAttribute('aria-checked', 'false');
|
||||
await expect(root.locator('#recipientSigningRequest')).toHaveAttribute('aria-checked', 'false');
|
||||
@@ -285,6 +376,7 @@ const assertEnvelopeSettingsPersistedInDatabase = async ({
|
||||
expect(envelope.documentMeta.envelopeExpirationPeriod).toEqual(
|
||||
DB_EXPECTED_VALUES.envelopeExpirationPeriod,
|
||||
);
|
||||
expect(envelope.documentMeta.reminderSettings).toEqual(DB_EXPECTED_VALUES.reminderSettings);
|
||||
expect(envelope.documentMeta.redirectUrl).toBe(TEST_SETTINGS_VALUES.redirectUrl);
|
||||
expect(envelope.documentMeta.emailReplyTo).toBe(TEST_SETTINGS_VALUES.replyTo);
|
||||
expect(envelope.documentMeta.subject).toBe(TEST_SETTINGS_VALUES.subject);
|
||||
|
||||
@@ -25,7 +25,7 @@ test('[ENVELOPE_EXPIRATION]: set custom expiration period at organisation level'
|
||||
await expect(page.getByRole('button', { name: 'Update' }).first()).toBeVisible();
|
||||
|
||||
// Change the amount to 2.
|
||||
const amountInput = page.getByRole('spinbutton');
|
||||
const amountInput = page.getByTestId('envelope-expiration-amount');
|
||||
await amountInput.clear();
|
||||
await amountInput.fill('2');
|
||||
|
||||
@@ -33,9 +33,7 @@ test('[ENVELOPE_EXPIRATION]: set custom expiration period at organisation level'
|
||||
// In the duration mode, there's a mode select and a unit select.
|
||||
// The unit select is inside the duration row, after the number input.
|
||||
// Let's find the select trigger that contains the unit text.
|
||||
const unitTrigger = page
|
||||
.locator('button[role="combobox"]')
|
||||
.filter({ hasText: /Months|Days|Weeks|Years/ });
|
||||
const unitTrigger = page.getByTestId('envelope-expiration-unit');
|
||||
|
||||
await unitTrigger.click();
|
||||
await page.getByRole('option', { name: 'Weeks' }).click();
|
||||
@@ -65,9 +63,7 @@ test('[ENVELOPE_EXPIRATION]: disable expiration at organisation level', async ({
|
||||
await expect(page.getByRole('button', { name: 'Update' }).first()).toBeVisible();
|
||||
|
||||
// Find the mode select (shows "Custom duration") and change to "Never expires".
|
||||
const modeTrigger = page
|
||||
.locator('button[role="combobox"]')
|
||||
.filter({ hasText: 'Custom duration' });
|
||||
const modeTrigger = page.getByTestId('envelope-expiration-mode');
|
||||
await modeTrigger.click();
|
||||
await page.getByRole('option', { name: 'Never expires' }).click();
|
||||
|
||||
@@ -118,11 +114,8 @@ test('[ENVELOPE_EXPIRATION]: team overrides organisation expiration', async ({ p
|
||||
|
||||
await expect(page.getByRole('button', { name: 'Update' }).first()).toBeVisible();
|
||||
|
||||
// Scope to the "Default Envelope Expiration" form field section.
|
||||
const expirationSection = page.getByText('Default Envelope Expiration').locator('..');
|
||||
|
||||
// The expiration picker mode select should show "Inherit from organisation" by default.
|
||||
const modeTrigger = expirationSection.locator('button[role="combobox"]').first();
|
||||
const modeTrigger = page.getByTestId('envelope-expiration-mode');
|
||||
await expect(modeTrigger).toBeVisible();
|
||||
|
||||
// Switch to custom duration.
|
||||
@@ -130,13 +123,11 @@ test('[ENVELOPE_EXPIRATION]: team overrides organisation expiration', async ({ p
|
||||
await page.getByRole('option', { name: 'Custom duration' }).click();
|
||||
|
||||
// Set to 5 days.
|
||||
const amountInput = expirationSection.getByRole('spinbutton');
|
||||
const amountInput = page.getByTestId('envelope-expiration-amount');
|
||||
await amountInput.clear();
|
||||
await amountInput.fill('5');
|
||||
|
||||
const unitTrigger = expirationSection
|
||||
.locator('button[role="combobox"]')
|
||||
.filter({ hasText: /Months|Days|Weeks|Years/ });
|
||||
const unitTrigger = page.getByTestId('envelope-expiration-unit');
|
||||
await unitTrigger.click();
|
||||
await page.getByRole('option', { name: 'Days' }).click();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user