Add missing screenshots

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
Michael Telatynski 2025-12-16 13:38:18 +00:00
parent e6d572c413
commit 9d3cba1621
No known key found for this signature in database
GPG Key ID: A2B008A5F49F5D0D
5 changed files with 157 additions and 157 deletions

View File

@ -30,76 +30,80 @@ test.describe("Cryptography", function () {
test.describe("decryption failure messages", () => {
test.skip(isDendrite, "Dendrite lacks support for MSC3967 so requires additional auth here");
test("should handle device-relative historical messages", async ({
homeserver,
page,
app,
credentials,
user,
}) => {
test.setTimeout(60000);
test(
"should handle device-relative historical messages",
{ tag: "@screenshot" },
async ({ homeserver, page, app, credentials, user }) => {
test.setTimeout(60000);
// Start with a logged-in session, without key backup, and send a message.
await createRoom(page, "Test room", true);
await sendMessageInCurrentRoom(page, "test test");
// Start with a logged-in session, without key backup, and send a message.
await createRoom(page, "Test room", true);
await sendMessageInCurrentRoom(page, "test test");
// Log out, discarding the key for the sent message.
await logOutOfElement(page, true);
// Log out, discarding the key for the sent message.
await logOutOfElement(page, true);
// Log in again, and see how the message looks.
await logIntoElement(page, credentials);
await app.viewRoomByName("Test room");
const lastTile = page.locator(".mx_EventTile").last();
await expect(lastTile).toContainText("Historical messages are not available on this device");
await expect(lastTile.locator(".mx_EventTile_e2eIcon")).toHaveAccessibleName(
"This message could not be decrypted",
);
await expect(lastTile).toMatchScreenshot("history-not-available.png");
// Now, we set up key backup, and then send another message.
const secretStorageKey = await enableKeyBackup(app);
await app.viewRoomByName("Test room");
await sendMessageInCurrentRoom(page, "test2 test2");
// Workaround for https://github.com/element-hq/element-web/issues/27267. It can take up to 10 seconds for
// the key to be backed up.
await page.waitForTimeout(10000);
// Finally, log out again, and back in, skipping verification for now, and see what we see.
await logOutOfElement(page);
await logIntoElement(page, credentials);
await page.locator(".mx_AuthPage").getByRole("button", { name: "Skip verification for now" }).click();
await page.locator(".mx_AuthPage").getByRole("button", { name: "I'll verify later" }).click();
await app.viewRoomByName("Test room");
// In this case, the call to cryptoApi.isEncryptionEnabledInRoom is taking a long time to resolve
await page.waitForTimeout(1000);
// There should be two historical events in the timeline
const tiles = await page.locator(".mx_EventTile").all();
expect(tiles.length).toBeGreaterThanOrEqual(2);
// look at the last two tiles only
for (const tile of tiles.slice(-2)) {
await expect(tile).toContainText("You need to verify this device for access to historical messages");
await expect(tile.locator(".mx_EventTile_e2eIcon")).toHaveAccessibleName(
// Log in again, and see how the message looks.
await logIntoElement(page, credentials);
await app.viewRoomByName("Test room");
const lastTile = page.locator(".mx_EventTile").last();
await expect(lastTile).toContainText("Historical messages are not available on this device");
await expect(lastTile.locator(".mx_EventTile_e2eIcon")).toHaveAccessibleName(
"This message could not be decrypted",
);
}
await expect(lastTile).toMatchScreenshot("history-not-available.png", {
mask: [page.locator(".mx_MessageTimestamp")],
});
// Now verify our device (setting up key backup), and check what happens
await verifySession(app, secretStorageKey);
const tilesAfterVerify = (await page.locator(".mx_EventTile").all()).slice(-2);
// Now, we set up key backup, and then send another message.
const secretStorageKey = await enableKeyBackup(app);
await app.viewRoomByName("Test room");
await sendMessageInCurrentRoom(page, "test2 test2");
// The first message still cannot be decrypted, because it was never backed up. It's now a regular UTD though.
await expect(tilesAfterVerify[0]).toContainText("Unable to decrypt message");
await expect(tilesAfterVerify[0].locator(".mx_EventTile_e2eIcon")).toHaveAccessibleName(
"This message could not be decrypted",
);
// Workaround for https://github.com/element-hq/element-web/issues/27267. It can take up to 10 seconds for
// the key to be backed up.
await page.waitForTimeout(10000);
// The second message should now be decrypted, with a grey shield
await expect(tilesAfterVerify[1]).toContainText("test2 test2");
await expect(tilesAfterVerify[1].locator(".mx_EventTile_e2eIcon")).toHaveAccessibleName("TODO");
});
// Finally, log out again, and back in, skipping verification for now, and see what we see.
await logOutOfElement(page);
await logIntoElement(page, credentials);
await page.locator(".mx_AuthPage").getByRole("button", { name: "Skip verification for now" }).click();
await page.locator(".mx_AuthPage").getByRole("button", { name: "I'll verify later" }).click();
await app.viewRoomByName("Test room");
// In this case, the call to cryptoApi.isEncryptionEnabledInRoom is taking a long time to resolve
await page.waitForTimeout(1000);
// There should be two historical events in the timeline
const tiles = await page.locator(".mx_EventTile").all();
expect(tiles.length).toBeGreaterThanOrEqual(2);
// look at the last two tiles only
for (const tile of tiles.slice(-2)) {
await expect(tile).toContainText(
"You need to verify this device for access to historical messages",
);
await expect(tile.locator(".mx_EventTile_e2eIcon")).toHaveAccessibleName(
"This message could not be decrypted",
);
}
// Now verify our device (setting up key backup), and check what happens
await verifySession(app, secretStorageKey);
const tilesAfterVerify = (await page.locator(".mx_EventTile").all()).slice(-2);
// The first message still cannot be decrypted, because it was never backed up. It's now a regular UTD though.
await expect(tilesAfterVerify[0]).toContainText("Unable to decrypt message");
await expect(tilesAfterVerify[0].locator(".mx_EventTile_e2eIcon")).toHaveAccessibleName(
"This message could not be decrypted",
);
// The second message should now be decrypted, with a grey shield
await expect(tilesAfterVerify[1]).toContainText("test2 test2");
await expect(tilesAfterVerify[1].locator(".mx_EventTile_e2eIcon")).toHaveAccessibleName(
"The authenticity of this encrypted message can't be guaranteed on this device.",
);
},
);
test.describe("non-joined historical messages", () => {
test.skip(isDendrite, "does not yet support membership on events");

View File

@ -150,55 +150,53 @@ test.describe("Cryptography", function () {
},
);
test("Should show a grey padlock for a key restored from backup", async ({
page,
app,
bot: bob,
homeserver,
user: aliceCredentials,
}) => {
test.slow();
const securityKey = await enableKeyBackup(app);
test(
"Should show a grey padlock for a key restored from backup",
{ tag: "@screenshot" },
async ({ page, app, bot: bob, homeserver, user: aliceCredentials }) => {
test.slow();
const securityKey = await enableKeyBackup(app);
// bob sends a valid event
await bob.sendMessage(testRoomId, "test encrypted 1");
// bob sends a valid event
await bob.sendMessage(testRoomId, "test encrypted 1");
const lastTile = page.locator(".mx_EventTile_last");
const lastTileE2eIcon = lastTile.locator(".mx_EventTile_e2eIcon");
await expect(lastTile).toContainText("test encrypted 1");
// no e2e icon
await expect(lastTileE2eIcon).not.toBeVisible();
const lastTile = page.locator(".mx_EventTile_last");
const lastTileE2eIcon = lastTile.locator(".mx_EventTile_e2eIcon");
await expect(lastTile).toContainText("test encrypted 1");
// no e2e icon
await expect(lastTileE2eIcon).not.toBeVisible();
// Workaround for https://github.com/element-hq/element-web/issues/27267. It can take up to 10 seconds for
// the key to be backed up.
await page.waitForTimeout(10000);
// Workaround for https://github.com/element-hq/element-web/issues/27267. It can take up to 10 seconds for
// the key to be backed up.
await page.waitForTimeout(10000);
/* log out, and back in */
await logOutOfElement(page);
// Reload to work around a Rust crypto bug where it can hold onto the indexeddb even after logout
// https://github.com/element-hq/element-web/issues/25779
await page.addInitScript(() => {
// When we reload, the initScript created by the `user`/`pageWithCredentials` fixtures
// will re-inject the original credentials into localStorage, which we don't want.
// To work around, we add a second initScript which will clear localStorage again.
window.localStorage.clear();
});
await page.reload();
await logIntoElementAndVerify(page, aliceCredentials, securityKey);
/* log out, and back in */
await logOutOfElement(page);
// Reload to work around a Rust crypto bug where it can hold onto the indexeddb even after logout
// https://github.com/element-hq/element-web/issues/25779
await page.addInitScript(() => {
// When we reload, the initScript created by the `user`/`pageWithCredentials` fixtures
// will re-inject the original credentials into localStorage, which we don't want.
// To work around, we add a second initScript which will clear localStorage again.
window.localStorage.clear();
});
await page.reload();
await logIntoElementAndVerify(page, aliceCredentials, securityKey);
/* go back to the test room and find Bob's message again */
await app.viewRoomById(testRoomId);
await expect(lastTile).toContainText("test encrypted 1");
// The gray shield would be a Compound info icon. The red shield would be a Compound error solid icon.
// No shield would have no div mx_EventTile_e2eIcon at all.
// The key is coming from backup, so it is not anymore possible to establish if the claimed device
// creator of this key is authentic. The tooltip should be "The authenticity of this encrypted message can't be guaranteed on this device."
// It is not "Encrypted by an unknown or deleted device." even if the claimed device is actually deleted.
await expect(lastTileE2eIcon).toHaveAccessibleName(
"The authenticity of this encrypted message can't be guaranteed on this device.",
);
await expect(lastTileE2eIcon).toMatchScreenshot("event-shield-authenticity.png");
});
/* go back to the test room and find Bob's message again */
await app.viewRoomById(testRoomId);
await expect(lastTile).toContainText("test encrypted 1");
// The gray shield would be a Compound info icon. The red shield would be a Compound error solid icon.
// No shield would have no div mx_EventTile_e2eIcon at all.
// The key is coming from backup, so it is not anymore possible to establish if the claimed device
// creator of this key is authentic. The tooltip should be "The authenticity of this encrypted message can't be guaranteed on this device."
// It is not "Encrypted by an unknown or deleted device." even if the claimed device is actually deleted.
await expect(lastTileE2eIcon).toHaveAccessibleName(
"The authenticity of this encrypted message can't be guaranteed on this device.",
);
await expect(lastTileE2eIcon).toMatchScreenshot("event-shield-authenticity.png");
},
);
test("should show the correct shield on edited e2e events", async ({ page, app, bot: bob, homeserver }) => {
// bob has a second, not cross-signed, device
@ -249,67 +247,65 @@ test.describe("Cryptography", function () {
).not.toBeVisible();
});
test("should show correct shields on events sent by devices which have since been deleted", async ({
page,
app,
bot: bob,
homeserver,
}) => {
// Workaround for https://github.com/element-hq/element-web/issues/28640:
// make sure that Alice has seen Bob's identity before she goes offline. We do this by opening
// his user info.
await waitForDevices(app, bob.credentials.userId, 1);
test(
"should show correct shields on events sent by devices which have since been deleted",
{ tag: "@screenshot" },
async ({ page, app, bot: bob, homeserver }) => {
// Workaround for https://github.com/element-hq/element-web/issues/28640:
// make sure that Alice has seen Bob's identity before she goes offline. We do this by opening
// his user info.
await waitForDevices(app, bob.credentials.userId, 1);
// Our app is blocked from syncing while Bob sends his messages.
await app.client.network.goOffline();
// Our app is blocked from syncing while Bob sends his messages.
await app.client.network.goOffline();
// Bob sends a message from his verified device
await bob.sendMessage(testRoomId, "test encrypted from verified");
// Bob sends a message from his verified device
await bob.sendMessage(testRoomId, "test encrypted from verified");
// And one from a second, not cross-signed, device
const bobSecondDevice = await createSecondBotDevice(page, homeserver, bob);
await bobSecondDevice.waitForNextSync(); // make sure the client knows the room is encrypted
await bobSecondDevice.sendMessage(testRoomId, "test encrypted from unverified");
// And one from a second, not cross-signed, device
const bobSecondDevice = await createSecondBotDevice(page, homeserver, bob);
await bobSecondDevice.waitForNextSync(); // make sure the client knows the room is encrypted
await bobSecondDevice.sendMessage(testRoomId, "test encrypted from unverified");
// ... and then logs out both devices.
await bob.evaluate((cli) => cli.logout(true));
await bobSecondDevice.evaluate((cli) => cli.logout(true));
// ... and then logs out both devices.
await bob.evaluate((cli) => cli.logout(true));
await bobSecondDevice.evaluate((cli) => cli.logout(true));
// Let our app start syncing again
await app.client.network.goOnline();
// Let our app start syncing again
await app.client.network.goOnline();
// Wait for the messages to arrive. It can take quite a while for the sync to wake up.
const last = page.locator(".mx_EventTile_last");
await expect(last).toContainText("test encrypted from unverified", { timeout: 20000 });
const lastE2eIcon = last.locator(".mx_EventTile_e2eIcon");
await expect(lastE2eIcon).toHaveAccessibleName("Encrypted by a device not verified by its owner.");
await expect(lastE2eIcon).toMatchScreenshot("event-shield-not-verified.png");
// Wait for the messages to arrive. It can take quite a while for the sync to wake up.
const last = page.locator(".mx_EventTile_last");
await expect(last).toContainText("test encrypted from unverified", { timeout: 20000 });
const lastE2eIcon = last.locator(".mx_EventTile_e2eIcon");
await expect(lastE2eIcon).toHaveAccessibleName("Encrypted by a device not verified by its owner.");
await expect(lastE2eIcon).toMatchScreenshot("event-shield-not-verified.png");
const penultimate = page.locator(".mx_EventTile").filter({ hasText: "test encrypted from verified" });
await assertNoE2EIcon(penultimate, app);
});
const penultimate = page.locator(".mx_EventTile").filter({ hasText: "test encrypted from verified" });
await assertNoE2EIcon(penultimate, app);
},
);
test("should show correct shields on events sent by users with changed identity", async ({
page,
app,
bot: bob,
homeserver,
}) => {
// Verify Bob
await verify(app, bob);
test(
"should show correct shields on events sent by users with changed identity",
{ tag: "@screenshot" },
async ({ page, app, bot: bob, homeserver }) => {
// Verify Bob
await verify(app, bob);
// Bob logs in a new device and resets cross-signing
const bobSecondDevice = await createSecondBotDevice(page, homeserver, bob);
await bootstrapCrossSigningForClient(await bobSecondDevice.prepareClient(), bob.credentials, true);
// Bob logs in a new device and resets cross-signing
const bobSecondDevice = await createSecondBotDevice(page, homeserver, bob);
await bootstrapCrossSigningForClient(await bobSecondDevice.prepareClient(), bob.credentials, true);
/* should show an error for a message from a previously verified device */
await bobSecondDevice.sendMessage(testRoomId, "test encrypted from user that was previously verified");
const last = page.locator(".mx_EventTile_last");
await expect(last).toContainText("test encrypted from user that was previously verified");
const lastE2eIcon = last.locator(".mx_EventTile_e2eIcon");
await expect(lastE2eIcon).toHaveAccessibleName("Sender's verified identity was reset");
await expect(lastE2eIcon).toMatchScreenshot("event-shield-identity-reset.png");
});
/* should show an error for a message from a previously verified device */
await bobSecondDevice.sendMessage(testRoomId, "test encrypted from user that was previously verified");
const last = page.locator(".mx_EventTile_last");
await expect(last).toContainText("test encrypted from user that was previously verified");
const lastE2eIcon = last.locator(".mx_EventTile_e2eIcon");
await expect(lastE2eIcon).toHaveAccessibleName("Sender's verified identity was reset");
await expect(lastE2eIcon).toMatchScreenshot("event-shield-identity-reset.png");
},
);
});
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 441 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 393 B