@@ -24,27 +24,27 @@ import 'test_app.dart';
24
24
void main () {
25
25
TestZulipBinding .ensureInitialized ();
26
26
27
- group ('markNarrowAsRead' , () {
28
- late PerAccountStore store;
29
- late FakeApiConnection connection;
30
- late BuildContext context;
27
+ late PerAccountStore store;
28
+ late FakeApiConnection connection;
29
+ late BuildContext context;
31
30
32
- Future <void > prepare (WidgetTester tester, {
33
- UnreadMessagesSnapshot ? unreadMsgs,
34
- }) async {
35
- addTearDown (testBinding.reset);
36
- await testBinding.globalStore.add (eg.selfAccount, eg.initialSnapshot (
37
- unreadMsgs: unreadMsgs));
38
- store = await testBinding.globalStore.perAccount (eg.selfAccount.id);
39
- connection = store.connection as FakeApiConnection ;
31
+ Future <void > prepare (WidgetTester tester, {
32
+ UnreadMessagesSnapshot ? unreadMsgs,
33
+ }) async {
34
+ addTearDown (testBinding.reset);
35
+ await testBinding.globalStore.add (eg.selfAccount, eg.initialSnapshot (
36
+ unreadMsgs: unreadMsgs));
37
+ store = await testBinding.globalStore.perAccount (eg.selfAccount.id);
38
+ connection = store.connection as FakeApiConnection ;
40
39
41
- await tester.pumpWidget (TestZulipApp (accountId: eg.selfAccount.id,
42
- child: const Scaffold (body: Placeholder ())));
43
- // global store, per-account store get loaded
44
- await tester.pumpAndSettle ();
45
- context = tester.element (find.byType (Placeholder ));
46
- }
40
+ await tester.pumpWidget (TestZulipApp (accountId: eg.selfAccount.id,
41
+ child: const Scaffold (body: Placeholder ())));
42
+ // global store, per-account store get loaded
43
+ await tester.pumpAndSettle ();
44
+ context = tester.element (find.byType (Placeholder ));
45
+ }
47
46
47
+ group ('markNarrowAsRead' , () {
48
48
testWidgets ('smoke test on modern server' , (tester) async {
49
49
final narrow = TopicNarrow .ofMessage (eg.streamMessage ());
50
50
await prepare (tester);
@@ -69,7 +69,6 @@ void main() {
69
69
});
70
70
});
71
71
72
-
73
72
testWidgets ('use is:unread optimization' , (tester) async {
74
73
const narrow = CombinedFeedNarrow ();
75
74
await prepare (tester);
@@ -93,51 +92,6 @@ void main() {
93
92
});
94
93
});
95
94
96
- testWidgets ('pagination' , (tester) async {
97
- // Check that `lastProcessedId` returned from an initial
98
- // response is used as `anchorId` for the subsequent request.
99
- final narrow = TopicNarrow .ofMessage (eg.streamMessage ());
100
- await prepare (tester);
101
-
102
- connection.prepare (json: UpdateMessageFlagsForNarrowResult (
103
- processedCount: 1000 , updatedCount: 890 ,
104
- firstProcessedId: 1 , lastProcessedId: 1989 ,
105
- foundOldest: true , foundNewest: false ).toJson ());
106
- markNarrowAsRead (context, narrow);
107
- final apiNarrow = narrow.apiEncode ()..add (ApiNarrowIsUnread ());
108
- check (connection.lastRequest).isA< http.Request > ()
109
- ..method.equals ('POST' )
110
- ..url.path.equals ('/api/v1/messages/flags/narrow' )
111
- ..bodyFields.deepEquals ({
112
- 'anchor' : 'oldest' ,
113
- 'include_anchor' : 'false' ,
114
- 'num_before' : '0' ,
115
- 'num_after' : '1000' ,
116
- 'narrow' : jsonEncode (apiNarrow),
117
- 'op' : 'add' ,
118
- 'flag' : 'read' ,
119
- });
120
-
121
- connection.prepare (json: UpdateMessageFlagsForNarrowResult (
122
- processedCount: 20 , updatedCount: 10 ,
123
- firstProcessedId: 2000 , lastProcessedId: 2023 ,
124
- foundOldest: false , foundNewest: true ).toJson ());
125
- await tester.pumpAndSettle ();
126
- check (find.bySubtype <SnackBar >().evaluate ()).length.equals (1 );
127
- check (connection.lastRequest).isA< http.Request > ()
128
- ..method.equals ('POST' )
129
- ..url.path.equals ('/api/v1/messages/flags/narrow' )
130
- ..bodyFields.deepEquals ({
131
- 'anchor' : '1989' ,
132
- 'include_anchor' : 'false' ,
133
- 'num_before' : '0' ,
134
- 'num_after' : '1000' ,
135
- 'narrow' : jsonEncode (apiNarrow),
136
- 'op' : 'add' ,
137
- 'flag' : 'read' ,
138
- });
139
- });
140
-
141
95
testWidgets ('on mark-all-as-read when Unreads.oldUnreadsMissing: true' , (tester) async {
142
96
const narrow = CombinedFeedNarrow ();
143
97
await prepare (tester);
@@ -153,36 +107,6 @@ void main() {
153
107
check (store.unreads.oldUnreadsMissing).isFalse ();
154
108
});
155
109
156
- testWidgets ('on invalid response' , (tester) async {
157
- final zulipLocalizations = GlobalLocalizations .zulipLocalizations;
158
- final narrow = TopicNarrow .ofMessage (eg.streamMessage ());
159
- await prepare (tester);
160
- connection.prepare (json: UpdateMessageFlagsForNarrowResult (
161
- processedCount: 1000 , updatedCount: 0 ,
162
- firstProcessedId: null , lastProcessedId: null ,
163
- foundOldest: true , foundNewest: false ).toJson ());
164
- markNarrowAsRead (context, narrow);
165
- await tester.pump (Duration .zero);
166
- final apiNarrow = narrow.apiEncode ()..add (ApiNarrowIsUnread ());
167
- check (connection.lastRequest).isA< http.Request > ()
168
- ..method.equals ('POST' )
169
- ..url.path.equals ('/api/v1/messages/flags/narrow' )
170
- ..bodyFields.deepEquals ({
171
- 'anchor' : 'oldest' ,
172
- 'include_anchor' : 'false' ,
173
- 'num_before' : '0' ,
174
- 'num_after' : '1000' ,
175
- 'narrow' : jsonEncode (apiNarrow),
176
- 'op' : 'add' ,
177
- 'flag' : 'read' ,
178
- });
179
-
180
- await tester.pumpAndSettle ();
181
- checkErrorDialog (tester,
182
- expectedTitle: zulipLocalizations.errorMarkAsReadFailedTitle,
183
- expectedMessage: zulipLocalizations.errorInvalidResponse);
184
- });
185
-
186
110
testWidgets ('CombinedFeedNarrow on legacy server' , (tester) async {
187
111
const narrow = CombinedFeedNarrow ();
188
112
await prepare (tester);
@@ -277,18 +201,133 @@ void main() {
277
201
'flag' : 'read' ,
278
202
});
279
203
});
204
+ });
280
205
281
- testWidgets ('catch-all api errors' , (tester) async {
206
+ group ('updateMessageFlagsStartingFromAnchor' , () {
207
+ String onCompletedMessage (int count) => 'onCompletedMessage($count )' ;
208
+ const progressMessage = 'progressMessage' ;
209
+ const onFailedTitle = 'onFailedTitle' ;
210
+ final narrow = TopicNarrow .ofMessage (eg.streamMessage ());
211
+ final apiNarrow = narrow.apiEncode ()..add (ApiNarrowIsUnread ());
212
+
213
+ Future <bool > invokeUpdateMessageFlagsStartingFromAnchor () =>
214
+ updateMessageFlagsStartingFromAnchor (
215
+ context: context,
216
+ apiNarrow: apiNarrow,
217
+ op: UpdateMessageFlagsOp .add,
218
+ flag: MessageFlag .read,
219
+ includeAnchor: false ,
220
+ startingAnchor: AnchorCode .oldest,
221
+ onCompletedMessage: onCompletedMessage,
222
+ onFailedTitle: onFailedTitle,
223
+ progressMessage: progressMessage);
224
+
225
+ testWidgets ('smoke test' , (tester) async {
226
+ await prepare (tester);
227
+ connection.prepare (json: UpdateMessageFlagsForNarrowResult (
228
+ processedCount: 11 , updatedCount: 3 ,
229
+ firstProcessedId: 1 , lastProcessedId: 1980 ,
230
+ foundOldest: true , foundNewest: true ).toJson ());
231
+ final didPass = invokeUpdateMessageFlagsStartingFromAnchor ();
232
+ await tester.pump (Duration .zero);
233
+ check (connection.lastRequest).isA< http.Request > ()
234
+ ..method.equals ('POST' )
235
+ ..url.path.equals ('/api/v1/messages/flags/narrow' )
236
+ ..bodyFields.deepEquals ({
237
+ 'anchor' : 'oldest' ,
238
+ 'include_anchor' : 'false' ,
239
+ 'num_before' : '0' ,
240
+ 'num_after' : '1000' ,
241
+ 'narrow' : jsonEncode (apiNarrow),
242
+ 'op' : 'add' ,
243
+ 'flag' : 'read' ,
244
+ });
245
+ check (await didPass).isTrue ();
246
+ });
247
+
248
+ testWidgets ('pagination' , (tester) async {
249
+ // Check that `lastProcessedId` returned from an initial
250
+ // response is used as `anchorId` for the subsequent request.
251
+ await prepare (tester);
252
+
253
+ connection.prepare (json: UpdateMessageFlagsForNarrowResult (
254
+ processedCount: 1000 , updatedCount: 890 ,
255
+ firstProcessedId: 1 , lastProcessedId: 1989 ,
256
+ foundOldest: true , foundNewest: false ).toJson ());
257
+ final didPass = invokeUpdateMessageFlagsStartingFromAnchor ();
258
+ check (connection.lastRequest).isA< http.Request > ()
259
+ ..method.equals ('POST' )
260
+ ..url.path.equals ('/api/v1/messages/flags/narrow' )
261
+ ..bodyFields.deepEquals ({
262
+ 'anchor' : 'oldest' ,
263
+ 'include_anchor' : 'false' ,
264
+ 'num_before' : '0' ,
265
+ 'num_after' : '1000' ,
266
+ 'narrow' : jsonEncode (apiNarrow),
267
+ 'op' : 'add' ,
268
+ 'flag' : 'read' ,
269
+ });
270
+
271
+ connection.prepare (json: UpdateMessageFlagsForNarrowResult (
272
+ processedCount: 20 , updatedCount: 10 ,
273
+ firstProcessedId: 2000 , lastProcessedId: 2023 ,
274
+ foundOldest: false , foundNewest: true ).toJson ());
275
+ await tester.pumpAndSettle ();
276
+ check (find.bySubtype <SnackBar >().evaluate ()).length.equals (1 );
277
+ check (connection.lastRequest).isA< http.Request > ()
278
+ ..method.equals ('POST' )
279
+ ..url.path.equals ('/api/v1/messages/flags/narrow' )
280
+ ..bodyFields.deepEquals ({
281
+ 'anchor' : '1989' ,
282
+ 'include_anchor' : 'false' ,
283
+ 'num_before' : '0' ,
284
+ 'num_after' : '1000' ,
285
+ 'narrow' : jsonEncode (apiNarrow),
286
+ 'op' : 'add' ,
287
+ 'flag' : 'read' ,
288
+ });
289
+ check (await didPass).isTrue ();
290
+ });
291
+
292
+ testWidgets ('on invalid response' , (tester) async {
282
293
final zulipLocalizations = GlobalLocalizations .zulipLocalizations;
283
- const narrow = CombinedFeedNarrow ();
294
+ await prepare (tester);
295
+ connection.prepare (json: UpdateMessageFlagsForNarrowResult (
296
+ processedCount: 1000 , updatedCount: 0 ,
297
+ firstProcessedId: null , lastProcessedId: null ,
298
+ foundOldest: true , foundNewest: false ).toJson ());
299
+ final didPass = invokeUpdateMessageFlagsStartingFromAnchor ();
300
+ await tester.pump (Duration .zero);
301
+ check (connection.lastRequest).isA< http.Request > ()
302
+ ..method.equals ('POST' )
303
+ ..url.path.equals ('/api/v1/messages/flags/narrow' )
304
+ ..bodyFields.deepEquals ({
305
+ 'anchor' : 'oldest' ,
306
+ 'include_anchor' : 'false' ,
307
+ 'num_before' : '0' ,
308
+ 'num_after' : '1000' ,
309
+ 'narrow' : jsonEncode (apiNarrow),
310
+ 'op' : 'add' ,
311
+ 'flag' : 'read' ,
312
+ });
313
+
314
+ await tester.pumpAndSettle ();
315
+ checkErrorDialog (tester,
316
+ expectedTitle: onFailedTitle,
317
+ expectedMessage: zulipLocalizations.errorInvalidResponse);
318
+ check (await didPass).isFalse ();
319
+ });
320
+
321
+ testWidgets ('catch-all api errors' , (tester) async {
284
322
await prepare (tester);
285
323
connection.prepare (exception: http.ClientException ('Oops' ));
286
- markNarrowAsRead (context, narrow );
324
+ final didPass = invokeUpdateMessageFlagsStartingFromAnchor ( );
287
325
await tester.pump (Duration .zero);
288
326
await tester.pumpAndSettle ();
289
327
checkErrorDialog (tester,
290
- expectedTitle: zulipLocalizations.errorMarkAsReadFailedTitle ,
328
+ expectedTitle: onFailedTitle ,
291
329
expectedMessage: 'NetworkException: Oops (ClientException: Oops)' );
330
+ check (await didPass).isFalse ();
292
331
});
293
332
});
294
333
}
0 commit comments