refactored broad range of the application, split files, modularized calendar and file views, centralized bottom sheets and clipboard handling, and implemented unit test coverage
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
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);
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user