-
Notifications
You must be signed in to change notification settings - Fork 485
ui: Distinguish bot users in more places #764
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -150,6 +150,14 @@ void main() { | |
| } | ||
| } | ||
|
|
||
| void checkBotIcon({required int count}) { | ||
| final botFinder = find.descendant( | ||
| of: find.byType(RecentDmConversationsItem), | ||
| matching: find.byIcon(ZulipIcons.bot)).hitTestable(); | ||
|
|
||
| check(botFinder.evaluate().length).equals(count); | ||
| } | ||
|
|
||
| Future<void> markMessageAsRead(WidgetTester tester, Message message) async { | ||
| final store = await testBinding.globalStore.perAccount(eg.selfAccount.id); | ||
| await store.handleEvent(UpdateMessageFlagsAddEvent( | ||
|
|
@@ -177,6 +185,7 @@ void main() { | |
|
|
||
| checkAvatar(tester, DmNarrow.ofMessage(message, selfUserId: eg.selfUser.userId)); | ||
| checkTitle(tester, eg.selfUser.fullName); | ||
| checkBotIcon(count: 0); | ||
| }); | ||
|
|
||
| testWidgets('short name takes one line', (WidgetTester tester) async { | ||
|
|
@@ -185,6 +194,7 @@ void main() { | |
| await setupPage(tester, users: [], dmMessages: [message], | ||
| newNameForSelfUser: name); | ||
| checkTitle(tester, name, 1); | ||
| checkBotIcon(count: 0); | ||
| }); | ||
|
|
||
| testWidgets('very long name takes two lines (must be ellipsized)', (WidgetTester tester) async { | ||
|
|
@@ -193,6 +203,7 @@ void main() { | |
| await setupPage(tester, users: [], dmMessages: [message], | ||
| newNameForSelfUser: name); | ||
| checkTitle(tester, name, 2); | ||
| checkBotIcon(count: 0); | ||
| }); | ||
|
|
||
| testWidgets('unread counts', (WidgetTester tester) async { | ||
|
|
@@ -206,39 +217,95 @@ void main() { | |
| }); | ||
|
|
||
| group('1:1', () { | ||
| testWidgets('has right title/avatar', (WidgetTester tester) async { | ||
| final user = eg.user(userId: 1); | ||
| final message = eg.dmMessage(from: eg.selfUser, to: [user]); | ||
| await setupPage(tester, users: [user], dmMessages: [message]); | ||
| group('has right avatar/title', () { | ||
| Future<void> checkRecipient(WidgetTester tester, { | ||
| required bool isBot, | ||
| required bool looksBot | ||
| }) async { | ||
| final user = eg.user(userId: 1, isBot: isBot); | ||
| final message = eg.dmMessage(from: eg.selfUser, to: [user]); | ||
| await setupPage(tester, users: [user], dmMessages: [message]); | ||
|
|
||
| checkAvatar(tester, DmNarrow.ofMessage(message, selfUserId: eg.selfUser.userId)); | ||
| checkTitle(tester, user.fullName); | ||
| checkBotIcon(count: looksBot ? 1 : 0); | ||
| } | ||
|
|
||
| checkAvatar(tester, DmNarrow.ofMessage(message, selfUserId: eg.selfUser.userId)); | ||
| checkTitle(tester, user.fullName); | ||
| testWidgets('bot recipient -> shows bot icon', (tester) async { | ||
| await checkRecipient(tester, isBot: true, looksBot: true); | ||
| }); | ||
|
|
||
| testWidgets('non-bot recipient -> shows no bot icon', (tester) async { | ||
| await checkRecipient(tester, isBot: false, looksBot: false); | ||
| }); | ||
| }); | ||
|
|
||
| testWidgets('no error when user somehow missing from store.users', (WidgetTester tester) async { | ||
| final user = eg.user(userId: 1); | ||
| final message = eg.dmMessage(from: eg.selfUser, to: [user]); | ||
| await setupPage(tester, | ||
| users: [], // exclude user | ||
| dmMessages: [message], | ||
| ); | ||
| group('no error when user somehow missing from store.users', () { | ||
| Future<void> checkRecipient(WidgetTester tester, { | ||
| required bool isBot, | ||
| required bool looksBot | ||
| }) async { | ||
| final user = eg.user(userId: 1, isBot: isBot); | ||
| final message = eg.dmMessage(from: eg.selfUser, to: [user]); | ||
| await setupPage(tester, | ||
| users: [], // exclude user | ||
| dmMessages: [message], | ||
| ); | ||
|
|
||
| checkAvatar(tester, DmNarrow.ofMessage(message, selfUserId: eg.selfUser.userId)); | ||
| checkTitle(tester, '(unknown user)'); | ||
| checkBotIcon(count: looksBot ? 1 : 0); | ||
| } | ||
|
|
||
| checkAvatar(tester, DmNarrow.ofMessage(message, selfUserId: eg.selfUser.userId)); | ||
| checkTitle(tester, '(unknown user)'); | ||
| testWidgets('bot recipient -> shows no bot icon', (tester) async { | ||
| await checkRecipient(tester, isBot: true, looksBot: false); | ||
| }); | ||
|
|
||
| testWidgets('non-bot recipient -> shows no bot icon', (tester) async { | ||
| await checkRecipient(tester, isBot: false, looksBot: false); | ||
| }); | ||
|
Comment on lines
+260
to
+266
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. group('no error when user somehow missing from store.users', () {
// […]
testWidgets('bot recipient -> shows no bot icon', (tester) async {
await checkRecipient(tester, isBot: true, looksBot: false);
});
testWidgets('non-bot recipient -> shows no bot icon', (tester) async {
await checkRecipient(tester, isBot: false, looksBot: false);
});The "bot recipient" test doesn't actually simulate a bot recipient, right, because these tests are checking what happens when the user data is missing. I see that the Simplest I think to leave this test is it was, but with an added |
||
| }); | ||
|
|
||
| testWidgets('short name takes one line', (WidgetTester tester) async { | ||
| final user = eg.user(userId: 1, fullName: 'Short name'); | ||
| final message = eg.dmMessage(from: eg.selfUser, to: [user]); | ||
| await setupPage(tester, users: [user], dmMessages: [message]); | ||
| checkTitle(tester, user.fullName, 1); | ||
| group('short name takes one line', () { | ||
| Future<void> checkRecipient(WidgetTester tester, { | ||
| required bool isBot, | ||
| required bool looksBot | ||
| }) async { | ||
| final user = eg.user(userId: 1, fullName: 'Short name', isBot: isBot); | ||
| final message = eg.dmMessage(from: eg.selfUser, to: [user]); | ||
| await setupPage(tester, users: [user], dmMessages: [message]); | ||
| checkTitle(tester, user.fullName, 1); | ||
| checkBotIcon(count: looksBot ? 1 : 0); | ||
| } | ||
|
|
||
| testWidgets('bot recipient -> shows bot icon', (tester) async { | ||
| await checkRecipient(tester, isBot: true, looksBot: true); | ||
| }); | ||
|
|
||
| testWidgets('non-bot recipient -> shows no bot icon', (tester) async { | ||
| await checkRecipient(tester, isBot: false, looksBot: false); | ||
| }); | ||
| }); | ||
|
|
||
| testWidgets('very long name takes two lines (must be ellipsized)', (WidgetTester tester) async { | ||
| final user = eg.user(userId: 1, fullName: 'Long name long name long name long name long name long name long name long name long name long name long name long name long name long name long name long name long name long name long name long name long name long name'); | ||
| final message = eg.dmMessage(from: eg.selfUser, to: [user]); | ||
| await setupPage(tester, users: [user], dmMessages: [message]); | ||
| checkTitle(tester, user.fullName, 2); | ||
| group('very long name takes two lines (must be ellipsized)', () { | ||
| Future<void> checkRecipient(WidgetTester tester, { | ||
| required bool isBot, | ||
| required bool looksBot | ||
| }) async { | ||
| final user = eg.user(userId: 1, isBot: isBot, fullName: 'Long name long name long name long name long name long name long name long name long name long name long name long name long name long name long name long name long name long name long name long name long name long name'); | ||
| final message = eg.dmMessage(from: eg.selfUser, to: [user]); | ||
| await setupPage(tester, users: [user], dmMessages: [message]); | ||
| checkTitle(tester, user.fullName, 2); | ||
| checkBotIcon(count: looksBot ? 1 : 0); | ||
| } | ||
|
|
||
| testWidgets('bot recipient -> shows no bot icon', (WidgetTester tester) async { | ||
| await checkRecipient(tester, isBot: true, looksBot: false); | ||
| }); | ||
|
Comment on lines
+302
to
+304
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We would like the bot icon to appear even when the name is long; see Alya's comment: #764 (comment) If that's hard to do and has to be left as a TODO, that might be OK, but we shouldn't have a test that confirms the undesired behavior. 🙂 |
||
|
|
||
| testWidgets('non-bot recipient -> shows no bot icon', (WidgetTester tester) async { | ||
| await checkRecipient(tester, isBot: false, looksBot: false); | ||
| }); | ||
| }); | ||
|
|
||
| testWidgets('unread counts', (WidgetTester tester) async { | ||
|
|
@@ -252,51 +319,59 @@ void main() { | |
| }); | ||
|
|
||
| group('group', () { | ||
| List<User> usersList(int count) { | ||
| List<User> usersList(int count, {List<int>? botUsers}) { | ||
| assert(() { | ||
| if (botUsers == null) return true; | ||
| for (int userIndex in botUsers) { | ||
| if (userIndex >= count) return false; | ||
| } | ||
| return true; | ||
| }()); | ||
| final result = <User>[]; | ||
| for (int i = 0; i < count; i++) { | ||
| result.add(eg.user(userId: i, fullName: 'User ${i.toString()}')); | ||
| result.add(eg.user(userId: i, fullName: 'User ${i.toString()}', | ||
| isBot: botUsers?.contains(i) ?? false)); | ||
| } | ||
| return result; | ||
| } | ||
|
|
||
| testWidgets('has right title/avatar', (WidgetTester tester) async { | ||
| final users = usersList(2); | ||
| final user0 = users[0]; | ||
| final user1 = users[1]; | ||
| final message = eg.dmMessage(from: eg.selfUser, to: [user0, user1]); | ||
| final users = usersList(3, botUsers: [0, 2]); | ||
| final message = eg.dmMessage(from: eg.selfUser, to: users); | ||
| await setupPage(tester, users: users, dmMessages: [message]); | ||
|
|
||
| checkAvatar(tester, DmNarrow.ofMessage(message, selfUserId: eg.selfUser.userId)); | ||
| checkTitle(tester, '${user0.fullName}, ${user1.fullName}'); | ||
| checkTitle(tester, users.map((u) => u.fullName).join(', ')); | ||
| checkBotIcon(count: 2); | ||
| }); | ||
|
|
||
| testWidgets('no error when one user somehow missing from store.users', (WidgetTester tester) async { | ||
| final users = usersList(2); | ||
| final user0 = users[0]; | ||
| final user1 = users[1]; | ||
| final message = eg.dmMessage(from: eg.selfUser, to: [user0, user1]); | ||
| final users = usersList(2, botUsers: [1]); | ||
| final message = eg.dmMessage(from: eg.selfUser, to: users); | ||
| await setupPage(tester, | ||
| users: [user0], // exclude user1 | ||
| users: [users[0]], // exclude user[1], which is bot | ||
| dmMessages: [message], | ||
| ); | ||
|
|
||
| checkAvatar(tester, DmNarrow.ofMessage(message, selfUserId: eg.selfUser.userId)); | ||
| checkTitle(tester, '${user0.fullName}, (unknown user)'); | ||
| checkTitle(tester, '${users[0].fullName}, (unknown user)'); | ||
| checkBotIcon(count: 0); | ||
| }); | ||
|
|
||
| testWidgets('few names takes one line', (WidgetTester tester) async { | ||
| final users = usersList(2); | ||
| final message = eg.dmMessage(from: eg.selfUser, to: users); | ||
| await setupPage(tester, users: users, dmMessages: [message]); | ||
| checkTitle(tester, users.map((u) => u.fullName).join(', '), 1); | ||
| checkBotIcon(count: 0); | ||
| }); | ||
|
|
||
| testWidgets('very many names takes two lines (must be ellipsized)', (WidgetTester tester) async { | ||
| final users = usersList(40); | ||
| final message = eg.dmMessage(from: eg.selfUser, to: users); | ||
| await setupPage(tester, users: users, dmMessages: [message]); | ||
| checkTitle(tester, users.map((u) => u.fullName).join(', '), 2); | ||
| checkBotIcon(count: 0); | ||
| }); | ||
|
|
||
| testWidgets('unread counts', (WidgetTester tester) async { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see a comment on the
switch:// TODO dedupe with DM items in [InboxPage]and that reminds me that we also show users' names in the Inbox page, when there are unread DMs. Would you add a prep commit that makes a helper function that can be used in this page and the Inbox page too? Perhaps it can return a
TextSpan, and it can live in either file or perhaps a new file.