Skip to content

Commit de71c95

Browse files
test(e2e): add sign herself with drawn signature spec
Full E2E test covering the complete self-signing flow: - Upload PDF via URL - Add signer by account with drawn signature method - Place signature position on PDF canvas using hover/rAF sync - Request and send the document - Assert signature position box is visible in signing screen - Draw signature, save and confirm Uses semantic locators throughout (getByRole, getByLabel, getByPlaceholder) to validate accessibility at each step. Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
1 parent 34b4845 commit de71c95

1 file changed

Lines changed: 110 additions & 0 deletions

File tree

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/**
2+
* SPDX-FileCopyrightText: 2026 LibreCode coop and contributors
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
6+
import { expect, test } from '@playwright/test'
7+
import { login } from '../support/nc-login'
8+
import { configureOpenSsl, setAppConfig } from '../support/nc-provisioning'
9+
10+
test('sign herself with drawn signature', async ({ page }) => {
11+
await login(
12+
page.request,
13+
process.env.NEXTCLOUD_ADMIN_USER ?? 'admin',
14+
process.env.NEXTCLOUD_ADMIN_PASSWORD ?? 'admin',
15+
)
16+
17+
await configureOpenSsl(page.request, 'LibreSign Test', {
18+
C: 'BR',
19+
OU: ['Organization Unit'],
20+
ST: 'Rio de Janeiro',
21+
O: 'LibreSign',
22+
L: 'Rio de Janeiro',
23+
})
24+
25+
await setAppConfig(
26+
page.request,
27+
'libresign',
28+
'identify_methods',
29+
JSON.stringify([
30+
{ name: 'account', enabled: true, mandatory: true, signatureMethods: { clickToSign: { enabled: true } } },
31+
{ name: 'email', enabled: false, mandatory: false },
32+
]),
33+
)
34+
35+
await page.goto('./apps/libresign')
36+
await page.getByRole('button', { name: 'Upload from URL' }).click();
37+
await page.getByRole('textbox', { name: 'URL of a PDF file' }).click();
38+
await page.getByRole('textbox', { name: 'URL of a PDF file' }).fill('https://raw.githubusercontent.com/LibreSign/libresign/main/tests/php/fixtures/pdfs/small_valid.pdf');
39+
await page.getByRole('button', { name: 'Send' }).click();
40+
await page.getByRole('button', { name: 'Add signer' }).click();
41+
await page.getByPlaceholder('Account').click();
42+
await page.getByPlaceholder('Account').fill('a');
43+
await page.getByRole('option', { name: 'admin@email.tld' }).click();
44+
45+
await page.getByRole('textbox', { name: 'Signer name' }).click();
46+
await page.getByRole('textbox', { name: 'Signer name' }).press('ControlOrMeta+a');
47+
await page.getByRole('textbox', { name: 'Signer name' }).fill('Admin Name');
48+
49+
50+
await page.getByRole('button', { name: 'Save' }).click();
51+
await page.getByRole('button', { name: 'Setup signature positions' }).click();
52+
await expect(page.getByLabel('Page 1 of 1.')).toBeVisible();
53+
await page.getByLabel('Signature positions').getByRole('link', { name: 'Edit signer Admin Name' }).click();
54+
55+
await expect(page.getByText('Click on the place you want to add.')).toBeVisible();
56+
57+
// Placing a signature element on the PDF canvas requires three steps:
58+
// 1. hover() triggers handleMouseMove, which sets previewVisible=true inside a
59+
// requestAnimationFrame callback.
60+
// 2. Waiting for .preview-element confirms the rAF ran. Without this, finishAdding()
61+
// (bound to mouseup on document) returns early because previewVisible is still false.
62+
// 3. click() fires mouseup on the document, which triggers finishAdding() and places
63+
// the element at the current preview position.
64+
const overlay = page.getByLabel('Page 1 of 1. Press Enter or Space to place the signature here.')
65+
await overlay.hover()
66+
await page.getByLabel('Signature positions').locator('.preview-element').first().waitFor({ state: 'visible' })
67+
await overlay.click()
68+
await expect(
69+
page.getByLabel('Signature positions').getByRole('img', { name: 'Signature position for Admin Name' })
70+
).toBeVisible()
71+
72+
await page.getByRole('button', { name: 'Save' }).click();
73+
await page.getByRole('button', { name: 'Request signatures' }).click();
74+
await page.getByRole('button', { name: 'Send' }).click();
75+
await page.getByRole('button', { name: 'Sign document' }).click();
76+
77+
await expect(
78+
page.getByLabel('PDF document to sign').getByRole('img', { name: 'Signature position for Admin Name' })
79+
).toBeVisible()
80+
81+
// If a signature already exists from a previous run, delete it before creating a new one
82+
const deleteSignatureBtn = page.getByRole('button', { name: 'Delete signature' })
83+
await deleteSignatureBtn.waitFor({ state: 'visible', timeout: 3000 }).catch(() => null)
84+
if (await deleteSignatureBtn.isVisible()) {
85+
await deleteSignatureBtn.click()
86+
}
87+
88+
await page.getByRole('button', { name: 'Define your signature.' }).click();
89+
90+
await page.getByRole('dialog', { name: 'Customize your signatures' }).locator('canvas').click({
91+
position: {
92+
x: 156,
93+
y: 132
94+
}
95+
});
96+
await page.getByRole('button', { name: 'Save' }).click();
97+
await expect(page.getByRole('heading', { name: 'Confirm your signature' })).toBeVisible();
98+
await expect(page.getByRole('img', { name: 'Signature preview' })).toBeVisible();
99+
await page.getByLabel('Confirm your signature').getByRole('button', { name: 'Save' }).click();
100+
101+
await page.getByRole('button', { name: 'Sign the document.' }).click();
102+
await page.getByRole('button', { name: 'Sign document' }).click();
103+
await page.waitForURL('**/validation/**')
104+
await expect(page.getByText('This document is valid')).toBeVisible()
105+
await page.getByRole('button', { name: 'Expand details' }).click()
106+
await page.getByRole('button', { name: 'Expand validation status', exact: true }).click()
107+
await expect(page.getByRole('link', { name: 'Document integrity verified' })).toBeVisible()
108+
await page.getByRole('button', { name: 'Expand document certification', exact: true }).click()
109+
await expect(page.getByRole('link', { name: 'Document has not been modified after signing' })).toBeVisible()
110+
});

0 commit comments

Comments
 (0)