83 lines
2.5 KiB
Dart
83 lines
2.5 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);
|
|
});
|
|
});
|
|
}
|