@@ -14,6 +14,7 @@ import 'package:zulip/api/model/model.dart';
1414import 'package:zulip/api/model/narrow.dart' ;
1515import 'package:zulip/api/route/channels.dart' ;
1616import 'package:zulip/api/route/messages.dart' ;
17+ import 'package:zulip/basic.dart' ;
1718import 'package:zulip/model/actions.dart' ;
1819import 'package:zulip/model/localizations.dart' ;
1920import 'package:zulip/model/message.dart' ;
@@ -26,6 +27,7 @@ import 'package:zulip/widgets/autocomplete.dart';
2627import 'package:zulip/widgets/color.dart' ;
2728import 'package:zulip/widgets/compose_box.dart' ;
2829import 'package:zulip/widgets/content.dart' ;
30+ import 'package:zulip/widgets/emoji.dart' ;
2931import 'package:zulip/widgets/icons.dart' ;
3032import 'package:zulip/widgets/message_list.dart' ;
3133import 'package:zulip/widgets/page.dart' ;
@@ -50,6 +52,22 @@ import 'message_list_checks.dart';
5052import 'page_checks.dart' ;
5153import 'test_app.dart' ;
5254
55+ /// Finder for [UserStatusEmoji] widget.
56+ ///
57+ /// Use [type] to specify the exact emoji child widget. It can be either
58+ /// [UnicodeEmojiWidget] or [ImageEmojiWidget] .
59+ Finder findStatusEmoji (Type type) {
60+ assert (type == UnicodeEmojiWidget || type == ImageEmojiWidget );
61+ return find.ancestor (
62+ of: find.byType (type),
63+ matching: find.byType (UserStatusEmoji ));
64+ }
65+
66+ void checkUserStatusEmoji (Finder emojiFinder, {required bool isAnimated}) {
67+ check ((emojiFinder
68+ .evaluate ().first.widget as UserStatusEmoji ).neverAnimate).equals (! isAnimated);
69+ }
70+
5371void main () {
5472 TestZulipBinding .ensureInitialized ();
5573 MessageListPage .debugEnableMarkReadOnScroll = false ;
@@ -66,6 +84,7 @@ void main() {
6684 List <ZulipStream >? streams,
6785 List <User >? users,
6886 List <int >? mutedUserIds,
87+ List <(int userId, UserStatusChange change)>? userStatuses,
6988 List <Subscription >? subscriptions,
7089 UnreadMessagesSnapshot ? unreadMsgs,
7190 int ? zulipFeatureLevel,
@@ -91,6 +110,7 @@ void main() {
91110 if (mutedUserIds != null ) {
92111 await store.setMutedUsers (mutedUserIds);
93112 }
113+ await store.changeUserStatuses (userStatuses ?? []);
94114 if (fetchResult != null ) {
95115 assert (foundOldest && messageCount == null && messages == null );
96116 } else {
@@ -1755,6 +1775,64 @@ void main() {
17551775 debugNetworkImageHttpClientProvider = null ;
17561776 });
17571777
1778+ group ('User status emoji' , () {
1779+ void checkStatusEmoji (User user, Type type, {required bool isPresent}) {
1780+ final nameFinder = find.text (user.fullName);
1781+ final statusEmojiFinder = findStatusEmoji (type);
1782+
1783+ check (nameFinder).findsOne ();
1784+ check (statusEmojiFinder).findsExactly (isPresent ? 1 : 0 );
1785+ if (isPresent) {
1786+ checkUserStatusEmoji (statusEmojiFinder, isAnimated: false );
1787+ }
1788+
1789+ final senderRowFinder = find.ancestor (of: nameFinder,
1790+ matching: find.ancestor (of: statusEmojiFinder,
1791+ matching: find.byType (Row )));
1792+ isPresent
1793+ ? check (senderRowFinder).findsAny ()
1794+ : check (senderRowFinder).findsNothing ();
1795+ }
1796+
1797+ final user1 = eg.user (userId: 1 ,
1798+ fullName: 'User with a very very very long name to check if emoji is still visible' );
1799+ final user2 = eg.user (userId: 2 , fullName: 'User 2' );
1800+
1801+ testWidgets ('status emoji is set -> emoji is displayed' , (tester) async {
1802+ await setupMessageListPage (tester,
1803+ users: [user1, user2],
1804+ messages: [eg.streamMessage (sender: user1), eg.streamMessage (sender: user2)],
1805+ userStatuses: [
1806+ (
1807+ user1.userId,
1808+ UserStatusChange (
1809+ text: OptionSome ('Busy' ),
1810+ emoji: OptionSome (StatusEmoji (emojiName: 'working_on_it' ,
1811+ emojiCode: '1f6e0' , reactionType: ReactionType .unicodeEmoji)))
1812+ ),
1813+ (
1814+ user2.userId,
1815+ UserStatusChange (
1816+ text: OptionSome ('Coding' ),
1817+ emoji: OptionSome (StatusEmoji (emojiName: 'zulip' ,
1818+ emojiCode: 'zulip' , reactionType: ReactionType .zulipExtraEmoji)))
1819+ ),
1820+ ],
1821+ );
1822+ checkStatusEmoji (user1, UnicodeEmojiWidget , isPresent: true );
1823+ checkStatusEmoji (user2, ImageEmojiWidget , isPresent: true );
1824+ });
1825+
1826+ testWidgets ('status emoji is not set -> emoji is not displayed' , (tester) async {
1827+ await setupMessageListPage (tester,
1828+ users: [user1],
1829+ messages: [eg.streamMessage (sender: user1)],
1830+ userStatuses: [],
1831+ );
1832+ checkStatusEmoji (user1, UnicodeEmojiWidget , isPresent: false );
1833+ });
1834+ });
1835+
17581836 group ('Muted sender' , () {
17591837 void checkMessage (Message message, {required bool expectIsMuted}) {
17601838 final mutedLabel = 'Muted user' ;
0 commit comments