@@ -1344,4 +1344,142 @@ void main() {
13441344 ..status.equals (AnimationStatus .dismissed);
13451345 });
13461346 });
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+ });
13471485}
0 commit comments