11import 'dart:convert' ;
22
33import 'package:checks/checks.dart' ;
4+ import 'package:http/http.dart' as http;
45import 'package:test/scaffolding.dart' ;
56import 'package:zulip/api/model/events.dart' ;
67import 'package:zulip/api/model/model.dart' ;
78import 'package:zulip/api/model/submessage.dart' ;
9+ import 'package:zulip/api/route/messages.dart' ;
10+ import 'package:zulip/model/message.dart' ;
811import 'package:zulip/model/message_list.dart' ;
912import 'package:zulip/model/narrow.dart' ;
1013import 'package:zulip/model/store.dart' ;
@@ -13,7 +16,9 @@ import '../api/fake_api.dart';
1316import '../api/model/model_checks.dart' ;
1417import '../api/model/submessage_checks.dart' ;
1518import '../example_data.dart' as eg;
19+ import '../fake_async.dart' ;
1620import '../stdlib_checks.dart' ;
21+ import 'message_checks.dart' ;
1722import 'message_list_test.dart' ;
1823import 'store_checks.dart' ;
1924import 'test_store.dart' ;
@@ -77,6 +82,69 @@ void main() {
7782 checkNotified (count: messageList.fetched ? messages.length : 0 );
7883 }
7984
85+ group ('sendMessage' , () {
86+ const destination =
87+ StreamDestination (eg.defaultStreamMessageStreamId, TopicName ('some topic' ));
88+
89+ test ('message sent successfully, message event arrives on time' , () async {
90+ await prepare ();
91+
92+ connection.prepare (json: SendMessageResult (id: 1 ).toJson (),
93+ delay: Duration .zero);
94+ final future = store.sendMessage (destination: destination, content: 'content' );
95+ final outboxMessage = store.outboxMessages.values.single;
96+ check (outboxMessage).state.equals (OutboxMessageLifecycle .sending);
97+ checkNotNotified ();
98+ check (connection.lastRequest).isA< http.Request > ()
99+ ..bodyFields['queue_id' ].equals (store.queueId)
100+ ..bodyFields['local_id' ].equals ('${outboxMessage .localMessageId }' );
101+
102+ await future;
103+ check (outboxMessage).state.equals (OutboxMessageLifecycle .sent);
104+ checkNotifiedOnce ();
105+
106+ await store.handleEvent (eg.messageEvent (
107+ eg.streamMessage (), localMessageId: outboxMessage.localMessageId));
108+ check (store.outboxMessages).isEmpty ();
109+ // TODO uncomment once message list support is added
110+ // checkNotifiedOnce();
111+ });
112+
113+ test ('message sent successfully, message event arrives after debounce timeout' , () => awaitFakeAsync ((async ) async {
114+ await prepare ();
115+
116+ connection.prepare (json: SendMessageResult (id: 1 ).toJson ());
117+ await store.sendMessage (destination: destination, content: 'content' );
118+ final outboxMessage = store.outboxMessages.values.single;
119+ check (outboxMessage).state.equals (OutboxMessageLifecycle .sent);
120+ checkNotifiedOnce ();
121+
122+ async .elapse (kLocalEchoDebounceDuration);
123+ check (outboxMessage).state.equals (OutboxMessageLifecycle .sent);
124+
125+ await store.handleEvent (eg.messageEvent (
126+ eg.streamMessage (), localMessageId: outboxMessage.localMessageId));
127+ check (store.outboxMessages).isEmpty ();
128+ // TODO uncomment once message list support is added
129+ // checkNotifiedOnce();
130+ }));
131+
132+ test ('message failed to send' , () async {
133+ await prepare ();
134+
135+ connection.prepare (apiException: eg.apiBadRequest (),
136+ delay: Duration .zero);
137+ final future = store.sendMessage (destination: destination, content: 'content' );
138+ final outboxMessage = store.outboxMessages.values.single;
139+ check (outboxMessage).state.equals (OutboxMessageLifecycle .sending);
140+ checkNotNotified ();
141+
142+ await check (future).throws ();
143+ check (outboxMessage).state.equals (OutboxMessageLifecycle .failed);
144+ checkNotifiedOnce ();
145+ });
146+ });
147+
80148 group ('reconcileMessages' , () {
81149 test ('from empty' , () async {
82150 await prepare ();
0 commit comments