@@ -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,44 @@ void main() {
157
158
await check (future).throws <AccountNotFoundException >();
158
159
}));
159
160
161
+ test ('GlobalStore.perAccount loading succeeds' , () => awaitFakeAsync ((async ) async {
162
+ final globalStore = UpdateMachineTestGlobalStore (
163
+ globalSettings: eg.globalSettings (), accounts: [eg.selfAccount]);
164
+ final connection = globalStore.apiConnectionFromAccount (eg.selfAccount) as FakeApiConnection ;
165
+
166
+ NotificationService .instance.token = ValueNotifier ('asdf' );
167
+ addTearDown (NotificationService .debugReset);
168
+
169
+ final future = globalStore.perAccount (eg.selfAccount.id);
170
+ check (connection.takeRequests ()).length.equals (1 ); // register request
171
+ await future;
172
+ // poll, server-emoji-data, register-token requests
173
+ check (connection.takeRequests ()).length.equals (3 );
174
+ check (connection).isOpen.isTrue ();
175
+ }));
176
+
177
+ test ('GlobalStore.perAccount account is logged out while loading; then succeeds' , () => awaitFakeAsync ((async ) async {
178
+ final globalStore = UpdateMachineTestGlobalStore (
179
+ globalSettings: eg.globalSettings (), accounts: [eg.selfAccount]);
180
+ globalStore.prepareRegisterQueueResponse = (connection) =>
181
+ connection.prepare (
182
+ delay: TestGlobalStore .removeAccountDuration + Duration (seconds: 1 ),
183
+ json: eg.initialSnapshot ().toJson ());
184
+ final connection = globalStore.apiConnectionFromAccount (eg.selfAccount) as FakeApiConnection ;
185
+ final future = globalStore.perAccount (eg.selfAccount.id);
186
+ check (connection.takeRequests ()).length.equals (1 ); // register request
187
+
188
+ await logOutAccount (globalStore, eg.selfAccount.id);
189
+ check (globalStore.takeDoRemoveAccountCalls ())
190
+ .single.equals (eg.selfAccount.id);
191
+
192
+ await check (future).throws <AccountNotFoundException >();
193
+ check (globalStore.takeDoRemoveAccountCalls ()).isEmpty ();
194
+ // no poll, server-emoji-data, or register-token requests
195
+ check (connection.takeRequests ()).isEmpty ();
196
+ check (connection).isOpen.isFalse ();
197
+ }));
198
+
160
199
test ('GlobalStore.perAccount account is logged out while loading; then fails with HTTP status code 401' , () => awaitFakeAsync ((async ) async {
161
200
final globalStore = UpdateMachineTestGlobalStore (
162
201
globalSettings: eg.globalSettings (), accounts: [eg.selfAccount]);
@@ -176,8 +215,32 @@ void main() {
176
215
check (globalStore.takeDoRemoveAccountCalls ()).isEmpty ();
177
216
// no poll, server-emoji-data, or register-token requests
178
217
check (connection.takeRequests ()).isEmpty ();
179
- // TODO(#1354) uncomment
180
- // check(connection).isOpen.isFalse();
218
+ check (connection).isOpen.isFalse ();
219
+ }));
220
+
221
+ test ('GlobalStore.perAccount account is logged out during transient-error backoff' , () => awaitFakeAsync ((async ) async {
222
+ final globalStore = UpdateMachineTestGlobalStore (
223
+ globalSettings: eg.globalSettings (), accounts: [eg.selfAccount]);
224
+ globalStore.prepareRegisterQueueResponse = (connection) =>
225
+ connection.prepare (
226
+ delay: Duration (seconds: 1 ),
227
+ httpException: http.ClientException ('Oops' ));
228
+ final connection = globalStore.apiConnectionFromAccount (eg.selfAccount) as FakeApiConnection ;
229
+ final future = globalStore.perAccount (eg.selfAccount.id);
230
+ BackoffMachine .debugDuration = Duration (seconds: 1 );
231
+ async .elapse (Duration (milliseconds: 1500 ));
232
+ check (connection.takeRequests ()).length.equals (1 ); // register request
233
+
234
+ assert (TestGlobalStore .removeAccountDuration < Duration (milliseconds: 500 ));
235
+ await logOutAccount (globalStore, eg.selfAccount.id);
236
+ check (globalStore.takeDoRemoveAccountCalls ())
237
+ .single.equals (eg.selfAccount.id);
238
+
239
+ await check (future).throws <AccountNotFoundException >();
240
+ check (globalStore.takeDoRemoveAccountCalls ()).isEmpty ();
241
+ // no retry-register, poll, server-emoji-data, or register-token requests
242
+ check (connection.takeRequests ()).isEmpty ();
243
+ check (connection).isOpen.isFalse ();
181
244
}));
182
245
183
246
// TODO test insertAccount
@@ -280,10 +343,10 @@ void main() {
280
343
checkGlobalStore (globalStore, eg.selfAccount.id,
281
344
expectAccount: true , expectStore: false );
282
345
283
- // assert(globalStore.useCachedApiConnections);
346
+ assert (globalStore.useCachedApiConnections);
284
347
// Cache a connection and get this reference to it,
285
348
// so we can check later that it gets closed.
286
- // final connection = globalStore.apiConnectionFromAccount(eg.selfAccount) as FakeApiConnection;
349
+ final connection = globalStore.apiConnectionFromAccount (eg.selfAccount) as FakeApiConnection ;
287
350
288
351
globalStore.prepareRegisterQueueResponse = (connection) {
289
352
connection.prepare (
@@ -303,14 +366,11 @@ void main() {
303
366
expectAccount: false , expectStore: false );
304
367
check (notifyCount).equals (1 );
305
368
306
- // Actually throws a null-check error; that's the bug #1354.
307
- // TODO(#1354) should specifically throw AccountNotFoundException
308
- await check (loadingFuture).throws ();
369
+ await check (loadingFuture).throws <AccountNotFoundException >();
309
370
checkGlobalStore (globalStore, eg.selfAccount.id,
310
371
expectAccount: false , expectStore: false );
311
372
check (notifyCount).equals (1 ); // no extra notify
312
- // TODO(#1354) uncomment
313
- // check(connection).isOpen.isFalse();
373
+ check (connection).isOpen.isFalse ();
314
374
315
375
check (globalStore.debugNumPerAccountStoresLoading).equals (0 );
316
376
});
@@ -1054,10 +1114,7 @@ void main() {
1054
1114
async .flushTimers ();
1055
1115
// Reload never succeeds and there are no unhandled errors.
1056
1116
check (globalStore.perAccountSync (eg.selfAccount.id)).isNull ();
1057
- }),
1058
- // An unhandled error is actually the bug #1354, so skip for now
1059
- // TODO(#1354) unskip
1060
- skip: true );
1117
+ }));
1061
1118
1062
1119
test ('new store is not loaded, gets HTTP 401 error instead' , () => awaitFakeAsync ((async ) async {
1063
1120
await prepareReload (async , prepareRegisterQueueResponse: (connection) {
0 commit comments