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(); final firstCanFinish = Completer(); 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); }); }); }