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