mirror of
https://github.com/hanzoai/sign.git
synced 2026-10-21 01:21:51 +00:00
The product is branded Hanzo eSign (esign.hanzo.ai, repo hanzoai/esign). Rename all workspace packages @hanzo/sign-* → @hanzo/esign-* (1052 files) and align docker/Dockerfile turbo --scope/--filter to the actual remix package name @hanzo/esign (was a pre-existing mismatch with -remix that broke the build). Protected deps (@hanzo/insights, @hanzo/logo) untouched.
327 lines
9.7 KiB
TypeScript
327 lines
9.7 KiB
TypeScript
import type { Page } from '@playwright/test';
|
|
import { expect, test } from '@playwright/test';
|
|
|
|
import { PDF_VIEWER_PAGE_SELECTOR } from '@hanzo/esign-lib/constants/pdf-viewer';
|
|
import { getTemplateById } from '@hanzo/esign-lib/server-only/template/get-template-by-id';
|
|
import { mapSecondaryIdToTemplateId } from '@hanzo/esign-lib/utils/envelope';
|
|
import { seedBlankTemplate } from '@hanzo/esign-prisma/seed/templates';
|
|
import { seedUser } from '@hanzo/esign-prisma/seed/users';
|
|
|
|
import { apiSignin } from '../fixtures/authentication';
|
|
|
|
const setupTemplateAndNavigateToFieldsStep = async (page: Page) => {
|
|
const { user, team } = await seedUser();
|
|
const template = await seedBlankTemplate(user, team.id);
|
|
|
|
await apiSignin({
|
|
page,
|
|
email: user.email,
|
|
redirectPath: `/t/${team.url}/templates/${mapSecondaryIdToTemplateId(template.secondaryId)}/edit`,
|
|
});
|
|
|
|
await page.getByRole('button', { name: 'Continue' }).click();
|
|
|
|
await page.getByPlaceholder('Email').fill('[email protected]');
|
|
await page.getByPlaceholder('Name').fill('Recipient 1');
|
|
|
|
await page.getByRole('button', { name: 'Add Placeholder Recipient' }).click();
|
|
|
|
await page.getByPlaceholder('Email').nth(1).fill('[email protected]');
|
|
await page.getByPlaceholder('Name').nth(1).fill('Recipient 2');
|
|
|
|
await page.getByRole('button', { name: 'Continue' }).click();
|
|
|
|
return { user, team, template };
|
|
};
|
|
|
|
const triggerAutosave = async (page: Page) => {
|
|
await page.locator('body').click({ position: { x: 0, y: 0 } });
|
|
await page.locator('#document-flow-form-container').blur();
|
|
|
|
await page.waitForTimeout(5000);
|
|
};
|
|
|
|
test.describe('AutoSave Fields Step', () => {
|
|
test('should autosave the fields without advanced settings', async ({ page }) => {
|
|
const { user, template, team } = await setupTemplateAndNavigateToFieldsStep(page);
|
|
|
|
await expect(page.getByRole('heading', { name: 'Add Fields' })).toBeVisible();
|
|
|
|
await page.getByRole('button', { name: 'Signature' }).click();
|
|
await page.locator(PDF_VIEWER_PAGE_SELECTOR).click({
|
|
position: {
|
|
x: 100,
|
|
y: 100,
|
|
},
|
|
});
|
|
|
|
await page.getByRole('button', { name: 'Text' }).click();
|
|
await page.locator(PDF_VIEWER_PAGE_SELECTOR).click({
|
|
position: {
|
|
x: 100,
|
|
y: 200,
|
|
},
|
|
});
|
|
|
|
await page.getByTestId('field-advanced-settings-footer').waitFor({ state: 'visible' });
|
|
|
|
await page
|
|
.getByTestId('field-advanced-settings-footer')
|
|
.getByRole('button', { name: 'Cancel' })
|
|
.click();
|
|
|
|
await triggerAutosave(page);
|
|
|
|
await page.getByRole('combobox').first().click();
|
|
await page.getByRole('option', { name: 'Recipient 2 ([email protected])' }).click();
|
|
|
|
await page.getByRole('button', { name: 'Signature' }).click();
|
|
await page.locator(PDF_VIEWER_PAGE_SELECTOR).click({
|
|
position: {
|
|
x: 100,
|
|
y: 500,
|
|
},
|
|
});
|
|
|
|
await triggerAutosave(page);
|
|
|
|
await expect(async () => {
|
|
const retrievedFields = await getTemplateById({
|
|
id: {
|
|
type: 'envelopeId',
|
|
id: template.id,
|
|
},
|
|
userId: user.id,
|
|
teamId: team.id,
|
|
});
|
|
|
|
const fields = retrievedFields.fields;
|
|
|
|
expect(fields.length).toBe(3);
|
|
|
|
expect(fields.map((field) => field.type).toSorted()).toEqual(
|
|
['SIGNATURE', 'TEXT', 'SIGNATURE'].toSorted(),
|
|
);
|
|
}).toPass();
|
|
});
|
|
|
|
test('should autosave the field deletion', async ({ page }) => {
|
|
const { user, template, team } = await setupTemplateAndNavigateToFieldsStep(page);
|
|
|
|
await expect(page.getByRole('heading', { name: 'Add Fields' })).toBeVisible();
|
|
|
|
await page.getByRole('button', { name: 'Signature' }).click();
|
|
await page.locator(PDF_VIEWER_PAGE_SELECTOR).click({
|
|
position: {
|
|
x: 100,
|
|
y: 100,
|
|
},
|
|
});
|
|
|
|
await page.getByRole('button', { name: 'Text' }).click();
|
|
await page.locator(PDF_VIEWER_PAGE_SELECTOR).click({
|
|
position: {
|
|
x: 100,
|
|
y: 200,
|
|
},
|
|
});
|
|
|
|
await page.getByTestId('field-advanced-settings-footer').waitFor({ state: 'visible' });
|
|
|
|
await page
|
|
.getByTestId('field-advanced-settings-footer')
|
|
.getByRole('button', { name: 'Cancel' })
|
|
.click();
|
|
|
|
await triggerAutosave(page);
|
|
|
|
await page.getByRole('combobox').first().click();
|
|
await page.getByRole('option', { name: 'Recipient 2 ([email protected])' }).click();
|
|
|
|
await page.getByRole('button', { name: 'Signature' }).click();
|
|
await page.locator(PDF_VIEWER_PAGE_SELECTOR).click({
|
|
position: {
|
|
x: 100,
|
|
y: 500,
|
|
},
|
|
});
|
|
|
|
await triggerAutosave(page);
|
|
|
|
await page.getByRole('combobox').first().click();
|
|
await page.getByRole('option', { name: 'Recipient 1 ([email protected])' }).click();
|
|
|
|
await page.getByText('Text').nth(1).click();
|
|
await page.getByRole('button', { name: 'Remove' }).click();
|
|
|
|
await triggerAutosave(page);
|
|
|
|
await expect(async () => {
|
|
const retrievedFields = await getTemplateById({
|
|
id: {
|
|
type: 'envelopeId',
|
|
id: template.id,
|
|
},
|
|
userId: user.id,
|
|
teamId: team.id,
|
|
});
|
|
|
|
const fields = retrievedFields.fields;
|
|
|
|
expect(fields.length).toBe(2);
|
|
expect(fields[0].type).toBe('SIGNATURE');
|
|
expect(fields[1].type).toBe('SIGNATURE');
|
|
}).toPass();
|
|
});
|
|
|
|
test('should autosave the field duplication', async ({ page }) => {
|
|
const { user, template, team } = await setupTemplateAndNavigateToFieldsStep(page);
|
|
|
|
await expect(page.getByRole('heading', { name: 'Add Fields' })).toBeVisible();
|
|
|
|
await page.getByRole('button', { name: 'Signature' }).click();
|
|
await page.locator(PDF_VIEWER_PAGE_SELECTOR).click({
|
|
position: {
|
|
x: 100,
|
|
y: 100,
|
|
},
|
|
});
|
|
|
|
await page.getByRole('button', { name: 'Text' }).click();
|
|
await page.locator(PDF_VIEWER_PAGE_SELECTOR).click({
|
|
position: {
|
|
x: 100,
|
|
y: 200,
|
|
},
|
|
});
|
|
|
|
await page.getByTestId('field-advanced-settings-footer').waitFor({ state: 'visible' });
|
|
|
|
await page
|
|
.getByTestId('field-advanced-settings-footer')
|
|
.getByRole('button', { name: 'Cancel' })
|
|
.click();
|
|
|
|
await triggerAutosave(page);
|
|
|
|
await page.getByRole('combobox').first().click();
|
|
await page.getByRole('option', { name: 'Recipient 2 ([email protected])' }).click();
|
|
|
|
await page.getByRole('button', { name: 'Signature' }).click();
|
|
await page.locator(PDF_VIEWER_PAGE_SELECTOR).click({
|
|
position: {
|
|
x: 100,
|
|
y: 500,
|
|
},
|
|
});
|
|
|
|
await triggerAutosave(page);
|
|
|
|
await page.getByRole('combobox').first().click();
|
|
await page.getByRole('option', { name: 'Recipient 1 ([email protected])' }).click();
|
|
|
|
await page.getByText('Signature').nth(1).click();
|
|
await page.getByRole('button', { name: 'Duplicate', exact: true }).click();
|
|
|
|
await triggerAutosave(page);
|
|
|
|
await expect(async () => {
|
|
const retrievedFields = await getTemplateById({
|
|
id: {
|
|
type: 'envelopeId',
|
|
id: template.id,
|
|
},
|
|
|
|
userId: user.id,
|
|
teamId: team.id,
|
|
});
|
|
|
|
const fields = retrievedFields.fields;
|
|
|
|
expect(fields.length).toBe(4);
|
|
expect(fields.map((field) => field.type).toSorted()).toEqual(
|
|
['SIGNATURE', 'TEXT', 'SIGNATURE', 'SIGNATURE'].toSorted(),
|
|
);
|
|
}).toPass();
|
|
});
|
|
|
|
test('should autosave the fields with advanced settings', async ({ page }) => {
|
|
const { user, template, team } = await setupTemplateAndNavigateToFieldsStep(page);
|
|
|
|
await expect(page.getByRole('heading', { name: 'Add Fields' })).toBeVisible();
|
|
|
|
await page.getByRole('button', { name: 'Signature' }).click();
|
|
await page.locator(PDF_VIEWER_PAGE_SELECTOR).click({
|
|
position: {
|
|
x: 100,
|
|
y: 100,
|
|
},
|
|
});
|
|
|
|
await page.getByRole('button', { name: 'Text' }).click();
|
|
await page.locator(PDF_VIEWER_PAGE_SELECTOR).click({
|
|
position: {
|
|
x: 100,
|
|
y: 200,
|
|
},
|
|
});
|
|
|
|
await page.getByRole('textbox', { name: 'Field label' }).fill('Test Field');
|
|
await page.getByRole('textbox', { name: 'Field placeholder' }).fill('Test Placeholder');
|
|
await page.getByRole('textbox', { name: 'Add text to the field' }).fill('Test Text');
|
|
|
|
await page.getByTestId('field-advanced-settings-footer').waitFor({ state: 'visible' });
|
|
|
|
await page
|
|
.getByTestId('field-advanced-settings-footer')
|
|
.getByRole('button', { name: 'Save' })
|
|
.click();
|
|
|
|
await page.waitForTimeout(2500);
|
|
await triggerAutosave(page);
|
|
|
|
await expect(async () => {
|
|
const retrievedTemplate = await getTemplateById({
|
|
id: {
|
|
type: 'envelopeId',
|
|
id: template.id,
|
|
},
|
|
userId: user.id,
|
|
teamId: team.id,
|
|
});
|
|
|
|
const fields = retrievedTemplate.fields;
|
|
|
|
expect(fields.length).toBe(2);
|
|
expect(fields.map((field) => field.type).toSorted()).toEqual(
|
|
['SIGNATURE', 'TEXT'].toSorted(),
|
|
);
|
|
|
|
const textField = fields.find((field) => field.type === 'TEXT');
|
|
expect(textField).toBeDefined();
|
|
|
|
if (!textField) {
|
|
throw new Error('No text field');
|
|
}
|
|
|
|
expect(textField.fieldMeta).toBeDefined();
|
|
|
|
if (
|
|
textField.fieldMeta &&
|
|
typeof textField.fieldMeta === 'object' &&
|
|
'type' in textField.fieldMeta
|
|
) {
|
|
expect(textField.fieldMeta.type).toBe('text');
|
|
expect(textField.fieldMeta.label).toBe('Test Field');
|
|
expect(textField.fieldMeta.placeholder).toBe('Test Placeholder');
|
|
|
|
if (textField.fieldMeta.type === 'text') {
|
|
expect(textField.fieldMeta.text).toBe('Test Text');
|
|
}
|
|
} else {
|
|
throw new Error('fieldMeta should be defined and contain advanced settings');
|
|
}
|
|
}).toPass();
|
|
});
|
|
});
|