From 62a287219dbbdbcbc48a2c2a039a48714190022f Mon Sep 17 00:00:00 2001 From: Hubert Chathi Date: Tue, 25 Feb 2025 08:46:57 -0500 Subject: [PATCH] add test to ensure that dehydrated device gets removed on identity reset (#29354) --- playwright/e2e/crypto/dehydration.spec.ts | 47 +++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/playwright/e2e/crypto/dehydration.spec.ts b/playwright/e2e/crypto/dehydration.spec.ts index 472ee39493..35b5fae1ad 100644 --- a/playwright/e2e/crypto/dehydration.spec.ts +++ b/playwright/e2e/crypto/dehydration.spec.ts @@ -116,6 +116,40 @@ test.describe("Dehydration", () => { expect(dehydratedDeviceIds.length).toBe(1); expect(dehydratedDeviceIds[0]).not.toEqual(initialDehydratedDeviceIds[0]); }); + + test("'Reset cryptographic identity' removes dehydrated device", async ({ page, homeserver, app, credentials }) => { + await logIntoElement(page, credentials); + + // Create a dehydrated device by setting up recovery (see "'Set up + // recovery' creates dehydrated device" test above) + const settingsDialogLocator = await app.settings.openUserSettings("Encryption"); + await settingsDialogLocator.getByRole("button", { name: "Set up recovery" }).click(); + + // First it displays an informative panel about the recovery key + await expect(settingsDialogLocator.getByRole("heading", { name: "Set up recovery" })).toBeVisible(); + await settingsDialogLocator.getByRole("button", { name: "Continue" }).click(); + + // Next, it displays the new recovery key. We click on the copy button. + await expect(settingsDialogLocator.getByText("Save your recovery key somewhere safe")).toBeVisible(); + await settingsDialogLocator.getByRole("button", { name: "Copy" }).click(); + const recoveryKey = await app.getClipboard(); + await settingsDialogLocator.getByRole("button", { name: "Continue" }).click(); + + await expect( + settingsDialogLocator.getByText("Enter your recovery key to confirm", { exact: true }), + ).toBeVisible(); + await settingsDialogLocator.getByRole("textbox").fill(recoveryKey); + await settingsDialogLocator.getByRole("button", { name: "Finish set up" }).click(); + + await expectDehydratedDeviceEnabled(app); + + // After recovery is set up, we reset our cryptographic identity, which + // should drop the dehydrated device. + await settingsDialogLocator.getByRole("button", { name: "Reset cryptographic identity" }).click(); + await settingsDialogLocator.getByRole("button", { name: "Continue" }).click(); + + await expectDehydratedDeviceDisabled(app); + }); }); async function getDehydratedDeviceIds(client: Client): Promise { @@ -144,3 +178,16 @@ async function expectDehydratedDeviceEnabled(app: ElementAppPage): Promise }) .toEqual(1); } + +/** Wait for our user to not have a dehydrated device */ +async function expectDehydratedDeviceDisabled(app: ElementAppPage): Promise { + // It might be nice to do this via the UI, but currently this info is not exposed via the UI. + // + // Note we might have to wait for the device list to be refreshed, so we wrap in `expect.poll`. + await expect + .poll(async () => { + const dehydratedDeviceIds = await getDehydratedDeviceIds(app.client); + return dehydratedDeviceIds.length; + }) + .toEqual(0); +}