element-web/playwright/e2e/settings/encryption-user-tab/recovery.spec.ts

141 lines
6.1 KiB
TypeScript

/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
* Please see LICENSE files in the repository root for full details.
*/
import { GeneratedSecretStorageKey } from "matrix-js-sdk/src/crypto-api";
import { test, expect } from ".";
import {
checkDeviceIsConnectedKeyBackup,
checkDeviceIsCrossSigned,
createBot,
verifySession,
} from "../../crypto/utils";
test.describe("Recovery section in Encryption tab", () => {
test.use({
displayName: "Alice",
});
let recoveryKey: GeneratedSecretStorageKey;
let expectedBackupVersion: string;
test.beforeEach(async ({ page, homeserver, credentials }) => {
const res = await createBot(page, homeserver, credentials);
recoveryKey = res.recoveryKey;
expectedBackupVersion = res.expectedBackupVersion;
});
test("should verify the device", { tag: "@screenshot" }, async ({ page, app, util }) => {
const dialog = await util.openEncryptionTab();
// The user's device is in an unverified state, therefore the only option available to them here is to verify it
const verifyButton = dialog.getByRole("button", { name: "Verify this device" });
await expect(verifyButton).toBeVisible();
await expect(util.getEncryptionTabContent()).toMatchScreenshot("verify-device-encryption-tab.png");
await verifyButton.click();
await util.verifyDevice(recoveryKey);
await expect(util.getEncryptionTabContent()).toMatchScreenshot("default-recovery.png");
// Check that our device is now cross-signed
await checkDeviceIsCrossSigned(app);
// Check that the current device is connected to key backup
// The backup decryption key should be in cache also, as we got it directly from the 4S
await app.closeDialog();
await checkDeviceIsConnectedKeyBackup(page, expectedBackupVersion, true);
});
test(
"should change the recovery key",
{ tag: "@screenshot" },
async ({ page, app, homeserver, credentials, util, context }) => {
await verifySession(app, "new passphrase");
const dialog = await util.openEncryptionTab();
// The user can only change the recovery key
const changeButton = dialog.getByRole("button", { name: "Change recovery key" });
await expect(changeButton).toBeVisible();
await expect(util.getEncryptionTabContent()).toMatchScreenshot("default-recovery.png");
await changeButton.click();
// Display the new recovery key and click on the copy button
await expect(dialog.getByText("Change recovery key?")).toBeVisible();
await expect(util.getEncryptionTabContent()).toMatchScreenshot("change-key-1-encryption-tab.png", {
mask: [dialog.getByTestId("recoveryKey")],
});
await dialog.getByRole("button", { name: "Copy" }).click();
await dialog.getByRole("button", { name: "Continue" }).click();
// Confirm the recovery key
await util.confirmRecoveryKey("change-key-2-encryption-tab.png");
},
);
test("should setup the recovery key", { tag: "@screenshot" }, async ({ page, app, util }) => {
await verifySession(app, "new passphrase");
await util.deleteKeyBackup(expectedBackupVersion);
// The key backup is deleted and the user needs to set up it
const dialog = await util.openEncryptionTab();
const setupButton = dialog.getByRole("button", { name: "Set up recovery" });
await expect(setupButton).toBeVisible();
await expect(util.getEncryptionTabContent()).toMatchScreenshot("set-up-recovery.png");
await setupButton.click();
// Display an informative panel about the recovery key
await expect(dialog.getByRole("heading", { name: "Set up recovery" })).toBeVisible();
await expect(util.getEncryptionTabContent()).toMatchScreenshot("set-up-key-1-encryption-tab.png");
await dialog.getByRole("button", { name: "Continue" }).click();
// Display the new recovery key and click on the copy button
await expect(dialog.getByText("Save your recovery key somewhere safe")).toBeVisible();
await expect(util.getEncryptionTabContent()).toMatchScreenshot("set-up-key-2-encryption-tab.png", {
mask: [dialog.getByTestId("recoveryKey")],
});
await dialog.getByRole("button", { name: "Copy" }).click();
await dialog.getByRole("button", { name: "Continue" }).click();
// Confirm the recovery key
await util.confirmRecoveryKey("set-up-key-3-encryption-tab.png");
await app.closeDialog();
// Check that the current device is connected to key backup and the backup version is the expected one
await checkDeviceIsConnectedKeyBackup(page, "2", true);
});
test(
"should enter the recovery key when the secrets are not cached",
{ tag: "@screenshot" },
async ({ page, app, util }) => {
await verifySession(app, "new passphrase");
// We need to delete the cached secrets
await util.deleteCachedSecrets();
await util.openEncryptionTab();
// We ask the user to enter the recovery key
const dialog = util.getEncryptionTabContent();
const enterKeyButton = dialog.getByRole("button", { name: "Enter recovery key" });
await expect(enterKeyButton).toBeVisible();
await expect(dialog).toMatchScreenshot("out-of-sync-recovery.png");
await enterKeyButton.click();
// Fill the recovery key
await util.enterRecoveryKey(recoveryKey);
await expect(dialog).toMatchScreenshot("default-recovery.png");
// Check that our device is now cross-signed
await checkDeviceIsCrossSigned(app);
// Check that the current device is connected to key backup
// The backup decryption key should be in cache also, as we got it directly from the 4S
await app.closeDialog();
await checkDeviceIsConnectedKeyBackup(page, expectedBackupVersion, true);
},
);
});