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