import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:get_it/get_it.dart'; import 'package:superport/screens/overview/controllers/overview_controller.dart'; import 'package:superport/services/dashboard_service.dart'; import '../../helpers/test_helpers.dart'; import '../../helpers/simple_mock_services.dart'; import '../../helpers/simple_mock_services.mocks.dart'; void main() { late OverviewController controller; late MockDashboardService mockDashboardService; late GetIt getIt; setUp(() { getIt = setupTestGetIt(); mockDashboardService = MockDashboardService(); // GetIt에 서비스 등록 getIt.registerSingleton(mockDashboardService); // Mock 설정 SimpleMockServiceHelpers.setupDashboardServiceMock(mockDashboardService); controller = OverviewController(); }); tearDown(() { controller.dispose(); getIt.reset(); }); group('OverviewController 테스트', () { test('초기 상태 확인', () { expect(controller.overviewStats, isNull); expect(controller.recentActivities, isEmpty); expect(controller.equipmentStatus, isNull); expect(controller.expiringLicenses, isEmpty); expect(controller.isLoading, isFalse); expect(controller.error, isNull); expect(controller.totalCompanies, equals(0)); expect(controller.totalUsers, equals(0)); }); group('대시보드 데이터 로드', () { test('데이터 로드 성공', () async { // given SimpleMockServiceHelpers.setupDashboardServiceMock( mockDashboardService, getOverviewStatsSuccess: true, getRecentActivitiesSuccess: true, getEquipmentStatusSuccess: true, getExpiringLicensesSuccess: true, ); // when await controller.loadData(); // then expect(controller.overviewStats, isNotNull); expect(controller.overviewStats!.totalCompanies, equals(50)); expect(controller.overviewStats!.totalUsers, equals(200)); expect(controller.recentActivities, isNotEmpty); expect(controller.equipmentStatus, isNotNull); expect(controller.equipmentStatus!.available, equals(350)); expect(controller.expiringLicenses, isNotEmpty); expect(controller.isLoading, isFalse); expect(controller.error, isNull); expect(controller.totalCompanies, equals(50)); expect(controller.totalUsers, equals(200)); }); test('loadDashboardData가 loadData를 호출하는지 확인', () async { // given SimpleMockServiceHelpers.setupDashboardServiceMock( mockDashboardService, getOverviewStatsSuccess: true, ); // when await controller.loadDashboardData(); // then expect(controller.overviewStats, isNotNull); }); }); group('개별 데이터 로드 오류 처리', () { test('대시보드 통계 로드 실패', () async { // given SimpleMockServiceHelpers.setupDashboardServiceMock( mockDashboardService, getOverviewStatsSuccess: false, getRecentActivitiesSuccess: true, getEquipmentStatusSuccess: true, getExpiringLicensesSuccess: true, ); // when await controller.loadData(); // then expect(controller.overviewStats, isNull); expect(controller.recentActivities, isNotEmpty); expect(controller.equipmentStatus, isNotNull); expect(controller.expiringLicenses, isNotEmpty); expect(controller.error, contains('대시보드 통계를 불러오는 중 오류가 발생했습니다.')); }); test('최근 활동 로드 실패', () async { // given SimpleMockServiceHelpers.setupDashboardServiceMock( mockDashboardService, getOverviewStatsSuccess: true, getRecentActivitiesSuccess: false, getEquipmentStatusSuccess: true, getExpiringLicensesSuccess: true, ); // when await controller.loadData(); // then expect(controller.overviewStats, isNotNull); expect(controller.recentActivities, isEmpty); expect(controller.equipmentStatus, isNotNull); expect(controller.expiringLicenses, isNotEmpty); expect(controller.error, contains('최근 활동을 불러오는 중 오류가 발생했습니다.')); }); test('장비 상태 분포 로드 실패', () async { // given SimpleMockServiceHelpers.setupDashboardServiceMock( mockDashboardService, getOverviewStatsSuccess: true, getRecentActivitiesSuccess: true, getEquipmentStatusSuccess: false, getExpiringLicensesSuccess: true, ); // when await controller.loadData(); // then expect(controller.overviewStats, isNotNull); expect(controller.recentActivities, isNotEmpty); expect(controller.equipmentStatus, isNull); expect(controller.expiringLicenses, isNotEmpty); expect(controller.error, contains('장비 상태 분포를 불러오는 중 오류가 발생했습니다.')); }); test('만료 예정 라이선스 로드 실패', () async { // given SimpleMockServiceHelpers.setupDashboardServiceMock( mockDashboardService, getOverviewStatsSuccess: true, getRecentActivitiesSuccess: true, getEquipmentStatusSuccess: true, getExpiringLicensesSuccess: false, ); // when await controller.loadData(); // then expect(controller.overviewStats, isNotNull); expect(controller.recentActivities, isNotEmpty); expect(controller.equipmentStatus, isNotNull); expect(controller.expiringLicenses, isEmpty); expect(controller.error, contains('만료 예정 라이선스를 불러오는 중 오류가 발생했습니다.')); }); }); group('활동 타입별 아이콘 및 색상', () { test('활동 타입별 아이콘 확인', () { expect(controller.getActivityIcon('equipment_in'), equals(Icons.input)); expect(controller.getActivityIcon('장비 입고'), equals(Icons.input)); expect(controller.getActivityIcon('equipment_out'), equals(Icons.output)); expect(controller.getActivityIcon('장비 출고'), equals(Icons.output)); expect(controller.getActivityIcon('user_create'), equals(Icons.person_add)); expect(controller.getActivityIcon('사용자 추가'), equals(Icons.person_add)); expect(controller.getActivityIcon('license_create'), equals(Icons.vpn_key)); expect(controller.getActivityIcon('라이선스 등록'), equals(Icons.vpn_key)); expect(controller.getActivityIcon('unknown'), equals(Icons.notifications)); }); test('활동 타입별 색상 확인', () { // 색상 값은 실제 AppThemeTailwind 값에 따라 다를 수 있으므로 // null이 아닌지만 확인 expect(controller.getActivityColor('equipment_in'), isNotNull); expect(controller.getActivityColor('장비 입고'), isNotNull); expect(controller.getActivityColor('equipment_out'), isNotNull); expect(controller.getActivityColor('장비 출고'), isNotNull); expect(controller.getActivityColor('user_create'), isNotNull); expect(controller.getActivityColor('사용자 추가'), isNotNull); expect(controller.getActivityColor('license_create'), isNotNull); expect(controller.getActivityColor('라이선스 등록'), isNotNull); expect(controller.getActivityColor('unknown'), isNotNull); }); }); group('로딩 상태 관리', () { test('로드 중 isLoading이 true가 되는지 확인', () async { // given bool loadingStateChanged = false; controller.addListener(() { if (controller.isLoading) { loadingStateChanged = true; } }); // when final loadFuture = controller.loadData(); // 잠시 대기하여 로딩 상태가 변경될 시간을 줌 await Future.delayed(const Duration(milliseconds: 10)); // then expect(loadingStateChanged, isTrue); // 로드 완료 대기 await loadFuture; expect(controller.isLoading, isFalse); }); }); test('모든 데이터 로드 실패 시 첫 번째 에러만 표시', () async { // given SimpleMockServiceHelpers.setupDashboardServiceMock( mockDashboardService, getOverviewStatsSuccess: false, getRecentActivitiesSuccess: false, getEquipmentStatusSuccess: false, getExpiringLicensesSuccess: false, ); // when await controller.loadData(); // then // error getter는 첫 번째 null이 아닌 에러를 반환 expect(controller.error, isNotNull); expect(controller.error, contains('오류가 발생했습니다')); }); }); }