Skip to content

Commit b24d434

Browse files
committed
fix more tests, remove all artificial waits
1 parent 4369dc5 commit b24d434

File tree

8 files changed

+53
-168
lines changed

8 files changed

+53
-168
lines changed

lib/src/adapter/remote_adapter.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,9 @@ mixin _RemoteAdapter<T extends DataModelMixin<T>> on _SerializationAdapter<T> {
101101
);
102102

103103
if (background) {
104-
// ignore: unawaited_futures
105-
future.then((_) => Future.value(_));
104+
(() async {
105+
await future;
106+
})();
106107
return models;
107108
} else {
108109
return await future ?? <T>[];

test/_support/setup.dart

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ Future<void> tearDownFn() async {
8383
await core.storage.destroy();
8484

8585
logging.clear();
86-
await oneMs();
8786
}
8887

8988
// utils
@@ -207,31 +206,4 @@ class DataStateNotifierTester<T> {
207206
extension SX<T> on DataStateNotifier<T> {
208207
DataStateNotifierTester tester({bool fireImmediately = false}) =>
209208
DataStateNotifierTester(this, fireImmediately: fireImmediately);
210-
211-
// Future<dynamic> expectDataState(dynamic model,
212-
// {dynamic isLoading,
213-
// dynamic exception,
214-
// bool fireImmediately = false}) async {
215-
// var m = isA<DataState<T>>();
216-
// if (model != null) {
217-
// if (model is List<(Function(T), dynamic)>) {
218-
// for (final (fn, arg) in model) {
219-
// m = m.having((s) => fn(s.model), 'model arg', arg);
220-
// }
221-
// } else {
222-
// m = m.having((s) => s.model, 'model', model);
223-
// }
224-
// }
225-
// if (isLoading != null) {
226-
// m = m.having((s) => s.isLoading, 'isLoading', isLoading);
227-
// }
228-
// if (exception != null) {
229-
// m = m.having((s) => s.exception, 'exception', exception);
230-
// }
231-
// final stream =
232-
// _streamWithInitialValueFor(this, fireImmediately: fireImmediately);
233-
// final result = expect(await stream.first, m);
234-
235-
// return result;
236-
// }
237209
}

test/model/relationship/has_many_test.dart

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,29 +87,24 @@ void main() async {
8787
final p2 = Person(name: 'b', age: 2).saveLocal();
8888

8989
familia.persons.add(p1);
90-
// await oneMs();
9190
expect(familia.persons.keys, {keyFor(p1)});
9291

9392
verify(listener({p1})).called(1);
9493

9594
expect(familia.persons.keys, {keyFor(p1)});
9695
familia.persons.add(p2);
97-
// await oneMs();
9896

9997
expect(familia.persons.keys, {keyFor(p1), keyFor(p2)});
10098
verify(listener({p1, p2})).called(1);
10199

102100
familia.persons.remove(p1);
103-
// await oneMs();
104101

105102
verify(listener({p2})).called(1);
106103

107104
familia.persons.add(p1);
108-
// await oneMs();
109105

110106
// NOTE: it is actually called once, I don't know what's wrong with this
111107
verify(listener({p1, p2})).called(1);
112-
// await oneMs();
113108
});
114109

115110
test('remove relationship', () async {

test/model/relationship/relationship_test.dart

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import 'package:flutter_data/flutter_data.dart';
2-
import 'package:mockito/mockito.dart';
32
import 'package:test/test.dart';
43

54
import '../../_support/book.dart';
@@ -260,21 +259,15 @@ void main() async {
260259
BookAuthor(id: 15, name: 'Lao Tzu', books: HasMany({book})).saveLocal();
261260
expect(author.books.first, book);
262261

263-
final listener = Listener<DataState<BookAuthor?>>();
264262
final notifier = container.bookAuthors.watchOneNotifier(author);
263+
final tester = notifier.tester(fireImmediately: true);
265264

266-
final dispose = notifier.addListener(listener);
267-
disposeFns.add(dispose);
268-
269-
verify(listener(DataState(author, isLoading: false))).called(1);
270-
verifyNoMoreInteractions(listener);
265+
await tester.expectDataState(author, isLoading: false);
271266

272267
final author2 = author.copyWith(name: 'Steve-O').saveLocal();
273268

274-
await oneMs();
275269
expect(author.books.first, book);
276-
verify(listener(DataState(author2, isLoading: false))).called(1);
277-
verifyNoMoreInteractions(listener);
270+
await tester.expectDataState(author2, isLoading: false);
278271

279272
expect(author.books.first.originalAuthor!.value,
280273
equals(BookAuthor(id: 15, name: 'Steve-O', books: HasMany({book}))));

test/repository/remote_adapter_offline_test.dart

Lines changed: 25 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
1-
@Timeout(Duration(minutes: 20))
2-
31
import 'dart:convert';
42
import 'dart:io';
53

64
import 'package:flutter_data/flutter_data.dart';
7-
import 'package:mockito/mockito.dart';
85
import 'package:test/test.dart';
96

107
import '../_support/familia.dart';
@@ -97,13 +94,12 @@ void main() async {
9794
exception: isA<OfflineException>());
9895

9996
// familia is remembered as failed to persist
100-
// TODO fix: at location [0] is <1> instead of '1' (need # and ## again?)
101-
// expect(
102-
// container.familia.offlineOperations
103-
// .only(DataRequestLabel('save', type: 'familia'))
104-
// .map((o) => o.label.id)
105-
// .toList(),
106-
// [familia.id]);
97+
expect(
98+
container.familia.offlineOperations
99+
.only(DataRequestLabel('save', type: 'familia'))
100+
.map((o) => o.label.id)
101+
.toList(),
102+
[familia.id]);
107103

108104
// try with familia2 (tests it can work without ID)
109105
final familia2 = Familia(surname: 'Montewicz');
@@ -114,17 +110,15 @@ void main() async {
114110
}
115111

116112
// now two familia failed to persist
117-
// expect(
118-
// container.familia.offlineOperations
119-
// .only(DataRequestLabel('save', type: 'familia'))
120-
// .map((o) => o.label.id)
121-
// .toList(),
122-
// unorderedEquals([familia.id, familia2.id]));
113+
expect(
114+
container.familia.offlineOperations
115+
.only(DataRequestLabel('save', type: 'familia'))
116+
.map((o) => o.label.id)
117+
.toList(),
118+
unorderedEquals([familia.id, familia2.id]));
123119

124120
// retry saving both
125121
await container.familia.offlineOperations.retry();
126-
// await 1ms for each familia
127-
await oneMs();
128122

129123
// none of them could be saved upon retry
130124
expect(container.familia.offlineOperations.map((o) {
@@ -143,7 +137,6 @@ void main() async {
143137

144138
// retry
145139
await container.familia.offlineOperations.retry();
146-
await oneMs();
147140

148141
// familia2 failed on retry, operation still pending
149142
expect(container.familia.offlineOperations.map((o) => o.model),
@@ -158,7 +151,6 @@ void main() async {
158151

159152
// retry
160153
await container.familia.offlineOperations.retry();
161-
await oneMs();
162154

163155
// should be empty as all saves succeeded
164156
expect(container.familia.offlineOperations.map((o) => o.model), isEmpty);
@@ -173,7 +165,6 @@ void main() async {
173165
} catch (_) {
174166
// without onError, ignore exception
175167
}
176-
await oneMs();
177168

178169
// assert familia3 hasn't been persisted
179170
expect(
@@ -194,42 +185,32 @@ void main() async {
194185
});
195186

196187
test('delete', () async {
197-
final listener = Listener<DataState<List<Familia>?>?>();
198188
// listening to local changes is enough
199189
final notifier = container.familia.watchAllNotifier();
200-
201-
final dispose = notifier.addListener(listener);
202-
disposeFns.add(dispose);
190+
final tester = notifier.tester();
203191

204192
final familia = Familia(id: '1', surname: 'Smith').saveLocal();
205-
await oneMs();
206193

207194
// should show up through watchAllNotifier
208-
verify(listener(
209-
argThat(isA<DataState>().having((s) => s.model, 'model', [familia])),
210-
)).called(1);
195+
await tester.expectDataState([familia]);
211196

212197
// network issue deleting familia
213198
container.read(responseProvider.notifier).state = TestResponse((_) {
214199
throw SocketException('unreachable');
215200
});
216201

217202
// delete familia and send offline exception to notifier
203+
// NOTE: keep await, so that we give onError the chance to update the notifier
218204
await familia.delete(
219205
onError: (e, _, __) async {
220-
await oneMs();
221206
expect(e, isA<OfflineException>());
222207
expect(e.error, isA<SocketException>());
223208
return null;
224209
},
225210
);
226211

227-
await oneMs();
228-
229212
// verify the model in local storage has been deleted
230-
verify(listener(
231-
argThat(isA<DataState>().having((s) => s.model, 'model', isEmpty)),
232-
)).called(2);
213+
await tester.expectDataState(isEmpty);
233214

234215
// familia is remembered as failed to persist
235216
expect(
@@ -240,7 +221,6 @@ void main() async {
240221

241222
// retry
242223
await container.familia.offlineOperations.retry();
243-
await oneMs();
244224

245225
// could not be deleted upon retry
246226
expect(
@@ -254,55 +234,43 @@ void main() async {
254234

255235
// retry
256236
await container.familia.offlineOperations.retry();
257-
await oneMs();
258237

259238
// now offline queue is empty
260239
expect(container.familia.offlineOperations, isEmpty);
261240
});
262241

263242
test('save & delete combined', () async {
264-
final listener = Listener<DataState<List<Familia>?>?>();
265243
// listening to local changes enough
266244
final notifier = container.familia.watchAllNotifier(remote: false);
267-
268-
final dispose = notifier.addListener(listener);
269-
disposeFns.add(dispose);
245+
final tester = notifier.tester();
270246

271247
// setup familia
272248
final familia = Familia(id: '19', surname: 'Ko');
273-
await oneMs();
274249

275250
// network issues
276251
container.read(responseProvider.notifier).state = TestResponse((_) {
277252
throw SocketException('unreachable');
278253
});
279254

280-
// save...
255+
// save
281256
await familia.save(
282257
headers: {'X-Override-Name': 'Johnson'},
283258
onError: (e, _, __) async {
284-
await oneMs();
285259
notifier.updateWith(exception: e);
286260
return null;
287261
},
288262
);
289263

290-
await oneMs();
291-
292-
// ...and immediately delete
264+
// immediately delete
293265
await familia.delete(
294266
onError: (e, _, __) async {
295-
await oneMs();
296267
notifier.updateWith(exception: e);
297268
return null;
298269
},
299270
);
300271

301-
// assert it's an OfflineException, TWICE (one call per updateWith(e))
302-
verify(listener(argThat(
303-
isA<DataState>()
304-
.having((s) => s.exception, 'exception', isA<OfflineException>()),
305-
))).called(1);
272+
// assert it's an OfflineException
273+
tester.expectDataState(isNotNull, exception: isA<OfflineException>());
306274

307275
// should see the failed save queued
308276
expect(
@@ -331,16 +299,16 @@ void main() async {
331299

332300
// retry
333301
await container.familia.offlineOperations.retry();
334-
await oneMs();
335-
// same result...
302+
303+
// same result
336304
expect(container.familia.offlineOperations, hasLength(2));
337305

338306
// change the response to success
339307
container.read(responseProvider.notifier).state = TestResponse.json('');
340308

341309
// retry
342310
await container.familia.offlineOperations.retry();
343-
await oneMs();
311+
344312
// done
345313
expect(container.familia.offlineOperations, isEmpty);
346314
});
@@ -367,7 +335,6 @@ void main() async {
367335
return result;
368336
},
369337
);
370-
await oneMs();
371338
// fails to go through
372339
expect(container.familia.offlineOperations, hasLength(1));
373340

@@ -383,7 +350,7 @@ void main() async {
383350

384351
// retry
385352
await container.familia.offlineOperations.retry();
386-
await oneMs();
353+
387354
// done
388355
expect(container.familia.offlineOperations, isEmpty);
389356
});

test/repository/remote_adapter_serialization_test.dart

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
@Timeout(Duration(minutes: 20))
2-
31
import 'dart:convert';
42

53
import 'package:flutter_data/flutter_data.dart';

0 commit comments

Comments
 (0)