@@ -1252,4 +1252,142 @@ void main() {
12521252 ..status.equals (AnimationStatus .dismissed);
12531253 });
12541254 });
1255+
1256+ group ('double-tap gesture' , () {
1257+ Future <void > setupMessageWithReactions (WidgetTester tester, {
1258+ required StreamMessage message,
1259+ required Narrow narrow,
1260+ List <Reaction >? reactions,
1261+ }) async {
1262+ addTearDown (testBinding.reset); // reset the test binding
1263+ assert (narrow.containsMessage (message)); // check that the narrow contains the message
1264+
1265+ await testBinding.globalStore.add (eg.selfAccount, eg.initialSnapshot ()); // add the self account
1266+ store = await testBinding.globalStore.perAccount (eg.selfAccount.id); // get the per account store
1267+ await store.addUsers ([
1268+ eg.selfUser,
1269+ eg.user (userId: message.senderId),
1270+ ]); // add the self user and the message sender
1271+ final stream = eg.stream (streamId: message.streamId); // create the stream
1272+ await store.addStream (stream); // add the stream
1273+ await store.addSubscription (eg.subscription (stream)); // add the subscription
1274+
1275+ connection = store.connection as FakeApiConnection ; // get the fake api connection
1276+ connection.prepare (json: eg.newestGetMessagesResult (
1277+ foundOldest: true , messages: [message]).toJson ()); // prepare the response for the message
1278+ await tester.pumpWidget (TestZulipApp (accountId: eg.selfAccount.id,
1279+ child: MessageListPage (initNarrow: narrow)),
1280+ ); // pump the widget
1281+
1282+ await tester.pumpAndSettle ();
1283+ }
1284+
1285+ testWidgets ('add thumbs up reaction on double-tap' , (tester) async {
1286+ final message = eg.streamMessage (); // create a message without any reactions
1287+ await setupMessageWithReactions (tester,
1288+ message: message,
1289+ narrow: TopicNarrow .ofMessage (message)); // setup the message and narrow
1290+
1291+ connection.prepare (json: {}); // prepare the response for the reaction
1292+ await tester.pump (); // pump the widget to make the reaction visible
1293+
1294+ final messageContent = find.byType (MessageContent ); // find the message content
1295+ await tester.tap (messageContent); // first tap
1296+ await tester.pump (const Duration (milliseconds: 50 )); // wait for some time so that the double-tap is detected
1297+ await tester.tap (messageContent); // second tap
1298+ await tester.pumpAndSettle (); // wait for the reaction to be added
1299+
1300+ check (connection.lastRequest).isA< http.Request > ()
1301+ ..method.equals ('POST' )
1302+ ..url.path.equals ('/api/v1/messages/${message .id }/reactions' )
1303+ ..bodyFields.deepEquals ({
1304+ 'reaction_type' : 'unicode_emoji' ,
1305+ 'emoji_code' : '1f44d' , // thumbs up emoji code
1306+ 'emoji_name' : '+1' ,
1307+ }); // check the last request
1308+ });
1309+
1310+ testWidgets ('remove thumbs up reaction on double-tap when already reacted' , (tester) async {
1311+ final message = eg.streamMessage (reactions: [
1312+ Reaction (
1313+ emojiName: '+1' ,
1314+ emojiCode: '1f44d' ,
1315+ reactionType: ReactionType .unicodeEmoji,
1316+ userId: eg.selfAccount.userId)
1317+ ]); // create a message with a thumbs up reaction
1318+ await setupMessageWithReactions (tester,
1319+ message: message,
1320+ narrow: TopicNarrow .ofMessage (message)); // setup the message and narrow
1321+
1322+ connection.prepare (json: {}); // prepare the response for the reaction
1323+ await tester.pump (); // pump the widget to make the reaction visible
1324+
1325+ final messageContent = find.byType (MessageContent ); // find the message content
1326+ await tester.tap (messageContent); // first tap
1327+ await tester.pump (const Duration (milliseconds: 50 )); // wait for some time so that the double-tap is detected
1328+ await tester.tap (messageContent); // second tap
1329+ await tester.pumpAndSettle (); // wait for the reaction to be removed
1330+
1331+ check (connection.lastRequest).isA< http.Request > ()
1332+ ..method.equals ('DELETE' )
1333+ ..url.path.equals ('/api/v1/messages/${message .id }/reactions' )
1334+ ..bodyFields.deepEquals ({
1335+ 'reaction_type' : 'unicode_emoji' ,
1336+ 'emoji_code' : '1f44d' ,
1337+ 'emoji_name' : '+1' ,
1338+ }); // check the last request
1339+ });
1340+
1341+ testWidgets ('shows error dialog when adding reaction fails' , (tester) async {
1342+ final message = eg.streamMessage ();
1343+ await setupMessageWithReactions (tester,
1344+ message: message,
1345+ narrow: TopicNarrow .ofMessage (message)); // setup the message and narrow
1346+
1347+ connection.prepare (httpStatus: 400 , json: {
1348+ 'code' : 'BAD_REQUEST' ,
1349+ 'msg' : 'Invalid message(s)' ,
1350+ 'result' : 'error' ,
1351+ });
1352+
1353+ final messageContent = find.byType (MessageContent );
1354+ await tester.tap (messageContent); // first tap
1355+ await tester.pump (const Duration (milliseconds: 50 )); // wait for some time so that the double-tap is detected
1356+ await tester.tap (messageContent); // second tap
1357+ await tester.pumpAndSettle (); // wait for the error dialog to show
1358+
1359+ checkErrorDialog (tester,
1360+ expectedTitle: 'Adding reaction failed' ,
1361+ expectedMessage: 'Invalid message(s)' ); // check the error dialog
1362+ });
1363+
1364+ testWidgets ('shows error dialog when removing reaction fails' , (tester) async {
1365+ final message = eg.streamMessage (reactions: [
1366+ Reaction (
1367+ emojiName: '+1' ,
1368+ emojiCode: '1f44d' ,
1369+ reactionType: ReactionType .unicodeEmoji,
1370+ userId: eg.selfAccount.userId)
1371+ ]); // create a message with a thumbs up reaction
1372+ await setupMessageWithReactions (tester,
1373+ message: message,
1374+ narrow: TopicNarrow .ofMessage (message)); // setup the message and narrow
1375+
1376+ connection.prepare (httpStatus: 400 , json: {
1377+ 'code' : 'BAD_REQUEST' ,
1378+ 'msg' : 'Invalid message(s)' ,
1379+ 'result' : 'error' ,
1380+ }); // prepare the response for the reaction
1381+
1382+ final messageContent = find.byType (MessageContent ); // find the message content
1383+ await tester.tap (messageContent); // first tap
1384+ await tester.pump (const Duration (milliseconds: 50 )); // wait for some time so that the double-tap is detected
1385+ await tester.tap (messageContent); // second tap
1386+ await tester.pumpAndSettle (); // wait for the error dialog to show
1387+
1388+ checkErrorDialog (tester,
1389+ expectedTitle: 'Removing reaction failed' ,
1390+ expectedMessage: 'Invalid message(s)' ); // check the error dialog
1391+ });
1392+ });
12551393}
0 commit comments