@@ -8,7 +8,15 @@ Please see LICENSE files in the repository root for full details.
88
99import { test , expect } from "../../element-web-test" ;
1010import { isDendrite } from "../../plugins/homeserver/dendrite" ;
11- import { createBot , logIntoElement } from "./utils.ts" ;
11+ import {
12+ autoJoin ,
13+ createBot ,
14+ createSharedEncryptedRoomWithUser ,
15+ enableKeyBackup ,
16+ logIntoElement ,
17+ logIntoElementAndVerify ,
18+ logOutOfElement ,
19+ } from "./utils.ts" ;
1220import { type Client } from "../../pages/client.ts" ;
1321import { type ElementAppPage } from "../../pages/ElementAppPage.ts" ;
1422
@@ -40,15 +48,10 @@ test.describe("Dehydration", () => {
4048 await settings . getByRole ( "button" , { name : "Verify this device" } ) . click ( ) ;
4149 await page . getByRole ( "button" , { name : "Can't confirm?" } ) . click ( ) ;
4250 await page . getByRole ( "button" , { name : "Continue" } ) . click ( ) ;
51+ await app . closeDialog ( ) ;
4352
4453 // Set up recovery
45- await page . getByRole ( "button" , { name : "Get recovery key" } ) . click ( ) ;
46- await page . getByRole ( "button" , { name : "Continue" } ) . click ( ) ;
47- const recoveryKey = await page . getByTestId ( "recoveryKey" ) . innerText ( ) ;
48- await page . getByRole ( "button" , { name : "Continue" } ) . click ( ) ;
49- await page . getByRole ( "textbox" ) . fill ( recoveryKey ) ;
50- await page . getByRole ( "button" , { name : "Finish set up" } ) . click ( ) ;
51- await page . getByRole ( "button" , { name : "Close" } ) . click ( ) ;
54+ await enableKeyBackup ( app ) ;
5255
5356 await expectDehydratedDeviceEnabled ( app ) ;
5457
@@ -61,28 +64,7 @@ test.describe("Dehydration", () => {
6164
6265 test ( "'Get recovery key' creates dehydrated device" , async ( { app, credentials, page } ) => {
6366 await logIntoElement ( page , credentials ) ;
64-
65- const settingsDialogLocator = await app . settings . openUserSettings ( "Encryption" ) ;
66- await settingsDialogLocator . getByRole ( "button" , { name : "Get recovery key" } ) . click ( ) ;
67-
68- // First it displays an informative panel about the recovery key
69- await expect ( settingsDialogLocator . getByRole ( "heading" , { name : "Get recovery key" } ) ) . toBeVisible ( ) ;
70- await settingsDialogLocator . getByRole ( "button" , { name : "Continue" } ) . click ( ) ;
71-
72- // Next, it displays the new recovery key. We click on the copy button.
73- await expect ( settingsDialogLocator . getByText ( "Save your recovery key somewhere safe" ) ) . toBeVisible ( ) ;
74- await settingsDialogLocator . getByRole ( "button" , { name : "Copy" } ) . click ( ) ;
75- const recoveryKey = await app . getClipboard ( ) ;
76- await settingsDialogLocator . getByRole ( "button" , { name : "Continue" } ) . click ( ) ;
77-
78- await expect (
79- settingsDialogLocator . getByText ( "Enter your recovery key to confirm" , { exact : true } ) ,
80- ) . toBeVisible ( ) ;
81- await settingsDialogLocator . getByRole ( "textbox" ) . fill ( recoveryKey ) ;
82- await settingsDialogLocator . getByRole ( "button" , { name : "Finish set up" } ) . click ( ) ;
83-
84- await app . settings . closeDialog ( ) ;
85-
67+ await enableKeyBackup ( app ) ;
8668 await expectDehydratedDeviceEnabled ( app ) ;
8769 } ) ;
8870
@@ -115,13 +97,7 @@ test.describe("Dehydration", () => {
11597 await page . getByRole ( "button" , { name : "Continue" } ) . click ( ) ;
11698
11799 // And set up recovery
118- const settings = await app . settings . openUserSettings ( "Encryption" ) ;
119- await settings . getByRole ( "button" , { name : "Get recovery key" } ) . click ( ) ;
120- await settings . getByRole ( "button" , { name : "Continue" } ) . click ( ) ;
121- const recoveryKey = await settings . getByTestId ( "recoveryKey" ) . innerText ( ) ;
122- await settings . getByRole ( "button" , { name : "Continue" } ) . click ( ) ;
123- await settings . getByRole ( "textbox" ) . fill ( recoveryKey ) ;
124- await settings . getByRole ( "button" , { name : "Finish set up" } ) . click ( ) ;
100+ await enableKeyBackup ( app ) ;
125101
126102 // There should be a brand new dehydrated device
127103 await expectDehydratedDeviceEnabled ( app ) ;
@@ -132,34 +108,54 @@ test.describe("Dehydration", () => {
132108
133109 // Create a dehydrated device by setting up recovery (see "'Set up
134110 // recovery' creates dehydrated device" test above)
135- const settingsDialogLocator = await app . settings . openUserSettings ( "Encryption" ) ;
136- await settingsDialogLocator . getByRole ( "button" , { name : "Get recovery key" } ) . click ( ) ;
137-
138- // First it displays an informative panel about the recovery key
139- await expect ( settingsDialogLocator . getByRole ( "heading" , { name : "Get recovery key" } ) ) . toBeVisible ( ) ;
140- await settingsDialogLocator . getByRole ( "button" , { name : "Continue" } ) . click ( ) ;
141-
142- // Next, it displays the new recovery key. We click on the copy button.
143- await expect ( settingsDialogLocator . getByText ( "Save your recovery key somewhere safe" ) ) . toBeVisible ( ) ;
144- await settingsDialogLocator . getByRole ( "button" , { name : "Copy" } ) . click ( ) ;
145- const recoveryKey = await app . getClipboard ( ) ;
146- await settingsDialogLocator . getByRole ( "button" , { name : "Continue" } ) . click ( ) ;
147-
148- await expect (
149- settingsDialogLocator . getByText ( "Enter your recovery key to confirm" , { exact : true } ) ,
150- ) . toBeVisible ( ) ;
151- await settingsDialogLocator . getByRole ( "textbox" ) . fill ( recoveryKey ) ;
152- await settingsDialogLocator . getByRole ( "button" , { name : "Finish set up" } ) . click ( ) ;
153-
111+ await enableKeyBackup ( app ) ;
154112 await expectDehydratedDeviceEnabled ( app ) ;
155113
156114 // After recovery is set up, we reset our cryptographic identity, which
157115 // should drop the dehydrated device.
116+ const settingsDialogLocator = await app . settings . openUserSettings ( "Encryption" ) ;
158117 await settingsDialogLocator . getByRole ( "button" , { name : "Reset cryptographic identity" } ) . click ( ) ;
159118 await settingsDialogLocator . getByRole ( "button" , { name : "Continue" } ) . click ( ) ;
160119
161120 await expectDehydratedDeviceDisabled ( app ) ;
162121 } ) ;
122+
123+ test ( "Can read messages sent while logged out" , async ( { page, user : credentials , app, bot : bob } ) => {
124+ const recoveryKey =
125+ await test . step ( "Alice sets up cross-signing and recovery => a dehydrated device is created" , async ( ) => {
126+ // Create an identity, then set up recovery, to create a dehydrated device.
127+ await app . client . bootstrapCrossSigning ( credentials ) ;
128+ const recoveryKey = await enableKeyBackup ( app ) ;
129+
130+ await expectDehydratedDeviceEnabled ( app ) ;
131+ return recoveryKey ;
132+ } ) ;
133+
134+ const testRoomId = await test . step ( "Bob and Alice make a shared room" , async ( ) => {
135+ await autoJoin ( bob ) ;
136+
137+ // create an encrypted room, and wait for Bob to join it.
138+ const testRoomId = await createSharedEncryptedRoomWithUser ( app , bob . credentials . userId ) ;
139+
140+ // Even though Alice has seen Bob's join event, Bob may not have done so yet. Wait for the sync to arrive.
141+ await bob . awaitRoomMembership ( testRoomId ) ;
142+ return testRoomId ;
143+ } ) ;
144+
145+ await test . step ( "Alice logs out" , async ( ) => {
146+ await logOutOfElement ( page ) ;
147+ } ) ;
148+
149+ await test . step ( "Bob sends a message" , async ( ) => {
150+ await bob . sendMessage ( testRoomId , "test encrypted 1" ) ;
151+ } ) ;
152+
153+ await test . step ( "Alice logs back in, and should be able to view Bob's message" , async ( ) => {
154+ await logIntoElementAndVerify ( page , credentials , recoveryKey ) ;
155+ await app . viewRoomById ( testRoomId ) ;
156+ await expect ( page . getByText ( "test encrypted 1" ) ) . toBeVisible ( ) ;
157+ } ) ;
158+ } ) ;
163159} ) ;
164160
165161async function getDehydratedDeviceIds ( client : Client ) : Promise < string [ ] > {
0 commit comments