@@ -78,6 +78,8 @@ void main() {
78
78
});
79
79
});
80
80
81
+ final popularCandidates = EmojiStore .popularEmojiCandidates;
82
+
81
83
Condition <Object ?> isUnicodeCandidate (String ? emojiCode, List <String >? names) {
82
84
return (it_) {
83
85
final it = it_.isA <EmojiCandidate >();
@@ -108,6 +110,9 @@ void main() {
108
110
..aliases.isEmpty ();
109
111
}
110
112
113
+ List <Condition <Object ?>> arePopularCandidates = popularCandidates.map (
114
+ (c) => isUnicodeCandidate (c.emojiCode, null )).toList ();
115
+
111
116
group ('allEmojiCandidates' , () {
112
117
// TODO test emojiDisplay of candidates matches emojiDisplayFor
113
118
@@ -123,12 +128,47 @@ void main() {
123
128
return store;
124
129
}
125
130
131
+ test ('popular emoji appear even when no server emoji data' , () {
132
+ final store = prepare (unicodeEmoji: null );
133
+ check (store.allEmojiCandidates ()).deepEquals ([
134
+ ...arePopularCandidates,
135
+ isZulipCandidate (),
136
+ ]);
137
+ });
138
+
139
+ test ('popular emoji appear in their canonical order' , () {
140
+ // In the server's emoji data, have the popular emoji in a permuted order,
141
+ // and interspersed with other emoji.
142
+ final store = prepare (unicodeEmoji: {
143
+ '1f603' : ['smiley' ],
144
+ for (final candidate in popularCandidates.skip (3 ))
145
+ candidate.emojiCode: [candidate.emojiName, ...candidate.aliases],
146
+ '1f34a' : ['orange' , 'tangerine' , 'mandarin' ],
147
+ for (final candidate in popularCandidates.take (3 ))
148
+ candidate.emojiCode: [candidate.emojiName, ...candidate.aliases],
149
+ '1f516' : ['bookmark' ],
150
+ });
151
+ // In the allEmojiCandidates result, the popular emoji come first
152
+ // and are in their canonical order, even though the other Unicode emoji
153
+ // are in the same order they were given in.
154
+ check (store.allEmojiCandidates ()).deepEquals ([
155
+ for (final candidate in popularCandidates)
156
+ isUnicodeCandidate (candidate.emojiCode,
157
+ [candidate.emojiName, ...candidate.aliases]),
158
+ isUnicodeCandidate ('1f603' , ['smiley' ]),
159
+ isUnicodeCandidate ('1f34a' , ['orange' , 'tangerine' , 'mandarin' ]),
160
+ isUnicodeCandidate ('1f516' , ['bookmark' ]),
161
+ isZulipCandidate (),
162
+ ]);
163
+ });
164
+
126
165
test ('realm emoji included only when active' , () {
127
166
final store = prepare (realmEmoji: {
128
167
'1' : eg.realmEmojiItem (emojiCode: '1' , emojiName: 'abc' , deactivated: true ),
129
168
'2' : eg.realmEmojiItem (emojiCode: '2' , emojiName: 'abcd' ),
130
169
});
131
170
check (store.allEmojiCandidates ()).deepEquals ([
171
+ ...arePopularCandidates,
132
172
isRealmCandidate (emojiCode: '2' , emojiName: 'abcd' ),
133
173
isZulipCandidate (),
134
174
]);
@@ -143,6 +183,7 @@ void main() {
143
183
'5' : eg.realmEmojiItem (emojiCode: '5' , emojiName: 'test' , deactivated: true ),
144
184
});
145
185
check (store.allEmojiCandidates ()).deepEquals ([
186
+ ...arePopularCandidates,
146
187
isRealmCandidate (emojiCode: '4' , emojiName: 'try' ),
147
188
isZulipCandidate (),
148
189
]);
@@ -156,6 +197,7 @@ void main() {
156
197
'1f603' : ['smiley' ],
157
198
});
158
199
check (store.allEmojiCandidates ()).deepEquals ([
200
+ ...arePopularCandidates,
159
201
isUnicodeCandidate ('1f516' , ['bookmark' ]),
160
202
isRealmCandidate (emojiCode: '1' , emojiName: 'smiley' ),
161
203
isZulipCandidate (),
@@ -169,6 +211,7 @@ void main() {
169
211
'1f41c' : ['ant' ],
170
212
});
171
213
check (store.allEmojiCandidates ()).deepEquals ([
214
+ ...arePopularCandidates,
172
215
isUnicodeCandidate ('1f41c' , ['ant' ]),
173
216
isZulipCandidate (),
174
217
]);
@@ -181,6 +224,7 @@ void main() {
181
224
'1f34a' : ['orange' , 'tangerine' , 'mandarin' ],
182
225
});
183
226
check (store.allEmojiCandidates ()).deepEquals ([
227
+ ...arePopularCandidates,
184
228
isUnicodeCandidate ('1f34a' , ['orange' , 'mandarin' ]),
185
229
isRealmCandidate (emojiCode: '1' , emojiName: 'tangerine' ),
186
230
isZulipCandidate (),
@@ -194,6 +238,7 @@ void main() {
194
238
'1f34a' : ['orange' , 'tangerine' , 'mandarin' ],
195
239
});
196
240
check (store.allEmojiCandidates ()).deepEquals ([
241
+ ...arePopularCandidates,
197
242
isUnicodeCandidate ('1f34a' , ['tangerine' , 'mandarin' ]),
198
243
isRealmCandidate (emojiCode: '1' , emojiName: 'orange' ),
199
244
isZulipCandidate (),
@@ -203,13 +248,15 @@ void main() {
203
248
test ('updates on setServerEmojiData' , () {
204
249
final store = prepare ();
205
250
check (store.allEmojiCandidates ()).deepEquals ([
251
+ ...arePopularCandidates,
206
252
isZulipCandidate (),
207
253
]);
208
254
209
255
store.setServerEmojiData (ServerEmojiData (codeToNames: {
210
256
'1f516' : ['bookmark' ],
211
257
}));
212
258
check (store.allEmojiCandidates ()).deepEquals ([
259
+ ...arePopularCandidates,
213
260
isUnicodeCandidate ('1f516' , ['bookmark' ]),
214
261
isZulipCandidate (),
215
262
]);
@@ -218,13 +265,15 @@ void main() {
218
265
test ('updates on RealmEmojiUpdateEvent' , () {
219
266
final store = prepare ();
220
267
check (store.allEmojiCandidates ()).deepEquals ([
268
+ ...arePopularCandidates,
221
269
isZulipCandidate (),
222
270
]);
223
271
224
272
store.handleEvent (RealmEmojiUpdateEvent (id: 1 , realmEmoji: {
225
273
'1' : eg.realmEmojiItem (emojiCode: '1' , emojiName: 'happy' ),
226
274
}));
227
275
check (store.allEmojiCandidates ()).deepEquals ([
276
+ ...arePopularCandidates,
228
277
isRealmCandidate (emojiCode: '1' , emojiName: 'happy' ),
229
278
isZulipCandidate (),
230
279
]);
@@ -257,6 +306,9 @@ void main() {
257
306
isZulipCandidate ());
258
307
}
259
308
309
+ List <Condition <Object ?>> arePopularResults = popularCandidates.map (
310
+ (c) => isUnicodeResult (emojiCode: c.emojiCode)).toList ();
311
+
260
312
PerAccountStore prepare ({
261
313
Map <String , String > realmEmoji = const {},
262
314
Map <String , List <String >>? unicodeEmoji,
@@ -282,6 +334,7 @@ void main() {
282
334
await Future (() {});
283
335
check (done).isTrue ();
284
336
check (view.results).deepEquals ([
337
+ ...arePopularResults,
285
338
isRealmResult (emojiName: 'happy' ),
286
339
isZulipResult (),
287
340
isUnicodeResult (names: ['bookmark' ]),
@@ -323,6 +376,45 @@ void main() {
323
376
return view.results;
324
377
}
325
378
379
+ test ('results preserve order of popular emoji within each rank' , () async {
380
+ // In other words, the sorting by rank is a stable sort.
381
+
382
+ // Full results list matches allEmojiCandidates.
383
+ check (prepare ().allEmojiCandidates ())
384
+ .deepEquals ([...arePopularCandidates, isZulipCandidate ()]);
385
+ check (await resultsOf ('' ))
386
+ .deepEquals ([...arePopularResults, isZulipResult ()]);
387
+
388
+ // Same list written out explicitly, for comparison with the cases below.
389
+ check (await resultsOf ('' )).deepEquals ([
390
+ isUnicodeResult (names: ['+1' , 'thumbs_up' , 'like' ]),
391
+ isUnicodeResult (names: ['tada' ]),
392
+ isUnicodeResult (names: ['smile' ]),
393
+ isUnicodeResult (names: ['heart' , 'love' , 'love_you' ]),
394
+ isUnicodeResult (names: ['working_on_it' , 'hammer_and_wrench' , 'tools' ]),
395
+ isUnicodeResult (names: ['octopus' ]),
396
+ isZulipResult (),
397
+ ]);
398
+
399
+ check (await resultsOf ('t' )).deepEquals ([
400
+ // prefix
401
+ isUnicodeResult (names: ['+1' , 'thumbs_up' , 'like' ]),
402
+ isUnicodeResult (names: ['tada' ]),
403
+ isUnicodeResult (names: ['working_on_it' , 'hammer_and_wrench' , 'tools' ]),
404
+ // other
405
+ isUnicodeResult (names: ['heart' , 'love' , 'love_you' ]),
406
+ isUnicodeResult (names: ['octopus' ]),
407
+ ]);
408
+
409
+ check (await resultsOf ('h' )).deepEquals ([
410
+ // prefix
411
+ isUnicodeResult (names: ['heart' , 'love' , 'love_you' ]),
412
+ isUnicodeResult (names: ['working_on_it' , 'hammer_and_wrench' , 'tools' ]),
413
+ // other
414
+ isUnicodeResult (names: ['+1' , 'thumbs_up' , 'like' ]),
415
+ ]);
416
+ });
417
+
326
418
test ('results end-to-end' , () async {
327
419
// (See more detailed rank tests below, on EmojiAutocompleteQuery.)
328
420
@@ -331,6 +423,7 @@ void main() {
331
423
332
424
// Empty query -> base ordering.
333
425
check (await resultsOf ('' , unicodeEmoji: unicodeEmoji)).deepEquals ([
426
+ ...arePopularResults,
334
427
isZulipResult (),
335
428
isUnicodeResult (names: ['notebook' ]),
336
429
isUnicodeResult (names: ['bookmark' ]),
0 commit comments