@@ -1344,4 +1344,142 @@ void main() {
1344
1344
..status.equals (AnimationStatus .dismissed);
1345
1345
});
1346
1346
});
1347
+
1348
+ group ('double-tap gesture' , () {
1349
+ Future <void > setupMessageWithReactions (WidgetTester tester, {
1350
+ required StreamMessage message,
1351
+ required Narrow narrow,
1352
+ List <Reaction >? reactions,
1353
+ }) async {
1354
+ addTearDown (testBinding.reset); // reset the test binding
1355
+ assert (narrow.containsMessage (message)); // check that the narrow contains the message
1356
+
1357
+ await testBinding.globalStore.add (eg.selfAccount, eg.initialSnapshot ()); // add the self account
1358
+ store = await testBinding.globalStore.perAccount (eg.selfAccount.id); // get the per account store
1359
+ await store.addUsers ([
1360
+ eg.selfUser,
1361
+ eg.user (userId: message.senderId),
1362
+ ]); // add the self user and the message sender
1363
+ final stream = eg.stream (streamId: message.streamId); // create the stream
1364
+ await store.addStream (stream); // add the stream
1365
+ await store.addSubscription (eg.subscription (stream)); // add the subscription
1366
+
1367
+ connection = store.connection as FakeApiConnection ; // get the fake api connection
1368
+ connection.prepare (json: eg.newestGetMessagesResult (
1369
+ foundOldest: true , messages: [message]).toJson ()); // prepare the response for the message
1370
+ await tester.pumpWidget (TestZulipApp (accountId: eg.selfAccount.id,
1371
+ child: MessageListPage (initNarrow: narrow)),
1372
+ ); // pump the widget
1373
+
1374
+ await tester.pumpAndSettle ();
1375
+ }
1376
+
1377
+ testWidgets ('add thumbs up reaction on double-tap' , (tester) async {
1378
+ final message = eg.streamMessage (); // create a message without any reactions
1379
+ await setupMessageWithReactions (tester,
1380
+ message: message,
1381
+ narrow: TopicNarrow .ofMessage (message)); // setup the message and narrow
1382
+
1383
+ connection.prepare (json: {}); // prepare the response for the reaction
1384
+ await tester.pump (); // pump the widget to make the reaction visible
1385
+
1386
+ final messageContent = find.byType (MessageContent ); // find the message content
1387
+ await tester.tap (messageContent); // first tap
1388
+ await tester.pump (const Duration (milliseconds: 50 )); // wait for some time so that the double-tap is detected
1389
+ await tester.tap (messageContent); // second tap
1390
+ await tester.pumpAndSettle (); // wait for the reaction to be added
1391
+
1392
+ check (connection.lastRequest).isA< http.Request > ()
1393
+ ..method.equals ('POST' )
1394
+ ..url.path.equals ('/api/v1/messages/${message .id }/reactions' )
1395
+ ..bodyFields.deepEquals ({
1396
+ 'reaction_type' : 'unicode_emoji' ,
1397
+ 'emoji_code' : '1f44d' , // thumbs up emoji code
1398
+ 'emoji_name' : '+1' ,
1399
+ }); // check the last request
1400
+ });
1401
+
1402
+ testWidgets ('remove thumbs up reaction on double-tap when already reacted' , (tester) async {
1403
+ final message = eg.streamMessage (reactions: [
1404
+ Reaction (
1405
+ emojiName: '+1' ,
1406
+ emojiCode: '1f44d' ,
1407
+ reactionType: ReactionType .unicodeEmoji,
1408
+ userId: eg.selfAccount.userId)
1409
+ ]); // create a message with a thumbs up reaction
1410
+ await setupMessageWithReactions (tester,
1411
+ message: message,
1412
+ narrow: TopicNarrow .ofMessage (message)); // setup the message and narrow
1413
+
1414
+ connection.prepare (json: {}); // prepare the response for the reaction
1415
+ await tester.pump (); // pump the widget to make the reaction visible
1416
+
1417
+ final messageContent = find.byType (MessageContent ); // find the message content
1418
+ await tester.tap (messageContent); // first tap
1419
+ await tester.pump (const Duration (milliseconds: 50 )); // wait for some time so that the double-tap is detected
1420
+ await tester.tap (messageContent); // second tap
1421
+ await tester.pumpAndSettle (); // wait for the reaction to be removed
1422
+
1423
+ check (connection.lastRequest).isA< http.Request > ()
1424
+ ..method.equals ('DELETE' )
1425
+ ..url.path.equals ('/api/v1/messages/${message .id }/reactions' )
1426
+ ..bodyFields.deepEquals ({
1427
+ 'reaction_type' : 'unicode_emoji' ,
1428
+ 'emoji_code' : '1f44d' ,
1429
+ 'emoji_name' : '+1' ,
1430
+ }); // check the last request
1431
+ });
1432
+
1433
+ testWidgets ('shows error dialog when adding reaction fails' , (tester) async {
1434
+ final message = eg.streamMessage ();
1435
+ await setupMessageWithReactions (tester,
1436
+ message: message,
1437
+ narrow: TopicNarrow .ofMessage (message)); // setup the message and narrow
1438
+
1439
+ connection.prepare (httpStatus: 400 , json: {
1440
+ 'code' : 'BAD_REQUEST' ,
1441
+ 'msg' : 'Invalid message(s)' ,
1442
+ 'result' : 'error' ,
1443
+ });
1444
+
1445
+ final messageContent = find.byType (MessageContent );
1446
+ await tester.tap (messageContent); // first tap
1447
+ await tester.pump (const Duration (milliseconds: 50 )); // wait for some time so that the double-tap is detected
1448
+ await tester.tap (messageContent); // second tap
1449
+ await tester.pumpAndSettle (); // wait for the error dialog to show
1450
+
1451
+ checkErrorDialog (tester,
1452
+ expectedTitle: 'Adding reaction failed' ,
1453
+ expectedMessage: 'Invalid message(s)' ); // check the error dialog
1454
+ });
1455
+
1456
+ testWidgets ('shows error dialog when removing reaction fails' , (tester) async {
1457
+ final message = eg.streamMessage (reactions: [
1458
+ Reaction (
1459
+ emojiName: '+1' ,
1460
+ emojiCode: '1f44d' ,
1461
+ reactionType: ReactionType .unicodeEmoji,
1462
+ userId: eg.selfAccount.userId)
1463
+ ]); // create a message with a thumbs up reaction
1464
+ await setupMessageWithReactions (tester,
1465
+ message: message,
1466
+ narrow: TopicNarrow .ofMessage (message)); // setup the message and narrow
1467
+
1468
+ connection.prepare (httpStatus: 400 , json: {
1469
+ 'code' : 'BAD_REQUEST' ,
1470
+ 'msg' : 'Invalid message(s)' ,
1471
+ 'result' : 'error' ,
1472
+ }); // prepare the response for the reaction
1473
+
1474
+ final messageContent = find.byType (MessageContent ); // find the message content
1475
+ await tester.tap (messageContent); // first tap
1476
+ await tester.pump (const Duration (milliseconds: 50 )); // wait for some time so that the double-tap is detected
1477
+ await tester.tap (messageContent); // second tap
1478
+ await tester.pumpAndSettle (); // wait for the error dialog to show
1479
+
1480
+ checkErrorDialog (tester,
1481
+ expectedTitle: 'Removing reaction failed' ,
1482
+ expectedMessage: 'Invalid message(s)' ); // check the error dialog
1483
+ });
1484
+ });
1347
1485
}
0 commit comments