Skip to content

Commit ff25f28

Browse files
committed
test(e2e): add sequential multi-signer signature request test
Upload PDF, add two email signers, enable 'Sign in order' switch, send the request and verify via mailpit that only signer01 receives an email immediately (signer02 is still in Draft). Then signer01 signs via the email link and the test verifies that signer02 now receives their notification, confirming sequential mode. Signed-off-by: Vitor Mattos <[email protected]>
1 parent 7773f28 commit ff25f28

1 file changed

Lines changed: 91 additions & 0 deletions

File tree

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
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+
import { createMailpitClient, waitForEmailTo, extractSignLink } from '../support/mailpit'
10+
11+
test('request signatures from two signers in sequential order', async ({ page }) => {
12+
await login(
13+
page.request,
14+
process.env.NEXTCLOUD_ADMIN_USER ?? 'admin',
15+
process.env.NEXTCLOUD_ADMIN_PASSWORD ?? 'admin',
16+
)
17+
18+
await configureOpenSsl(page.request, 'LibreSign Test', {
19+
C: 'BR',
20+
OU: ['Organization Unit'],
21+
ST: 'Rio de Janeiro',
22+
O: 'LibreSign',
23+
L: 'Rio de Janeiro',
24+
})
25+
26+
await setAppConfig(
27+
page.request,
28+
'libresign',
29+
'identify_methods',
30+
JSON.stringify([
31+
{ name: 'account', enabled: false, mandatory: false },
32+
{ name: 'email', enabled: true, mandatory: true, signatureMethods: { clickToSign: { enabled: true } }, can_create_account: false },
33+
]),
34+
)
35+
36+
const mailpit = createMailpitClient()
37+
await mailpit.deleteMessages()
38+
39+
await page.goto('./apps/libresign')
40+
await page.getByRole('button', { name: 'Upload from URL' }).click()
41+
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')
42+
await page.getByRole('button', { name: 'Send' }).click()
43+
44+
// Add first signer via email tab
45+
await page.getByRole('button', { name: 'Add signer' }).click()
46+
await page.getByRole('tab', { name: 'Email' }).click()
47+
await page.getByPlaceholder('Email').fill('[email protected]')
48+
await page.getByRole('option', { name: '[email protected]' }).click()
49+
await page.getByRole('textbox', { name: 'Signer name' }).fill('Signer 01')
50+
await page.getByRole('button', { name: 'Save' }).click()
51+
52+
// Add second signer via email tab
53+
await page.getByRole('button', { name: 'Add signer' }).click()
54+
await page.getByRole('tab', { name: 'Email' }).click()
55+
await page.getByPlaceholder('Email').fill('[email protected]')
56+
await page.getByRole('option', { name: '[email protected]' }).click()
57+
await page.getByRole('textbox', { name: 'Signer name' }).fill('Signer 02')
58+
await page.getByRole('button', { name: 'Save' }).click()
59+
60+
// Enable sequential signing — the switch must be accessible by role="switch"
61+
const signInOrderSwitch = page.getByRole('switch', { name: 'Sign in order' })
62+
await expect(signInOrderSwitch).toBeVisible()
63+
await signInOrderSwitch.click()
64+
await expect(signInOrderSwitch).toBeChecked()
65+
66+
// Send the signature request
67+
await page.getByRole('button', { name: 'Request signatures' }).click()
68+
await page.getByRole('button', { name: 'Send' }).click()
69+
70+
// In sequential mode only signer01 (order 1) gets the email immediately.
71+
// Proof: signer01's email arrives, but signer02's does NOT at this point.
72+
const email01 = await waitForEmailTo(mailpit, '[email protected]', 'LibreSign: There is a file for you to sign')
73+
74+
const afterFirst = await mailpit.searchMessages({ query: 'subject:"LibreSign: There is a file for you to sign"' })
75+
expect(afterFirst.messages).toHaveLength(1)
76+
77+
// Signer01 signs via the link received in the email
78+
const signLink = extractSignLink(email01.Text)
79+
if (!signLink) throw new Error('Sign link not found in email')
80+
await page.goto(signLink)
81+
await page.getByRole('button', { name: 'Sign the document.' }).click()
82+
await page.getByRole('button', { name: 'Sign document' }).click()
83+
await page.waitForURL('**/validation/**')
84+
await expect(page.getByText('This document is valid')).toBeVisible()
85+
86+
// Now that signer01 has signed, signer02 must receive their notification.
87+
await waitForEmailTo(mailpit, '[email protected]', 'LibreSign: There is a file for you to sign')
88+
89+
const afterSecond = await mailpit.searchMessages({ query: 'subject:"LibreSign: There is a file for you to sign"' })
90+
expect(afterSecond.messages).toHaveLength(2)
91+
})

0 commit comments

Comments
 (0)