@@ -16,9 +16,9 @@ limitations under the License.
16
16
17
17
/// <reference types="cypress" />
18
18
19
- import type { MsgType } from "matrix-js-sdk/src/@types/event" ;
19
+ import type { EventType , MsgType } from "matrix-js-sdk/src/@types/event" ;
20
20
import type { ISendEventResponse } from "matrix-js-sdk/src/@types/requests" ;
21
- import type { EventType } from "matrix-js-sdk/src/@types /event" ;
21
+ import type { IContent } from "matrix-js-sdk/src/models /event" ;
22
22
import { HomeserverInstance } from "../../plugins/utils/homeserver" ;
23
23
import Chainable = Cypress . Chainable ;
24
24
@@ -29,6 +29,16 @@ const sendEvent = (roomId: string): Chainable<ISendEventResponse> => {
29
29
} ) ;
30
30
} ;
31
31
32
+ /** generate a message event which will take up some room on the page. */
33
+ function mkPadding ( n : number ) : IContent {
34
+ return {
35
+ msgtype : "m.text" as MsgType ,
36
+ body : `padding ${ n } ` ,
37
+ format : "org.matrix.custom.html" ,
38
+ formatted_body : `<h3>Test event ${ n } </h3>\n` . repeat ( 10 ) ,
39
+ } ;
40
+ }
41
+
32
42
describe ( "Editing" , ( ) => {
33
43
let homeserver : HomeserverInstance ;
34
44
@@ -37,7 +47,6 @@ describe("Editing", () => {
37
47
homeserver = data ;
38
48
cy . initTestUser ( homeserver , "Edith" ) . then ( ( ) => {
39
49
cy . injectAxe ( ) ;
40
- return cy . createRoom ( { name : "Test room" } ) . as ( "roomId" ) ;
41
50
} ) ;
42
51
} ) ;
43
52
} ) ;
@@ -47,6 +56,8 @@ describe("Editing", () => {
47
56
} ) ;
48
57
49
58
it ( "should close the composer when clicking save after making a change and undoing it" , ( ) => {
59
+ cy . createRoom ( { name : "Test room" } ) . as ( "roomId" ) ;
60
+
50
61
cy . get < string > ( "@roomId" ) . then ( ( roomId ) => {
51
62
sendEvent ( roomId ) ;
52
63
cy . visit ( "/#/room/" + roomId ) ;
@@ -64,4 +75,77 @@ describe("Editing", () => {
64
75
// Assert that the edit composer has gone away
65
76
cy . get ( ".mx_EditMessageComposer" ) . should ( "not.exist" ) ;
66
77
} ) ;
78
+
79
+ it ( "should correctly display events which are edited, where we lack the edit event" , ( ) => {
80
+ // This tests the behaviour when a message has been edited some time after it has been sent, and we
81
+ // jump back in room history to view the event, but do not have the actual edit event.
82
+ //
83
+ // In that scenario, we rely on the server to replace the content (pre-MSC3925), or do it ourselves based on
84
+ // the bundled edit event (post-MSC3925).
85
+ //
86
+ // To test it, we need to have a room with lots of events in, so we can jump around the timeline without
87
+ // paginating in the event itself. Hence, we create a bot user which creates the room and populates it before
88
+ // we join.
89
+
90
+ let testRoomId : string ;
91
+ let originalEventId : string ;
92
+ let editEventId : string ;
93
+
94
+ // create a second user
95
+ const bobChainable = cy . getBot ( homeserver , { displayName : "Bob" , userIdPrefix : "bob_" } ) ;
96
+
97
+ cy . all ( [ cy . window ( { log : false } ) , bobChainable ] ) . then ( async ( [ win , bob ] ) => {
98
+ // "bob" now creates the room, and sends a load of events in it. Note that all of this happens via calls on
99
+ // the js-sdk rather than Cypress commands, so uses regular async/await.
100
+
101
+ const room = await bob . createRoom ( { name : "TestRoom" , visibility : win . matrixcs . Visibility . Public } ) ;
102
+ testRoomId = room . room_id ;
103
+ cy . log ( `Bot user created room ${ room . room_id } ` ) ;
104
+
105
+ originalEventId = ( await bob . sendMessage ( room . room_id , { body : "original" , msgtype : "m.text" } ) ) . event_id ;
106
+ cy . log ( `Bot user sent original event ${ originalEventId } ` ) ;
107
+
108
+ // send a load of padding events. We make them large, so that they fill the whole screen
109
+ // and the client doesn't end up paginating into the event we want.
110
+ let i = 0 ;
111
+ while ( i < 10 ) {
112
+ await bob . sendMessage ( room . room_id , mkPadding ( i ++ ) ) ;
113
+ }
114
+
115
+ // ... then the edit ...
116
+ editEventId = (
117
+ await bob . sendMessage ( room . room_id , {
118
+ "m.new_content" : { body : "Edited body" , msgtype : "m.text" } ,
119
+ "m.relates_to" : {
120
+ rel_type : "m.replace" ,
121
+ event_id : originalEventId ,
122
+ } ,
123
+ "body" : "* edited" ,
124
+ "msgtype" : "m.text" ,
125
+ } )
126
+ ) . event_id ;
127
+ cy . log ( `Bot user sent edit event ${ editEventId } ` ) ;
128
+
129
+ // ... then a load more padding ...
130
+ while ( i < 20 ) {
131
+ await bob . sendMessage ( room . room_id , mkPadding ( i ++ ) ) ;
132
+ }
133
+ } ) ;
134
+
135
+ cy . getClient ( ) . then ( ( cli ) => {
136
+ // now have the cypress user join the room, jump to the original event, and wait for the event to be
137
+ // visible
138
+ cy . joinRoom ( testRoomId ) ;
139
+ cy . viewRoomByName ( "TestRoom" ) ;
140
+ cy . visit ( `#/room/${ testRoomId } /${ originalEventId } ` ) ;
141
+ cy . get ( `[data-event-id="${ originalEventId } "]` ) . should ( ( messageTile ) => {
142
+ // at this point, the edit event should still be unknown
143
+ expect ( cli . getRoom ( testRoomId ) . getTimelineForEvent ( editEventId ) ) . to . be . null ;
144
+
145
+ // nevertheless, the event should be updated
146
+ expect ( messageTile . find ( ".mx_EventTile_body" ) . text ( ) ) . to . eq ( "Edited body" ) ;
147
+ expect ( messageTile . find ( ".mx_EventTile_edited" ) ) . to . exist ;
148
+ } ) ;
149
+ } ) ;
150
+ } ) ;
67
151
} ) ;
0 commit comments