@@ -6,6 +6,7 @@ import 'package:fake_async/fake_async.dart';
6
6
import 'package:flutter/foundation.dart' ;
7
7
import 'package:http/http.dart' as http;
8
8
import 'package:test/scaffolding.dart' ;
9
+ import 'package:zulip/api/backoff.dart' ;
9
10
import 'package:zulip/api/core.dart' ;
10
11
import 'package:zulip/api/model/events.dart' ;
11
12
import 'package:zulip/api/model/model.dart' ;
@@ -157,6 +158,42 @@ void main() {
157
158
await check (future).throws <AccountNotFoundException >();
158
159
}));
159
160
161
+ test ('GlobalStore.perAccount loading succeeds' , () => awaitFakeAsync ((async ) async {
162
+ NotificationService .instance.token = ValueNotifier ('asdf' );
163
+ addTearDown (NotificationService .debugReset);
164
+
165
+ final globalStore = UpdateMachineTestGlobalStore (accounts: [eg.selfAccount]);
166
+ final connection = globalStore.apiConnectionFromAccount (eg.selfAccount) as FakeApiConnection ;
167
+ final future = globalStore.perAccount (eg.selfAccount.id);
168
+ check (connection.takeRequests ()).length.equals (1 ); // register request
169
+
170
+ await future;
171
+ // poll, server-emoji-data, register-token requests
172
+ check (connection.takeRequests ()).length.equals (3 );
173
+ check (connection).isOpen.isTrue ();
174
+ }));
175
+
176
+ test ('GlobalStore.perAccount account is logged out while loading; then succeeds' , () => awaitFakeAsync ((async ) async {
177
+ final globalStore = UpdateMachineTestGlobalStore (accounts: [eg.selfAccount]);
178
+ globalStore.prepareRegisterQueueResponse = (connection) =>
179
+ connection.prepare (
180
+ delay: TestGlobalStore .removeAccountDuration + Duration (seconds: 1 ),
181
+ json: eg.initialSnapshot ().toJson ());
182
+ final connection = globalStore.apiConnectionFromAccount (eg.selfAccount) as FakeApiConnection ;
183
+ final future = globalStore.perAccount (eg.selfAccount.id);
184
+ check (connection.takeRequests ()).length.equals (1 ); // register request
185
+
186
+ await logOutAccount (globalStore, eg.selfAccount.id);
187
+ check (globalStore.takeDoRemoveAccountCalls ())
188
+ .single.equals (eg.selfAccount.id);
189
+
190
+ await check (future).throws <AccountNotFoundException >();
191
+ check (globalStore.takeDoRemoveAccountCalls ()).isEmpty ();
192
+ // no poll, server-emoji-data, or register-token requests
193
+ check (connection.takeRequests ()).isEmpty ();
194
+ check (connection).isOpen.isFalse ();
195
+ }));
196
+
160
197
test ('GlobalStore.perAccount account is logged out while loading; then fails with HTTP status code 401' , () => awaitFakeAsync ((async ) async {
161
198
final globalStore = UpdateMachineTestGlobalStore (accounts: [eg.selfAccount]);
162
199
globalStore.prepareRegisterQueueResponse = (connection) =>
@@ -175,8 +212,31 @@ void main() {
175
212
check (globalStore.takeDoRemoveAccountCalls ()).isEmpty ();
176
213
// no poll, server-emoji-data, or register-token requests
177
214
check (connection.takeRequests ()).isEmpty ();
178
- // TODO(#1354) uncomment
179
- // check(connection).isOpen.isFalse();
215
+ check (connection).isOpen.isFalse ();
216
+ }));
217
+
218
+ test ('GlobalStore.perAccount account is logged out during transient-error backoff' , () => awaitFakeAsync ((async ) async {
219
+ final globalStore = UpdateMachineTestGlobalStore (accounts: [eg.selfAccount]);
220
+ globalStore.prepareRegisterQueueResponse = (connection) =>
221
+ connection.prepare (
222
+ delay: Duration (seconds: 1 ),
223
+ httpException: http.ClientException ('Oops' ));
224
+ final connection = globalStore.apiConnectionFromAccount (eg.selfAccount) as FakeApiConnection ;
225
+ final future = globalStore.perAccount (eg.selfAccount.id);
226
+ BackoffMachine .debugDuration = Duration (seconds: 1 );
227
+ async .elapse (Duration (milliseconds: 1500 ));
228
+ check (connection.takeRequests ()).length.equals (1 ); // register request
229
+
230
+ assert (TestGlobalStore .removeAccountDuration < Duration (milliseconds: 500 ));
231
+ await logOutAccount (globalStore, eg.selfAccount.id);
232
+ check (globalStore.takeDoRemoveAccountCalls ())
233
+ .single.equals (eg.selfAccount.id);
234
+
235
+ await check (future).throws <AccountNotFoundException >();
236
+ check (globalStore.takeDoRemoveAccountCalls ()).isEmpty ();
237
+ // no retry-register, poll, server-emoji-data, or register-token requests
238
+ check (connection.takeRequests ()).isEmpty ();
239
+ check (connection).isOpen.isFalse ();
180
240
}));
181
241
182
242
// TODO test insertAccount
@@ -278,10 +338,10 @@ void main() {
278
338
checkGlobalStore (globalStore, eg.selfAccount.id,
279
339
expectAccount: true , expectStore: false );
280
340
281
- // assert(globalStore.useCachedApiConnections);
341
+ assert (globalStore.useCachedApiConnections);
282
342
// Cache a connection and get this reference to it,
283
343
// so we can check later that it gets closed.
284
- // final connection = globalStore.apiConnectionFromAccount(eg.selfAccount) as FakeApiConnection;
344
+ final connection = globalStore.apiConnectionFromAccount (eg.selfAccount) as FakeApiConnection ;
285
345
286
346
globalStore.prepareRegisterQueueResponse = (connection) {
287
347
connection.prepare (
@@ -301,14 +361,11 @@ void main() {
301
361
expectAccount: false , expectStore: false );
302
362
check (notifyCount).equals (1 );
303
363
304
- // Actually throws a null-check error; that's the bug #1354.
305
- // TODO(#1354) should specifically throw AccountNotFoundException
306
- await check (loadingFuture).throws ();
364
+ await check (loadingFuture).throws <AccountNotFoundException >();
307
365
checkGlobalStore (globalStore, eg.selfAccount.id,
308
366
expectAccount: false , expectStore: false );
309
367
check (notifyCount).equals (1 ); // no extra notify
310
- // TODO(#1354) uncomment
311
- // check(connection).isOpen.isFalse();
368
+ check (connection).isOpen.isFalse ();
312
369
313
370
check (globalStore.debugNumPerAccountStoresLoading).equals (0 );
314
371
});
@@ -1051,10 +1108,7 @@ void main() {
1051
1108
async .flushTimers ();
1052
1109
// Reload never succeeds and there are no unhandled errors.
1053
1110
check (globalStore.perAccountSync (eg.selfAccount.id)).isNull ();
1054
- }),
1055
- // An unhandled error is actually the bug #1354, so skip for now
1056
- // TODO(#1354) unskip
1057
- skip: true );
1111
+ }));
1058
1112
1059
1113
test ('new store is not loaded, gets HTTP 401 error instead' , () => awaitFakeAsync ((async ) async {
1060
1114
await prepareReload (async , prepareRegisterQueueResponse: (connection) {
0 commit comments