import 'package:flutter_test/flutter_test.dart'; import 'package:get_it/get_it.dart'; import 'package:superport/data/datasources/remote/api_client.dart'; import 'package:superport/data/datasources/remote/auth_remote_datasource.dart'; import 'package:superport/data/datasources/remote/company_remote_datasource.dart'; import 'package:superport/data/datasources/remote/warehouse_remote_datasource.dart'; import 'package:superport/data/datasources/remote/equipment_remote_datasource.dart'; import 'package:superport/services/auth_service.dart'; import 'package:superport/services/company_service.dart'; import 'package:superport/services/warehouse_service.dart'; import 'package:superport/services/equipment_service.dart'; import 'package:superport/data/models/auth/login_request.dart'; import 'package:superport/data/models/company/company_dto.dart'; import 'package:superport/data/models/warehouse/warehouse_dto.dart'; import 'package:superport/data/models/equipment/equipment_request.dart'; import 'package:superport/models/equipment_unified_model.dart'; import 'package:superport/models/company_model.dart'; import 'package:superport/models/warehouse_location_model.dart'; import 'package:superport/models/address_model.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; void main() { late GetIt getIt; late ApiClient apiClient; late AuthService authService; late CompanyService companyService; late WarehouseService warehouseService; late EquipmentService equipmentService; // 테스트용 데이터 late Company testCompany; late WarehouseLocation testWarehouse; final List createdEquipmentIds = []; setUpAll(() async { // GetIt 초기화 getIt = GetIt.instance; await getIt.reset(); // 환경 변수 로드 try { await dotenv.load(fileName: '.env'); } catch (e) { // Environment file not found, using defaults } // API 클라이언트 설정 apiClient = ApiClient(); getIt.registerSingleton(apiClient); // SecureStorage 설정 const secureStorage = FlutterSecureStorage(); getIt.registerSingleton(secureStorage); // DataSource 등록 getIt.registerLazySingleton( () => AuthRemoteDataSourceImpl(apiClient), ); getIt.registerLazySingleton( () => CompanyRemoteDataSourceImpl(apiClient), ); getIt.registerLazySingleton( () => WarehouseRemoteDataSourceImpl(apiClient: apiClient), ); getIt.registerLazySingleton( () => EquipmentRemoteDataSourceImpl(), ); // Service 등록 getIt.registerLazySingleton( () => AuthServiceImpl( getIt(), getIt(), ), ); getIt.registerLazySingleton( () => CompanyService(getIt()), ); getIt.registerLazySingleton( () => WarehouseService(), ); getIt.registerLazySingleton( () => EquipmentService(), ); authService = getIt(); companyService = getIt(); warehouseService = getIt(); equipmentService = getIt(); // 테스트 계정으로 로그인 final loginRequest = LoginRequest( email: 'admin@superport.kr', password: 'admin123!', ); final loginResult = await authService.login(loginRequest); loginResult.fold( (failure) => throw Exception('로그인 실패: ${failure.message}'), (_) => {}, ); // 테스트용 회사 생성 final createCompanyRequest = CreateCompanyRequest( name: 'Equipment_Test_Company_${DateTime.now().millisecondsSinceEpoch}', address: '서울시 강남구 테스트로 123', contactName: '테스트 담당자', contactPosition: '과장', contactPhone: '010-1234-5678', contactEmail: 'equipment.test@test.com', companyTypes: ['customer'], remark: '장비 테스트용 회사', ); final company = Company( name: createCompanyRequest.name, address: Address.fromFullAddress(createCompanyRequest.address), contactName: createCompanyRequest.contactName, contactPosition: createCompanyRequest.contactPosition, contactPhone: createCompanyRequest.contactPhone, contactEmail: createCompanyRequest.contactEmail, companyTypes: [CompanyType.customer], remark: createCompanyRequest.remark, ); testCompany = await companyService.createCompany(company); // 테스트 회사 생성: ${testCompany.name} (ID: ${testCompany.id}) // 테스트용 창고 생성 final createWarehouseRequest = CreateWarehouseLocationRequest( name: 'Equipment_Test_Warehouse_${DateTime.now().millisecondsSinceEpoch}', address: '서울시 강남구 창고로 456', city: '서울', state: '서울특별시', postalCode: '12345', country: '대한민국', capacity: 1000, managerId: null, ); testWarehouse = await warehouseService.createWarehouseLocation( WarehouseLocation( id: 0, // 임시 ID, 서버에서 할당 name: createWarehouseRequest.name, address: Address( zipCode: createWarehouseRequest.postalCode ?? '', region: createWarehouseRequest.city ?? '', detailAddress: createWarehouseRequest.address ?? '', ), remark: '테스트 창고', ), ); // 테스트 창고 생성: ${testWarehouse.name} (ID: ${testWarehouse.id}) }); tearDownAll(() async { // 생성된 장비 삭제 for (final id in createdEquipmentIds) { try { await equipmentService.deleteEquipment(id); // 테스트 장비 삭제: ID $id } catch (e) { // 장비 삭제 실패 (ID: $id): $e } } // 테스트 창고 삭제 try { await warehouseService.deleteWarehouseLocation(testWarehouse.id); // 테스트 창고 삭제: ${testWarehouse.name} } catch (e) { // 창고 삭제 실패: $e } // 테스트 회사 삭제 try { await companyService.deleteCompany(testCompany.id!); // 테스트 회사 삭제: ${testCompany.name} } catch (e) { // 회사 삭제 실패: $e } // 로그아웃 try { await authService.logout(); } catch (e) { // 로그아웃 중 오류: $e } // GetIt 정리 await getIt.reset(); }); group('장비 관리 화면 통합 테스트', () { test('장비 목록 조회', () async { // Act final equipments = await equipmentService.getEquipments( page: 1, perPage: 20, ); // Assert expect(equipments, isNotNull); // 장비 목록 조회 성공: 총 ${equipments.length}개 장비 조회됨 if (equipments.isNotEmpty) { // 첫 번째 장비: ${equipments.first.name} (${equipments.first.manufacturer}) } }); test('장비 입고 (생성)', () async { // Arrange final equipmentData = CreateEquipmentRequest( equipmentNumber: 'EQ-${DateTime.now().millisecondsSinceEpoch}', category1: '노트북', category2: '비즈니스용', manufacturer: '삼성전자', modelName: 'Galaxy Book Pro', serialNumber: 'SN-${DateTime.now().millisecondsSinceEpoch}', purchaseDate: DateTime.now().subtract(Duration(days: 30)), purchasePrice: 1500000, remark: '테스트 장비', ); // Act final equipment = Equipment( manufacturer: equipmentData.manufacturer, name: equipmentData.modelName ?? equipmentData.equipmentNumber, category: equipmentData.category1 ?? '미분류', subCategory: equipmentData.category2 ?? '미분류', subSubCategory: equipmentData.category3 ?? '미분류', serialNumber: equipmentData.serialNumber, quantity: 1, inDate: equipmentData.purchaseDate, remark: equipmentData.remark, ); final newEquipment = await equipmentService.createEquipment(equipment); // Assert expect(newEquipment, isNotNull); expect(newEquipment.id, isNotNull); expect(newEquipment.serialNumber, equals(equipmentData.serialNumber)); expect(newEquipment.name, equals(equipmentData.modelName)); expect(newEquipment.manufacturer, equals(equipmentData.manufacturer)); createdEquipmentIds.add(newEquipment.id!); // 장비 입고 성공 }); test('장비 상세 정보 조회', () async { // Arrange - 먼저 장비 생성 final equipmentData = CreateEquipmentRequest( equipmentNumber: 'EQ-${DateTime.now().millisecondsSinceEpoch}', category1: '노트북', category2: '비즈니스용', manufacturer: '삼성전자', modelName: 'Galaxy Book Pro', serialNumber: 'SN-${DateTime.now().millisecondsSinceEpoch}', purchaseDate: DateTime.now().subtract(Duration(days: 30)), purchasePrice: 1500000, remark: '테스트 장비', ); final equipment = Equipment( manufacturer: equipmentData.manufacturer, name: equipmentData.modelName ?? equipmentData.equipmentNumber, category: equipmentData.category1 ?? '미분류', subCategory: equipmentData.category2 ?? '미분류', subSubCategory: equipmentData.category3 ?? '미분류', serialNumber: equipmentData.serialNumber, quantity: 1, inDate: equipmentData.purchaseDate, remark: equipmentData.remark, ); final createdEquipment = await equipmentService.createEquipment(equipment); final equipmentId = createdEquipment.id!; createdEquipmentIds.add(equipmentId); // Act final detailEquipment = await equipmentService.getEquipmentDetail(equipmentId); // Assert expect(detailEquipment, isNotNull); expect(detailEquipment.id, equals(equipmentId)); expect(detailEquipment.name, equals(equipmentData.modelName)); expect(detailEquipment.serialNumber, equals(equipmentData.serialNumber)); // 장비 상세 정보 조회 성공 }); test('장비 출고', () async { // Arrange - 먼저 장비 생성 final equipmentData = CreateEquipmentRequest( equipmentNumber: 'EQ-${DateTime.now().millisecondsSinceEpoch}', category1: '노트북', category2: '비즈니스용', manufacturer: '삼성전자', modelName: 'Galaxy Book Pro', serialNumber: 'SN-${DateTime.now().millisecondsSinceEpoch}', purchaseDate: DateTime.now().subtract(Duration(days: 30)), purchasePrice: 1500000, remark: '테스트 장비', ); final equipment = Equipment( manufacturer: equipmentData.manufacturer, name: equipmentData.modelName ?? equipmentData.equipmentNumber, category: equipmentData.category1 ?? '미분류', subCategory: equipmentData.category2 ?? '미분류', subSubCategory: equipmentData.category3 ?? '미분류', serialNumber: equipmentData.serialNumber, quantity: 1, inDate: equipmentData.purchaseDate, remark: equipmentData.remark, ); final createdEquipment = await equipmentService.createEquipment(equipment); createdEquipmentIds.add(createdEquipment.id!); // 출고 요청 데이터 // Act final outResult = await equipmentService.equipmentOut( equipmentId: createdEquipment.id!, quantity: 1, companyId: testCompany.id!, notes: '통합 테스트를 위한 장비 출고', ); // Assert expect(outResult, isNotNull); // 장비 출고 성공 // 출고 후 상태 확인 // Equipment 모델에는 status 필드가 없음 }); test('장비 검색 기능', () async { // Arrange - 검색용 장비 생성 final searchKeyword = 'SEARCH_${DateTime.now().millisecondsSinceEpoch}'; final equipmentData = CreateEquipmentRequest( equipmentNumber: searchKeyword, category1: '노트북', category2: '비즈니스용', manufacturer: '삼성전자', modelName: 'SearchModel_$searchKeyword', serialNumber: 'SN-${DateTime.now().millisecondsSinceEpoch}', purchaseDate: DateTime.now().subtract(Duration(days: 30)), purchasePrice: 1500000, remark: '테스트 장비', ); final equipment = Equipment( manufacturer: equipmentData.manufacturer, name: searchKeyword, category: equipmentData.category1 ?? '미분류', subCategory: equipmentData.category2 ?? '미분류', subSubCategory: equipmentData.category3 ?? '미분류', serialNumber: equipmentData.serialNumber, quantity: 1, inDate: equipmentData.purchaseDate, remark: equipmentData.remark, ); final createdEquipment = await equipmentService.createEquipment(equipment); createdEquipmentIds.add(createdEquipment.id!); // Act - 모든 장비 조회 final searchByNumber = await equipmentService.getEquipments( page: 1, perPage: 100, ); // Assert expect(searchByNumber, isNotEmpty); expect( searchByNumber.any((e) => e.name.contains(searchKeyword)), true, ); // 장비 검색 성공: 검색어: $searchKeyword, 결과: ${searchByNumber.length}개 }); test('장비 필터링 기본 테스트', () async { // Act - 장비 조회 final equipments = await equipmentService.getEquipments( page: 1, perPage: 20, ); // Assert expect(equipments, isNotNull); // 장비 필터링 테스트: 총 ${equipments.length}개 }); test('카테고리별 필터링', () async { // Arrange - 특정 카테고리 장비 생성 final category = '노트북'; final equipmentData = CreateEquipmentRequest( equipmentNumber: 'EQ-${DateTime.now().millisecondsSinceEpoch}', category1: 'IT장비', category2: '컴퓨터', category3: category, manufacturer: '삼성전자', modelName: 'Galaxy Book Pro', serialNumber: 'SN-${DateTime.now().millisecondsSinceEpoch}', purchaseDate: DateTime.now().subtract(Duration(days: 30)), purchasePrice: 1500000, remark: '테스트 장비', ); final equipment = Equipment( manufacturer: equipmentData.manufacturer, name: equipmentData.modelName ?? equipmentData.equipmentNumber, category: equipmentData.category1 ?? '미분류', subCategory: equipmentData.category2 ?? '미분류', subSubCategory: equipmentData.category3 ?? '미분류', serialNumber: equipmentData.serialNumber, quantity: 1, inDate: equipmentData.purchaseDate, remark: equipmentData.remark, ); final createdEquipment = await equipmentService.createEquipment(equipment); createdEquipmentIds.add(createdEquipment.id!); // Act final categoryEquipments = await equipmentService.getEquipments( page: 1, perPage: 100, ); // Assert expect( categoryEquipments.any((e) => e.category == 'IT장비' || e.subCategory == '컴퓨터' || e.subSubCategory == category ), true, ); // 카테고리별 필터링 성공: 카테고리: $category, 조회 결과: ${categoryEquipments.length}개 }); test('장비 정보 수정', () async { // Arrange - 먼저 장비 생성 final equipmentData = CreateEquipmentRequest( equipmentNumber: 'EQ-${DateTime.now().millisecondsSinceEpoch}', category1: '노트북', category2: '비즈니스용', manufacturer: '삼성전자', modelName: 'Galaxy Book Pro', serialNumber: 'SN-${DateTime.now().millisecondsSinceEpoch}', purchaseDate: DateTime.now().subtract(Duration(days: 30)), purchasePrice: 1500000, remark: '테스트 장비', ); final equipment = Equipment( manufacturer: equipmentData.manufacturer, name: equipmentData.modelName ?? equipmentData.equipmentNumber, category: equipmentData.category1 ?? '미분류', subCategory: equipmentData.category2 ?? '미분류', subSubCategory: equipmentData.category3 ?? '미분류', serialNumber: equipmentData.serialNumber, quantity: 1, inDate: equipmentData.purchaseDate, remark: equipmentData.remark, ); final createdEquipment = await equipmentService.createEquipment(equipment); createdEquipmentIds.add(createdEquipment.id!); // 수정할 데이터 final updatedEquipment = Equipment( id: createdEquipment.id, manufacturer: createdEquipment.manufacturer, name: '${createdEquipment.name}_수정됨', category: createdEquipment.category, subCategory: createdEquipment.subCategory, subSubCategory: createdEquipment.subSubCategory, serialNumber: createdEquipment.serialNumber, quantity: createdEquipment.quantity + 1, inDate: createdEquipment.inDate, remark: '수정된 비고', ); // Act final result = await equipmentService.updateEquipment( createdEquipment.id!, updatedEquipment, ); // Assert expect(result.name, equals(updatedEquipment.name)); expect(result.quantity, equals(updatedEquipment.quantity)); expect(result.remark, equals(updatedEquipment.remark)); // 장비 정보 수정 성공 }); test('대량 장비 입고 성능 테스트', () async { // Arrange final stopwatch = Stopwatch()..start(); final batchSize = 5; final createdIds = []; // Act - 5개 장비 동시 생성 for (int i = 0; i < batchSize; i++) { final equipmentData = CreateEquipmentRequest( equipmentNumber: 'BATCH_${DateTime.now().millisecondsSinceEpoch}_$i', category1: '노트북', category2: '비즈니스용', manufacturer: '삼성전자', modelName: 'Galaxy Book Pro', serialNumber: 'SN-BATCH-${DateTime.now().millisecondsSinceEpoch}_$i', purchaseDate: DateTime.now().subtract(Duration(days: 30)), purchasePrice: 1500000, remark: '대량 테스트 장비 $i', ); final equipment = Equipment( manufacturer: equipmentData.manufacturer, name: equipmentData.modelName ?? equipmentData.equipmentNumber, category: equipmentData.category1 ?? '미분류', subCategory: equipmentData.category2 ?? '미분류', subSubCategory: equipmentData.category3 ?? '미분류', serialNumber: equipmentData.serialNumber, quantity: 1, inDate: equipmentData.purchaseDate, remark: equipmentData.remark, ); final created = await equipmentService.createEquipment(equipment); createdIds.add(created.id!); createdEquipmentIds.add(created.id!); } stopwatch.stop(); // Assert expect(createdIds.length, equals(batchSize)); // 대량 장비 입고 성능 테스트 완료 }); }); }