mirror of
https://github.com/documenso/documenso.git
synced 2026-07-24 08:54:20 +10:00
fix: add sticky form update button (#3056)
This commit is contained in:
@@ -526,7 +526,7 @@ test('[ADMIN]: verify organisation access after ownership change', async ({ page
|
||||
// Should be able to access organisation settings
|
||||
await expect(page.getByText('Organisation Settings')).toBeVisible();
|
||||
await expect(page.getByLabel('Organisation Name*')).toBeVisible();
|
||||
await expect(page.getByRole('button', { name: 'Update organisation' })).toBeVisible();
|
||||
await expect(page.getByLabel('Organisation Name*')).toBeEnabled();
|
||||
|
||||
// Should have delete permissions
|
||||
await expect(page.getByRole('button', { name: 'Delete' })).toBeVisible();
|
||||
|
||||
@@ -19,7 +19,7 @@ test('[ENVELOPE_EXPIRATION]: set custom expiration period at organisation level'
|
||||
});
|
||||
|
||||
// Wait for the form to load.
|
||||
await expect(page.getByRole('button', { name: 'Update' }).first()).toBeVisible();
|
||||
await expect(page.getByTestId('document-language-trigger')).toBeVisible();
|
||||
|
||||
// Change the amount to 2.
|
||||
const amountInput = page.getByTestId('envelope-expiration-amount');
|
||||
@@ -35,7 +35,7 @@ test('[ENVELOPE_EXPIRATION]: set custom expiration period at organisation level'
|
||||
await unitTrigger.click();
|
||||
await page.getByRole('option', { name: 'Weeks' }).click();
|
||||
|
||||
await page.getByRole('button', { name: 'Update' }).first().click();
|
||||
await page.getByRole('button', { name: 'Save changes' }).first().click();
|
||||
await expect(page.getByText('Your document preferences have been updated').first()).toBeVisible();
|
||||
|
||||
// Verify via database.
|
||||
@@ -57,14 +57,14 @@ test('[ENVELOPE_EXPIRATION]: disable expiration at organisation level', async ({
|
||||
redirectPath: `/o/${organisation.url}/settings/document`,
|
||||
});
|
||||
|
||||
await expect(page.getByRole('button', { name: 'Update' }).first()).toBeVisible();
|
||||
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 modeTrigger.click();
|
||||
await page.getByRole('option', { name: 'Never expires' }).click();
|
||||
|
||||
await page.getByRole('button', { name: 'Update' }).first().click();
|
||||
await page.getByRole('button', { name: 'Save changes' }).first().click();
|
||||
await expect(page.getByText('Your document preferences have been updated').first()).toBeVisible();
|
||||
|
||||
// Verify via database.
|
||||
@@ -109,7 +109,7 @@ test('[ENVELOPE_EXPIRATION]: team overrides organisation expiration', async ({ p
|
||||
redirectPath: `/t/${team.url}/settings/document`,
|
||||
});
|
||||
|
||||
await expect(page.getByRole('button', { name: 'Update' }).first()).toBeVisible();
|
||||
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');
|
||||
@@ -128,7 +128,7 @@ test('[ENVELOPE_EXPIRATION]: team overrides organisation expiration', async ({ p
|
||||
await unitTrigger.click();
|
||||
await page.getByRole('option', { name: 'Days' }).click();
|
||||
|
||||
await page.getByRole('button', { name: 'Update' }).first().click();
|
||||
await page.getByRole('button', { name: 'Save changes' }).first().click();
|
||||
await expect(page.getByText('Your document preferences have been updated').first()).toBeVisible();
|
||||
|
||||
// Verify team setting is overridden.
|
||||
|
||||
@@ -324,10 +324,7 @@ test.describe('Signing Certificate Tests', () => {
|
||||
.click();
|
||||
await page.getByRole('option', { name: 'No' }).click();
|
||||
|
||||
await page
|
||||
.getByRole('button', { name: /Update/ })
|
||||
.first()
|
||||
.click();
|
||||
await page.getByRole('button', { name: 'Save changes' }).first().click();
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
@@ -347,10 +344,7 @@ test.describe('Signing Certificate Tests', () => {
|
||||
.getByRole('combobox')
|
||||
.click();
|
||||
await page.getByRole('option', { name: 'Yes' }).click();
|
||||
await page
|
||||
.getByRole('button', { name: /Update/ })
|
||||
.first()
|
||||
.click();
|
||||
await page.getByRole('button', { name: 'Save changes' }).first().click();
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ test('[ORGANISATIONS]: manage general settings', async ({ page }) => {
|
||||
await page.getByLabel('Organisation URL*').clear();
|
||||
await page.getByLabel('Organisation URL*').fill(updatedOrganisationId);
|
||||
|
||||
await page.getByRole('button', { name: 'Update organisation' }).click();
|
||||
await page.getByRole('button', { name: 'Save changes' }).click();
|
||||
|
||||
// Check we have been redirected to the new organisation URL and the name is updated.
|
||||
await page.waitForURL(`/o/${updatedOrganisationId}/settings/general`);
|
||||
|
||||
@@ -39,7 +39,7 @@ test('[ORGANISATIONS]: manage document preferences', async ({ page }) => {
|
||||
await page.getByRole('option', { name: 'No' }).click();
|
||||
await page.getByTestId('include-signing-certificate-trigger').click();
|
||||
await page.getByRole('option', { name: 'No' }).click();
|
||||
await page.getByRole('button', { name: 'Update' }).first().click();
|
||||
await page.getByRole('button', { name: 'Save changes' }).first().click();
|
||||
await expect(page.getByText('Your document preferences have been updated').first()).toBeVisible();
|
||||
|
||||
const teamSettings = await getTeamSettings({
|
||||
@@ -73,7 +73,7 @@ test('[ORGANISATIONS]: manage document preferences', async ({ page }) => {
|
||||
await page.getByTestId('document-date-format-trigger').click();
|
||||
await page.getByRole('option', { name: 'MM/DD/YYYY', exact: true }).click();
|
||||
|
||||
await page.getByRole('button', { name: 'Update' }).first().click();
|
||||
await page.getByRole('button', { name: 'Save changes' }).first().click();
|
||||
await expect(page.getByText('Your document preferences have been updated').first()).toBeVisible();
|
||||
|
||||
const updatedTeamSettings = await getTeamSettings({
|
||||
@@ -128,7 +128,7 @@ test('[ORGANISATIONS]: manage branding preferences', async ({ page }) => {
|
||||
await page.getByRole('textbox', { name: 'Brand Website' }).fill('https://documenso.com');
|
||||
await page.getByRole('textbox', { name: 'Brand Details' }).click();
|
||||
await page.getByRole('textbox', { name: 'Brand Details' }).fill('BrandDetails');
|
||||
await page.getByRole('button', { name: 'Update' }).first().click();
|
||||
await page.getByRole('button', { name: 'Save changes' }).first().click();
|
||||
await expect(page.getByText('Your branding preferences have been updated').first()).toBeVisible();
|
||||
|
||||
const teamSettings = await getTeamSettings({
|
||||
@@ -150,7 +150,7 @@ test('[ORGANISATIONS]: manage branding preferences', async ({ page }) => {
|
||||
await page.getByRole('textbox', { name: 'Brand Website' }).fill('https://example.com');
|
||||
await page.getByRole('textbox', { name: 'Brand Details' }).click();
|
||||
await page.getByRole('textbox', { name: 'Brand Details' }).fill('UpdatedBrandDetails');
|
||||
await page.getByRole('button', { name: 'Update' }).first().click();
|
||||
await page.getByRole('button', { name: 'Save changes' }).first().click();
|
||||
await expect(page.getByText('Your branding preferences have been updated').first()).toBeVisible();
|
||||
|
||||
const updatedTeamSettings = await getTeamSettings({
|
||||
@@ -165,7 +165,7 @@ test('[ORGANISATIONS]: manage branding preferences', async ({ page }) => {
|
||||
// Test inheritance by setting team back to inherit from organisation
|
||||
await page.getByTestId('enable-branding').click();
|
||||
await page.getByRole('option', { name: 'Inherit from organisation' }).click();
|
||||
await page.getByRole('button', { name: 'Update' }).first().click();
|
||||
await page.getByRole('button', { name: 'Save changes' }).first().click();
|
||||
await expect(page.getByText('Your branding preferences have been updated').first()).toBeVisible();
|
||||
|
||||
await page.waitForTimeout(2000);
|
||||
@@ -208,7 +208,7 @@ test('[ORGANISATIONS]: manage email preferences', async ({ page }) => {
|
||||
await page.getByRole('checkbox', { name: 'Email the signer if the document is still pending' }).uncheck();
|
||||
await page.getByRole('checkbox', { name: 'Email recipients when a pending document is deleted' }).uncheck();
|
||||
|
||||
await page.getByRole('button', { name: 'Update' }).first().click();
|
||||
await page.getByRole('button', { name: 'Save changes' }).first().click();
|
||||
await expect(page.getByText('Your email preferences have been updated').first()).toBeVisible();
|
||||
|
||||
const teamSettings = await getTeamSettings({
|
||||
@@ -245,7 +245,7 @@ test('[ORGANISATIONS]: manage email preferences', async ({ page }) => {
|
||||
await page.getByRole('checkbox', { name: 'Email recipients when the document is completed', exact: true }).uncheck();
|
||||
await page.getByRole('checkbox', { name: 'Email the owner when the document is completed' }).uncheck();
|
||||
|
||||
await page.getByRole('button', { name: 'Update' }).first().click();
|
||||
await page.getByRole('button', { name: 'Save changes' }).first().click();
|
||||
await expect(page.getByText('Your email preferences have been updated').first()).toBeVisible();
|
||||
|
||||
const updatedTeamSettings = await getTeamSettings({
|
||||
@@ -292,7 +292,7 @@ test('[ORGANISATIONS]: manage email preferences', async ({ page }) => {
|
||||
await page.getByRole('textbox', { name: 'Reply to email' }).fill('');
|
||||
await page.getByRole('combobox').filter({ hasText: 'Override organisation settings' }).click();
|
||||
await page.getByRole('option', { name: 'Inherit from organisation' }).click();
|
||||
await page.getByRole('button', { name: 'Update' }).first().click();
|
||||
await page.getByRole('button', { name: 'Save changes' }).first().click();
|
||||
await expect(page.getByText('Your email preferences have been updated').first()).toBeVisible();
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
@@ -66,7 +66,7 @@ test('[TEAMS]: update team', async ({ page }) => {
|
||||
await page.getByLabel('Team URL*').clear();
|
||||
await page.getByLabel('Team URL*').fill(updatedTeamId);
|
||||
|
||||
await page.getByRole('button', { name: 'Update team' }).click();
|
||||
await page.getByRole('button', { name: 'Save changes' }).click();
|
||||
|
||||
// Check we have been redirected to the new team URL and the name is updated.
|
||||
await page.waitForURL(`${NEXT_PUBLIC_WEBAPP_URL()}/t/${updatedTeamId}/settings`);
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
import { seedUser } from '@documenso/prisma/seed/users';
|
||||
import { expect, test } from '@playwright/test';
|
||||
|
||||
import { apiSignin } from '../fixtures/authentication';
|
||||
|
||||
test('[TEAMS]: settings save bar docks at the bottom of the form', async ({ page }) => {
|
||||
const { user, team } = await seedUser();
|
||||
|
||||
await apiSignin({
|
||||
page,
|
||||
email: user.email,
|
||||
redirectPath: `/t/${team.url}/settings`,
|
||||
});
|
||||
|
||||
await expect(page.getByLabel('Team Name*')).toBeVisible();
|
||||
|
||||
const saveButton = page.getByRole('button', { name: 'Save changes' });
|
||||
|
||||
// Pristine: the docked Save button is present but disabled; no Undo, no floating notice.
|
||||
await expect(saveButton).toBeVisible();
|
||||
await expect(saveButton).toBeDisabled();
|
||||
await expect(page.getByRole('button', { name: 'Undo' })).toHaveCount(0);
|
||||
await expect(page.getByText('You have unsaved changes')).not.toBeVisible();
|
||||
|
||||
// Make a change → Save enables and Undo appears.
|
||||
const updatedName = `team-${Date.now()}`;
|
||||
await page.getByLabel('Team Name*').clear();
|
||||
await page.getByLabel('Team Name*').fill(updatedName);
|
||||
|
||||
await expect(saveButton).toBeEnabled();
|
||||
await expect(page.getByRole('button', { name: 'Undo' })).toBeVisible();
|
||||
|
||||
// Undo → value restored, Save disabled again, Undo gone.
|
||||
await page.getByRole('button', { name: 'Undo' }).click();
|
||||
await expect(page.getByLabel('Team Name*')).toHaveValue(team.name);
|
||||
await expect(saveButton).toBeDisabled();
|
||||
await expect(page.getByRole('button', { name: 'Undo' })).toHaveCount(0);
|
||||
|
||||
// Change again → Save → success toast, returns to a pristine (disabled) state.
|
||||
await page.getByLabel('Team Name*').clear();
|
||||
await page.getByLabel('Team Name*').fill(updatedName);
|
||||
await expect(saveButton).toBeEnabled();
|
||||
await saveButton.click();
|
||||
|
||||
await expect(page.getByText('Your team has been successfully updated.').first()).toBeVisible();
|
||||
await expect(saveButton).toBeDisabled();
|
||||
});
|
||||
|
||||
test('[ORGANISATIONS]: settings save bar floats when the form footer is off-screen', async ({ page }) => {
|
||||
const { user, organisation } = await seedUser({
|
||||
isPersonalOrganisation: false,
|
||||
});
|
||||
|
||||
await apiSignin({
|
||||
page,
|
||||
email: user.email,
|
||||
redirectPath: `/o/${organisation.url}/settings/document`,
|
||||
});
|
||||
|
||||
// Wait for the long document-preferences form to load.
|
||||
await expect(page.getByTestId('document-language-trigger')).toBeVisible();
|
||||
|
||||
// Pristine: no floating notice even though the footer is below the fold.
|
||||
await expect(page.getByText('You have unsaved changes')).not.toBeVisible();
|
||||
|
||||
// Edit a field near the top → the footer is off-screen, so the floating pill appears.
|
||||
await page.getByTestId('document-language-trigger').click();
|
||||
await page.getByRole('option', { name: 'German' }).click();
|
||||
|
||||
await expect(page.getByText('You have unsaved changes')).toBeVisible();
|
||||
await expect(page.getByRole('button', { name: 'Save changes' })).toBeVisible();
|
||||
|
||||
// Scroll to the footer → the floating pill merges into the docked buttons and the
|
||||
// notice disappears.
|
||||
await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));
|
||||
|
||||
await expect(page.getByText('You have unsaved changes')).not.toBeVisible();
|
||||
await expect(page.getByRole('button', { name: 'Save changes' })).toBeVisible();
|
||||
});
|
||||
@@ -75,7 +75,7 @@ test('[TEAMS]: check signature modes can be disabled', async ({ page }) => {
|
||||
await item.click();
|
||||
}
|
||||
|
||||
await page.getByRole('button', { name: 'Update' }).first().click();
|
||||
await page.getByRole('button', { name: 'Save changes' }).first().click();
|
||||
|
||||
// Wait for the update to complete
|
||||
await expect(page.getByText('Document preferences updated', { exact: true })).toBeVisible();
|
||||
@@ -140,7 +140,7 @@ test('[TEAMS]: check signature modes work for templates', async ({ page }) => {
|
||||
await item.click();
|
||||
}
|
||||
|
||||
await page.getByRole('button', { name: 'Update' }).first().click();
|
||||
await page.getByRole('button', { name: 'Save changes' }).first().click();
|
||||
|
||||
// Wait for finish
|
||||
await expect(page.getByText('Document preferences updated', { exact: true })).toBeVisible();
|
||||
|
||||
Reference in New Issue
Block a user