@@ -177,6 +177,67 @@ void main() {
177
177
178
178
debugNetworkImageHttpClientProvider = null ;
179
179
});
180
+
181
+ testWidgets ('user options appear in the correct rendering order and do not scroll down' , (tester) async {
182
+ final List <User > users = [
183
+ eg.user (userId: 1 , fullName: 'Aaditya' , avatarUrl: 'user1.png' ),
184
+ eg.user (userId: 2 , fullName: 'Alya' , avatarUrl: 'user2.png' ),
185
+ eg.user (userId: 3 , fullName: 'Aman' , avatarUrl: 'user3.png' ),
186
+ eg.user (userId: 4 , fullName: 'Anders' , avatarUrl: 'user4.png' ),
187
+ eg.user (userId: 5 , fullName: 'Anthony' , avatarUrl: 'user5.png' ),
188
+ eg.user (userId: 6 , fullName: 'Apoorva' , avatarUrl: 'user6.png' ),
189
+ eg.user (userId: 7 , fullName: 'Asif' , avatarUrl: 'user7.png' ),
190
+ eg.user (userId: 8 , fullName: 'Asim' , avatarUrl: 'user8.png' )];
191
+
192
+ final composeInputFinder = await setupToComposeInput (tester, users: users);
193
+ final store = await testBinding.globalStore.perAccount (eg.selfAccount.id);
194
+
195
+ // Options are filtered correctly for query
196
+ // TODO(#226): Remove this extra edit when this bug is fixed.
197
+ await tester.enterText (composeInputFinder, 'hello @' );
198
+ await tester.enterText (composeInputFinder, 'hello @A' );
199
+ await tester.pump ();
200
+ // Only first seven users render initially, 8th user has to be accessed by scrolling up
201
+ final List <double > positions = [];
202
+ for (int i = 0 ;i < 7 ;i++ ) {
203
+ final user = users[i];
204
+ checkUserShown (user, store, expected: true );
205
+ positions.add (tester.getTopLeft (find.text (user.fullName)).dy);
206
+ }
207
+ for (int i = 7 ; i < users.length;i++ ) {
208
+ final user = users[i];
209
+ checkUserShown (user, store, expected: false );
210
+ }
211
+ final listViewFinder = find.byType (ListView );
212
+
213
+ final initialScrollOffset = tester.getTopLeft (listViewFinder).dy;
214
+ await tester.drag (listViewFinder, const Offset (0 , - 50 ));
215
+ await tester.pumpAndSettle ();
216
+ final scrollOffsetAfterDragDown = tester.getTopLeft (listViewFinder).dy;
217
+
218
+ check (
219
+ because: 'ListView should not scroll down because it is already at the bottom' ,
220
+ scrollOffsetAfterDragDown
221
+ ).equals (initialScrollOffset);
222
+
223
+ for (int i = 0 ;i < 6 ;i++ ) {
224
+ check (
225
+ because: """${users [i + 1 ]} should appear above
226
+ ${users [i ]} because of reverse order""" ,
227
+ positions[i]).isGreaterThan (positions[i+ 1 ]);
228
+ }
229
+
230
+ await tester.drag (listViewFinder, const Offset (0 , 200 )); // Should be capped at prev position
231
+ await tester.pump ();
232
+
233
+ checkUserShown (users.last, store, expected: true );
234
+ checkUserShown (users.first, store, expected: false );
235
+
236
+ // 8th user should be above 7th user
237
+ check (because: "8th user should be above 7th user" ,
238
+ tester.getTopLeft (find.text (users.last.fullName)).dy).isLessThan (tester.getTopLeft (find.text (users[users.length - 2 ].fullName)).dy);
239
+ debugNetworkImageHttpClientProvider = null ;
240
+ });
180
241
});
181
242
182
243
group ('emoji' , () {
@@ -247,6 +308,98 @@ void main() {
247
308
debugNetworkImageHttpClientProvider = null ;
248
309
});
249
310
311
+ testWidgets ('emoji options appear in the correct rendering order and do not scroll down' , (tester) async {
312
+ final composeInputFinder = await setupToComposeInput (tester);
313
+ final store = await testBinding.globalStore.perAccount (eg.selfAccount.id);
314
+
315
+ store.setServerEmojiData (
316
+ ServerEmojiData (
317
+ codeToNames: {
318
+ '1f4a4' : ['zzz' , 'sleepy' ], // Unicode emoji for "zzz"
319
+ '1f52a' : ['biohazard' ],
320
+ '1f92a' : ['zany_face' ],
321
+ '1f993' : ['zebra' ],
322
+ '0030-fe0f-20e3' : ['zero' ],
323
+ '1f9d0' : ['zombie' ],
324
+ }));
325
+
326
+ await store.handleEvent (
327
+ RealmEmojiUpdateEvent (
328
+ id: 1 ,
329
+ realmEmoji: {
330
+ '1' : eg.realmEmojiItem (emojiCode: '1' , emojiName: 'buzzing' )}));
331
+
332
+ const zulipOptionLabel = 'zulip' ;
333
+ const zanyFaceOptionLabel = 'zany_face' ;
334
+ const zebraOptionLabel = 'zebra' ;
335
+ const zzzOptionLabel = 'zzz, sleepy' ;
336
+ const unicodeGlyph = '💤' ;
337
+ const zombieOptionLabel = 'zombie' ;
338
+ const zeroOptionLabel = 'zero' ;
339
+ const buzzingOptionLabel = 'buzzing' ;
340
+ const biohazardOptionLabel = 'biohazard' ;
341
+
342
+ // Adjust the order so the best match appears last
343
+ final emojiSequence = [
344
+ zulipOptionLabel,
345
+ zzzOptionLabel,
346
+ unicodeGlyph,
347
+ zanyFaceOptionLabel,
348
+ zebraOptionLabel,
349
+ zeroOptionLabel,
350
+ zombieOptionLabel,
351
+ buzzingOptionLabel,
352
+ // biohazardOptionLabel, this won't be rendered in the list initally since it is the 7th option.
353
+ ];
354
+
355
+ // Enter a query; options appear, of all three emoji types.
356
+ // TODO(#226): Remove this extra edit when this bug is fixed.
357
+ await tester.enterText (composeInputFinder, 'hi :' );
358
+ await tester.enterText (composeInputFinder, 'hi :z' );
359
+ await tester.pump ();
360
+
361
+ final positions = emojiSequence.map ((icon) {
362
+ final finder = find.text (icon);
363
+ check (because: "Each emoji option should be rendered" , finder).findsOne ();
364
+ return tester.getTopLeft (finder).dy;
365
+ }).toList ();
366
+
367
+ for (int i = 0 ; i < positions.length - 1 ; i++ ) {
368
+ check (because: "${emojiSequence [i + 1 ]} should appear above ${emojiSequence [i ]} because of reverse order" ,
369
+ positions[i]).isGreaterThan (positions[i + 1 ]);
370
+ }
371
+
372
+ final listViewFinder = find.byType (ListView );
373
+
374
+ final initialScrollOffset = tester.getTopLeft (listViewFinder).dy;
375
+ await tester.drag (listViewFinder, const Offset (0 , - 50 ));
376
+ await tester.pumpAndSettle ();
377
+ final scrollOffsetAfterDragDown = tester.getTopLeft (listViewFinder).dy;
378
+
379
+ check (
380
+ because: "ListView should not scroll down because it is already at the bottom" ,
381
+ scrollOffsetAfterDragDown
382
+ ).equals (initialScrollOffset);
383
+
384
+ final biohazardFinder = find.text (biohazardOptionLabel);
385
+ check (
386
+ because: "The biohazard emoji should not be visible before scrolling up"
387
+ ,biohazardFinder
388
+ ).findsNothing ();
389
+
390
+ // Scroll up
391
+ await tester.drag (listViewFinder, const Offset (0 , 50 ));
392
+ await tester.pump ();
393
+
394
+ check (because: "The biohazard emoji should be visible after scrolling up" ,biohazardFinder).findsOne ();
395
+
396
+ final firstEmojiPositionAfterScrollUp = tester.getTopLeft (find.text (emojiSequence[0 ])).dy;
397
+ check (because: "Scrolling up should reveal other emoji matches" ,firstEmojiPositionAfterScrollUp).isGreaterOrEqual (positions[0 ]);
398
+
399
+ debugNetworkImageHttpClientProvider = null ;
400
+
401
+ });
402
+
250
403
testWidgets ('text emoji means just show text' , (tester) async {
251
404
final composeInputFinder = await setupToComposeInput (tester);
252
405
final store = await testBinding.globalStore.perAccount (eg.selfAccount.id);
0 commit comments