1
+ import 'package:checks/checks.dart' ;
2
+ import 'package:test/scaffolding.dart' ;
3
+ import 'package:zulip/api/model/events.dart' ;
4
+ import 'package:zulip/api/model/model.dart' ;
5
+ import 'package:zulip/api/route/messages.dart' ;
6
+ import 'package:zulip/model/message_list.dart' ;
7
+ import 'package:zulip/model/narrow.dart' ;
8
+ import 'package:zulip/model/store.dart' ;
9
+ import '../api/fake_api.dart' ;
10
+ import '../api/model/model_checks.dart' ;
11
+ import '../model/binding.dart' ;
12
+ import '../model/test_store.dart' ;
13
+ import '../example_data.dart' as eg;
14
+
15
+ const int userId = 1 ;
16
+ const int streamId = 2 ;
17
+
18
+ Future <PerAccountStore > setupStore (ZulipStream stream) async {
19
+ await TestZulipBinding .instance.globalStore.add (eg.selfAccount, eg.initialSnapshot ());
20
+ PerAccountStore store = await TestZulipBinding .instance.globalStore.perAccount (eg.selfAccount.id);
21
+ store.addUser (eg.user (userId: userId));
22
+ store.addStream (stream);
23
+ return store;
24
+ }
25
+
26
+ Future <MessageListView > messageListViewWithMessages (List <Message > messages, PerAccountStore store, Narrow narrow) async {
27
+ MessageListView messageList = MessageListView .init (store: store, narrow: narrow);
28
+
29
+ final connection = store.connection as FakeApiConnection ;
30
+
31
+ connection.prepare (json: GetMessagesResult (
32
+ anchor: messages.first.id,
33
+ foundNewest: true ,
34
+ foundOldest: true ,
35
+ foundAnchor: true ,
36
+ historyLimited: false ,
37
+ messages: messages,
38
+ ).toJson ());
39
+
40
+ await messageList.fetch ();
41
+
42
+ check (messageList.messages.length).equals (messages.length);
43
+
44
+ return messageList;
45
+ }
46
+
47
+ void main () async {
48
+ TestZulipBinding .ensureInitialized ();
49
+ const narrow = StreamNarrow (streamId);
50
+
51
+ final ZulipStream stream = eg.stream (streamId: streamId);
52
+ PerAccountStore store = await setupStore (stream);
53
+
54
+ group ('update message tests' , () {
55
+
56
+ test ('find message in message list returns index of message' , () async {
57
+ Message m1 = eg.streamMessage (id: 792 , stream: stream);
58
+ Message m2 = eg.streamMessage (id: 793 , stream: stream);
59
+ Message m3 = eg.streamMessage (id: 794 , stream: stream);
60
+
61
+ MessageListView messageList = await messageListViewWithMessages ([m1, m2, m3], store, narrow);
62
+
63
+ int idx = messageList.findMessageWithId (793 );
64
+ check (idx).equals (1 );
65
+
66
+ idx = messageList.findMessageWithId (999 );
67
+ check (idx).equals (- 1 );
68
+ });
69
+
70
+ test ('update events are correctly applied to message when it is in the stream' , () async {
71
+ String oldContent = "<p>Hello, world</p>" ;
72
+ String newContent = "<p>Hello, edited</p>" ;
73
+ int newTimestamp = 99999 ;
74
+
75
+ List <String > oldFlags = [];
76
+ List <String > newFlags = ["starred" ];
77
+
78
+ Message mockMessage = eg.streamMessage (id: 243 , stream: stream, content: oldContent, flags: oldFlags);
79
+ MessageListView messageList = await messageListViewWithMessages ([mockMessage], store, narrow);
80
+
81
+ UpdateMessageEvent updateEvent = UpdateMessageEvent (
82
+ id: 1 ,
83
+ messageId: mockMessage.id,
84
+ messageIds: [mockMessage.id],
85
+ flags: newFlags,
86
+ renderedContent: newContent,
87
+ editTimestamp: newTimestamp,
88
+ isMeMessage: true ,
89
+ userId: userId
90
+ );
91
+
92
+ Message message = messageList.messages[0 ];
93
+ check (message)
94
+ ..content.equals (oldContent)
95
+ ..flags.deepEquals (oldFlags)
96
+ ..isMeMessage.equals (false );
97
+
98
+ bool listenersNotified = false ;
99
+
100
+ messageList.addListener (() { listenersNotified = true ; });
101
+ messageList.maybeUpdateMessage (updateEvent);
102
+
103
+ Message updatedMessage = messageList.messages[0 ];
104
+ check (updatedMessage).identicalTo (message);
105
+ check (listenersNotified).equals (true );
106
+
107
+ check (message)
108
+ ..content.equals (newContent)
109
+ ..lastEditTimestamp.equals (newTimestamp)
110
+ ..flags.equals (newFlags)
111
+ ..isMeMessage.equals (true );
112
+ });
113
+
114
+ test ('update event is ignored when message is not in the message list' , () async {
115
+ String oldContent = "<p>Hello, world</p>" ;
116
+ String newContent = "<p>Hello, edited</p>" ;
117
+ int newTimestamp = 99999 ;
118
+
119
+ Message mockMessage = eg.streamMessage (id: 243 , stream: stream, content: oldContent);
120
+ MessageListView messageList = await messageListViewWithMessages ([mockMessage], store, narrow);
121
+
122
+ UpdateMessageEvent updateEvent = UpdateMessageEvent (
123
+ id: 1 ,
124
+ messageId: 972 ,
125
+ messageIds: [972 ],
126
+ flags: mockMessage.flags,
127
+ renderedContent: newContent,
128
+ editTimestamp: newTimestamp,
129
+ userId: userId,
130
+ );
131
+
132
+ Message message = messageList.messages[0 ];
133
+ check (message).content.equals (oldContent);
134
+
135
+ bool listenersNotified = false ;
136
+
137
+ messageList.addListener (() { listenersNotified = true ; });
138
+ messageList.maybeUpdateMessage (updateEvent);
139
+
140
+ Message updatedMessage = messageList.messages[0 ];
141
+
142
+ check (listenersNotified).equals (false );
143
+ check (updatedMessage).identicalTo (message);
144
+ check (message).content.equals (oldContent);
145
+
146
+ });
147
+ test ('rendering-only update does not change timestamp' , () async {
148
+ String oldContent = "<p>Hello, world</p>" ;
149
+ String newContent = "<p>Hello, world</p> <div>Some link preview</div>" ;
150
+ int newTimestamp = 99999 ;
151
+
152
+ Message mockMessage = eg.streamMessage (id: 972 , stream: stream, content: oldContent);
153
+ MessageListView messageList = await messageListViewWithMessages ([mockMessage], store, narrow);
154
+
155
+ UpdateMessageEvent updateEvent = UpdateMessageEvent (
156
+ id: 1 ,
157
+ messageId: 972 ,
158
+ messageIds: [972 ],
159
+ flags: mockMessage.flags,
160
+ renderedContent: newContent,
161
+ editTimestamp: newTimestamp,
162
+ renderingOnly: true ,
163
+ userId: null ,
164
+ );
165
+
166
+ Message message = messageList.messages[0 ];
167
+ messageList.maybeUpdateMessage (updateEvent);
168
+ check (message)
169
+ ..content.equals (newContent)
170
+ ..lastEditTimestamp.isNull ();
171
+ });
172
+
173
+ test ('rendering-only update does not change timestamp (for old server versions)' , () async {
174
+ String oldContent = "<p>Hello, world</p>" ;
175
+ String newContent = "<p>Hello, world</p> <div>Some link preview</div>" ;
176
+ int newTimestamp = 99999 ;
177
+
178
+ Message mockMessage = eg.streamMessage (id: 972 , stream: stream, content: oldContent);
179
+ MessageListView messageList = await messageListViewWithMessages ([mockMessage], store, narrow);
180
+
181
+ UpdateMessageEvent updateEvent = UpdateMessageEvent (
182
+ id: 1 ,
183
+ messageId: 972 ,
184
+ messageIds: [972 ],
185
+ flags: mockMessage.flags,
186
+ renderedContent: newContent,
187
+ editTimestamp: newTimestamp,
188
+ userId: null ,
189
+ );
190
+
191
+ Message message = messageList.messages[0 ];
192
+ messageList.maybeUpdateMessage (updateEvent);
193
+ check (message)
194
+ ..content.equals (newContent)
195
+ ..lastEditTimestamp.isNull ();
196
+ });
197
+
198
+
199
+ });
200
+ }
0 commit comments