141 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			TypeScript
		
	
	
			
		
		
	
	
			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 it up
 | |
|         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);
 | |
|         },
 | |
|     );
 | |
| });
 |