@@ -20,6 +20,7 @@ import { HomeserverInstance } from "../../plugins/utils/homeserver";
20
20
import { MatrixClient } from "../../global" ;
21
21
import { SettingLevel } from "../../../src/settings/SettingLevel" ;
22
22
import { Layout } from "../../../src/settings/enums/Layout" ;
23
+ import Chainable = Cypress . Chainable ;
23
24
24
25
describe ( "Threads" , ( ) => {
25
26
let homeserver : HomeserverInstance ;
@@ -64,6 +65,9 @@ describe("Threads", () => {
64
65
// --MessageTimestamp-color = #acacac = rgb(172, 172, 172)
65
66
// See: _MessageTimestamp.pcss
66
67
const MessageTimestampColor = "rgb(172, 172, 172)" ;
68
+ const ThreadViewGroupSpacingStart = "56px" ; // --ThreadView_group_spacing-start
69
+ // Exclude timestamp and read marker from snapshots
70
+ const percyCSS = ".mx_MessageTimestamp, .mx_RoomView_myReadMarker { visibility: hidden !important; }" ;
67
71
68
72
// User sends message
69
73
cy . get ( ".mx_RoomView_body .mx_BasicMessageComposer_input" ) . type ( "Hello Mr. Bot{enter}" ) ;
@@ -90,9 +94,29 @@ describe("Threads", () => {
90
94
} ) ;
91
95
92
96
// User asserts timeline thread summary visible & clicks it
93
- cy . get ( ".mx_RoomView_body .mx_ThreadSummary .mx_ThreadSummary_sender" ) . should ( "contain" , "BotBob" ) ;
94
- cy . get ( ".mx_RoomView_body .mx_ThreadSummary .mx_ThreadSummary_content" ) . should ( "contain" , "Hello there" ) ;
95
- cy . get ( ".mx_RoomView_body .mx_ThreadSummary" ) . click ( ) ;
97
+ cy . get ( ".mx_RoomView_body" ) . within ( ( ) => {
98
+ cy . get ( ".mx_ThreadSummary .mx_ThreadSummary_sender" ) . should ( "contain" , "BotBob" ) ;
99
+ cy . get ( ".mx_ThreadSummary .mx_ThreadSummary_content" ) . should ( "contain" , "Hello there" ) ;
100
+ cy . get ( ".mx_ThreadSummary" ) . click ( ) ;
101
+ } ) ;
102
+
103
+ // Wait until the both messages are read
104
+ cy . get ( ".mx_ThreadView .mx_EventTile_last[data-layout=group]" ) . within ( ( ) => {
105
+ cy . get ( ".mx_EventTile_line .mx_MTextBody" ) . should ( "have.text" , MessageLong ) ;
106
+ cy . get ( ".mx_ReadReceiptGroup .mx_BaseAvatar_image" ) . should ( "be.visible" ) ;
107
+
108
+ // Make sure the CSS style for spacing is applied to mx_EventTile_line on group/modern layout
109
+ cy . get ( ".mx_EventTile_line" ) . should ( "have.css" , "padding-inline-start" , ThreadViewGroupSpacingStart ) ;
110
+ } ) ;
111
+
112
+ // Take Percy snapshots in group layout and bubble layout (IRC layout is not available on ThreadView)
113
+ cy . get ( ".mx_ThreadView" ) . percySnapshotElement ( "Initial ThreadView on group layout" , { percyCSS } ) ;
114
+ cy . setSettingValue ( "layout" , null , SettingLevel . DEVICE , Layout . Bubble ) ;
115
+ cy . get ( ".mx_ThreadView .mx_EventTile[data-layout='bubble']" ) . should ( "be.visible" ) ;
116
+ cy . get ( ".mx_ThreadView" ) . percySnapshotElement ( "Initial ThreadView on bubble layout" , { percyCSS } ) ;
117
+
118
+ // Set the group layout
119
+ cy . setSettingValue ( "layout" , null , SettingLevel . DEVICE , Layout . Group ) ;
96
120
97
121
cy . get ( ".mx_ThreadView .mx_EventTile[data-layout='group'].mx_EventTile_last" ) . within ( ( ) => {
98
122
// Wait until the messages are rendered
@@ -130,8 +154,17 @@ describe("Threads", () => {
130
154
) ;
131
155
132
156
// User asserts summary was updated correctly
133
- cy . get ( ".mx_RoomView_body .mx_ThreadSummary .mx_ThreadSummary_sender" ) . should ( "contain" , "Tom" ) ;
134
- cy . get ( ".mx_RoomView_body .mx_ThreadSummary .mx_ThreadSummary_content" ) . should ( "contain" , "Test" ) ;
157
+ cy . get ( ".mx_RoomView_body .mx_ThreadSummary" ) . within ( ( ) => {
158
+ cy . get ( ".mx_ThreadSummary_sender" ) . should ( "contain" , "Tom" ) ;
159
+ cy . get ( ".mx_ThreadSummary_content" ) . should ( "contain" , "Test" ) ;
160
+ } ) ;
161
+
162
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
163
+ // Check reactions and hidden events
164
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
165
+
166
+ // Enable hidden events to make the event for reaction displayed
167
+ cy . setSettingValue ( "showHiddenEventsInTimeline" , null , SettingLevel . DEVICE , true ) ;
135
168
136
169
// User reacts to message instead
137
170
cy . contains ( ".mx_ThreadView .mx_EventTile .mx_EventTile_line" , "Hello there" )
@@ -142,6 +175,58 @@ describe("Threads", () => {
142
175
cy . contains ( '[role="menuitem"]' , "👋" ) . click ( ) ;
143
176
} ) ;
144
177
178
+ cy . get ( ".mx_ThreadView" ) . within ( ( ) => {
179
+ // Make sure the CSS style for spacing is applied to mx_ReactionsRow on group/modern layout
180
+ cy . get ( ".mx_EventTile[data-layout=group] .mx_ReactionsRow" ) . should (
181
+ "have.css" ,
182
+ "margin-inline-start" ,
183
+ ThreadViewGroupSpacingStart ,
184
+ ) ;
185
+
186
+ // Make sure the CSS style for spacing is applied to the hidden event on group/modern layout
187
+ cy . get (
188
+ ".mx_GenericEventListSummary[data-layout=group] .mx_EventTile_info.mx_EventTile_last " +
189
+ ".mx_EventTile_line" ,
190
+ ) . should ( "have.css" , "padding-inline-start" , ThreadViewGroupSpacingStart ) ;
191
+ } ) ;
192
+
193
+ // Take Percy snapshot of group layout (IRC layout is not available on ThreadView)
194
+ cy . get ( ".mx_ThreadView" ) . percySnapshotElement ( "ThreadView with reaction and a hidden event on group layout" , {
195
+ percyCSS,
196
+ } ) ;
197
+
198
+ // Enable bubble layout
199
+ cy . setSettingValue ( "layout" , null , SettingLevel . DEVICE , Layout . Bubble ) ;
200
+
201
+ // Make sure the CSS style for spacing is applied to the hidden event on bubble layout
202
+ cy . get (
203
+ ".mx_ThreadView .mx_GenericEventListSummary[data-layout=bubble] .mx_EventTile_info.mx_EventTile_last" ,
204
+ ) . within ( ( ) => {
205
+ cy . get ( ".mx_EventTile_line .mx_EventTile_content" )
206
+ // 76px: ThreadViewGroupSpacingStart + 14px + 6px
207
+ // 14px: avatar width
208
+ // See: _EventTile.pcss
209
+ . should ( "have.css" , "margin-inline-start" , "76px" ) ;
210
+ cy . get ( ".mx_EventTile_line" )
211
+ // Make sure the margin is NOT applied to mx_EventTile_line
212
+ . should ( "have.css" , "margin-inline-start" , "0px" ) ;
213
+ } ) ;
214
+
215
+ // Take Percy snapshot of bubble layout
216
+ cy . get ( ".mx_ThreadView" ) . percySnapshotElement ( "ThreadView with reaction and a hidden event on bubble layout" , {
217
+ percyCSS,
218
+ } ) ;
219
+
220
+ // Disable hidden events
221
+ cy . setSettingValue ( "showHiddenEventsInTimeline" , null , SettingLevel . DEVICE , false ) ;
222
+
223
+ // Reset to the group layout
224
+ cy . setSettingValue ( "layout" , null , SettingLevel . DEVICE , Layout . Group ) ;
225
+
226
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
227
+ // Check redactions
228
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
229
+
145
230
// User redacts their prior response
146
231
cy . contains ( ".mx_ThreadView .mx_EventTile .mx_EventTile_line" , "Test" )
147
232
. find ( '[aria-label="Options"]' )
@@ -153,6 +238,23 @@ describe("Threads", () => {
153
238
cy . contains ( ".mx_Dialog_primary" , "Remove" ) . click ( ) ;
154
239
} ) ;
155
240
241
+ // Wait until the response is redacted
242
+ cy . get ( ".mx_ThreadView .mx_EventTile_last .mx_EventTile_receiptSent" ) . should ( "be.visible" ) ;
243
+
244
+ // Take Percy snapshots in group layout and bubble layout (IRC layout is not available on ThreadView)
245
+ cy . get ( ".mx_ThreadView .mx_EventTile[data-layout='group']" ) . should ( "be.visible" ) ;
246
+ cy . get ( ".mx_ThreadView" ) . percySnapshotElement ( "ThreadView with redacted messages on group layout" , {
247
+ percyCSS,
248
+ } ) ;
249
+ cy . setSettingValue ( "layout" , null , SettingLevel . DEVICE , Layout . Bubble ) ;
250
+ cy . get ( ".mx_ThreadView .mx_EventTile[data-layout='bubble']" ) . should ( "be.visible" ) ;
251
+ cy . get ( ".mx_ThreadView" ) . percySnapshotElement ( "ThreadView with redacted messages on bubble layout" , {
252
+ percyCSS,
253
+ } ) ;
254
+
255
+ // Set the group layout
256
+ cy . setSettingValue ( "layout" , null , SettingLevel . DEVICE , Layout . Group ) ;
257
+
156
258
// User asserts summary was updated correctly
157
259
cy . get ( ".mx_RoomView_body .mx_ThreadSummary .mx_ThreadSummary_sender" ) . should ( "contain" , "BotBob" ) ;
158
260
cy . get ( ".mx_RoomView_body .mx_ThreadSummary .mx_ThreadSummary_content" ) . should ( "contain" , "Hello there" ) ;
@@ -182,9 +284,15 @@ describe("Threads", () => {
182
284
cy . get ( ".mx_EventTile_body" ) . should ( "contain" , "Hello Mr. Bot" ) ;
183
285
cy . get ( ".mx_ThreadSummary_content" ) . should ( "contain" , "How are things?" ) ;
184
286
287
+ // Check the number of the replies
288
+ cy . get ( ".mx_ThreadPanel_replies_amount" ) . should ( "have.text" , "2" ) ;
289
+
185
290
// Check the colour of timestamp on thread list
186
291
cy . get ( ".mx_EventTile_details .mx_MessageTimestamp" ) . should ( "have.css" , "color" , MessageTimestampColor ) ;
187
292
293
+ // Make sure the notification dot is visible
294
+ cy . get ( ".mx_NotificationBadge_visible" ) . should ( "be.visible" ) ;
295
+
188
296
// User opens thread via threads list
189
297
cy . get ( ".mx_EventTile_line" ) . click ( ) ;
190
298
} ) ;
@@ -281,6 +389,80 @@ describe("Threads", () => {
281
389
cy . get ( ".mx_ThreadView .mx_MVoiceMessageBody" ) . should ( "have.length" , 1 ) ;
282
390
} ) ;
283
391
392
+ it ( "should send location and reply to the location on ThreadView" , ( ) => {
393
+ // See: location.spec.ts
394
+ const selectLocationShareTypeOption = ( shareType : string ) : Chainable < JQuery > => {
395
+ return cy . get ( `[data-test-id="share-location-option-${ shareType } "]` ) ;
396
+ } ;
397
+ const submitShareLocation = ( ) : void => {
398
+ cy . get ( '[data-testid="location-picker-submit-button"]' ) . click ( ) ;
399
+ } ;
400
+
401
+ let bot : MatrixClient ;
402
+ cy . getBot ( homeserver , {
403
+ displayName : "BotBob" ,
404
+ autoAcceptInvites : false ,
405
+ } ) . then ( ( _bot ) => {
406
+ bot = _bot ;
407
+ } ) ;
408
+
409
+ let roomId : string ;
410
+ cy . createRoom ( { } ) . then ( ( _roomId ) => {
411
+ roomId = _roomId ;
412
+ cy . inviteUser ( roomId , bot . getUserId ( ) ) ;
413
+ bot . joinRoom ( roomId ) ;
414
+ cy . visit ( "/#/room/" + roomId ) ;
415
+ } ) ;
416
+
417
+ // Exclude timestamp, read marker, and mapboxgl-map from snapshots
418
+ const percyCSS =
419
+ ".mx_MessageTimestamp, .mx_RoomView_myReadMarker, .mapboxgl-map { visibility: hidden !important; }" ;
420
+
421
+ // User sends message
422
+ cy . get ( ".mx_RoomView_body .mx_BasicMessageComposer_input" ) . type ( "Hello Mr. Bot{enter}" ) ;
423
+
424
+ // Wait for message to send, get its ID and save as @threadId
425
+ cy . contains ( ".mx_RoomView_body .mx_EventTile[data-scroll-tokens]" , "Hello Mr. Bot" )
426
+ . invoke ( "attr" , "data-scroll-tokens" )
427
+ . as ( "threadId" ) ;
428
+
429
+ // Bot starts thread
430
+ cy . get < string > ( "@threadId" ) . then ( ( threadId ) => {
431
+ bot . sendMessage ( roomId , threadId , {
432
+ body : "Hello there" ,
433
+ msgtype : "m.text" ,
434
+ } ) ;
435
+ } ) ;
436
+
437
+ // User clicks thread summary
438
+ cy . get ( ".mx_RoomView_body .mx_ThreadSummary" ) . click ( ) ;
439
+
440
+ // User sends location on ThreadView
441
+ cy . get ( ".mx_ThreadView" ) . should ( "exist" ) ;
442
+ cy . openMessageComposerOptions ( true ) . find ( "[aria-label='Location']" ) . click ( ) ;
443
+ selectLocationShareTypeOption ( "Pin" ) . click ( ) ;
444
+ cy . get ( "#mx_LocationPicker_map" ) . click ( "center" ) ;
445
+ submitShareLocation ( ) ;
446
+ cy . get ( ".mx_ThreadView .mx_EventTile_last .mx_MLocationBody" , { timeout : 10000 } ) . should ( "exist" ) ;
447
+
448
+ // User replies to the location
449
+ cy . get ( ".mx_ThreadView" ) . within ( ( ) => {
450
+ cy . get ( ".mx_EventTile_last" )
451
+ . realHover ( )
452
+ . within ( ( ) => {
453
+ cy . get ( "[aria-label='Reply']" ) . click ( { force : false } ) ;
454
+ } ) ;
455
+
456
+ cy . get ( ".mx_BasicMessageComposer_input" ) . type ( "Please come here.{enter}" ) ;
457
+
458
+ // Wait until the reply is sent
459
+ cy . get ( ".mx_EventTile_last .mx_EventTile_receiptSent" ) . should ( "be.visible" ) ;
460
+ } ) ;
461
+
462
+ // Take a snapshot of reply to the shared location
463
+ cy . get ( ".mx_ThreadView" ) . percySnapshotElement ( "Reply to the location on ThreadView" , { percyCSS } ) ;
464
+ } ) ;
465
+
284
466
it ( "right panel behaves correctly" , ( ) => {
285
467
// Create room
286
468
let roomId : string ;
0 commit comments