1
0
mirror of https://github.com/element-hq/element-web.git synced 2025-08-08 03:42:14 +03:00

e2e test: by default the bot should not use a passphrase to create the recovery key (#29214)

* test(crypto): by default do not use a passphrase to create the recovery key

* test(crypto): update tests
This commit is contained in:
Florian D
2025-02-07 10:39:36 +01:00
committed by GitHub
parent 4a231c6450
commit 7b3ce5d9b2
7 changed files with 21 additions and 14 deletions

View File

@@ -29,7 +29,7 @@ test.describe("Device verification", { tag: "@no-webkit" }, () => {
let expectedBackupVersion: string; let expectedBackupVersion: string;
test.beforeEach(async ({ page, homeserver, credentials }) => { test.beforeEach(async ({ page, homeserver, credentials }) => {
const res = await createBot(page, homeserver, credentials); const res = await createBot(page, homeserver, credentials, true);
aliceBotClient = res.botClient; aliceBotClient = res.botClient;
expectedBackupVersion = res.expectedBackupVersion; expectedBackupVersion = res.expectedBackupVersion;
}); });

View File

@@ -34,7 +34,6 @@ test.describe("Key storage out of sync toast", () => {
await expect(page.getByRole("alert").first()).toMatchScreenshot("key-storage-out-of-sync-toast.png"); await expect(page.getByRole("alert").first()).toMatchScreenshot("key-storage-out-of-sync-toast.png");
await page.getByRole("button", { name: "Enter recovery key" }).click(); await page.getByRole("button", { name: "Enter recovery key" }).click();
await page.locator(".mx_Dialog").getByRole("button", { name: "use your Security Key" }).click();
await page.getByRole("textbox", { name: "Security key" }).fill(recoveryKey.encodedPrivateKey); await page.getByRole("textbox", { name: "Security key" }).fill(recoveryKey.encodedPrivateKey);
await page.getByRole("button", { name: "Continue" }).click(); await page.getByRole("button", { name: "Continue" }).click();

View File

@@ -28,11 +28,13 @@ import { Bot } from "../../pages/bot";
* @param page - the playwright `page` fixture * @param page - the playwright `page` fixture
* @param homeserver - the homeserver to use * @param homeserver - the homeserver to use
* @param credentials - the credentials to use for the bot client * @param credentials - the credentials to use for the bot client
* @param usePassphrase - whether to use a passphrase when creating the recovery key
*/ */
export async function createBot( export async function createBot(
page: Page, page: Page,
homeserver: HomeserverInstance, homeserver: HomeserverInstance,
credentials: Credentials, credentials: Credentials,
usePassphrase = false,
): Promise<{ botClient: Bot; recoveryKey: GeneratedSecretStorageKey; expectedBackupVersion: string }> { ): Promise<{ botClient: Bot; recoveryKey: GeneratedSecretStorageKey; expectedBackupVersion: string }> {
// Visit the login page of the app, to load the matrix sdk // Visit the login page of the app, to load the matrix sdk
await page.goto("/#/login"); await page.goto("/#/login");
@@ -44,6 +46,7 @@ export async function createBot(
const botClient = new Bot(page, homeserver, { const botClient = new Bot(page, homeserver, {
bootstrapCrossSigning: true, bootstrapCrossSigning: true,
bootstrapSecretStorage: true, bootstrapSecretStorage: true,
usePassphrase,
}); });
botClient.setCredentials(credentials); botClient.setCredentials(credentials);
// Backup is prepared in the background. Poll until it is ready. // Backup is prepared in the background. Poll until it is ready.

View File

@@ -67,7 +67,7 @@ test.describe("Encryption tab", () => {
"should prompt to enter the recovery key when the secrets are not cached locally", "should prompt to enter the recovery key when the secrets are not cached locally",
{ tag: "@screenshot" }, { tag: "@screenshot" },
async ({ page, app, util }) => { async ({ page, app, util }) => {
await verifySession(app, "new passphrase"); await verifySession(app, recoveryKey.encodedPrivateKey);
// We need to delete the cached secrets // We need to delete the cached secrets
await deleteCachedSecrets(page); await deleteCachedSecrets(page);
@@ -99,7 +99,7 @@ test.describe("Encryption tab", () => {
app, app,
util, util,
}) => { }) => {
await verifySession(app, "new passphrase"); await verifySession(app, recoveryKey.encodedPrivateKey);
// We need to delete the cached secrets // We need to delete the cached secrets
await deleteCachedSecrets(page); await deleteCachedSecrets(page);

View File

@@ -43,7 +43,7 @@ class Helpers {
*/ */
async verifyDevice(recoveryKey: GeneratedSecretStorageKey) { async verifyDevice(recoveryKey: GeneratedSecretStorageKey) {
// Select the security phrase // Select the security phrase
await this.page.getByRole("button", { name: "Verify with Security Key or Phrase" }).click(); await this.page.getByRole("button", { name: "Verify with Security Key" }).click();
await this.enterRecoveryKey(recoveryKey); await this.enterRecoveryKey(recoveryKey);
await this.page.getByRole("button", { name: "Done" }).click(); await this.page.getByRole("button", { name: "Done" }).click();
} }
@@ -53,9 +53,6 @@ class Helpers {
* @param recoveryKey * @param recoveryKey
*/ */
async enterRecoveryKey(recoveryKey: GeneratedSecretStorageKey) { async enterRecoveryKey(recoveryKey: GeneratedSecretStorageKey) {
// Select to use recovery key
await this.page.getByRole("button", { name: "use your Security Key" }).click();
// Fill the recovery key // Fill the recovery key
const dialog = this.page.locator(".mx_Dialog"); const dialog = this.page.locator(".mx_Dialog");
await dialog.getByRole("textbox").fill(recoveryKey.encodedPrivateKey); await dialog.getByRole("textbox").fill(recoveryKey.encodedPrivateKey);

View File

@@ -7,22 +7,25 @@
import { test, expect } from "."; import { test, expect } from ".";
import { checkDeviceIsConnectedKeyBackup, createBot, verifySession } from "../../crypto/utils"; import { checkDeviceIsConnectedKeyBackup, createBot, verifySession } from "../../crypto/utils";
import type { GeneratedSecretStorageKey } from "matrix-js-sdk/src/crypto-api";
test.describe("Recovery section in Encryption tab", () => { test.describe("Recovery section in Encryption tab", () => {
test.use({ test.use({
displayName: "Alice", displayName: "Alice",
}); });
let recoveryKey: GeneratedSecretStorageKey;
test.beforeEach(async ({ page, homeserver, credentials }) => { test.beforeEach(async ({ page, homeserver, credentials }) => {
// The bot bootstraps cross-signing, creates a key backup and sets up a recovery key // The bot bootstraps cross-signing, creates a key backup and sets up a recovery key
await createBot(page, homeserver, credentials); const res = await createBot(page, homeserver, credentials);
recoveryKey = res.recoveryKey;
}); });
test( test(
"should change the recovery key", "should change the recovery key",
{ tag: ["@screenshot", "@no-webkit"] }, { tag: ["@screenshot", "@no-webkit"] },
async ({ page, app, homeserver, credentials, util, context }) => { async ({ page, app, homeserver, credentials, util, context }) => {
await verifySession(app, "new passphrase"); await verifySession(app, recoveryKey.encodedPrivateKey);
const dialog = await util.openEncryptionTab(); const dialog = await util.openEncryptionTab();
// The user can only change the recovery key // The user can only change the recovery key
@@ -49,7 +52,7 @@ test.describe("Recovery section in Encryption tab", () => {
); );
test("should setup the recovery key", { tag: ["@screenshot", "@no-webkit"] }, async ({ page, app, util }) => { test("should setup the recovery key", { tag: ["@screenshot", "@no-webkit"] }, async ({ page, app, util }) => {
await verifySession(app, "new passphrase"); await verifySession(app, recoveryKey.encodedPrivateKey);
await util.removeSecretStorageDefaultKeyId(); await util.removeSecretStorageDefaultKeyId();
// The key backup is deleted and the user needs to set it up // The key backup is deleted and the user needs to set it up

View File

@@ -41,6 +41,10 @@ export interface CreateBotOpts {
* Whether to bootstrap the secret storage * Whether to bootstrap the secret storage
*/ */
bootstrapSecretStorage?: boolean; bootstrapSecretStorage?: boolean;
/**
* Whether to use a passphrase when creating the recovery key
*/
usePassphrase?: boolean;
} }
const defaultCreateBotOptions = { const defaultCreateBotOptions = {
@@ -48,6 +52,7 @@ const defaultCreateBotOptions = {
autoAcceptInvites: true, autoAcceptInvites: true,
startClient: true, startClient: true,
bootstrapCrossSigning: true, bootstrapCrossSigning: true,
usePassphrase: false,
} satisfies CreateBotOpts; } satisfies CreateBotOpts;
type ExtendedMatrixClient = MatrixClient & { __playwright_recovery_key: GeneratedSecretStorageKey }; type ExtendedMatrixClient = MatrixClient & { __playwright_recovery_key: GeneratedSecretStorageKey };
@@ -206,8 +211,8 @@ export class Bot extends Client {
} }
if (this.opts.bootstrapSecretStorage) { if (this.opts.bootstrapSecretStorage) {
await clientHandle.evaluate(async (cli) => { await clientHandle.evaluate(async (cli, usePassphrase) => {
const passphrase = "new passphrase"; const passphrase = usePassphrase ? "new passphrase" : undefined;
const recoveryKey = await cli.getCrypto().createRecoveryKeyFromPassphrase(passphrase); const recoveryKey = await cli.getCrypto().createRecoveryKeyFromPassphrase(passphrase);
Object.assign(cli, { __playwright_recovery_key: recoveryKey }); Object.assign(cli, { __playwright_recovery_key: recoveryKey });
@@ -216,7 +221,7 @@ export class Bot extends Client {
setupNewKeyBackup: true, setupNewKeyBackup: true,
createSecretStorageKey: () => Promise.resolve(recoveryKey), createSecretStorageKey: () => Promise.resolve(recoveryKey),
}); });
}); }, this.opts.usePassphrase);
} }
return clientHandle; return clientHandle;