@@ -1359,9 +1359,12 @@ void main() {
1359
1359
final contentInputFinder = find.byWidgetPredicate (
1360
1360
(widget) => widget is TextField && widget.controller is ComposeContentController );
1361
1361
1362
- Finder findTextInMessages ( String text) => find.descendant (
1362
+ Finder outboxMessageFinder = find.descendant (
1363
1363
of: find.byType (MessageItem ),
1364
- matching: find.text (content, findRichText: true ));
1364
+ matching: find.text (content, findRichText: true )).hitTestable ();
1365
+
1366
+ Finder messageIsntSentErrorFinder = find.text (
1367
+ 'MESSAGE ISN\' T SENT. CHECK YOUR CONNECTION.' ).hitTestable ();
1365
1368
1366
1369
testWidgets ('sent message appear in message list after debounce timeout' , (tester) async {
1367
1370
await setupMessageListPage (tester,
@@ -1372,10 +1375,131 @@ void main() {
1372
1375
await tester.enterText (contentInputFinder, content);
1373
1376
await tester.tap (find.byIcon (ZulipIcons .send));
1374
1377
await tester.pump (Duration .zero);
1375
- check (findTextInMessages (content) ).findsNothing ();
1378
+ check (outboxMessageFinder ).findsNothing ();
1376
1379
1377
1380
await tester.pump (kLocalEchoDebounceDuration);
1378
- check (findTextInMessages (content)).findsOne ();
1381
+ check (outboxMessageFinder).findsOne ();
1382
+ check (find.descendant (
1383
+ of: find.byType (MessageItem ),
1384
+ matching: find.byType (LinearProgressIndicator ))).findsOne ();
1385
+ });
1386
+
1387
+ testWidgets ('failed to send message, retrieve the content to compose box' , (tester) async {
1388
+ await setupMessageListPage (tester,
1389
+ narrow: eg.topicNarrow (stream.streamId, 'topic' ), streams: [stream],
1390
+ messages: []);
1391
+
1392
+ // Send a message and fail. Dismiss the error dialog as it pops up.
1393
+ connection.prepare (apiException: eg.apiBadRequest ());
1394
+ await tester.enterText (contentInputFinder, content);
1395
+ await tester.tap (find.byIcon (ZulipIcons .send));
1396
+ await tester.pump (Duration .zero);
1397
+ await tester.tap (find.byWidget (
1398
+ checkErrorDialog (tester, expectedTitle: 'Message not sent' )));
1399
+ await tester.pump ();
1400
+ check (outboxMessageFinder).findsOne ();
1401
+ check (messageIsntSentErrorFinder).findsOne ();
1402
+
1403
+ final controller = tester.state <ComposeBoxState >(find.byType (ComposeBox )).controller;
1404
+ check (controller.content).text.isNotNull ().isEmpty ();
1405
+
1406
+ // Tap the message. This should put its content back into the compose box
1407
+ // and remove it.
1408
+ await tester.tap (outboxMessageFinder);
1409
+ await tester.pump ();
1410
+ check (outboxMessageFinder).findsNothing ();
1411
+ check (controller.content).text.equals ('$content \n\n ' );
1412
+
1413
+ await tester.pump (kLocalEchoDebounceDuration);
1414
+ });
1415
+
1416
+ testWidgets ('tapping does nothing if compose box is not offered' , (tester) async {
1417
+ final messages = [eg.streamMessage (stream: stream, topic: 'some topic' )];
1418
+ await setupMessageListPage (tester,
1419
+ narrow: const CombinedFeedNarrow (), streams: [stream], subscriptions: [eg.subscription (stream)],
1420
+ messages: messages);
1421
+
1422
+ // Navigate to a message list page in a topic narrow,
1423
+ // which has a compose box.
1424
+ connection.prepare (json:
1425
+ eg.newestGetMessagesResult (foundOldest: true , messages: messages).toJson ());
1426
+ await tester.tap (find.text ('some topic' ));
1427
+ await tester.pump (); // handle tap
1428
+ await tester.pump (); // wait for navigation
1429
+
1430
+ // Send a message and fail. Dismiss the error dialog as it pops up.
1431
+ connection.prepare (apiException: eg.apiBadRequest ());
1432
+ await tester.enterText (contentInputFinder, content);
1433
+ await tester.tap (find.byIcon (ZulipIcons .send));
1434
+ await tester.pump (Duration .zero);
1435
+ await tester.tap (find.byWidget (
1436
+ checkErrorDialog (tester, expectedTitle: 'Message not sent' )));
1437
+ await tester.pump (); // handle tap
1438
+ check (outboxMessageFinder).findsOne ();
1439
+ check (messageIsntSentErrorFinder).findsOne ();
1440
+
1441
+ // Navigate back to the message list page without a compose box,
1442
+ // where the failed to send message should still be visible.
1443
+ await tester.pageBack ();
1444
+ await tester.pump (); // handle tap
1445
+ await tester.pump (); // wait for navigation
1446
+ check (contentInputFinder).findsNothing ();
1447
+ check (outboxMessageFinder).findsOne ();
1448
+ check (messageIsntSentErrorFinder).findsOne ();
1449
+
1450
+ // Tap the failed to send message.
1451
+ // This should not remove it from the message list.
1452
+ await tester.tap (outboxMessageFinder);
1453
+ await tester.pump ();
1454
+ check (outboxMessageFinder).findsOne ();
1455
+ });
1456
+
1457
+ testWidgets ('tapping does nothing if message was successfully sent' , (tester) async {
1458
+ await setupMessageListPage (tester,
1459
+ narrow: eg.topicNarrow (stream.streamId, 'topic' ), streams: [stream],
1460
+ messages: []);
1461
+ final controller = tester.state <ComposeBoxState >(find.byType (ComposeBox )).controller;
1462
+
1463
+ // Send a message and wait until the debounce timer expires.
1464
+ connection.prepare (json: SendMessageResult (id: 1 ).toJson ());
1465
+ await tester.enterText (contentInputFinder, content);
1466
+ await tester.tap (find.byIcon (ZulipIcons .send));
1467
+ await tester.pump (Duration .zero);
1468
+ await tester.pump (kLocalEchoDebounceDuration);
1469
+ check (controller.content).text.isNotNull ().isEmpty ();
1470
+
1471
+ await tester.tap (outboxMessageFinder);
1472
+ await tester.pump ();
1473
+ check (outboxMessageFinder).findsOne ();
1474
+ check (controller.content).text.isNotNull ().isEmpty ();
1475
+ });
1476
+
1477
+ testWidgets ('tapping does nothing if message is still being sent' , (tester) async {
1478
+ await setupMessageListPage (tester,
1479
+ narrow: eg.topicNarrow (stream.streamId, 'topic' ), streams: [stream],
1480
+ messages: []);
1481
+ final controller = tester.state <ComposeBoxState >(find.byType (ComposeBox )).controller;
1482
+
1483
+ // Send a message and wait until the debounce timer expires but before
1484
+ // the message is successfully sent.
1485
+ connection.prepare (json: SendMessageResult (id: 1 ).toJson (),
1486
+ delay: kLocalEchoDebounceDuration + Duration (seconds: 1 ));
1487
+ await tester.enterText (contentInputFinder, content);
1488
+ await tester.tap (find.byIcon (ZulipIcons .send));
1489
+ await tester.pump (Duration .zero);
1490
+ await tester.pump (kLocalEchoDebounceDuration);
1491
+ check (controller.content).text.isNotNull ().isEmpty ();
1492
+
1493
+ await tester.tap (outboxMessageFinder);
1494
+ await tester.pump ();
1495
+ check (outboxMessageFinder).findsOne ();
1496
+ check (controller.content).text.isNotNull ().isEmpty ();
1497
+
1498
+ // Wait till the send request completes. The outbox message should
1499
+ // remain visible because the message event didn't arrive.
1500
+ await tester.pump (Duration (seconds: 1 ));
1501
+ check (outboxMessageFinder).findsOne ();
1502
+ check (controller.content).text.isNotNull ().isEmpty ();
1379
1503
});
1380
1504
});
1381
1505
0 commit comments