From 3f4792a39b7d456342f3e2a9fca9992820820940 Mon Sep 17 00:00:00 2001 From: Ilia Denisov Date: Fri, 3 Jul 2026 10:04:54 +0200 Subject: [PATCH] =?UTF-8?q?test(e2e):=20sign-in=20methods=20matrix=20?= =?UTF-8?q?=E2=80=94=20change-email=20+=20link/unlink=20Telegram?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the stale skipped linking specs: change-email refuses a taken address with the non-disclosing message (never revealing the other account) and replaces a free one; the web Telegram link control links then unlinks through the confirm dialog. Chromium + WebKit. --- ui/e2e/social.spec.ts | 56 ++++++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 16 deletions(-) diff --git a/ui/e2e/social.spec.ts b/ui/e2e/social.spec.ts index 1562d9a..69be846 100644 --- a/ui/e2e/social.spec.ts +++ b/ui/e2e/social.spec.ts @@ -292,32 +292,56 @@ test('profile edit disables Save and flags an invalid display name', async ({ pa await expect(save).toBeEnabled(); }); -// The email upgrade box is now shown to guests (email bind + the merge dialog). These specs -// still assume a non-guest login and the visible Telegram control, so they stay skipped until -// PR2 re-enables provider linking and adds a guest-login setup. -test.skip('link account: a taken email opens the irreversible merge confirmation', async ({ page }) => { +// The profile's sign-in-methods matrix (email add/change + provider link/unlink). The mock +// profile is a durable account already holding an email, so the email control is the change +// flow; a new address containing "taken" stands in (in the mock) for one owned by another +// account, driving the non-disclosing refusal. +test('change email: a taken address is refused without disclosure', async ({ page }) => { await loginLobby(page); await openProfile(page); - // The email box is shown to guests (this spec needs a guest login — re-enabled in PR2). - await expect(page.getByRole('heading', { name: 'Link an account' })).toBeVisible(); - // An address containing "merge" stands in (in the mock) for one already owned by - // another account, so the confirm step reveals a required merge. - await page.locator('.emailbox input[type="email"]').fill('merge@example.com'); + await expect(page.getByText('you@example.com')).toBeVisible(); + await page.getByRole('button', { name: 'Change' }).click(); + await page.getByPlaceholder('New email address').fill('taken@example.com'); await page.getByRole('button', { name: 'Send code' }).click(); - await page.locator('.emailbox .codein').fill('123456'); + await page.locator('.accounts .codein').fill('123456'); await page.getByRole('button', { name: 'OK' }).click(); - // The reveal happens only after the code, and names the other account. - await expect(page.getByText('Merge accounts?')).toBeVisible(); - await expect(page.getByText(/Ann/)).toBeVisible(); - await page.getByRole('button', { name: 'Merge' }).click(); - await expect(page.getByText('Merge accounts?')).toBeHidden(); + // The neutral message never reveals the other account. + await expect(page.getByText('Check the address or contact support.')).toBeVisible(); + await expect(page.getByText(/belongs to another account/)).toHaveCount(0); + await expect(page.getByText('you@example.com')).toBeVisible(); }); -test.skip('link account: the Telegram web sign-in control is offered in a browser', async ({ page }) => { +test('change email: a free address replaces the current one', async ({ page }) => { await loginLobby(page); await openProfile(page); + + await page.getByRole('button', { name: 'Change' }).click(); + await page.getByPlaceholder('New email address').fill('fresh@example.com'); + await page.getByRole('button', { name: 'Send code' }).click(); + await page.locator('.accounts .codein').fill('123456'); + await page.getByRole('button', { name: 'OK' }).click(); + + await expect(page.getByText('fresh@example.com')).toBeVisible(); + await expect(page.getByText('you@example.com')).toHaveCount(0); +}); + +test('link then unlink Telegram from the sign-in methods', async ({ page }) => { + await loginLobby(page); + await openProfile(page); + + // On the web the Telegram login-widget control is offered; the mock links it instantly. + await page.getByRole('button', { name: 'Link Telegram' }).click(); + const tgRow = page.locator('.acctrow').filter({ hasText: 'Telegram' }); + await expect(tgRow).toBeVisible(); + + // With email + Telegram two methods remain, so Unlink is offered; confirm it in the dialog. + await tgRow.getByRole('button', { name: 'Unlink' }).click(); + await expect(page.getByText('Unlink account?')).toBeVisible(); + await page.getByRole('dialog').getByRole('button', { name: 'Unlink' }).click(); + + await expect(page.locator('.acctrow').filter({ hasText: 'Telegram' })).toHaveCount(0); await expect(page.getByRole('button', { name: 'Link Telegram' })).toBeVisible(); });