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/services/auth_service.dart'; import 'package:superport/services/company_service.dart'; import 'package:superport/data/models/auth/login_request.dart'; import 'package:superport/data/models/company/company_dto.dart'; import 'package:superport/models/company_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; final List createdCompanyIds = []; 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), ); // Service 등록 getIt.registerLazySingleton( () => AuthServiceImpl( getIt(), getIt(), ), ); getIt.registerLazySingleton( () => CompanyService(getIt()), ); authService = getIt(); companyService = getIt(); // 테스트 계정으로 로그인 final loginRequest = LoginRequest( email: 'admin@superport.kr', password: 'admin123!', ); final loginResult = await authService.login(loginRequest); loginResult.fold( (failure) => throw Exception('로그인 실패: ${failure.message}'), (_) => {}, ); }); tearDownAll(() async { // 생성된 테스트 데이터 정리 for (final id in createdCompanyIds) { try { await companyService.deleteCompany(id); // 테스트 회사 삭제: ID $id } catch (e) { // 회사 삭제 실패 (ID: $id): $e } } // 로그아웃 try { await authService.logout(); } catch (e) { // 로그아웃 중 오류: $e } // GetIt 정리 await getIt.reset(); }); group('회사 관리 화면 통합 테스트', () { test('회사 목록 조회', () async { // Act final companies = await companyService.getCompanies( page: 1, perPage: 20, ); // Assert expect(companies, isNotEmpty); // 회사 목록 조회 성공: 총 ${companies.length}개 회사 조회됨 // 첫 번째 회사 정보 확인 if (companies.isNotEmpty) { final firstCompany = companies.first; expect(firstCompany.id, isNotNull); expect(firstCompany.name, isNotEmpty); // expect(firstCompany.businessNumber, isNotEmpty); // 첫 번째 회사: ${firstCompany.name} } }); test('새 회사 생성', () async { // Arrange final createRequest = CreateCompanyRequest( name: 'TestCompany_${DateTime.now().millisecondsSinceEpoch}', address: '서울시 강남구 테헤란로 123', contactName: '홍길동', contactPosition: '대표이사', contactPhone: '010-1234-5678', contactEmail: 'test@test.com', companyTypes: ['customer'], remark: '테스트 회사', ); // Act final company = Company( name: createRequest.name, address: Address.fromFullAddress(createRequest.address), contactName: createRequest.contactName, contactPosition: createRequest.contactPosition, contactPhone: createRequest.contactPhone, contactEmail: createRequest.contactEmail, companyTypes: createRequest.companyTypes.map((e) => CompanyType.customer).toList(), remark: createRequest.remark, ); final newCompany = await companyService.createCompany(company); // Assert expect(newCompany, isNotNull); expect(newCompany.id, isNotNull); expect(newCompany.name, equals(createRequest.name)); expect(newCompany.address.toString(), contains(createRequest.address)); // Company 모델에는 isActive 속성이 없음 // 생성된 ID 저장 (나중에 삭제하기 위해) createdCompanyIds.add(newCompany.id!); // 회사 생성 성공: ID: ${newCompany.id}, 이름: ${newCompany.name} }); test('회사 상세 정보 조회', () async { // Arrange - 먼저 회사 생성 final createRequest = CreateCompanyRequest( name: 'TestCompany_${DateTime.now().millisecondsSinceEpoch}', address: '서울시 강남구 테헤란로 456', contactName: '홍길동', contactPosition: '대표이사', contactPhone: '010-2345-6789', contactEmail: 'detail@test.com', companyTypes: ['customer'], remark: '상세 조회 테스트', ); final company = Company( name: createRequest.name, address: Address.fromFullAddress(createRequest.address), contactName: createRequest.contactName, contactPosition: createRequest.contactPosition, contactPhone: createRequest.contactPhone, contactEmail: createRequest.contactEmail, companyTypes: createRequest.companyTypes.map((e) => CompanyType.customer).toList(), remark: createRequest.remark, ); final createdCompany = await companyService.createCompany(company); createdCompanyIds.add(createdCompany.id!); // Act final detailCompany = await companyService.getCompanyDetail(createdCompany.id!); // Assert expect(detailCompany, isNotNull); expect(detailCompany.id, equals(createdCompany.id)); expect(detailCompany.name, equals(createdCompany.name)); expect(detailCompany.address.toString(), equals(createdCompany.address.toString())); expect(detailCompany.contactName, equals(createdCompany.contactName)); // 회사 상세 정보 조회 성공 // print('- ID: ${detailCompany.id}'); // print('- 이름: ${detailCompany.name}'); // print('- 담당자: ${detailCompany.contactName}'); // print('- 연락처: ${detailCompany.contactPhone}'); }); test('회사 정보 수정', () async { // Arrange - 먼저 회사 생성 final createRequest = CreateCompanyRequest( name: 'TestCompany_${DateTime.now().millisecondsSinceEpoch}', address: '서울시 강남구 테헤란로 456', contactName: '홍길동', contactPosition: '대표이사', contactPhone: '010-2345-6789', contactEmail: 'detail@test.com', companyTypes: ['customer'], remark: '상세 조회 테스트', ); final company = Company( name: createRequest.name, address: Address.fromFullAddress(createRequest.address), contactName: createRequest.contactName, contactPosition: createRequest.contactPosition, contactPhone: createRequest.contactPhone, contactEmail: createRequest.contactEmail, companyTypes: createRequest.companyTypes.map((e) => CompanyType.customer).toList(), remark: createRequest.remark, ); final createdCompany = await companyService.createCompany(company); createdCompanyIds.add(createdCompany.id!); // 수정할 데이터 final updatedName = '${createdCompany.name}_수정됨'; final updatedPhone = '02-1234-5678'; final updatedCompany = Company( id: createdCompany.id, name: updatedName, address: createdCompany.address, contactName: createdCompany.contactName, contactPosition: createdCompany.contactPosition, contactPhone: updatedPhone, contactEmail: createdCompany.contactEmail, companyTypes: createdCompany.companyTypes.map((e) => CompanyType.customer).toList(), remark: createdCompany.remark, ); // Act final result = await companyService.updateCompany( createdCompany.id!, updatedCompany, ); // Assert expect(result, isNotNull); expect(result.id, equals(createdCompany.id)); expect(result.name, equals(updatedName)); expect(result.contactPhone, equals(updatedPhone)); // 회사 정보 수정 성공 }); test('회사 삭제', () async { // Arrange - 먼저 회사 생성 final createRequest = CreateCompanyRequest( name: 'TestCompany_${DateTime.now().millisecondsSinceEpoch}', address: '서울시 강남구 테헤란로 456', contactName: '홍길동', contactPosition: '대표이사', contactPhone: '010-2345-6789', contactEmail: 'detail@test.com', companyTypes: ['customer'], remark: '상세 조회 테스트', ); final company = Company( name: createRequest.name, address: Address.fromFullAddress(createRequest.address), contactName: createRequest.contactName, contactPosition: createRequest.contactPosition, contactPhone: createRequest.contactPhone, contactEmail: createRequest.contactEmail, companyTypes: createRequest.companyTypes.map((e) => CompanyType.customer).toList(), remark: createRequest.remark, ); final createdCompany = await companyService.createCompany(company); // Act await companyService.deleteCompany(createdCompany.id!); // Assert - 삭제된 회사 조회 시도 try { await companyService.getCompanyDetail(createdCompany.id!); fail('삭제된 회사가 조회되었습니다'); } catch (e) { // 회사 삭제 성공: ID ${createdCompany.id} } }); test('회사 검색 기능', () async { // Arrange - 검색용 회사 생성 final searchKeyword = 'TestCompany_Search_${DateTime.now().millisecondsSinceEpoch}'; final createRequest = CreateCompanyRequest( name: searchKeyword, address: '서울시 강남구 검색로 1', contactName: '검색테스트', contactPosition: '팀장', contactPhone: '010-5678-9012', contactEmail: 'search@test.com', companyTypes: ['customer'], remark: '검색 테스트', ); final company = Company( name: createRequest.name, address: Address.fromFullAddress(createRequest.address), contactName: createRequest.contactName, contactPosition: createRequest.contactPosition, contactPhone: createRequest.contactPhone, contactEmail: createRequest.contactEmail, companyTypes: createRequest.companyTypes.map((e) => CompanyType.customer).toList(), remark: createRequest.remark, ); final createdCompany = await companyService.createCompany(company); createdCompanyIds.add(createdCompany.id!); // Act - 모든 회사를 조회하여 검색 final searchResults = await companyService.getCompanies( page: 1, perPage: 100, ); // Assert expect(searchResults, isNotEmpty); expect( searchResults.any((company) => company.name.contains(searchKeyword)), true, ); // 회사 검색 성공: 검색어: $searchKeyword, 결과: ${searchResults.length}개 }); test('회사 조회 기본 테스트', () async { // Act - 회사 조회 final companies = await companyService.getCompanies( page: 1, perPage: 20, ); // Assert expect(companies, isNotEmpty); expect(companies.length, lessThanOrEqualTo(20)); // 회사 조회 성공: 총 ${companies.length}개 }); test('페이지네이션', () async { // Act - 첫 번째 페이지 final page1 = await companyService.getCompanies( page: 1, perPage: 5, ); // Act - 두 번째 페이지 final page2 = await companyService.getCompanies( page: 2, perPage: 5, ); // Assert expect(page1.length, lessThanOrEqualTo(5)); expect(page2.length, lessThanOrEqualTo(5)); // 페이지 간 중복 확인 final page1Ids = page1.map((c) => c.id).toSet(); final page2Ids = page2.map((c) => c.id).toSet(); expect(page1Ids.intersection(page2Ids).isEmpty, true); // 페이지네이션 테스트 성공 }); test('대량 데이터 생성 및 조회 성능 테스트', () async { // Arrange - 10개 회사 생성 final stopwatch = Stopwatch()..start(); final createdIds = []; for (int i = 0; i < 10; i++) { final createRequest = CreateCompanyRequest( name: '성능테스트_${DateTime.now().millisecondsSinceEpoch}_$i', address: '서울시 강남구 성능로 $i', contactName: '성능테스트$i', contactPosition: '대표', contactPhone: '010-9999-${i.toString().padLeft(4, '0')}', contactEmail: 'perf$i@test.com', companyTypes: ['customer'], remark: '성능 테스트 $i', ); final company = Company( name: createRequest.name, address: Address.fromFullAddress(createRequest.address), contactName: createRequest.contactName, contactPosition: createRequest.contactPosition, contactPhone: createRequest.contactPhone, contactEmail: createRequest.contactEmail, companyTypes: createRequest.companyTypes.map((e) => CompanyType.customer).toList(), remark: createRequest.remark, ); final created = await companyService.createCompany(company); createdIds.add(created.id!); createdCompanyIds.add(created.id!); } stopwatch.stop(); // 대량 데이터 생성 완료: ${createdIds.length}개 // Act - 전체 조회 stopwatch.reset(); stopwatch.start(); final allCompanies = await companyService.getCompanies( page: 1, perPage: 100, ); stopwatch.stop(); // 대량 데이터 조회 완료: ${allCompanies.length}개 // Assert expect(allCompanies.length, greaterThanOrEqualTo(createdIds.length)); }); }); }