93 lines
2.6 KiB
Dart
93 lines
2.6 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:marianum_mobile/widget/async_action_button.dart';
|
|
|
|
void main() {
|
|
group('AsyncActionController.run', () {
|
|
test('toggles busy true while running and false after success', () async {
|
|
final controller = AsyncActionController();
|
|
addTearDown(controller.dispose);
|
|
|
|
var seenBusyInsideCallback = false;
|
|
final ok = await controller.run(() async {
|
|
seenBusyInsideCallback = controller.busy;
|
|
});
|
|
|
|
expect(
|
|
seenBusyInsideCallback,
|
|
isTrue,
|
|
reason: 'busy must be true while the callback is running',
|
|
);
|
|
expect(ok, isTrue);
|
|
expect(controller.busy, isFalse);
|
|
expect(controller.error, isNull);
|
|
});
|
|
|
|
test(
|
|
'captures mapped error message on failure and returns false',
|
|
() async {
|
|
final controller = AsyncActionController();
|
|
addTearDown(controller.dispose);
|
|
|
|
final ok = await controller.run(
|
|
() async => throw Exception('boom'),
|
|
errorBuilder: (e) => 'custom: $e',
|
|
);
|
|
|
|
expect(ok, isFalse);
|
|
expect(controller.busy, isFalse);
|
|
expect(controller.error, contains('custom:'));
|
|
expect(controller.error, contains('boom'));
|
|
},
|
|
);
|
|
|
|
test('rejects re-entry while busy', () async {
|
|
final controller = AsyncActionController();
|
|
addTearDown(controller.dispose);
|
|
|
|
final firstStarted = Completer<void>();
|
|
final firstCanFinish = Completer<void>();
|
|
final firstFuture = controller.run(() async {
|
|
firstStarted.complete();
|
|
await firstCanFinish.future;
|
|
});
|
|
|
|
await firstStarted.future;
|
|
expect(controller.busy, isTrue);
|
|
|
|
final reentrant = await controller.run(() async {});
|
|
expect(
|
|
reentrant,
|
|
isFalse,
|
|
reason:
|
|
'second run while busy must be rejected without invoking callback',
|
|
);
|
|
|
|
firstCanFinish.complete();
|
|
expect(await firstFuture, isTrue);
|
|
expect(controller.busy, isFalse);
|
|
});
|
|
|
|
test('clearError resets error and notifies listeners', () async {
|
|
final controller = AsyncActionController();
|
|
addTearDown(controller.dispose);
|
|
|
|
var notifyCount = 0;
|
|
controller.addListener(() => notifyCount++);
|
|
|
|
await controller.run(() async => throw Exception('x'));
|
|
expect(controller.error, isNotNull);
|
|
final beforeClear = notifyCount;
|
|
|
|
controller.clearError();
|
|
expect(controller.error, isNull);
|
|
expect(notifyCount, beforeClear + 1);
|
|
|
|
// No-op when already cleared.
|
|
controller.clearError();
|
|
expect(notifyCount, beforeClear + 1);
|
|
});
|
|
});
|
|
}
|