Files
superport/test/integration/automated/interactive_search_test.dart

514 lines
16 KiB
Dart

import 'package:flutter_test/flutter_test.dart';
import 'package:get_it/get_it.dart';
import 'package:dio/dio.dart';
import 'package:superport/data/datasources/remote/api_client.dart';
import 'package:superport/services/company_service.dart';
import 'package:superport/services/user_service.dart';
// License service removed - Sprint 5 migration to Maintenance system
import 'package:superport/services/warehouse_service.dart';
import 'package:superport/services/equipment_service.dart';
import 'package:superport/services/auth_service.dart';
import 'package:superport/data/models/auth/login_request.dart';
import 'package:superport/models/company_model.dart';
import 'package:superport/models/user_model.dart';
// License model removed - Sprint 5 migration to Maintenance system
import 'package:superport/models/warehouse_location_model.dart';
import 'package:superport/models/equipment_unified_model.dart';
import 'package:superport/core/utils/debug_logger.dart';
import '../real_api/test_helper.dart';
/// 인터랙티브 검색 기능 자동 테스트 및 수정
///
/// 각 화면의 검색 기능을 체계적으로 테스트하고
/// 발견된 문제를 자동으로 수정합니다.
class InteractiveSearchTest {
final ApiClient apiClient;
final GetIt getIt;
// 테스트 대상 서비스들
late CompanyService companyService;
late UserService userService;
late LicenseService licenseService;
late WarehouseService warehouseService;
late EquipmentService equipmentService;
late AuthService authService;
// 테스트 데이터
final List<Map<String, dynamic>> testResults = [];
InteractiveSearchTest({
required this.apiClient,
required this.getIt,
});
/// 서비스 초기화 및 인증
Future<void> initialize() async {
print('\n${'=' * 60}');
print('인터랙티브 검색 기능 테스트 시작');
print('${'=' * 60}\n');
// 서비스 초기화
companyService = getIt<CompanyService>();
userService = getIt<UserService>();
licenseService = getIt<LicenseService>();
warehouseService = getIt<WarehouseService>();
equipmentService = getIt<EquipmentService>();
authService = getIt<AuthService>();
// 인증
await _ensureAuthenticated();
}
/// 인증 확인
Future<void> _ensureAuthenticated() async {
try {
final isAuthenticated = await authService.isLoggedIn();
if (!isAuthenticated) {
print('로그인 시도...');
final loginRequest = LoginRequest(
email: 'admin@example.com',
password: 'password123',
);
await authService.login(loginRequest);
print('로그인 성공');
}
} catch (e) {
print('인증 실패: $e');
// throw e;
}
}
/// 모든 검색 기능 테스트 실행
Future<void> runAllTests() async {
await initialize();
// 1. Company 검색 테스트
await testCompanySearch();
// 2. User 검색 테스트
await testUserSearch();
// 3. License 검색 테스트
await testLicenseSearch();
// 4. Warehouse Location 검색 테스트
await testWarehouseLocationSearch();
// 5. Equipment 검색 테스트 (현재 미구현)
await testEquipmentSearch();
// 결과 출력
_printTestResults();
}
/// Company 검색 기능 테스트
Future<void> testCompanySearch() async {
print('\n--- Company 검색 기능 테스트 ---');
final result = <String, dynamic>{
'screen': 'Company',
'tests': [],
};
try {
// 1. 빈 검색어 테스트
print('테스트 1: 빈 검색어로 전체 목록 조회');
var companies = await companyService.getCompanies(
page: 1,
perPage: 10,
search: null,
);
result['tests'].add({
'name': '빈 검색어 조회',
'status': companies != null ? 'PASS' : 'FAIL',
'count': companies.items.length ?? 0,
});
print(' 결과: ${companies.items.length ?? 0}개 회사 조회됨');
// 2. 특정 검색어 테스트
if (companies.items.isNotEmpty) {
final testCompany = companies.items.first;
final searchKeyword = testCompany.name.substring(0, testCompany.name.length > 3 ? 3 : testCompany.name.length);
print('테스트 2: "$searchKeyword" 검색어로 조회');
companies = await companyService.getCompanies(
page: 1,
perPage: 10,
search: searchKeyword,
);
final hasMatch = companies.items.any((c) =>
c.name.toLowerCase().contains(searchKeyword.toLowerCase())
) ?? false;
result['tests'].add({
'name': '검색어 필터링',
'status': hasMatch ? 'PASS' : 'FAIL',
'keyword': searchKeyword,
'count': companies.items.length ?? 0,
});
print(' 결과: ${companies.items.length ?? 0}개 회사 조회됨 (매칭: $hasMatch)');
}
// 3. 특수문자 검색 테스트
print('테스트 3: 특수문자 포함 검색');
try {
companies = await companyService.getCompanies(
page: 1,
perPage: 10,
search: '@#\$%^&*',
);
result['tests'].add({
'name': '특수문자 검색',
'status': 'PASS',
'count': companies.items.length ?? 0,
});
print(' 결과: 에러 없이 처리됨');
} catch (e) {
result['tests'].add({
'name': '특수문자 검색',
'status': 'FAIL',
'error': e.toString(),
});
print(' 결과: 에러 발생 - $e');
}
// 4. 긴 검색어 테스트
print('테스트 4: 매우 긴 검색어');
final longKeyword = 'a' * 100;
try {
companies = await companyService.getCompanies(
page: 1,
perPage: 10,
search: longKeyword,
);
result['tests'].add({
'name': '긴 검색어',
'status': 'PASS',
'keywordLength': longKeyword.length,
});
print(' 결과: 에러 없이 처리됨');
} catch (e) {
result['tests'].add({
'name': '긴 검색어',
'status': 'FAIL',
'error': e.toString(),
});
print(' 결과: 에러 발생 - $e');
}
// 5. 한글 검색 테스트
print('테스트 5: 한글 검색어');
try {
companies = await companyService.getCompanies(
page: 1,
perPage: 10,
search: '테스트',
);
result['tests'].add({
'name': '한글 검색',
'status': 'PASS',
'count': companies.items.length ?? 0,
});
print(' 결과: ${companies.items.length ?? 0}개 회사 조회됨');
} catch (e) {
result['tests'].add({
'name': '한글 검색',
'status': 'FAIL',
'error': e.toString(),
});
print(' 결과: 에러 발생 - $e');
}
result['overall'] = 'PASS';
} catch (e) {
result['overall'] = 'FAIL';
result['error'] = e.toString();
print('Company 검색 테스트 실패: $e');
}
testResults.add(result);
}
/// User 검색 기능 테스트
Future<void> testUserSearch() async {
print('\n--- User 검색 기능 테스트 ---');
final result = <String, dynamic>{
'screen': 'User',
'tests': [],
};
try {
// 1. 빈 검색어 테스트
print('테스트 1: 빈 검색어로 전체 목록 조회');
var users = await userService.getUsers(
page: 1,
perPage: 10,
);
result['tests'].add({
'name': '빈 검색어 조회',
'status': users != null ? 'PASS' : 'FAIL',
'count': users.items.length ?? 0,
});
print(' 결과: ${users.items.length ?? 0}명 사용자 조회됨');
// 2. 이름으로 검색
if (users.items.isNotEmpty) {
final testUser = users.items.first;
final searchKeyword = testUser.name.substring(0, testUser.name.length > 2 ? 2 : testUser.name.length);
print('테스트 2: "$searchKeyword" 검색어로 조회');
// UserService에 search 파라미터 지원 확인 필요
// 현재 UserService API를 확인해야 함
result['tests'].add({
'name': '이름 검색',
'status': 'PENDING',
'note': 'UserService API 확인 필요',
});
}
result['overall'] = 'PARTIAL';
} catch (e) {
result['overall'] = 'FAIL';
result['error'] = e.toString();
print('User 검색 테스트 실패: $e');
}
testResults.add(result);
}
/// License 검색 기능 테스트
Future<void> testLicenseSearch() async {
print('\n--- License 검색 기능 테스트 ---');
final result = <String, dynamic>{
'screen': 'License',
'tests': [],
};
try {
// 1. 빈 검색어 테스트
print('테스트 1: 빈 검색어로 전체 목록 조회');
var licenses = await licenseService.getLicenses(
page: 1,
perPage: 10,
);
result['tests'].add({
'name': '빈 검색어 조회',
'status': licenses != null ? 'PASS' : 'FAIL',
'count': licenses?.items.length ?? 0,
});
print(' 결과: ${licenses?.items.length ?? 0}개 라이선스 조회됨');
result['overall'] = 'PARTIAL';
} catch (e) {
result['overall'] = 'FAIL';
result['error'] = e.toString();
print('License 검색 테스트 실패: $e');
}
testResults.add(result);
}
/// Warehouse Location 검색 기능 테스트
Future<void> testWarehouseLocationSearch() async {
print('\n--- Warehouse Location 검색 기능 테스트 ---');
final result = <String, dynamic>{
'screen': 'WarehouseLocation',
'tests': [],
};
try {
// 1. 빈 검색어 테스트
print('테스트 1: 빈 검색어로 전체 목록 조회');
var warehouses = await warehouseService.getWarehouseLocations(
page: 1,
perPage: 10,
);
result['tests'].add({
'name': '빈 검색어 조회',
'status': warehouses != null ? 'PASS' : 'FAIL',
'count': warehouses.items.length ?? 0,
});
print(' 결과: ${warehouses.items.length ?? 0}개 창고 위치 조회됨');
result['overall'] = 'PARTIAL';
} catch (e) {
result['overall'] = 'FAIL';
result['error'] = e.toString();
print('Warehouse Location 검색 테스트 실패: $e');
}
testResults.add(result);
}
/// Equipment 검색 기능 테스트
Future<void> testEquipmentSearch() async {
print('\n--- Equipment 검색 기능 테스트 ---');
final result = <String, dynamic>{
'screen': 'Equipment',
'tests': [],
};
try {
// 1. 빈 검색어 테스트
print('테스트 1: 빈 검색어로 전체 목록 조회');
var equipments = await equipmentService.getEquipmentsWithStatus(
page: 1,
perPage: 10,
search: null,
);
result['tests'].add({
'name': '빈 검색어 조회',
'status': equipments != null ? 'PASS' : 'FAIL',
'count': equipments.items.length ?? 0,
});
print(' 결과: ${equipments.items.length ?? 0}개 장비 조회됨');
// 2. 특정 검색어 테스트
if (equipments.items.isNotEmpty) {
final testEquipment = equipments.items.first;
final searchKeyword = testEquipment.manufacturer?.substring(0,
testEquipment.manufacturer!.length > 3 ? 3 : testEquipment.manufacturer!.length) ?? 'test';
print('테스트 2: "$searchKeyword" 검색어로 조회');
equipments = await equipmentService.getEquipmentsWithStatus(
page: 1,
perPage: 10,
search: searchKeyword,
);
final hasMatch = equipments.items.any((e) =>
(e.manufacturer?.toLowerCase().contains(searchKeyword.toLowerCase()) ?? false) ||
(e.modelName?.toLowerCase().contains(searchKeyword.toLowerCase()) ?? false) ||
(e.equipmentNumber.toLowerCase().contains(searchKeyword.toLowerCase()) ?? false)
) ?? false;
result['tests'].add({
'name': '검색어 필터링',
'status': hasMatch ? 'PASS' : 'FAIL',
'keyword': searchKeyword,
'count': equipments.items.length ?? 0,
});
print(' 결과: ${equipments.items.length ?? 0}개 장비 조회됨 (매칭: $hasMatch)');
}
// 3. 특수문자 검색 테스트
print('테스트 3: 특수문자 포함 검색');
try {
equipments = await equipmentService.getEquipmentsWithStatus(
page: 1,
perPage: 10,
search: '@#\$%^&*',
);
result['tests'].add({
'name': '특수문자 검색',
'status': 'PASS',
'count': equipments.items.length ?? 0,
});
print(' 결과: 에러 없이 처리됨');
} catch (e) {
result['tests'].add({
'name': '특수문자 검색',
'status': 'FAIL',
'error': e.toString(),
});
print(' 결과: 에러 발생 - $e');
}
// 4. 한글 검색 테스트
print('테스트 4: 한글 검색어');
try {
equipments = await equipmentService.getEquipmentsWithStatus(
page: 1,
perPage: 10,
search: '테스트',
);
result['tests'].add({
'name': '한글 검색',
'status': 'PASS',
'count': equipments.items.length ?? 0,
});
print(' 결과: ${equipments.items.length ?? 0}개 장비 조회됨');
} catch (e) {
result['tests'].add({
'name': '한글 검색',
'status': 'FAIL',
'error': e.toString(),
});
print(' 결과: 에러 발생 - $e');
}
result['overall'] = 'PASS';
result['needsImplementation'] = false;
} catch (e) {
result['overall'] = 'FAIL';
result['error'] = e.toString();
print('Equipment 검색 테스트 실패: $e');
}
testResults.add(result);
}
/// 테스트 결과 출력
void _printTestResults() {
print('\n${'=' * 60}');
print('테스트 결과 요약');
print('${'=' * 60}\n');
for (final result in testResults) {
print('화면: ${result['screen']}');
print('전체 결과: ${result['overall']}');
if (result['tests'] != null) {
for (final test in result['tests']) {
print(' - ${test['name']}: ${test['status']}');
if (test['note'] != null) {
print(' 참고: ${test['note']}');
}
}
}
if (result['needsImplementation'] == true) {
print(' ⚠️ 구현 필요!');
}
print('');
}
// 수정이 필요한 항목 식별
print('수정 필요 항목:');
if (testResults.any((r) => r['screen'] == 'Equipment' && r['overall'] == 'PASS')) {
print('✅ Equipment 화면: 검색 기능 구현 완료!');
} else {
print('❌ Equipment 화면: 검색 기능 오류');
}
print('⚠️ User/License: API 응답 형식 문제 수정 필요');
}
}
/// 테스트 실행
void main() async {
// 실제 API 환경 설정
await RealApiTestHelper.setupTestEnvironment();
final getIt = GetIt.instance;
group('인터랙티브 검색 기능 테스트', () {
setUpAll(() async {
// 로그인 및 토큰 설정
await RealApiTestHelper.loginAndGetToken();
});
tearDownAll(() async {
await RealApiTestHelper.teardownTestEnvironment();
});
test('모든 화면의 검색 기능 테스트', () async {
final tester = InteractiveSearchTest(
apiClient: getIt.get<ApiClient>(),
getIt: getIt,
);
await tester.runAllTests();
}, timeout: Timeout(Duration(minutes: 5)));
});
}