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/user_remote_datasource.dart'; import 'package:superport/services/auth_service.dart'; import 'package:superport/services/company_service.dart'; import 'package:superport/services/user_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/user/user_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; late UserService userService; // 테스트용 데이터 late Company testCompany; final List createdUserIds = []; 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( () => UserRemoteDataSource(), ); // Service 등록 getIt.registerLazySingleton( () => AuthServiceImpl( getIt(), getIt(), ), ); getIt.registerLazySingleton( () => CompanyService(getIt()), ); getIt.registerLazySingleton( () => UserService(), ); authService = getIt(); companyService = getIt(); userService = 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: 'User_Test_Company_${DateTime.now().millisecondsSinceEpoch}', address: '서울시 강남구 테스트로 999', contactName: '사용자 테스트', contactPosition: '팀장', contactPhone: '010-9999-9999', contactEmail: 'user.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}) }); tearDownAll(() async { // 생성된 사용자 삭제 for (final id in createdUserIds) { try { await userService.deleteUser(id); // 테스트 사용자 삭제: ID $id } catch (e) { // 사용자 삭제 실패 (ID: $id): $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 users = await userService.getUsers( page: 1, perPage: 20, ); // Assert expect(users, isNotEmpty); // 사용자 목록 조회 성공: 총 ${users.length}명 조회됨 if (users.isNotEmpty) { // 첫 번째 사용자: ${users.first.name} (${users.first.email}) } }); test('신규 사용자 생성', () async { // Arrange final timestamp = DateTime.now().millisecondsSinceEpoch; final createRequest = CreateUserRequest( username: 'user_$timestamp', password: 'Test1234!@', name: '테스트사용자_$timestamp', email: 'user_$timestamp@test.com', phone: '010-1234-5678', role: 'user', companyId: testCompany.id as int, ); // Act final newUser = await userService.createUser( username: createRequest.username, email: createRequest.email, password: createRequest.password, name: createRequest.name, role: createRequest.role, companyId: createRequest.companyId!, phone: createRequest.phone, ); // Assert expect(newUser, isNotNull); expect(newUser.id, isNotNull); expect(newUser.username, equals(createRequest.username)); expect(newUser.name, equals(createRequest.name)); expect(newUser.email, equals(createRequest.email)); expect(newUser.companyId, equals(testCompany.id)); expect(newUser.role, equals('user')); expect(newUser.isActive, true); createdUserIds.add(newUser.id!); // 사용자 생성 성공 }); test('사용자 상세 정보 조회', () async { // Arrange - 먼저 사용자 생성 final timestamp = DateTime.now().millisecondsSinceEpoch; final createRequest = CreateUserRequest( username: 'detail_user_$timestamp', password: 'Test1234!@', name: '상세조회테스트_$timestamp', email: 'detail_$timestamp@test.com', phone: '010-2222-3333', companyId: testCompany.id as int, role: 'user', ); final createdUser = await userService.createUser( username: createRequest.username, email: createRequest.email, password: createRequest.password, name: createRequest.name, role: createRequest.role, companyId: createRequest.companyId!, phone: createRequest.phone, ); createdUserIds.add(createdUser.id!); // Act final detailUser = await userService.getUser(createdUser.id!); // Assert expect(detailUser, isNotNull); expect(detailUser.id, equals(createdUser.id)); expect(detailUser.username, equals(createdUser.username)); expect(detailUser.name, equals(createdUser.name)); expect(detailUser.email, equals(createdUser.email)); expect(detailUser.companyId, equals(createdUser.companyId)); // 사용자 상세 정보 조회 성공 }); test('사용자 정보 수정', () async { // Arrange - 먼저 사용자 생성 final timestamp = DateTime.now().millisecondsSinceEpoch; final createRequest = CreateUserRequest( username: 'update_user_$timestamp', password: 'Test1234!@', name: '수정테스트_$timestamp', email: 'update_$timestamp@test.com', phone: '010-3333-4444', companyId: testCompany.id as int, role: 'user', ); final createdUser = await userService.createUser( username: createRequest.username, email: createRequest.email, password: createRequest.password, name: createRequest.name, role: createRequest.role, companyId: createRequest.companyId!, phone: createRequest.phone, ); createdUserIds.add(createdUser.id!); // 수정할 데이터 final updatedPhone = '010-9999-8888'; final updateRequest = UpdateUserRequest( name: createdUser.name, email: createdUser.email, phone: updatedPhone, role: createdUser.role, companyId: testCompany.id as int, ); // Act final updatedUser = await userService.updateUser( createdUser.id!, name: updateRequest.name, email: updateRequest.email, phone: updatedPhone, ); // Assert expect(updatedUser, isNotNull); expect(updatedUser.id, equals(createdUser.id)); expect(updatedUser.phoneNumbers.isNotEmpty ? updatedUser.phoneNumbers.first['number'] : null, equals(updatedPhone)); // 사용자 정보 수정 성공 }); test('사용자 상태 변경 (활성/비활성)', () async { // Arrange - 먼저 활성 사용자 생성 final timestamp = DateTime.now().millisecondsSinceEpoch; final createRequest = CreateUserRequest( username: 'status_user_$timestamp', password: 'Test1234!@', name: '상태변경테스트_$timestamp', email: 'status_$timestamp@test.com', phone: '010-4444-5555', companyId: testCompany.id as int, role: 'user', ); final createdUser = await userService.createUser( username: createRequest.username, email: createRequest.email, password: createRequest.password, name: createRequest.name, role: createRequest.role, companyId: createRequest.companyId!, phone: createRequest.phone, ); createdUserIds.add(createdUser.id!); // Act - 비활성화 await userService.changeUserStatus(createdUser.id!, false); // Assert var updatedUser = await userService.getUser(createdUser.id!); expect(updatedUser.isActive, false); // 사용자 비활성화 성공 // Act - 다시 활성화 await userService.changeUserStatus(createdUser.id!, true); // Assert updatedUser = await userService.getUser(createdUser.id!); expect(updatedUser.isActive, true); // 사용자 활성화 성공 }); test('역할별 필터링', () async { // Arrange - admin 역할 사용자 생성 final timestamp = DateTime.now().millisecondsSinceEpoch; final adminRequest = CreateUserRequest( username: 'admin_$timestamp', password: 'Test1234!@', name: '관리자_$timestamp', email: 'admin_$timestamp@test.com', phone: '010-9999-9999', role: 'admin', companyId: testCompany.id as int, ); final adminUser = await userService.createUser( username: adminRequest.username, email: adminRequest.email, password: adminRequest.password, name: adminRequest.name, role: adminRequest.role, companyId: adminRequest.companyId!, phone: adminRequest.phone, ); createdUserIds.add(adminUser.id!); // Act - admin 역할만 조회 final adminUsers = await userService.getUsers( page: 1, perPage: 20, role: 'admin', ); // Assert expect(adminUsers, isNotEmpty); expect( adminUsers.every((user) => user.role == 'S'), true, ); // 역할별 필터링 성공: admin 사용자: ${adminUsers.length}명 // Act - user 역할만 조회 final normalUsers = await userService.getUsers( page: 1, perPage: 20, role: 'user', ); expect( normalUsers.every((user) => user.role == 'M'), true, ); // user 사용자: ${normalUsers.length}명 }); test('회사별 필터링', () async { // Act - 테스트 회사의 사용자만 조회 final companyUsers = await userService.getUsers( page: 1, perPage: 20, companyId: testCompany.id, ); // Assert expect( companyUsers.every((user) => user.companyId == testCompany.id), true, ); // 회사별 필터링 성공: ${testCompany.name} 소속 사용자: ${companyUsers.length}명 if (companyUsers.isNotEmpty) { // 첫 3명의 사용자 정보 } }); test('사용자 검색 기능', () async { // Arrange - 검색용 사용자 생성 final searchKeyword = 'SearchUser_${DateTime.now().millisecondsSinceEpoch}'; final timestamp = DateTime.now().millisecondsSinceEpoch; final createRequest = CreateUserRequest( username: 'search_user_$timestamp', password: 'Test1234!@', name: searchKeyword, email: 'search_$timestamp@test.com', phone: '010-5555-6666', companyId: testCompany.id as int, role: 'user', ); final createdUser = await userService.createUser( username: createRequest.username, email: createRequest.email, password: createRequest.password, name: createRequest.name, role: createRequest.role, companyId: createRequest.companyId!, phone: createRequest.phone, ); createdUserIds.add(createdUser.id!); // Act - 이름으로 검색 final searchResults = await userService.searchUsers( query: searchKeyword, page: 1, perPage: 20, ); // Assert expect(searchResults, isNotEmpty); expect( searchResults.any((user) => user.name.contains(searchKeyword)), true, ); // 사용자 검색 성공: 검색어: $searchKeyword, 결과: ${searchResults.length}명 }); test('사용자 삭제', () async { // Arrange - 먼저 사용자 생성 final timestamp = DateTime.now().millisecondsSinceEpoch; final createRequest = CreateUserRequest( username: 'delete_user_$timestamp', password: 'Test1234!@', name: '삭제테스트_$timestamp', email: 'delete_$timestamp@test.com', phone: '010-6666-7777', companyId: testCompany.id as int, role: 'user', ); final createdUser = await userService.createUser( username: createRequest.username, email: createRequest.email, password: createRequest.password, name: createRequest.name, role: createRequest.role, companyId: createRequest.companyId!, phone: createRequest.phone, ); // Act await userService.deleteUser(createdUser.id!); // Assert - 삭제된 사용자 조회 시도 try { await userService.getUser(createdUser.id!); fail('삭제된 사용자가 조회되었습니다'); } catch (e) { // 사용자 삭제 성공: ID ${createdUser.id} } }); test('비밀번호 변경 기능', () async { // Arrange - 먼저 사용자 생성 final timestamp = DateTime.now().millisecondsSinceEpoch; final createRequest = CreateUserRequest( username: 'password_user_$timestamp', password: 'OldPassword1234!', name: '비밀번호테스트_$timestamp', email: 'password_$timestamp@test.com', phone: '010-7777-8888', companyId: testCompany.id as int, role: 'user', ); final createdUser = await userService.createUser( username: createRequest.username, email: createRequest.email, password: createRequest.password, name: createRequest.name, role: createRequest.role, companyId: createRequest.companyId!, phone: createRequest.phone, ); createdUserIds.add(createdUser.id!); // Act - 비밀번호 변경 final newPassword = 'NewPassword5678!'; await userService.changePassword( createdUser.id!, 'OldPassword1234!', newPassword, ); // Assert - 새 비밀번호로 로그인 시도 // 실제 로그인 테스트는 별도 사용자 계정이 필요하므로 생략 // 비밀번호 변경 성공 }); }); }