@@ -3,6 +3,8 @@ import 'package:flutter/material.dart';
33import 'package:flutter_checks/flutter_checks.dart' ;
44import 'package:flutter_test/flutter_test.dart' ;
55import 'package:zulip/api/model/model.dart' ;
6+ import 'package:zulip/basic.dart' ;
7+ import 'package:zulip/model/store.dart' ;
68import 'package:zulip/widgets/app_bar.dart' ;
79import 'package:zulip/widgets/compose_box.dart' ;
810import 'package:zulip/widgets/content.dart' ;
@@ -19,6 +21,8 @@ import '../model/test_store.dart';
1921import '../test_navigation.dart' ;
2022import 'test_app.dart' ;
2123
24+ late PerAccountStore store;
25+
2226Future <void > setupSheet (WidgetTester tester, {
2327 required List <User > users,
2428 List <int >? mutedUserIds,
@@ -30,7 +34,7 @@ Future<void> setupSheet(WidgetTester tester, {
3034 ..onPushed = (route, _) => lastPushedRoute = route;
3135
3236 await testBinding.globalStore.add (eg.selfAccount, eg.initialSnapshot ());
33- final store = await testBinding.globalStore.perAccount (eg.selfAccount.id);
37+ store = await testBinding.globalStore.perAccount (eg.selfAccount.id);
3438 await store.addUsers (users);
3539 if (mutedUserIds != null ) {
3640 await store.setMutedUsers (mutedUserIds);
@@ -65,7 +69,8 @@ void main() {
6569 }
6670
6771 Finder findUserTile (User user) =>
68- find.widgetWithText (InkWell , user.fullName).first;
72+ find.ancestor (of: find.textContaining (user.fullName),
73+ matching: find.byType (InkWell )).first;
6974
7075 Finder findUserChip (User user) {
7176 final findAvatar = find.byWidgetPredicate ((widget) =>
@@ -120,23 +125,23 @@ void main() {
120125
121126 testWidgets ('shows all non-muted users initially' , (tester) async {
122127 await setupSheet (tester, users: testUsers, mutedUserIds: [mutedUser.userId]);
123- check (find.text ('Alice Anderson' )).findsOne ();
124- check (find.text ('Bob Brown' )).findsOne ();
125- check (find.text ('Charlie Carter' )).findsOne ();
128+ check (find.textContaining ('Alice Anderson' )).findsOne ();
129+ check (find.textContaining ('Bob Brown' )).findsOne ();
130+ check (find.textContaining ('Charlie Carter' )).findsOne ();
126131
127132 check (find.byIcon (ZulipIcons .check_circle_unchecked)).findsExactly (3 );
128133 check (find.byIcon (ZulipIcons .check_circle_checked)).findsNothing ();
129- check (find.text ('Someone Muted' )).findsNothing ();
130- check (find.text ('Muted user' )).findsNothing ();
134+ check (find.textContaining ('Someone Muted' )).findsNothing ();
135+ check (find.textContaining ('Muted user' )).findsNothing ();
131136 });
132137
133138 testWidgets ('shows filtered users based on search' , (tester) async {
134139 await setupSheet (tester, users: testUsers);
135140 await tester.enterText (find.byType (TextField ), 'Alice' );
136141 await tester.pump ();
137- check (find.text ('Alice Anderson' )).findsOne ();
138- check (find.text ('Charlie Carter' )).findsNothing ();
139- check (find.text ('Bob Brown' )).findsNothing ();
142+ check (find.textContaining ('Alice Anderson' )).findsOne ();
143+ check (find.textContaining ('Charlie Carter' )).findsNothing ();
144+ check (find.textContaining ('Bob Brown' )).findsNothing ();
140145 });
141146
142147 // TODO test sorting by recent-DMs
@@ -146,43 +151,43 @@ void main() {
146151 await setupSheet (tester, users: testUsers);
147152 await tester.enterText (find.byType (TextField ), 'alice' );
148153 await tester.pump ();
149- check (find.text ('Alice Anderson' )).findsOne ();
154+ check (find.textContaining ('Alice Anderson' )).findsOne ();
150155
151156 await tester.enterText (find.byType (TextField ), 'ALICE' );
152157 await tester.pump ();
153- check (find.text ('Alice Anderson' )).findsOne ();
158+ check (find.textContaining ('Alice Anderson' )).findsOne ();
154159 });
155160
156161 testWidgets ('partial name and last name search handling' , (tester) async {
157162 await setupSheet (tester, users: testUsers);
158163
159164 await tester.enterText (find.byType (TextField ), 'Ali' );
160165 await tester.pump ();
161- check (find.text ('Alice Anderson' )).findsOne ();
162- check (find.text ('Bob Brown' )).findsNothing ();
163- check (find.text ('Charlie Carter' )).findsNothing ();
166+ check (find.textContaining ('Alice Anderson' )).findsOne ();
167+ check (find.textContaining ('Bob Brown' )).findsNothing ();
168+ check (find.textContaining ('Charlie Carter' )).findsNothing ();
164169
165170 await tester.enterText (find.byType (TextField ), 'Anderson' );
166171 await tester.pump ();
167- check (find.text ('Alice Anderson' )).findsOne ();
168- check (find.text ('Charlie Carter' )).findsNothing ();
169- check (find.text ('Bob Brown' )).findsNothing ();
172+ check (find.textContaining ('Alice Anderson' )).findsOne ();
173+ check (find.textContaining ('Charlie Carter' )).findsNothing ();
174+ check (find.textContaining ('Bob Brown' )).findsNothing ();
170175
171176 await tester.enterText (find.byType (TextField ), 'son' );
172177 await tester.pump ();
173- check (find.text ('Alice Anderson' )).findsOne ();
174- check (find.text ('Charlie Carter' )).findsNothing ();
175- check (find.text ('Bob Brown' )).findsNothing ();
178+ check (find.textContaining ('Alice Anderson' )).findsOne ();
179+ check (find.textContaining ('Charlie Carter' )).findsNothing ();
180+ check (find.textContaining ('Bob Brown' )).findsNothing ();
176181 });
177182
178183 testWidgets ('shows empty state when no users match' , (tester) async {
179184 await setupSheet (tester, users: testUsers);
180185 await tester.enterText (find.byType (TextField ), 'Zebra' );
181186 await tester.pump ();
182- check (find.text ('No users found' )).findsOne ();
183- check (find.text ('Alice Anderson' )).findsNothing ();
184- check (find.text ('Bob Brown' )).findsNothing ();
185- check (find.text ('Charlie Carter' )).findsNothing ();
187+ check (find.textContaining ('No users found' )).findsOne ();
188+ check (find.textContaining ('Alice Anderson' )).findsNothing ();
189+ check (find.textContaining ('Bob Brown' )).findsNothing ();
190+ check (find.textContaining ('Charlie Carter' )).findsNothing ();
186191 });
187192
188193 testWidgets ('search text clears when user is selected' , (tester) async {
@@ -252,7 +257,7 @@ void main() {
252257 await tester.tap (findUserTile (eg.selfUser));
253258 await tester.pump ();
254259 checkUserSelected (tester, eg.selfUser, true );
255- check (find.text (eg.selfUser.fullName)).findsExactly (2 );
260+ check (find.textContaining (eg.selfUser.fullName)).findsExactly (2 );
256261
257262 await tester.tap (findUserTile (otherUser));
258263 await tester.pump ();
@@ -264,7 +269,7 @@ void main() {
264269 final otherUser = eg.user (fullName: 'Other User' );
265270 await setupSheet (tester, users: [eg.selfUser, otherUser]);
266271
267- check (find.text (eg.selfUser.fullName)).findsOne ();
272+ check (find.textContaining (eg.selfUser.fullName)).findsOne ();
268273
269274 await tester.tap (findUserTile (otherUser));
270275 await tester.pump ();
@@ -285,6 +290,75 @@ void main() {
285290 });
286291 });
287292
293+ group ('User status' , () {
294+ void checkFindsTileStatusEmoji (WidgetTester tester, User user, Finder emojiFinder) {
295+ final statusEmojiFinder = find.ancestor (of: emojiFinder,
296+ matching: find.byType (UserStatusEmoji ));
297+ final tileStatusEmojiFinder = find.descendant (of: findUserTile (user),
298+ matching: statusEmojiFinder);
299+ check (tester.firstWidget <UserStatusEmoji >(tileStatusEmojiFinder)
300+ .neverAnimate).isTrue ();
301+ check (tileStatusEmojiFinder).findsOne ();
302+ }
303+
304+ void checkFindsChipStatusEmoji (WidgetTester tester, User user, Finder emojiFinder) {
305+ final statusEmojiFinder = find.ancestor (of: emojiFinder,
306+ matching: find.byType (UserStatusEmoji ));
307+ final chipStatusEmojiFinder = find.descendant (of: findUserChip (user),
308+ matching: statusEmojiFinder);
309+ check (tester.firstWidget <UserStatusEmoji >(chipStatusEmojiFinder)
310+ .neverAnimate).isTrue ();
311+ check (chipStatusEmojiFinder).findsOne ();
312+ }
313+
314+ testWidgets ('status emoji & text are set -> emoji is displayed, text is not' , (tester) async {
315+ final user = eg.user ();
316+ await setupSheet (tester, users: [user]);
317+ await store.changeUserStatus (user.userId, UserStatusChange (
318+ text: OptionSome ('Busy' ),
319+ emoji: OptionSome (StatusEmoji (emojiName: 'working_on_it' ,
320+ emojiCode: '1f6e0' , reactionType: ReactionType .unicodeEmoji))));
321+ await tester.pump ();
322+
323+ checkFindsTileStatusEmoji (tester, user, find.text ('\u {1f6e0}' ));
324+ check (find.descendant (of: findUserTile (user),
325+ matching: find.textContaining ('Busy' ))).findsNothing ();
326+ check (findUserChip (user)).findsNothing ();
327+
328+ await tester.tap (findUserTile (user));
329+ await tester.pump ();
330+
331+ checkFindsTileStatusEmoji (tester, user, find.text ('\u {1f6e0}' ));
332+ check (find.descendant (of: findUserTile (user),
333+ matching: find.textContaining ('Busy' ))).findsNothing ();
334+ check (findUserChip (user)).findsOne ();
335+ checkFindsChipStatusEmoji (tester, user, find.text ('\u {1f6e0}' ));
336+ check (find.descendant (of: findUserChip (user),
337+ matching: find.text ('Busy' ))).findsNothing ();
338+ });
339+
340+ testWidgets ('status emoji is not set, text is set -> text is not displayed' , (tester) async {
341+ final user = eg.user ();
342+ await setupSheet (tester, users: [user]);
343+ await store.changeUserStatus (user.userId, UserStatusChange (
344+ text: OptionSome ('Busy' ), emoji: OptionNone ()));
345+ await tester.pump ();
346+
347+ check (find.descendant (of: findUserTile (user),
348+ matching: find.textContaining ('Busy' ))).findsNothing ();
349+ check (findUserChip (user)).findsNothing ();
350+
351+ await tester.tap (findUserTile (user));
352+ await tester.pump ();
353+
354+ check (find.descendant (of: findUserTile (user),
355+ matching: find.textContaining ('Busy' ))).findsNothing ();
356+ check (findUserChip (user)).findsOne ();
357+ check (find.descendant (of: findUserChip (user),
358+ matching: find.text ('Busy' ))).findsNothing ();
359+ });
360+ });
361+
288362 group ('navigation to DM Narrow' , () {
289363 Future <void > runAndCheck (WidgetTester tester, {
290364 required List <User > users,
0 commit comments