Skip to content

Commit 850c1a5

Browse files
authored
e2e test: Check key backup with js-sdk api instead of relying of Security & Privacy tab (#29066)
* test(e2e): `checkDeviceIsConnectedKeyBackup` is checking the key backup with the matrix client and the crypto api instead of relying of the `Security & Privacy` tab. * test(e2e): renaming and improve documentation
1 parent ec4ae9e commit 850c1a5

File tree

3 files changed

+51
-31
lines changed

3 files changed

+51
-31
lines changed

playwright/e2e/crypto/device-verification.spec.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ test.describe("Device verification", { tag: "@no-webkit" }, () => {
6868

6969
// Check that the current device is connected to key backup
7070
// For now we don't check that the backup key is in cache because it's a bit flaky,
71-
// as we need to wait for the secret gossiping to happen and the settings dialog doesn't refresh automatically.
72-
await checkDeviceIsConnectedKeyBackup(page, expectedBackupVersion, false);
71+
// as we need to wait for the secret gossiping to happen.
72+
await checkDeviceIsConnectedKeyBackup(app, expectedBackupVersion, false);
7373
});
7474

7575
test("Verify device with QR code during login", async ({ page, app, credentials, homeserver }) => {
@@ -112,9 +112,7 @@ test.describe("Device verification", { tag: "@no-webkit" }, () => {
112112
await checkDeviceIsCrossSigned(app);
113113

114114
// Check that the current device is connected to key backup
115-
// For now we don't check that the backup key is in cache because it's a bit flaky,
116-
// as we need to wait for the secret gossiping to happen and the settings dialog doesn't refresh automatically.
117-
await checkDeviceIsConnectedKeyBackup(page, expectedBackupVersion, false);
115+
await checkDeviceIsConnectedKeyBackup(app, expectedBackupVersion, true);
118116
});
119117

120118
test("Verify device with Security Phrase during login", async ({ page, app, credentials, homeserver }) => {
@@ -135,7 +133,7 @@ test.describe("Device verification", { tag: "@no-webkit" }, () => {
135133

136134
// Check that the current device is connected to key backup
137135
// The backup decryption key should be in cache also, as we got it directly from the 4S
138-
await checkDeviceIsConnectedKeyBackup(page, expectedBackupVersion, true);
136+
await checkDeviceIsConnectedKeyBackup(app, expectedBackupVersion, true);
139137
});
140138

141139
test("Verify device with Security Key during login", async ({ page, app, credentials, homeserver }) => {
@@ -158,7 +156,7 @@ test.describe("Device verification", { tag: "@no-webkit" }, () => {
158156

159157
// Check that the current device is connected to key backup
160158
// The backup decryption key should be in cache also, as we got it directly from the 4S
161-
await checkDeviceIsConnectedKeyBackup(page, expectedBackupVersion, true);
159+
await checkDeviceIsConnectedKeyBackup(app, expectedBackupVersion, true);
162160
});
163161

164162
test("Handle incoming verification request with SAS", async ({ page, credentials, homeserver, toasts }) => {

playwright/e2e/crypto/utils.ts

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -139,14 +139,14 @@ export async function checkDeviceIsCrossSigned(app: ElementAppPage): Promise<voi
139139
* Check that the current device is connected to the expected key backup.
140140
* Also checks that the decryption key is known and cached locally.
141141
*
142-
* @param page - the page to check
142+
* @param app -` ElementAppPage` wrapper for the playwright `Page`.
143143
* @param expectedBackupVersion - the version of the backup we expect to be connected to.
144-
* @param checkBackupKeyInCache - whether to check that the backup key is cached locally.
144+
* @param checkBackupPrivateKeyInCache - whether to check that the backup decryption key is cached locally
145145
*/
146146
export async function checkDeviceIsConnectedKeyBackup(
147-
page: Page,
147+
app: ElementAppPage,
148148
expectedBackupVersion: string,
149-
checkBackupKeyInCache: boolean,
149+
checkBackupPrivateKeyInCache: boolean,
150150
): Promise<void> {
151151
// Sanity check the given backup version: if it's null, something went wrong earlier in the test.
152152
if (!expectedBackupVersion) {
@@ -155,23 +155,48 @@ export async function checkDeviceIsConnectedKeyBackup(
155155
);
156156
}
157157

158-
await page.getByRole("button", { name: "User menu" }).click();
159-
await page.locator(".mx_UserMenu_contextMenu").getByRole("menuitem", { name: "Security & Privacy" }).click();
160-
await expect(page.locator(".mx_Dialog").getByRole("button", { name: "Restore from Backup" })).toBeVisible();
161-
162-
// expand the advanced section to see the active version in the reports
163-
await page.locator(".mx_SecureBackupPanel_advanced").locator("..").click();
158+
const backupData = await app.client.evaluate(async (client: MatrixClient) => {
159+
const crypto = client.getCrypto();
160+
if (!crypto) return;
161+
162+
const backupInfo = await crypto.getKeyBackupInfo();
163+
const backupKeyIn4S = Boolean(await client.isKeyBackupKeyStored());
164+
const backupPrivateKeyFromCache = await crypto.getSessionBackupPrivateKey();
165+
const hasBackupPrivateKeyFromCache = Boolean(backupPrivateKeyFromCache);
166+
const backupPrivateKeyWellFormed = backupPrivateKeyFromCache instanceof Uint8Array;
167+
const activeBackupVersion = await crypto.getActiveSessionBackupVersion();
168+
169+
return {
170+
backupInfo,
171+
hasBackupPrivateKeyFromCache,
172+
backupPrivateKeyWellFormed,
173+
backupKeyIn4S,
174+
activeBackupVersion,
175+
};
176+
});
164177

165-
if (checkBackupKeyInCache) {
166-
const cacheDecryptionKeyStatusElement = page.locator(".mx_SecureBackupPanel_statusList tr:nth-child(2) td");
167-
await expect(cacheDecryptionKeyStatusElement).toHaveText("cached locally, well formed");
178+
if (!backupData) {
179+
throw new Error("Crypto module is not available");
168180
}
169181

170-
await expect(page.locator(".mx_SecureBackupPanel_statusList tr:nth-child(5) td")).toHaveText(
171-
expectedBackupVersion + " (Algorithm: m.megolm_backup.v1.curve25519-aes-sha2)",
172-
);
173-
174-
await expect(page.locator(".mx_SecureBackupPanel_statusList tr:nth-child(6) td")).toHaveText(expectedBackupVersion);
182+
const { backupInfo, backupKeyIn4S, hasBackupPrivateKeyFromCache, backupPrivateKeyWellFormed, activeBackupVersion } =
183+
backupData;
184+
185+
// We have a key backup
186+
expect(backupInfo).toBeDefined();
187+
// The key backup version is as expected
188+
expect(backupInfo.version).toBe(expectedBackupVersion);
189+
// The active backup version is as expected
190+
expect(activeBackupVersion).toBe(expectedBackupVersion);
191+
// The backup key is stored in 4S
192+
expect(backupKeyIn4S).toBe(true);
193+
194+
if (checkBackupPrivateKeyInCache) {
195+
// The backup key is available locally
196+
expect(hasBackupPrivateKeyFromCache).toBe(true);
197+
// The backup key is well-formed
198+
expect(backupPrivateKeyWellFormed).toBe(true);
199+
}
175200
}
176201

177202
/**

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

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,7 @@ test.describe("Recovery section in Encryption tab", () => {
5151

5252
// Check that the current device is connected to key backup
5353
// The backup decryption key should be in cache also, as we got it directly from the 4S
54-
await app.closeDialog();
55-
await checkDeviceIsConnectedKeyBackup(page, expectedBackupVersion, true);
54+
await checkDeviceIsConnectedKeyBackup(app, expectedBackupVersion, true);
5655
});
5756

5857
test(
@@ -119,9 +118,8 @@ test.describe("Recovery section in Encryption tab", () => {
119118
// The recovery key is now set up and the user can change it
120119
await expect(dialog.getByRole("button", { name: "Change recovery key" })).toBeVisible();
121120

122-
await app.closeDialog();
123121
// Check that the current device is connected to key backup and the backup version is the expected one
124-
await checkDeviceIsConnectedKeyBackup(page, "1", true);
122+
await checkDeviceIsConnectedKeyBackup(app, "1", true);
125123
});
126124

127125
// Test what happens if the cross-signing secrets are in secret storage but are not cached in the local DB.
@@ -153,8 +151,7 @@ test.describe("Recovery section in Encryption tab", () => {
153151

154152
// Check that the current device is connected to key backup
155153
// The backup decryption key should be in cache also, as we got it directly from the 4S
156-
await app.closeDialog();
157-
await checkDeviceIsConnectedKeyBackup(page, expectedBackupVersion, true);
154+
await checkDeviceIsConnectedKeyBackup(app, expectedBackupVersion, true);
158155
},
159156
);
160157
});

0 commit comments

Comments
 (0)