1
+ import 'dart:convert' ;
2
+
1
3
import 'package:checks/checks.dart' ;
2
4
import 'package:flutter/material.dart' ;
3
5
import 'package:flutter/services.dart' ;
@@ -7,10 +9,12 @@ import 'package:http/http.dart' as http;
7
9
import 'package:zulip/api/model/model.dart' ;
8
10
import 'package:zulip/api/route/messages.dart' ;
9
11
import 'package:zulip/model/compose.dart' ;
12
+ import 'package:zulip/model/localizations.dart' ;
10
13
import 'package:zulip/model/narrow.dart' ;
11
14
import 'package:zulip/model/store.dart' ;
12
15
import 'package:zulip/widgets/compose_box.dart' ;
13
16
import 'package:zulip/widgets/content.dart' ;
17
+ import 'package:zulip/widgets/icons.dart' ;
14
18
import 'package:zulip/widgets/message_list.dart' ;
15
19
import 'package:zulip/widgets/store.dart' ;
16
20
import 'package:share_plus_platform_interface/method_channel/method_channel_share.dart' ;
@@ -387,4 +391,100 @@ void main() {
387
391
check (await Clipboard .getData ('text/plain' )).isNull ();
388
392
});
389
393
});
394
+
395
+ group ('StarButton' , () {
396
+ Future <void > tapButton (WidgetTester tester) async {
397
+ // Starred messages include the same icon so we need to
398
+ // match only by descendants of [BottomSheet].
399
+ await tester.ensureVisible (find.descendant (
400
+ of: find.byType (BottomSheet ),
401
+ matching: find.byIcon (ZulipIcons .star, skipOffstage: false )));
402
+ await tester.tap (find.descendant (
403
+ of: find.byType (BottomSheet ),
404
+ matching: find.byIcon (ZulipIcons .star)));
405
+ await tester.pump (); // [MenuItemButton.onPressed] called in a post-frame callback: flutter/flutter@e4a39fa2e
406
+ }
407
+
408
+ testWidgets ('star success' , (WidgetTester tester) async {
409
+ final message = eg.streamMessage (flags: []);
410
+ await setupToMessageActionSheet (tester, message: message, narrow: TopicNarrow .ofMessage (message));
411
+ final store = await testBinding.globalStore.perAccount (eg.selfAccount.id);
412
+
413
+ final connection = store.connection as FakeApiConnection ;
414
+ connection.prepare (json: {});
415
+ await tapButton (tester);
416
+ await tester.pump (Duration .zero);
417
+
418
+ check (connection.lastRequest).isA< http.Request > ()
419
+ ..method.equals ('POST' )
420
+ ..url.path.equals ('/api/v1/messages/flags' )
421
+ ..bodyFields.deepEquals ({
422
+ 'messages' : jsonEncode ([message.id]),
423
+ 'op' : 'add' ,
424
+ 'flag' : 'starred' ,
425
+ });
426
+ });
427
+
428
+ testWidgets ('unstar success' , (WidgetTester tester) async {
429
+ final message = eg.streamMessage (flags: [MessageFlag .starred]);
430
+ await setupToMessageActionSheet (tester, message: message, narrow: TopicNarrow .ofMessage (message));
431
+ final store = await testBinding.globalStore.perAccount (eg.selfAccount.id);
432
+
433
+ final connection = store.connection as FakeApiConnection ;
434
+ connection.prepare (json: {});
435
+ await tapButton (tester);
436
+ await tester.pump (Duration .zero);
437
+
438
+ check (connection.lastRequest).isA< http.Request > ()
439
+ ..method.equals ('POST' )
440
+ ..url.path.equals ('/api/v1/messages/flags' )
441
+ ..bodyFields.deepEquals ({
442
+ 'messages' : jsonEncode ([message.id]),
443
+ 'op' : 'remove' ,
444
+ 'flag' : 'starred' ,
445
+ });
446
+ });
447
+
448
+ testWidgets ('star request has an error' , (WidgetTester tester) async {
449
+ final message = eg.streamMessage (flags: []);
450
+ await setupToMessageActionSheet (tester, message: message, narrow: TopicNarrow .ofMessage (message));
451
+ final store = await testBinding.globalStore.perAccount (eg.selfAccount.id);
452
+ final zulipLocalizations = GlobalLocalizations .zulipLocalizations;
453
+
454
+ final connection = store.connection as FakeApiConnection ;
455
+
456
+ connection.prepare (httpStatus: 400 , json: {
457
+ 'code' : 'BAD_REQUEST' ,
458
+ 'msg' : 'Invalid message(s)' ,
459
+ 'result' : 'error' ,
460
+ });
461
+ await tapButton (tester);
462
+ await tester.pump (Duration .zero); // error arrives; error dialog shows
463
+
464
+ await tester.tap (find.byWidget (checkErrorDialog (tester,
465
+ expectedTitle: zulipLocalizations.errorStarMessageFailedTitle,
466
+ expectedMessage: 'Invalid message(s)' )));
467
+ });
468
+
469
+ testWidgets ('unstar request has an error' , (WidgetTester tester) async {
470
+ final message = eg.streamMessage (flags: [MessageFlag .starred]);
471
+ await setupToMessageActionSheet (tester, message: message, narrow: TopicNarrow .ofMessage (message));
472
+ final store = await testBinding.globalStore.perAccount (eg.selfAccount.id);
473
+ final zulipLocalizations = GlobalLocalizations .zulipLocalizations;
474
+
475
+ final connection = store.connection as FakeApiConnection ;
476
+
477
+ connection.prepare (httpStatus: 400 , json: {
478
+ 'code' : 'BAD_REQUEST' ,
479
+ 'msg' : 'Invalid message(s)' ,
480
+ 'result' : 'error' ,
481
+ });
482
+ await tapButton (tester);
483
+ await tester.pump (Duration .zero); // error arrives; error dialog shows
484
+
485
+ await tester.tap (find.byWidget (checkErrorDialog (tester,
486
+ expectedTitle: zulipLocalizations.errorUnstarMessageFailedTitle,
487
+ expectedMessage: 'Invalid message(s)' )));
488
+ });
489
+ });
390
490
}
0 commit comments