Skip to content

Commit 8a98ba9

Browse files
test(e2e): sign document with email token as authenticated signer
When the signer's email matches the authenticated user's Nextcloud account email, LibreSign must allow the sign flow to proceed normally through the email+token identify method. The test logs in as admin (admin@email.tld), creates an email-only sign request using that same address, stays logged in, follows the sign link from the notification email, submits the token received in the email, and signs with click-to-sign — asserting the document reaches the signed state. Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
1 parent 50b6dda commit 8a98ba9

1 file changed

Lines changed: 94 additions & 0 deletions

File tree

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/**
2+
* SPDX-FileCopyrightText: 2026 LibreCode coop and contributors
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
6+
import { test, expect } from '@playwright/test'
7+
import { login } from '../support/nc-login'
8+
import { configureOpenSsl, setAppConfig } from '../support/nc-provisioning'
9+
import { createMailpitClient, waitForEmailTo, extractSignLink, extractTokenFromEmail } from '../support/mailpit'
10+
11+
/**
12+
* An authenticated Nextcloud user can sign a document via the email+token
13+
* identify method when the signer's email matches their Nextcloud account email.
14+
*
15+
* The admin's Nextcloud account email is admin@email.tld. This test adds that
16+
* same email as the signer's email, keeps the admin logged in, and verifies the
17+
* full email-token flow succeeds (the backend allows it because the session
18+
* email matches the signer email in throwIfIsAuthenticatedWithDifferentAccount).
19+
*/
20+
test('sign document with email token as authenticated signer', async ({ page }) => {
21+
await login(
22+
page.request,
23+
process.env.NEXTCLOUD_ADMIN_USER ?? 'admin',
24+
process.env.NEXTCLOUD_ADMIN_PASSWORD ?? 'admin',
25+
)
26+
27+
await configureOpenSsl(page.request, 'LibreSign Test', {
28+
C: 'BR',
29+
OU: ['Organization Unit'],
30+
ST: 'Rio de Janeiro',
31+
O: 'LibreSign',
32+
L: 'Rio de Janeiro',
33+
})
34+
35+
await setAppConfig(
36+
page.request,
37+
'libresign',
38+
'identify_methods',
39+
JSON.stringify([
40+
{ name: 'account', enabled: false, mandatory: false },
41+
{ name: 'email', enabled: true, mandatory: true, signatureMethods: { emailToken: { enabled: true } }, can_create_account: false },
42+
]),
43+
)
44+
45+
const mailpit = createMailpitClient()
46+
await mailpit.deleteMessages()
47+
48+
await page.goto('./apps/libresign')
49+
await page.getByRole('button', { name: 'Upload from URL' }).click()
50+
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')
51+
await page.getByRole('button', { name: 'Send' }).click()
52+
53+
// Add the admin's own email as the signer.
54+
// Only the email method is active so there are no tabs in the Add signer dialog.
55+
await page.getByRole('button', { name: 'Add signer' }).click()
56+
await page.getByPlaceholder('Email').click()
57+
await page.getByPlaceholder('Email').pressSequentially('admin@email.tld', { delay: 50 })
58+
await page.getByRole('option', { name: 'admin@email.tld' }).click()
59+
await page.getByRole('textbox', { name: 'Signer name' }).fill('Admin')
60+
await page.getByRole('button', { name: 'Save' }).click()
61+
62+
await page.getByRole('button', { name: 'Request signatures' }).click()
63+
await page.getByRole('button', { name: 'Send' }).click()
64+
65+
// Get the sign link from the notification email sent to admin@email.tld.
66+
// The admin is intentionally NOT logged out — this tests the authenticated path.
67+
const notificationEmail = await waitForEmailTo(mailpit, 'admin@email.tld', 'LibreSign: There is a file for you to sign')
68+
const signLink = extractSignLink(notificationEmail.Text)
69+
if (!signLink) throw new Error('Sign link not found in notification email')
70+
71+
// Navigate to the sign link while still logged in as admin.
72+
// throwIfIsAuthenticatedWithDifferentAccount allows this because
73+
// admin@email.tld === the signer's email address.
74+
await page.goto(signLink)
75+
await page.getByRole('button', { name: 'Sign the document.' }).click()
76+
77+
// Complete the email token identification flow.
78+
// The email field may be pre-filled with the admin's address; fill() is safe either way.
79+
await page.getByRole('textbox', { name: 'Email' }).fill('admin@email.tld')
80+
await page.getByRole('button', { name: 'Send verification code' }).click()
81+
82+
const tokenEmail = await waitForEmailTo(mailpit, 'admin@email.tld', 'LibreSign: Code to sign file')
83+
const token = extractTokenFromEmail(tokenEmail.Text)
84+
if (!token) throw new Error('Token not found in email')
85+
await page.getByRole('textbox', { name: 'Enter your code' }).fill(token)
86+
await page.getByRole('button', { name: 'Validate code' }).click()
87+
88+
await expect(page.getByRole('heading', { name: 'Signature confirmation' })).toBeVisible()
89+
await expect(page.getByText('Your identity has been')).toBeVisible()
90+
await page.getByRole('button', { name: 'Sign document' }).click()
91+
await page.waitForURL('**/validation/**')
92+
await expect(page.getByText('This document is valid')).toBeVisible()
93+
await expect(page.getByText('Congratulations you have')).toBeVisible()
94+
})

0 commit comments

Comments
 (0)