Show 'Verify this device' toast even if there are no encrypted rooms yet (#32891)

* Show 'Verify this device' toast even if there are no encrypted rooms yet

* Close verify toast in more tests
This commit is contained in:
Andy Balaam
2026-04-24 11:39:59 +00:00
committed by GitHub
parent 6c7c90c15d
commit 76b65b14de
36 changed files with 219 additions and 144 deletions
@@ -85,6 +85,7 @@ test.describe("Encryption tab", () => {
// Fill the recovery key
await util.enterRecoveryKey(recoveryKey);
await dialog.getByRole("heading", { name: "Key storage" }).scrollIntoViewIfNeeded();
await expect(dialog).toMatchScreenshot("default-tab.png", {
mask: [dialog.getByTestId("deviceId"), dialog.getByTestId("sessionKey")],
});
@@ -6,10 +6,13 @@
*/
import { createNewInstance } from "@element-hq/element-web-playwright-common";
import { type StartedHomeserverContainer } from "@element-hq/element-web-playwright-common/lib/testcontainers";
import { type Page, type Browser, type TestInfo } from "@playwright/test";
import { test, expect } from "./index";
import { ElementAppPage } from "../../../pages/ElementAppPage";
import { createRoom, sendMessageInCurrentRoom, verifyApp } from "../../crypto/utils";
import { type CredentialsOptionalAccessToken } from "../../../pages/bot";
test.describe("Other people's devices section in Encryption tab", () => {
test.use({
@@ -23,21 +26,13 @@ test.describe("Other people's devices section in Encryption tab", () => {
browser,
user: aliceCredentials,
}, testInfo) => {
await aliceElementApp.client.bootstrapCrossSigning(aliceCredentials);
await prepForEncryption(aliceElementApp, aliceCredentials);
// Create a second browser instance.
const bobCredentials = await homeserver.registerUser(`user_${testInfo.testId}_bob`, "password", "bob");
const bobPage = await createNewInstance(browser, bobCredentials, {});
const bobElementApp = new ElementAppPage(bobPage);
await bobElementApp.client.bootstrapCrossSigning(bobCredentials);
const { bobCredentials, bobPage } = await newBrowser(homeserver, testInfo, browser);
// Create the room and invite bob
await createRoom(alicePage, "TestRoom", true);
await aliceElementApp.inviteUserToCurrentRoom(bobCredentials.userId, { confirmUnknownUser: true });
// Bob accepts the invite
await bobPage.getByRole("option", { name: "TestRoom" }).click();
await bobPage.getByRole("button", { name: "Accept" }).click();
await inviteBobToNewRoom(alicePage, aliceElementApp, bobCredentials, bobPage);
// Alice sends a message, which Bob should be able to decrypt
await sendMessageInCurrentRoom(alicePage, "Decryptable");
@@ -52,7 +47,7 @@ test.describe("Other people's devices section in Encryption tab", () => {
user: aliceCredentials,
util,
}, testInfo) => {
await aliceElementApp.client.bootstrapCrossSigning(aliceCredentials);
await prepForEncryption(aliceElementApp, aliceCredentials);
// Enable blacklist toggle.
const dialog = await util.openEncryptionTab();
@@ -65,18 +60,10 @@ test.describe("Other people's devices section in Encryption tab", () => {
await aliceElementApp.settings.closeDialog();
// Create a second browser instance.
const bobCredentials = await homeserver.registerUser(`user_${testInfo.testId}_bob`, "password", "bob");
const bobPage = await createNewInstance(browser, bobCredentials, {});
const bobElementApp = new ElementAppPage(bobPage);
await bobElementApp.client.bootstrapCrossSigning(bobCredentials);
const { bobCredentials, bobPage } = await newBrowser(homeserver, testInfo, browser);
// Create the room and invite bob
await createRoom(alicePage, "TestRoom", true);
await aliceElementApp.inviteUserToCurrentRoom(bobCredentials.userId, { confirmUnknownUser: true });
// Bob accepts the invite
await bobPage.getByRole("option", { name: "TestRoom" }).click();
await bobPage.getByRole("button", { name: "Accept" }).click();
await inviteBobToNewRoom(alicePage, aliceElementApp, bobCredentials, bobPage);
// Alice sends a message, which Bob should not be able to decrypt
await sendMessageInCurrentRoom(alicePage, "Undecryptable");
@@ -95,7 +82,7 @@ test.describe("Other people's devices section in Encryption tab", () => {
user: aliceCredentials,
util,
}, testInfo) => {
await aliceElementApp.client.bootstrapCrossSigning(aliceCredentials);
await prepForEncryption(aliceElementApp, aliceCredentials);
// Enable blacklist toggle.
const dialog = await util.openEncryptionTab();
@@ -108,21 +95,11 @@ test.describe("Other people's devices section in Encryption tab", () => {
await aliceElementApp.settings.closeDialog();
// Create a second browser instance.
const bobCredentials = await homeserver.registerUser(`user_${testInfo.testId}_bob`, "password", "bob");
const bobPage = await createNewInstance(browser, bobCredentials, {});
const bobElementApp = new ElementAppPage(bobPage);
await bobElementApp.client.bootstrapCrossSigning(bobCredentials);
const { bobCredentials, bobPage, bobElementApp } = await newBrowser(homeserver, testInfo, browser);
// Create the room and invite bob
await createRoom(alicePage, "TestRoom", true);
await aliceElementApp.inviteUserToCurrentRoom(bobCredentials.userId, { confirmUnknownUser: true });
// Bob accepts the invite and dismisses the warnings.
await bobPage.getByRole("option", { name: "TestRoom" }).click();
await bobPage.getByRole("button", { name: "Accept" }).click();
await bobPage.getByRole("button", { name: "Dismiss" }).click(); // enable notifications
await bobPage.getByRole("button", { name: "Dismiss" }).click(); // enable key storage
await bobPage.getByRole("button", { name: "Yes, dismiss" }).click(); // enable key storage x2
await inviteBobToNewRoom(alicePage, aliceElementApp, bobCredentials, bobPage);
await bobElementApp.closeNotificationToast();
// Perform verification.
await verifyApp("alice", aliceElementApp, "bob", bobElementApp);
@@ -139,21 +116,13 @@ test.describe("Other people's devices section in Encryption tab", () => {
browser,
user: aliceCredentials,
}, testInfo) => {
await aliceElementApp.client.bootstrapCrossSigning(aliceCredentials);
await prepForEncryption(aliceElementApp, aliceCredentials);
// Create a second browser instance.
const bobCredentials = await homeserver.registerUser(`user_${testInfo.testId}_bob`, "password", "bob");
const bobPage = await createNewInstance(browser, bobCredentials, {});
const bobElementApp = new ElementAppPage(bobPage);
await bobElementApp.client.bootstrapCrossSigning(bobCredentials);
const { bobCredentials, bobPage } = await newBrowser(homeserver, testInfo, browser);
// Alice creates the room and invite Bob.
await createRoom(alicePage, "TestRoom", true);
await aliceElementApp.inviteUserToCurrentRoom(bobCredentials.userId, { confirmUnknownUser: true });
// Bob accepts the invite.
await bobPage.getByRole("option", { name: "TestRoom" }).click();
await bobPage.getByRole("button", { name: "Accept" }).click();
// Alice creates the room and invites Bob.
await inviteBobToNewRoom(alicePage, aliceElementApp, bobCredentials, bobPage);
// Alice configures her client to blacklist unverified users in this room.
const dialog = await aliceElementApp.settings.openRoomSettings("Security & Privacy");
@@ -168,10 +137,6 @@ test.describe("Other people's devices section in Encryption tab", () => {
),
).toBeVisible();
// Alice dismisses key storage warnings, as they now hide the "New conversation" button.
await alicePage.getByRole("button", { name: "Dismiss" }).click(); // enable key storage
await alicePage.getByRole("button", { name: "Yes, dismiss" }).click(); // enable key storage x2
// Alice creates a second room and invites Bob.
await createRoom(alicePage, "TestRoom2", true);
await aliceElementApp.toggleRoomInfoPanel(); // should not be necessary, called in body of below
@@ -194,7 +159,7 @@ test.describe("Other people's devices section in Encryption tab", () => {
user: aliceCredentials,
util,
}, testInfo) => {
await aliceElementApp.client.bootstrapCrossSigning(aliceCredentials);
await prepForEncryption(aliceElementApp, aliceCredentials);
// Enable blacklist toggle.
let dialog = await util.openEncryptionTab();
@@ -207,18 +172,10 @@ test.describe("Other people's devices section in Encryption tab", () => {
await aliceElementApp.settings.closeDialog();
// Create a second browser instance.
const bobCredentials = await homeserver.registerUser(`user_${testInfo.testId}_bob`, "password", "bob");
const bobPage = await createNewInstance(browser, bobCredentials, {});
const bobElementApp = new ElementAppPage(bobPage);
await bobElementApp.client.bootstrapCrossSigning(bobCredentials);
const { bobCredentials, bobPage } = await newBrowser(homeserver, testInfo, browser);
// Alice creates the room and invite Bob.
await createRoom(alicePage, "TestRoom", true);
await aliceElementApp.inviteUserToCurrentRoom(bobCredentials.userId, { confirmUnknownUser: true });
// Bob accepts the invite.
await bobPage.getByRole("option", { name: "TestRoom" }).click();
await bobPage.getByRole("button", { name: "Accept" }).click();
// Alice creates the room and invites Bob.
await inviteBobToNewRoom(alicePage, aliceElementApp, bobCredentials, bobPage);
// Alice configures her client to allow sending to unverified users in this room.
dialog = await aliceElementApp.settings.openRoomSettings("Security & Privacy");
@@ -229,10 +186,6 @@ test.describe("Other people's devices section in Encryption tab", () => {
await sendMessageInCurrentRoom(alicePage, "Decryptable");
await expect(bobPage.getByText("Decryptable")).toBeVisible();
// Alice dismisses key storage warnings, as they now hide the "New conversation" button.
await alicePage.getByRole("button", { name: "Dismiss" }).click(); // enable key storage
await alicePage.getByRole("button", { name: "Yes, dismiss" }).click(); // enable key storage x2
// Alice creates a second room and invites Bob.
await createRoom(alicePage, "TestRoom2", true);
await aliceElementApp.toggleRoomInfoPanel(); // should not be necessary, called in body of below
@@ -251,3 +204,32 @@ test.describe("Other people's devices section in Encryption tab", () => {
).toBeVisible();
});
});
async function inviteBobToNewRoom(
alicePage: Page,
aliceElementApp: ElementAppPage,
bobCredentials: CredentialsOptionalAccessToken,
bobPage: Page,
) {
await createRoom(alicePage, "TestRoom", true);
await aliceElementApp.inviteUserToCurrentRoom(bobCredentials.userId, { confirmUnknownUser: true });
await bobPage.getByRole("option", { name: "TestRoom" }).click();
await bobPage.getByRole("button", { name: "Accept" }).click();
}
async function newBrowser(
homeserver: StartedHomeserverContainer,
testInfo: TestInfo,
browser: Browser,
): Promise<{ bobCredentials: CredentialsOptionalAccessToken; bobPage: Page; bobElementApp: ElementAppPage }> {
const bobCredentials = await homeserver.registerUser(`user_${testInfo.testId}_bob`, "password", "bob");
const bobPage = await createNewInstance(browser, bobCredentials, {});
const bobElementApp = new ElementAppPage(bobPage);
await prepForEncryption(bobElementApp, bobCredentials);
return { bobCredentials, bobPage, bobElementApp };
}
async function prepForEncryption(app: ElementAppPage, credentials: CredentialsOptionalAccessToken): Promise<void> {
await app.client.bootstrapCrossSigning(credentials);
await app.closeKeyStorageToast();
}