사용하지 않는 파일 정리 전 백업 (Phase 10 완료 후 상태)

This commit is contained in:
JiWoong Sul
2025-08-29 15:11:59 +09:00
parent a740ff10c8
commit d916b281a7
333 changed files with 53617 additions and 22574 deletions

View File

@@ -17,8 +17,8 @@ void main() {
test('Check all entity counts from API', () async {
// 먼저 로그인
final loginResponse = await dio.post('/auth/login', data: {
'email': 'admin@superport.kr',
'password': 'admin123!',
'email': 'admin@example.com',
'password': 'password123',
});
final token = loginResponse.data['data']['access_token'];

View File

@@ -5,7 +5,6 @@ import 'package:superport/services/equipment_service.dart';
import 'package:superport/services/company_service.dart';
import 'package:superport/services/auth_service.dart';
import 'package:superport/data/models/auth/login_request.dart';
import 'package:superport/data/models/equipment/equipment_out_request.dart';
import 'package:superport/models/equipment_unified_model.dart';
import 'package:superport/screens/equipment/controllers/equipment_list_controller.dart';
// MockDataService는 제거됨
@@ -58,8 +57,8 @@ class CheckboxEquipmentOutTest {
if (!isAuthenticated) {
print('로그인 시도...');
final loginRequest = LoginRequest(
email: 'admin@superport.kr',
password: 'admin123!',
email: 'admin@example.com',
password: 'password123',
);
await authService.login(loginRequest);
print('로그인 성공');
@@ -372,7 +371,7 @@ class CheckboxEquipmentOutTest {
// 회사 목록 조회 (출고 대상)
final companies = await companyService.getCompanies(page: 1, perPage: 5);
if (companies != null && companies.items.isNotEmpty) {
if (companies.items.isNotEmpty) {
final targetCompany = companies.items.first;
try {

View File

@@ -1,7 +1,6 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import '../real_api/test_helper.dart';
import 'test_result.dart';
/// 통합 테스트에서 호출할 수 있는 회사 관리 테스트 함수
@@ -406,8 +405,8 @@ void main() {
final loginResponse = await dio.post(
'$baseUrl/auth/login',
data: {
'email': 'admin@superport.kr',
'password': 'admin123!',
'email': 'admin@example.com',
'password': 'password123',
},
);

View File

@@ -6,9 +6,6 @@ import 'package:superport/data/datasources/remote/api_client.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/models/company_model.dart';
import 'package:superport/models/warehouse_location_model.dart';
import 'package:superport/models/address_model.dart';
import 'package:superport/data/models/auth/login_request.dart';
import '../real_api/test_helper.dart';
import 'test_result.dart';
@@ -614,8 +611,8 @@ void main() {
debugPrint('🔐 로그인 중...');
final loginResult = await authService.login(
LoginRequest(
email: 'admin@superport.kr',
password: 'admin123!',
email: 'admin@example.com',
password: 'password123',
),
);

View File

@@ -88,19 +88,19 @@ Future<TestResult> runEquipmentOutTests({
if (testCompanyId != null && testWarehouseId != null) {
final timestamp = DateTime.now().millisecondsSinceEpoch;
final equipmentData = {
'equipment_number': 'OUT-TEST-${timestamp}',
'equipment_number': 'OUT-TEST-$timestamp',
'category1': '네트워크',
'category2': '스위치',
'category3': 'L3',
'manufacturer': 'Test Manufacturer',
'model_name': 'Out Model',
'serial_number': 'OUT-SN-${timestamp}',
'serial_number': 'OUT-SN-$timestamp',
'purchase_date': DateTime.now().toIso8601String(),
'purchase_price': 1500000.0,
'quantity': 1,
'remark': '출고 테스트용 장비',
'company_id': int.parse(testCompanyId!),
'warehouse_location_id': int.parse(testWarehouseId!),
'company_id': int.parse(testCompanyId),
'warehouse_location_id': int.parse(testWarehouseId),
'status': 'I', // 입고 상태
};
@@ -189,18 +189,18 @@ Future<TestResult> runEquipmentOutTests({
for (int i = 0; i < 3; i++) {
final equipmentData = {
'equipment_number': 'MULTI-OUT-${timestamp}-${i}',
'equipment_number': 'MULTI-OUT-$timestamp-$i',
'category1': '서버',
'category2': '물리서버',
'category3': '블레이드',
'manufacturer': 'Multi Manufacturer',
'model_name': 'Multi Model',
'serial_number': 'MULTI-SN-${timestamp}-${i}',
'serial_number': 'MULTI-SN-$timestamp-$i',
'purchase_date': DateTime.now().toIso8601String(),
'purchase_price': 500000.0,
'quantity': 1,
'company_id': int.parse(testCompanyId!),
'warehouse_location_id': int.parse(testWarehouseId!),
'company_id': int.parse(testCompanyId),
'warehouse_location_id': int.parse(testWarehouseId),
'status': 'I',
};
@@ -278,18 +278,18 @@ Future<TestResult> runEquipmentOutTests({
// 대여할 장비 생성
final timestamp = DateTime.now().millisecondsSinceEpoch;
final equipmentData = {
'equipment_number': 'RENTAL-${timestamp}',
'equipment_number': 'RENTAL-$timestamp',
'category1': '네트워크',
'category2': '라우터',
'category3': '무선',
'manufacturer': 'Rental Manufacturer',
'model_name': 'Rental Model',
'serial_number': 'RENTAL-SN-${timestamp}',
'serial_number': 'RENTAL-SN-$timestamp',
'purchase_date': DateTime.now().toIso8601String(),
'purchase_price': 800000.0,
'quantity': 1,
'company_id': int.parse(testCompanyId!),
'warehouse_location_id': int.parse(testWarehouseId!),
'company_id': int.parse(testCompanyId),
'warehouse_location_id': int.parse(testWarehouseId),
'status': 'I',
};
@@ -338,18 +338,18 @@ Future<TestResult> runEquipmentOutTests({
// 폐기할 장비 생성
final timestamp = DateTime.now().millisecondsSinceEpoch;
final equipmentData = {
'equipment_number': 'DISPOSAL-${timestamp}',
'equipment_number': 'DISPOSAL-$timestamp',
'category1': '스토리지',
'category2': 'HDD',
'category3': 'SATA',
'manufacturer': 'Old Manufacturer',
'model_name': 'Old Model',
'serial_number': 'DISPOSAL-SN-${timestamp}',
'serial_number': 'DISPOSAL-SN-$timestamp',
'purchase_date': DateTime.now().subtract(Duration(days: 1095)).toIso8601String(), // 3년 전
'purchase_price': 100000.0,
'quantity': 1,
'company_id': int.parse(testCompanyId!),
'warehouse_location_id': int.parse(testWarehouseId!),
'company_id': int.parse(testCompanyId),
'warehouse_location_id': int.parse(testWarehouseId),
'status': 'I',
};
@@ -422,18 +422,18 @@ Future<TestResult> runEquipmentOutTests({
// 먼저 출고할 장비 생성
final timestamp = DateTime.now().millisecondsSinceEpoch;
final equipmentData = {
'equipment_number': 'CANCEL-${timestamp}',
'equipment_number': 'CANCEL-$timestamp',
'category1': '네트워크',
'category2': '허브',
'category3': '기가비트',
'manufacturer': 'Cancel Manufacturer',
'model_name': 'Cancel Model',
'serial_number': 'CANCEL-SN-${timestamp}',
'serial_number': 'CANCEL-SN-$timestamp',
'purchase_date': DateTime.now().toIso8601String(),
'purchase_price': 200000.0,
'quantity': 1,
'company_id': int.parse(testCompanyId!),
'warehouse_location_id': int.parse(testWarehouseId!),
'company_id': int.parse(testCompanyId),
'warehouse_location_id': int.parse(testWarehouseId),
'status': 'I',
};
@@ -555,7 +555,7 @@ Future<TestResult> runEquipmentOutTests({
if (response.statusCode == 200) {
// throw Exception('이미 출고된 장비가 다시 출고됨 (검증 실패)');
}
} on DioException catch (e) {
} on DioException {
// assert(e.response?.statusCode == 400 || e.response?.statusCode == 409);
}
}
@@ -575,7 +575,7 @@ Future<TestResult> runEquipmentOutTests({
if (response.statusCode == 200) {
// throw Exception('존재하지 않는 장비가 출고됨 (검증 실패)');
}
} on DioException catch (e) {
} on DioException {
// assert(e.response?.statusCode == 404);
}
@@ -626,8 +626,8 @@ void main() {
debugPrint('🔐 로그인 중...');
final loginResult = await authService.login(
LoginRequest(
email: 'admin@superport.kr',
password: 'admin123!',
email: 'admin@example.com',
password: 'password123',
),
);
@@ -692,13 +692,13 @@ void main() {
debugPrint('📦 출고할 테스트 장비 생성 중...');
final timestamp = DateTime.now().millisecondsSinceEpoch;
final equipmentData = {
'equipment_number': 'OUT-TEST-${timestamp}',
'equipment_number': 'OUT-TEST-$timestamp',
'category1': '네트워크',
'category2': '스위치',
'category3': 'L3',
'manufacturer': 'Test Manufacturer',
'model_name': 'Out Model',
'serial_number': 'OUT-SN-${timestamp}',
'serial_number': 'OUT-SN-$timestamp',
'purchase_date': DateTime.now().toIso8601String(),
'purchase_price': 1500000.0,
'quantity': 1,
@@ -716,7 +716,7 @@ void main() {
if (createResponse.statusCode == 200 || createResponse.statusCode == 201) {
testEquipmentId = createResponse.data['data']['id'];
debugPrint('✅ 출고 테스트용 장비 생성: ID ${testEquipmentId}');
debugPrint('✅ 출고 테스트용 장비 생성: ID $testEquipmentId');
}
} catch (e) {
debugPrint('⚠️ 장비 생성 중 오류: $e');
@@ -768,13 +768,13 @@ void main() {
for (int i = 0; i < 3; i++) {
final equipmentData = {
'equipment_number': 'MULTI-OUT-${timestamp}-${i}',
'equipment_number': 'MULTI-OUT-$timestamp-$i',
'category1': '서버',
'category2': '물리서버',
'category3': '블레이드',
'manufacturer': 'Multi Manufacturer',
'model_name': 'Multi Model',
'serial_number': 'MULTI-SN-${timestamp}-${i}',
'serial_number': 'MULTI-SN-$timestamp-$i',
'purchase_date': DateTime.now().toIso8601String(),
'purchase_price': 500000.0,
'quantity': 1,
@@ -837,13 +837,13 @@ void main() {
// 대여할 장비 생성
final timestamp = DateTime.now().millisecondsSinceEpoch;
final equipmentData = {
'equipment_number': 'RENTAL-${timestamp}',
'equipment_number': 'RENTAL-$timestamp',
'category1': '네트워크',
'category2': '라우터',
'category3': '무선',
'manufacturer': 'Rental Manufacturer',
'model_name': 'Rental Model',
'serial_number': 'RENTAL-SN-${timestamp}',
'serial_number': 'RENTAL-SN-$timestamp',
'purchase_date': DateTime.now().toIso8601String(),
'purchase_price': 800000.0,
'quantity': 1,
@@ -861,7 +861,7 @@ void main() {
if (createResponse.statusCode == 200 || createResponse.statusCode == 201) {
rentalEquipmentId = createResponse.data['data']['id'];
debugPrint('✅ 대여용 장비 생성: ID ${rentalEquipmentId}');
debugPrint('✅ 대여용 장비 생성: ID $rentalEquipmentId');
}
} catch (e) {
debugPrint('⚠️ 대여용 장비 생성 실패: $e');
@@ -902,13 +902,13 @@ void main() {
// 폐기할 장비 생성
final timestamp = DateTime.now().millisecondsSinceEpoch;
final equipmentData = {
'equipment_number': 'DISPOSAL-${timestamp}',
'equipment_number': 'DISPOSAL-$timestamp',
'category1': '스토리지',
'category2': 'HDD',
'category3': 'SATA',
'manufacturer': 'Old Manufacturer',
'model_name': 'Old Model',
'serial_number': 'DISPOSAL-SN-${timestamp}',
'serial_number': 'DISPOSAL-SN-$timestamp',
'purchase_date': DateTime.now().subtract(Duration(days: 1095)).toIso8601String(), // 3년 전
'purchase_price': 100000.0,
'quantity': 1,
@@ -926,7 +926,7 @@ void main() {
if (createResponse.statusCode == 200 || createResponse.statusCode == 201) {
disposalEquipmentId = createResponse.data['data']['id'];
debugPrint('✅ 폐기용 장비 생성: ID ${disposalEquipmentId}');
debugPrint('✅ 폐기용 장비 생성: ID $disposalEquipmentId');
}
} catch (e) {
debugPrint('⚠️ 폐기용 장비 생성 실패: $e');
@@ -989,13 +989,13 @@ void main() {
// 먼저 출고할 장비 생성
final timestamp = DateTime.now().millisecondsSinceEpoch;
final equipmentData = {
'equipment_number': 'CANCEL-${timestamp}',
'equipment_number': 'CANCEL-$timestamp',
'category1': '네트워크',
'category2': '허브',
'category3': '기가비트',
'manufacturer': 'Cancel Manufacturer',
'model_name': 'Cancel Model',
'serial_number': 'CANCEL-SN-${timestamp}',
'serial_number': 'CANCEL-SN-$timestamp',
'purchase_date': DateTime.now().toIso8601String(),
'purchase_price': 200000.0,
'quantity': 1,
@@ -1034,7 +1034,7 @@ void main() {
if (outResponse.statusCode == 200) {
outId = outResponse.data['data']['id'];
debugPrint('✅ 출고 완료: ID ${outId}');
debugPrint('✅ 출고 완료: ID $outId');
}
} catch (e) {
debugPrint('⚠️ 출고 실패: $e');

View File

@@ -1,4 +1,3 @@
import 'dart:io';
import 'package:test/test.dart';
// import 'screens/equipment/equipment_in_full_test.dart'; // 파일 삭제됨

View File

@@ -4,11 +4,10 @@ import 'package:superport/data/datasources/remote/api_client.dart';
import 'package:superport/services/company_service.dart';
import 'package:superport/services/equipment_service.dart';
import 'package:superport/services/user_service.dart';
import 'package:superport/services/license_service.dart';
// License service removed - Sprint 5 migration to Maintenance system
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/equipment_unified_model.dart';
import 'package:superport/models/user_model.dart';
import '../real_api/test_helper.dart';
@@ -23,7 +22,7 @@ class FilterSortTest {
late CompanyService companyService;
late EquipmentService equipmentService;
late UserService userService;
late LicenseService licenseService;
// late LicenseService licenseService; // Removed - Sprint 5 Maintenance migration
late AuthService authService;
// 테스트 결과
@@ -44,7 +43,7 @@ class FilterSortTest {
companyService = getIt<CompanyService>();
equipmentService = getIt<EquipmentService>();
userService = getIt<UserService>();
licenseService = getIt<LicenseService>();
// licenseService = getIt<LicenseService>(); // Removed - Sprint 5 Maintenance migration
authService = getIt<AuthService>();
// 인증
@@ -59,8 +58,8 @@ class FilterSortTest {
if (!isAuthenticated) {
print('로그인 시도...');
final loginRequest = LoginRequest(
email: 'admin@superport.kr',
password: 'admin123!',
email: 'admin@example.com',
password: 'password123',
);
await authService.login(loginRequest);
print('로그인 성공');

View File

@@ -4,14 +4,12 @@ import 'package:superport/data/datasources/remote/api_client.dart';
import 'package:superport/services/company_service.dart';
import 'package:superport/services/equipment_service.dart';
import 'package:superport/services/user_service.dart';
import 'package:superport/services/license_service.dart';
// License service removed - Sprint 5 migration to Maintenance system
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/address_model.dart';
import 'package:superport/models/equipment_unified_model.dart';
import 'package:superport/models/user_model.dart';
import 'package:superport/data/models/equipment/equipment_in_request.dart';
import '../real_api/test_helper.dart';
/// 폼 입력 → 제출 인터랙티브 기능 테스트
@@ -25,7 +23,7 @@ class FormSubmissionTest {
late CompanyService companyService;
late EquipmentService equipmentService;
late UserService userService;
late LicenseService licenseService;
// late LicenseService licenseService; // Removed - Sprint 5
late AuthService authService;
// 테스트 결과
@@ -46,7 +44,7 @@ class FormSubmissionTest {
companyService = getIt<CompanyService>();
equipmentService = getIt<EquipmentService>();
userService = getIt<UserService>();
licenseService = getIt<LicenseService>();
// licenseService = getIt<LicenseService>(); // Removed - Sprint 5
authService = getIt<AuthService>();
// 인증
@@ -61,8 +59,8 @@ class FormSubmissionTest {
if (!isAuthenticated) {
print('로그인 시도...');
final loginRequest = LoginRequest(
email: 'admin@superport.kr',
password: 'admin123!',
email: 'admin@example.com',
password: 'password123',
);
await authService.login(loginRequest);
print('로그인 성공');

View File

@@ -4,14 +4,14 @@ 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';
import 'package:superport/services/license_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';
import 'package:superport/models/license_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';
@@ -67,8 +67,8 @@ class InteractiveSearchTest {
if (!isAuthenticated) {
print('로그인 시도...');
final loginRequest = LoginRequest(
email: 'admin@superport.kr',
password: 'admin123!',
email: 'admin@example.com',
password: 'password123',
);
await authService.login(loginRequest);
print('로그인 성공');
@@ -121,12 +121,12 @@ class InteractiveSearchTest {
result['tests'].add({
'name': '빈 검색어 조회',
'status': companies != null ? 'PASS' : 'FAIL',
'count': companies?.items.length ?? 0,
'count': companies.items.length ?? 0,
});
print(' 결과: ${companies?.items.length ?? 0}개 회사 조회됨');
print(' 결과: ${companies.items.length ?? 0}개 회사 조회됨');
// 2. 특정 검색어 테스트
if (companies != null && companies.items.isNotEmpty) {
if (companies.items.isNotEmpty) {
final testCompany = companies.items.first;
final searchKeyword = testCompany.name.substring(0, testCompany.name.length > 3 ? 3 : testCompany.name.length);
@@ -137,7 +137,7 @@ class InteractiveSearchTest {
search: searchKeyword,
);
final hasMatch = companies?.items.any((c) =>
final hasMatch = companies.items.any((c) =>
c.name.toLowerCase().contains(searchKeyword.toLowerCase())
) ?? false;
@@ -145,9 +145,9 @@ class InteractiveSearchTest {
'name': '검색어 필터링',
'status': hasMatch ? 'PASS' : 'FAIL',
'keyword': searchKeyword,
'count': companies?.items.length ?? 0,
'count': companies.items.length ?? 0,
});
print(' 결과: ${companies?.items.length ?? 0}개 회사 조회됨 (매칭: $hasMatch)');
print(' 결과: ${companies.items.length ?? 0}개 회사 조회됨 (매칭: $hasMatch)');
}
// 3. 특수문자 검색 테스트
@@ -161,7 +161,7 @@ class InteractiveSearchTest {
result['tests'].add({
'name': '특수문자 검색',
'status': 'PASS',
'count': companies?.items.length ?? 0,
'count': companies.items.length ?? 0,
});
print(' 결과: 에러 없이 처리됨');
} catch (e) {
@@ -208,9 +208,9 @@ class InteractiveSearchTest {
result['tests'].add({
'name': '한글 검색',
'status': 'PASS',
'count': companies?.items.length ?? 0,
'count': companies.items.length ?? 0,
});
print(' 결과: ${companies?.items.length ?? 0}개 회사 조회됨');
print(' 결과: ${companies.items.length ?? 0}개 회사 조회됨');
} catch (e) {
result['tests'].add({
'name': '한글 검색',
@@ -248,12 +248,12 @@ class InteractiveSearchTest {
result['tests'].add({
'name': '빈 검색어 조회',
'status': users != null ? 'PASS' : 'FAIL',
'count': users?.items.length ?? 0,
'count': users.items.length ?? 0,
});
print(' 결과: ${users?.items.length ?? 0}명 사용자 조회됨');
print(' 결과: ${users.items.length ?? 0}명 사용자 조회됨');
// 2. 이름으로 검색
if (users != null && users.items.isNotEmpty) {
if (users.items.isNotEmpty) {
final testUser = users.items.first;
final searchKeyword = testUser.name.substring(0, testUser.name.length > 2 ? 2 : testUser.name.length);
@@ -327,9 +327,9 @@ class InteractiveSearchTest {
result['tests'].add({
'name': '빈 검색어 조회',
'status': warehouses != null ? 'PASS' : 'FAIL',
'count': warehouses?.items.length ?? 0,
'count': warehouses.items.length ?? 0,
});
print(' 결과: ${warehouses?.items.length ?? 0}개 창고 위치 조회됨');
print(' 결과: ${warehouses.items.length ?? 0}개 창고 위치 조회됨');
result['overall'] = 'PARTIAL';
} catch (e) {
@@ -360,12 +360,12 @@ class InteractiveSearchTest {
result['tests'].add({
'name': '빈 검색어 조회',
'status': equipments != null ? 'PASS' : 'FAIL',
'count': equipments?.items.length ?? 0,
'count': equipments.items.length ?? 0,
});
print(' 결과: ${equipments?.items.length ?? 0}개 장비 조회됨');
print(' 결과: ${equipments.items.length ?? 0}개 장비 조회됨');
// 2. 특정 검색어 테스트
if (equipments != null && equipments.items.isNotEmpty) {
if (equipments.items.isNotEmpty) {
final testEquipment = equipments.items.first;
final searchKeyword = testEquipment.manufacturer?.substring(0,
testEquipment.manufacturer!.length > 3 ? 3 : testEquipment.manufacturer!.length) ?? 'test';
@@ -377,19 +377,19 @@ class InteractiveSearchTest {
search: searchKeyword,
);
final hasMatch = equipments?.items.any((e) =>
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)
(e.equipmentNumber.toLowerCase().contains(searchKeyword.toLowerCase()) ?? false)
) ?? false;
result['tests'].add({
'name': '검색어 필터링',
'status': hasMatch ? 'PASS' : 'FAIL',
'keyword': searchKeyword,
'count': equipments?.items.length ?? 0,
'count': equipments.items.length ?? 0,
});
print(' 결과: ${equipments?.items.length ?? 0}개 장비 조회됨 (매칭: $hasMatch)');
print(' 결과: ${equipments.items.length ?? 0}개 장비 조회됨 (매칭: $hasMatch)');
}
// 3. 특수문자 검색 테스트
@@ -403,7 +403,7 @@ class InteractiveSearchTest {
result['tests'].add({
'name': '특수문자 검색',
'status': 'PASS',
'count': equipments?.items.length ?? 0,
'count': equipments.items.length ?? 0,
});
print(' 결과: 에러 없이 처리됨');
} catch (e) {
@@ -426,9 +426,9 @@ class InteractiveSearchTest {
result['tests'].add({
'name': '한글 검색',
'status': 'PASS',
'count': equipments?.items.length ?? 0,
'count': equipments.items.length ?? 0,
});
print(' 결과: ${equipments?.items.length ?? 0}개 장비 조회됨');
print(' 결과: ${equipments.items.length ?? 0}개 장비 조회됨');
} catch (e) {
result['tests'].add({
'name': '한글 검색',

View File

@@ -1,541 +0,0 @@
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/services/auth_service.dart';
import 'package:superport/services/license_service.dart';
import 'package:superport/services/company_service.dart';
import 'package:superport/models/license_model.dart';
import 'package:superport/models/company_model.dart';
import 'package:superport/models/address_model.dart';
import 'package:superport/data/models/auth/login_request.dart';
import 'package:dartz/dartz.dart';
import 'package:dio/dio.dart';
import 'dart:math';
import '../real_api/test_helper.dart';
import 'test_result.dart';
/// 라이센스 관리 전체 사용자 시나리오 테스트
/// 모든 인터랙티브 기능을 실제 API로 테스트
Future<TestResult> runLicenseTests({
Dio? dio,
String? authToken,
bool verbose = false,
}) async {
final stopwatch = Stopwatch()..start();
int totalTests = 10;
int passedTests = 0;
final List<String> failedTestNames = [];
// 내부 테스트 실행
_runLicenseTestsInternal();
// 테스트 결과 수집 (실제로는 test framework에서 가져와야 함)
// 현재는 예상 값으로 설정
passedTests = 1; // 에러 처리 테스트만 통과
failedTestNames.addAll([
'6. 🔎 라이센스 필터링 및 검색',
'7. ⏰ 만료 예정 라이센스 조회',
'8. 👥 라이센스 할당 및 해제',
'10. 📊 대량 작업 테스트',
]);
stopwatch.stop();
if (verbose) {
print('\n📋 라이센스 테스트 결과: $passedTests/$totalTests 통과');
}
return TestResult(
name: '라이센스 관리 API',
totalTests: totalTests,
passedTests: passedTests,
failedTests: totalTests - passedTests,
failedTestNames: failedTestNames,
executionTime: stopwatch.elapsed,
);
}
void _runLicenseTestsInternal() {
group('📋 라이센스(유지보수) 관리 통합 테스트', () {
late GetIt getIt;
late AuthService authService;
late LicenseService licenseService;
late CompanyService companyService;
late ApiClient apiClient;
late Company testCompany;
final random = Random();
// 테스트 데이터 - 한국 비즈니스 환경
final testData = {
'products': [
'MS Office 365',
'Adobe Creative Cloud',
'AutoCAD 2024',
'Photoshop CC',
'Visual Studio Enterprise',
'IntelliJ IDEA Ultimate',
'Windows 11 Pro',
'한컴오피스 2024',
'V3 365 클리닉',
'TeamViewer Business',
],
'vendors': [
'Microsoft',
'Adobe',
'Autodesk',
'JetBrains',
'한글과컴퓨터',
'안랩',
'TeamViewer GmbH',
],
'licenseTypes': [
'subscription',
'perpetual',
'trial',
'oem',
'volume',
],
};
setUpAll(() async {
print('\n🚀 라이센스 테스트 환경 설정 중...');
await RealApiTestHelper.setupTestEnvironment();
getIt = GetIt.instance;
// 서비스 초기화
apiClient = getIt<ApiClient>();
authService = getIt<AuthService>();
licenseService = getIt<LicenseService>();
companyService = getIt<CompanyService>();
// 관리자 로그인
print('🔐 관리자 계정으로 로그인...');
final loginResult = await authService.login(
LoginRequest(
email: 'admin@superport.kr',
password: 'admin123!',
),
);
loginResult.fold(
(failure) => throw Exception('로그인 실패: $failure'),
(response) => print('✅ 로그인 성공: ${response.user.email}'),
);
// 테스트용 회사 준비
print('🏢 테스트용 회사 준비...');
final companies = await companyService.getCompanies();
if (companies.items.isNotEmpty) {
testCompany = companies.items.first;
print('✅ 기존 회사 사용: ${testCompany.name}');
} else {
// 회사가 없으면 생성
testCompany = await companyService.createCompany(
Company(
name: '(주)테크노바 ${random.nextInt(1000)}',
address: Address(
detailAddress: '서울시 강남구 테헤란로 123 IT타워 15층',
),
contactName: '김철수',
contactPhone: '010-1234-5678',
contactEmail: 'kim@technova.co.kr',
),
);
print('✅ 새 회사 생성: ${testCompany.name}');
}
});
tearDownAll(() async {
print('\n🧹 테스트 환경 정리 중...');
await authService.logout();
await RealApiTestHelper.teardownTestEnvironment();
print('✅ 정리 완료');
});
test('1. 📋 라이센스 목록 조회 및 페이지네이션', () async {
print('\n📋 라이센스 목록 조회 테스트...');
// 전체 목록 조회
final licenses = await licenseService.getLicenses();
print('✅ 전체 라이센스 ${licenses.items.length}개 조회');
expect(licenses, isA<List<License>>());
// 페이지네이션 테스트
print('📄 페이지네이션 테스트...');
final page1 = await licenseService.getLicenses(page: 1, perPage: 5);
print(' - 1페이지: ${page1.items.length}');
final page2 = await licenseService.getLicenses(page: 2, perPage: 5);
print(' - 2페이지: ${page2.items.length}');
expect(page1.items.length, lessThanOrEqualTo(5));
expect(page2.items.length, lessThanOrEqualTo(5));
// 전체 개수 확인
final total = await licenseService.getTotalLicenses();
print('✅ 전체 라이센스 수: $total개');
expect(total, greaterThanOrEqualTo(0));
});
test('2. 라이센스 생성 (폼 입력 → 유효성 검증 → 저장)', () async {
print('\n 라이센스 생성 테스트...');
// 실제 비즈니스 데이터로 라이센스 생성
final productIndex = random.nextInt(testData['products']!.length);
final vendorIndex = random.nextInt(testData['vendors']!.length);
final typeIndex = random.nextInt(testData['licenseTypes']!.length);
final newLicense = License(
licenseKey: 'LIC-${DateTime.now().millisecondsSinceEpoch}',
productName: testData['products']![productIndex],
vendor: testData['vendors']![vendorIndex],
licenseType: testData['licenseTypes']![typeIndex],
userCount: random.nextInt(50) + 1,
purchaseDate: DateTime.now().subtract(Duration(days: random.nextInt(365))),
expiryDate: DateTime.now().add(Duration(days: random.nextInt(365) + 30)),
purchasePrice: (random.nextInt(500) + 10) * 10000.0, // 10만원 ~ 500만원
companyId: testCompany.id,
remark: '통합 테스트용 라이센스 - ${DateTime.now().toIso8601String()}',
isActive: true,
);
print('📝 라이센스 정보:');
print(' - 제품명: ${newLicense.productName}');
print(' - 벤더: ${newLicense.vendor}');
print(' - 타입: ${newLicense.licenseType}');
print(' - 사용자 수: ${newLicense.userCount}');
print(' - 가격: ${newLicense.purchasePrice?.toStringAsFixed(0)}');
final createdLicense = await licenseService.createLicense(newLicense);
print('✅ 라이센스 생성 성공: ${createdLicense.licenseKey}');
expect(createdLicense.id, isNotNull);
expect(createdLicense.licenseKey, equals(newLicense.licenseKey));
expect(createdLicense.companyId, equals(testCompany.id));
expect(createdLicense.productName, equals(newLicense.productName));
});
test('3. 🔍 라이센스 상세 조회', () async {
print('\n🔍 라이센스 상세 조회 테스트...');
// 목록에서 첫 번째 라이센스 선택
final licenses = await licenseService.getLicenses();
if (licenses.items.isEmpty) {
print('⚠️ 조회할 라이센스가 없습니다. 새로 생성...');
// 라이센스 생성
final newLicense = License(
licenseKey: 'DETAIL-TEST-${DateTime.now().millisecondsSinceEpoch}',
productName: 'Windows 11 Pro',
vendor: 'Microsoft',
licenseType: 'oem',
userCount: 1,
purchaseDate: DateTime.now(),
expiryDate: DateTime.now().add(Duration(days: 365)),
purchasePrice: 250000.0,
companyId: testCompany.id,
isActive: true,
);
final created = await licenseService.createLicense(newLicense);
// 생성된 라이센스 상세 조회
final license = await licenseService.getLicenseById(created.id!);
print('✅ 라이센스 상세 조회 성공: ${license.productName}');
expect(license.id, equals(created.id));
} else {
// 기존 라이센스 상세 조회
final targetId = licenses.items.first.id!;
final license = await licenseService.getLicenseById(targetId);
print('✅ 라이센스 상세 정보:');
print(' - ID: ${license.id}');
print(' - 제품: ${license.productName}');
print(' - 벤더: ${license.vendor}');
print(' - 회사: ${license.companyName ?? "N/A"}');
print(' - 만료일: ${license.expiryDate?.toIso8601String() ?? "N/A"}');
expect(license.id, equals(targetId));
expect(license.licenseKey, isNotEmpty);
}
});
test('4. ✏️ 라이센스 수정 (선택 → 편집 → 저장)', () async {
print('\n✏️ 라이센스 수정 테스트...');
// 수정할 라이센스 생성
final originalLicense = License(
licenseKey: 'EDIT-TEST-${DateTime.now().millisecondsSinceEpoch}',
productName: 'Photoshop CC',
vendor: 'Adobe',
licenseType: 'subscription',
userCount: 5,
purchaseDate: DateTime.now(),
expiryDate: DateTime.now().add(Duration(days: 180)),
purchasePrice: 300000.0,
companyId: testCompany.id,
remark: '수정 전',
isActive: true,
);
final createdLicense = await licenseService.createLicense(originalLicense);
print('✅ 원본 라이센스 생성: ${createdLicense.productName}');
// 라이센스 수정
final updatedLicense = License(
id: createdLicense.id,
licenseKey: createdLicense.licenseKey,
productName: 'Adobe Creative Cloud', // 변경
vendor: 'Adobe Systems', // 변경
licenseType: 'subscription',
userCount: 20, // 변경
purchaseDate: createdLicense.purchaseDate,
expiryDate: DateTime.now().add(Duration(days: 365)), // 변경
purchasePrice: 1200000.0, // 변경
companyId: testCompany.id,
remark: '수정됨 - ${DateTime.now().toIso8601String()}', // 변경
isActive: true,
);
print('📝 수정 내용:');
print(' - 제품명: ${originalLicense.productName}${updatedLicense.productName}');
print(' - 사용자 수: ${originalLicense.userCount}${updatedLicense.userCount}');
print(' - 가격: ${originalLicense.purchasePrice}${updatedLicense.purchasePrice}');
final result = await licenseService.updateLicense(updatedLicense);
print('✅ 라이센스 수정 성공');
expect(result.productName, equals('Adobe Creative Cloud'));
expect(result.userCount, equals(20));
expect(result.purchasePrice, equals(1200000.0));
});
test('5. 🗑️ 라이센스 삭제 (선택 → 확인 → 삭제)', () async {
print('\n🗑️ 라이센스 삭제 테스트...');
// 삭제할 라이센스 생성
final newLicense = License(
licenseKey: 'DELETE-TEST-${DateTime.now().millisecondsSinceEpoch}',
productName: 'Trial Software',
vendor: 'Test Vendor',
licenseType: 'trial',
userCount: 1,
purchaseDate: DateTime.now(),
expiryDate: DateTime.now().add(Duration(days: 30)),
purchasePrice: 0.0,
companyId: testCompany.id,
remark: '삭제 예정',
isActive: true,
);
final createdLicense = await licenseService.createLicense(newLicense);
print('✅ 삭제할 라이센스 생성: ${createdLicense.licenseKey}');
// 삭제 확인 다이얼로그 시뮬레이션
print('❓ 삭제 확인: "${createdLicense.productName}"을(를) 삭제하시겠습니까?');
// 라이센스 삭제
await licenseService.deleteLicense(createdLicense.id!);
print('✅ 라이센스 삭제 성공');
// 삭제 확인
try {
await licenseService.getLicenseById(createdLicense.id!);
fail('삭제된 라이센스가 여전히 조회됩니다');
} catch (e) {
print('✅ 삭제 확인: 라이센스가 정상적으로 삭제되었습니다');
}
});
test('6. 🔎 라이센스 필터링 및 검색', () async {
print('\n🔎 라이센스 필터링 및 검색 테스트...');
// 활성 라이센스만 조회
print('📌 활성 라이센스 필터링...');
final activeLicenses = await licenseService.getLicenses(isActive: true);
print('✅ 활성 라이센스: ${activeLicenses.items.length}');
expect(activeLicenses, isA<List<License>>());
// 특정 회사 라이센스만 조회
print('🏢 회사별 라이센스 필터링...');
final companyLicenses = await licenseService.getLicenses(
companyId: testCompany.id,
);
print('${testCompany.name} 라이센스: ${companyLicenses.items.length}');
expect(companyLicenses, isA<List<License>>());
// 라이센스 타입별 필터링
print('📊 라이센스 타입별 필터링...');
final subscriptionLicenses = await licenseService.getLicenses(
licenseType: 'subscription',
);
print('✅ 구독형 라이센스: ${subscriptionLicenses.items.length}');
});
test('7. ⏰ 만료 예정 라이센스 조회', () async {
print('\n⏰ 만료 예정 라이센스 조회 테스트...');
// 30일 이내 만료 예정 라이센스 생성
final expiringLicense = License(
licenseKey: 'EXPIRING-${DateTime.now().millisecondsSinceEpoch}',
productName: 'V3 365 클리닉',
vendor: '안랩',
licenseType: 'subscription',
userCount: 10,
purchaseDate: DateTime.now().subtract(Duration(days: 335)),
expiryDate: DateTime.now().add(Duration(days: 15)), // 15일 후 만료
purchasePrice: 500000.0,
companyId: testCompany.id,
remark: '곧 만료 예정 - 갱신 필요',
isActive: true,
);
await licenseService.createLicense(expiringLicense);
print('✅ 만료 예정 라이센스 생성 (15일 후 만료)');
// 30일 이내 만료 예정 라이센스 조회
final expiringLicenses = await licenseService.getExpiringLicenses(days: 30);
print('📊 만료 예정 라이센스 현황:');
for (var license in expiringLicenses.take(5)) {
final daysLeft = license.expiryDate?.difference(DateTime.now()).inDays ?? 0;
print(' - ${license.productName}: ${daysLeft}일 남음');
}
print('✅ 만료 예정 라이센스 ${expiringLicenses.length}개 조회');
expect(expiringLicenses, isA<List<License>>());
});
test('8. 👥 라이센스 할당 및 해제', () async {
print('\n👥 라이센스 할당 및 해제 테스트...');
// 할당할 라이센스 생성
final assignLicense = License(
licenseKey: 'ASSIGN-${DateTime.now().millisecondsSinceEpoch}',
productName: 'IntelliJ IDEA Ultimate',
vendor: 'JetBrains',
licenseType: 'subscription',
userCount: 5,
purchaseDate: DateTime.now(),
expiryDate: DateTime.now().add(Duration(days: 365)),
purchasePrice: 800000.0,
companyId: testCompany.id,
remark: '개발팀 라이센스',
isActive: true,
);
final created = await licenseService.createLicense(assignLicense);
print('✅ 할당할 라이센스 생성: ${created.productName}');
// 사용자에게 할당 (테스트용 사용자 ID)
try {
final assigned = await licenseService.assignLicense(created.id!, 1);
print('✅ 라이센스 할당 성공: 사용자 ID 1');
expect(assigned.assignedUserId, equals(1));
// 할당 해제
final unassigned = await licenseService.unassignLicense(created.id!);
print('✅ 라이센스 할당 해제 성공');
expect(unassigned.assignedUserId, isNull);
} catch (e) {
print('⚠️ 할당/해제 기능 미구현 또는 오류: $e');
}
});
test('9. ❌ 에러 처리 테스트', () async {
print('\n❌ 에러 처리 테스트...');
// 1. 잘못된 ID로 조회
print('🔍 존재하지 않는 라이센스 조회...');
try {
await licenseService.getLicenseById(999999);
fail('존재하지 않는 라이센스 조회가 성공했습니다');
} catch (e) {
print('✅ 404 에러 처리 성공: $e');
}
// 2. 필수 필드 누락
print('📝 유효성 검증 테스트...');
try {
final invalidLicense = License(
licenseKey: '', // 빈 라이센스 키
productName: '', // 빈 제품명
companyId: testCompany.id,
);
await licenseService.createLicense(invalidLicense);
fail('유효하지 않은 라이센스 생성이 성공했습니다');
} catch (e) {
print('✅ 유효성 검증 에러 처리 성공: $e');
}
// 3. 중복 라이센스 키
print('🔑 중복 라이센스 키 테스트...');
try {
final licenseKey = 'DUPLICATE-${DateTime.now().millisecondsSinceEpoch}';
// 첫 번째 라이센스 생성
await licenseService.createLicense(License(
licenseKey: licenseKey,
productName: 'Product 1',
companyId: testCompany.id,
));
// 동일한 키로 두 번째 라이센스 생성 시도
await licenseService.createLicense(License(
licenseKey: licenseKey,
productName: 'Product 2',
companyId: testCompany.id,
));
print('⚠️ 중복 라이센스 키 검증이 백엔드에 구현되지 않음');
} catch (e) {
print('✅ 중복 키 에러 처리 성공: $e');
}
});
test('10. 📊 대량 작업 테스트', () async {
print('\n📊 대량 라이센스 작업 테스트...');
// 여러 라이센스 일괄 생성
print('🔄 10개 라이센스 일괄 생성...');
final createdIds = <int>[];
for (int i = 0; i < 10; i++) {
final productIndex = random.nextInt(testData['products']!.length);
final bulkLicense = License(
licenseKey: 'BULK-${DateTime.now().millisecondsSinceEpoch}-$i',
productName: testData['products']![productIndex],
vendor: testData['vendors']![random.nextInt(testData['vendors']!.length)],
licenseType: 'volume',
userCount: random.nextInt(100) + 10,
purchaseDate: DateTime.now(),
expiryDate: DateTime.now().add(Duration(days: 365)),
purchasePrice: (random.nextInt(1000) + 100) * 10000.0,
companyId: testCompany.id,
remark: '대량 구매 라이센스 #$i',
isActive: true,
);
final created = await licenseService.createLicense(bulkLicense);
createdIds.add(created.id!);
print(' ${i + 1}. ${created.productName} 생성 완료');
}
print('${createdIds.length}개 라이센스 일괄 생성 완료');
// 일괄 삭제 (멀티 선택 → 일괄 삭제)
print('🗑️ 생성된 라이센스 일괄 삭제...');
for (var id in createdIds) {
await licenseService.deleteLicense(id);
}
print('${createdIds.length}개 라이센스 일괄 삭제 완료');
});
print('\n🎉 라이센스 관리 통합 테스트 완료!');
});
}
void main() async {
final result = await runLicenseTests(verbose: true);
print(result.summary);
}

View File

@@ -1,7 +1,6 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import '../real_api/test_helper.dart';
import 'test_result.dart';
/// 통합 테스트에서 호출할 수 있는 오버뷰 대시보드 테스트 함수
@@ -488,8 +487,8 @@ void main() {
final loginResponse = await dio.post(
'$baseUrl/auth/login',
data: {
'email': 'admin@superport.kr',
'password': 'admin123!',
'email': 'admin@example.com',
'password': 'password123',
},
);

View File

@@ -53,8 +53,8 @@ class PaginationTest {
if (!isAuthenticated) {
print('로그인 시도...');
final loginRequest = LoginRequest(
email: 'admin@superport.kr',
password: 'admin123!',
email: 'admin@example.com',
password: 'password123',
);
await authService.login(loginRequest);
print('로그인 성공');

View File

@@ -52,8 +52,8 @@ void main() {
test('로그인 테스트', () async {
// debugPrint('\n[TEST] 로그인 테스트 시작...');
const email = 'admin@superport.kr';
const password = 'admin123!';
const email = 'admin@example.com';
const password = 'password123';
// debugPrint('[TEST] 로그인 정보:');
// debugPrint('[TEST] - Email: $email');

View File

@@ -61,7 +61,7 @@ class TestSuiteResult {
String get summary {
final buffer = StringBuffer();
buffer.writeln('\n' + '=' * 60);
buffer.writeln('\n${'=' * 60}');
buffer.writeln('📊 테스트 실행 결과 요약');
buffer.writeln('=' * 60);
buffer.writeln('실행 시간: ${timestamp.toLocal()}');

View File

@@ -443,8 +443,8 @@ void main() async {
final loginResponse = await dio.post(
'$baseUrl/auth/login',
data: {
'email': 'admin@superport.kr',
'password': 'admin123!',
'email': 'admin@example.com',
'password': 'password123',
},
);

View File

@@ -32,12 +32,12 @@ Future<TestResult> runWarehouseTests({
'ceo_name': '김창고',
'address': '경기도 용인시 처인구 물류단지로 123',
'phone': '031-${1000 + (timestamp % 8999)}-${1000 + (timestamp % 8999)}',
'email': 'warehouse_${timestamp}@hanmail.net',
'email': 'warehouse_$timestamp@hanmail.net',
'business_type': '도소매업',
'business_item': '물류창고업',
'contact_name': '박물류',
'contact_phone': '010-${1000 + (timestamp % 8999)}-${1000 + (timestamp % 8999)}',
'contact_email': 'contact_${timestamp}@naver.com',
'contact_email': 'contact_$timestamp@naver.com',
'is_branch': false,
},
);
@@ -91,7 +91,7 @@ Future<TestResult> runWarehouseTests({
'address': '경기도 용인시 처인구 백암면 물류단지로 ${100 + (timestamp % 200)}',
'manager_name': '이물류',
'manager_phone': '010-${2000 + (timestamp % 7999)}-${1000 + (timestamp % 8999)}',
'manager_email': 'manager_${timestamp}@daum.net',
'manager_email': 'manager_$timestamp@daum.net',
'description': '대형 물류 보관 창고',
'is_active': true,
};
@@ -194,7 +194,7 @@ Future<TestResult> runWarehouseTests({
currentData['address'] = '경기도 용인시 기흥구 신갈동 물류대로 789';
currentData['manager_name'] = '최창고';
currentData['manager_phone'] = '010-${3000 + (timestamp % 6999)}-${2000 + (timestamp % 7999)}';
currentData['manager_email'] = 'new_manager_${timestamp}@gmail.com';
currentData['manager_email'] = 'new_manager_$timestamp@gmail.com';
currentData['description'] = '확장된 대형 물류 센터';
// Optional 필드들
@@ -459,7 +459,7 @@ Future<TestResult> runWarehouseTests({
'address': '경기도 김포시 대곶면 물류단지 ${i + 1}',
'manager_name': '관리자${i + 1}',
'manager_phone': '010-${5000 + i}-${1000 + (timestamp % 8999)}',
'manager_email': 'bulk_${i}_${timestamp}@korea.com',
'manager_email': 'bulk_${i}_$timestamp@korea.com',
'description': '벌크 테스트용 창고 ${i + 1}',
'is_active': true,
},
@@ -526,8 +526,8 @@ void main() {
final loginResponse = await dio.post(
'$baseUrl/auth/login',
data: {
'email': 'admin@superport.kr',
'password': 'admin123!',
'email': 'admin@example.com',
'password': 'password123',
},
);

View File

@@ -3,11 +3,11 @@ import 'package:get_it/get_it.dart';
import 'package:superport/injection_container.dart' as di;
import 'package:superport/services/warehouse_service.dart';
import 'package:superport/services/company_service.dart';
import 'package:superport/services/license_service.dart';
// import 'package:superport/services/license_service.dart'; // License 시스템 제거
import 'package:superport/services/equipment_service.dart';
import 'package:superport/models/warehouse_location_model.dart';
import 'package:superport/models/company_model.dart';
import 'package:superport/models/license_model.dart';
// import 'package:superport/models/license_model.dart'; // License 시스템 제거
import 'package:superport/models/address_model.dart';
import 'package:superport/models/equipment_unified_model.dart';
import 'package:superport/utils/phone_utils.dart';
@@ -16,7 +16,7 @@ void main() {
TestWidgetsFlutterBinding.ensureInitialized();
late WarehouseService warehouseService;
late CompanyService companyService;
late LicenseService licenseService;
// late LicenseService licenseService; // License 시스템 제거
late EquipmentService equipmentService;
setUpAll(() async {
@@ -27,7 +27,7 @@ void main() {
warehouseService = GetIt.instance<WarehouseService>();
companyService = GetIt.instance<CompanyService>();
licenseService = GetIt.instance<LicenseService>();
// licenseService = GetIt.instance<LicenseService>(); // License 시스템 제거
equipmentService = GetIt.instance<EquipmentService>();
});
@@ -191,105 +191,17 @@ void main() {
});
});
group('유지보수 라이선스 CRUD 테스트', () {
int? createdLicenseId;
int? testCompanyId;
setUpAll(() async {
// 테스트용 회사 생성
final company = Company(
name: 'License Test Company ${DateTime.now().millisecondsSinceEpoch}',
address: const Address(region: '서울'),
companyTypes: [CompanyType.customer],
);
final created = await companyService.createCompany(company);
testCompanyId = created.id;
});
tearDownAll(() async {
// 테스트용 회사 삭제
if (testCompanyId != null) {
await companyService.deleteCompany(testCompanyId!);
}
});
test('라이선스 생성', () async {
final license = License(
licenseKey: 'TEST-KEY-${DateTime.now().millisecondsSinceEpoch}',
productName: 'Test Product',
vendor: 'Test Vendor',
companyId: testCompanyId,
purchaseDate: DateTime.now().subtract(const Duration(days: 30)),
expiryDate: DateTime.now().add(const Duration(days: 335)),
isActive: true,
);
final created = await licenseService.createLicense(license);
createdLicenseId = created.id;
expect(created.id, isNotNull);
expect(created.licenseKey, equals(license.licenseKey));
expect(created.productName, equals(license.productName));
});
test('라이선스 수정 - 제한된 필드만 수정 가능', () async {
if (createdLicenseId == null) {
return; // skip 대신 return 사용
}
// UpdateLicenseRequest DTO에 포함된 필드만 수정 가능
final license = License(
id: createdLicenseId,
licenseKey: 'SHOULD-NOT-CHANGE', // 수정 불가
productName: 'Updated Product', // 수정 가능
vendor: 'Updated Vendor', // 수정 가능
expiryDate: DateTime.now().add(const Duration(days: 365)), // 수정 가능
isActive: false, // 수정 가능
);
final updated = await licenseService.updateLicense(license);
expect(updated.productName, equals('Updated Product'));
expect(updated.vendor, equals('Updated Vendor'));
expect(updated.isActive, equals(false));
// license_key는 수정되지 않아야 함
expect(updated.licenseKey, isNot(equals('SHOULD-NOT-CHANGE')));
});
test('라이선스 조회', () async {
if (createdLicenseId == null) {
return; // skip 대신 return 사용
}
final license = await licenseService.getLicenseById(createdLicenseId!);
expect(license.id, equals(createdLicenseId));
expect(license.licenseKey, isNotEmpty);
});
test('라이선스 삭제', () async {
if (createdLicenseId == null) {
return; // skip 대신 return 사용
}
await expectLater(
licenseService.deleteLicense(createdLicenseId!),
completes,
);
});
});
// License 시스템이 Maintenance 시스템으로 대체되었습니다.
// 이전 License 관련 테스트는 제거되었습니다.
// Maintenance 테스트는 별도 파일에서 관리합니다.
group('장비 관리 CRUD 테스트', () {
int? createdEquipmentId;
test('장비 생성', () async {
final equipment = Equipment(
manufacturer: 'Test Manufacturer',
equipmentNumber: 'Test Equipment ${DateTime.now().millisecondsSinceEpoch}', // name → equipmentNumber
modelName: 'Test Model ${DateTime.now().millisecondsSinceEpoch}', // 새로운 필수 필드
category1: 'Test Category', // category → category1
category2: 'Test SubCategory', // subCategory → category2
category3: 'Test SubSubCategory', // subSubCategory → category3
equipmentNumber: 'Test Equipment ${DateTime.now().millisecondsSinceEpoch}',
modelsId: 1, // Vendor→Model 관계로 변경됨
quantity: 5,
serialNumber: 'SN-${DateTime.now().millisecondsSinceEpoch}',
);
@@ -298,7 +210,7 @@ void main() {
createdEquipmentId = created.id;
expect(created.id, isNotNull);
expect(created.manufacturer, equals(equipment.manufacturer));
// expect(created.manufacturer, equals(equipment.manufacturer)); // manufacturer 필드 제거됨
expect(created.equipmentNumber, equals(equipment.equipmentNumber)); // name → equipmentNumber
});
@@ -311,24 +223,20 @@ void main() {
final loaded = await equipmentService.getEquipmentDetail(createdEquipmentId!);
expect(loaded.id, equals(createdEquipmentId));
expect(loaded.manufacturer, isNotEmpty);
// expect(loaded.manufacturer, isNotEmpty); // manufacturer 필드 제거됨
expect(loaded.equipmentNumber, isNotEmpty); // name → equipmentNumber
// 수정
final equipment = Equipment(
id: createdEquipmentId,
manufacturer: 'Updated Manufacturer',
equipmentNumber: 'Updated Equipment', // name → equipmentNumber
modelName: 'Updated Model', // 새로운 필수 필드
category1: loaded.category1, // category → category1
category2: loaded.category2, // subCategory → category2
category3: loaded.category3, // subSubCategory → category3
equipmentNumber: 'Updated Equipment',
modelsId: loaded.modelsId, // Vendor→Model 관계 유지
quantity: 10,
);
final updated = await equipmentService.updateEquipment(createdEquipmentId!, equipment);
expect(updated.manufacturer, equals('Updated Manufacturer'));
// expect(updated.manufacturer, equals('Updated Manufacturer')); // manufacturer 필드 제거됨
expect(updated.name, equals('Updated Equipment'));
expect(updated.quantity, equals(10));
});

View File

@@ -1,303 +0,0 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:get_it/get_it.dart';
import 'package:superport/services/auth_service.dart';
import 'package:superport/services/license_service.dart';
import 'package:superport/services/company_service.dart';
import 'package:superport/models/license_model.dart';
import 'package:superport/models/company_model.dart';
import 'package:superport/models/address_model.dart';
import 'package:superport/data/models/auth/login_request.dart';
import 'dart:math';
import 'real_api/test_helper.dart';
void main() {
late GetIt getIt;
late AuthService authService;
late LicenseService licenseService;
late CompanyService companyService;
setUpAll(() async {
// RealApiTestHelper를 사용하여 Mock Storage와 함께 테스트 환경 설정
await RealApiTestHelper.setupTestEnvironment();
// GetIt 인스턴스 가져오기
getIt = GetIt.instance;
// 서비스 초기화
authService = getIt<AuthService>();
licenseService = getIt<LicenseService>();
companyService = getIt<CompanyService>();
// 로그인
print('🔐 로그인 중...');
final loginResult = await authService.login(
LoginRequest(
email: 'admin@superport.kr',
password: 'admin123!',
),
);
loginResult.fold(
(failure) => throw Exception('로그인 실패: $failure'),
(response) => print('✅ 로그인 성공: ${response.user.email}'),
);
});
tearDownAll(() async {
await authService.logout();
await RealApiTestHelper.teardownTestEnvironment();
});
group('라이센스 관리 통합 테스트', () {
late Company testCompany;
final random = Random();
setUpAll(() async {
// 테스트용 회사 조회 또는 생성
print('🏢 테스트용 회사 준비 중...');
final companiesResponse = await companyService.getCompanies();
if (companiesResponse.items.isNotEmpty) {
testCompany = companiesResponse.items.first;
print('✅ 기존 회사 사용: ${testCompany.name}');
} else {
// 회사가 없으면 생성
testCompany = await companyService.createCompany(
Company(
name: 'Test Company ${random.nextInt(10000)}',
address: Address(
detailAddress: '서울시 강남구 테헤란로 123',
),
contactName: '테스트 담당자',
contactPhone: '010-1234-5678',
contactEmail: 'test@test.com',
),
);
print('✅ 새 회사 생성: ${testCompany.name}');
}
});
test('1. 라이센스 목록 조회', () async {
print('\n📋 라이센스 목록 조회 테스트...');
final licensesResult = await licenseService.getLicenses();
final licenses = licensesResult.items;
print('✅ 라이센스 ${licenses.length}개 조회 성공');
expect(licenses, isA<List<License>>());
});
test('2. 라이센스 생성', () async {
print('\n 라이센스 생성 테스트...');
final newLicense = License(
licenseKey: 'TEST-${DateTime.now().millisecondsSinceEpoch}',
productName: 'Flutter Test Product',
vendor: 'Test Vendor',
licenseType: 'subscription',
userCount: 10,
purchaseDate: DateTime.now(),
expiryDate: DateTime.now().add(Duration(days: 365)),
purchasePrice: 100000.0,
companyId: testCompany.id,
remark: '통합 테스트용 라이센스',
isActive: true,
);
final createdLicense = await licenseService.createLicense(newLicense);
print('✅ 라이센스 생성 성공: ${createdLicense.licenseKey}');
expect(createdLicense.id, isNotNull);
expect(createdLicense.licenseKey, equals(newLicense.licenseKey));
expect(createdLicense.companyId, equals(testCompany.id));
});
test('3. 라이센스 상세 조회', () async {
print('\n🔍 라이센스 상세 조회 테스트...');
// 먼저 목록을 조회하여 ID 획득
final licensesResult = await licenseService.getLicenses();
final licenses = licensesResult.items;
if (licenses.isEmpty) {
print('⚠️ 조회할 라이센스가 없습니다.');
return;
}
final targetId = licenses.first.id!;
final license = await licenseService.getLicenseById(targetId);
print('✅ 라이센스 상세 조회 성공: ${license.licenseKey}');
expect(license.id, equals(targetId));
expect(license.licenseKey, isNotEmpty);
});
test('4. 라이센스 수정', () async {
print('\n✏️ 라이센스 수정 테스트...');
// 먼저 라이센스 생성
final newLicense = License(
licenseKey: 'UPDATE-TEST-${DateTime.now().millisecondsSinceEpoch}',
productName: 'Original Product',
vendor: 'Original Vendor',
licenseType: 'perpetual',
userCount: 5,
purchaseDate: DateTime.now(),
expiryDate: DateTime.now().add(Duration(days: 180)),
purchasePrice: 50000.0,
companyId: testCompany.id,
remark: '수정 테스트용',
isActive: true,
);
final createdLicense = await licenseService.createLicense(newLicense);
print('✅ 수정할 라이센스 생성: ${createdLicense.licenseKey}');
// 라이센스 수정
final updatedLicense = License(
id: createdLicense.id,
licenseKey: createdLicense.licenseKey,
productName: 'Updated Product',
vendor: 'Updated Vendor',
licenseType: 'subscription',
userCount: 20,
purchaseDate: createdLicense.purchaseDate,
expiryDate: DateTime.now().add(Duration(days: 730)),
purchasePrice: 200000.0,
companyId: testCompany.id,
remark: '수정됨',
isActive: true,
);
final result = await licenseService.updateLicense(updatedLicense);
print('✅ 라이센스 수정 성공');
expect(result.productName, equals('Updated Product'));
expect(result.vendor, equals('Updated Vendor'));
expect(result.userCount, equals(20));
});
test('5. 라이센스 삭제', () async {
print('\n🗑️ 라이센스 삭제 테스트...');
// 삭제할 라이센스 생성
final newLicense = License(
licenseKey: 'DELETE-TEST-${DateTime.now().millisecondsSinceEpoch}',
productName: 'Delete Test Product',
vendor: 'Delete Test Vendor',
licenseType: 'trial',
userCount: 1,
purchaseDate: DateTime.now(),
expiryDate: DateTime.now().add(Duration(days: 30)),
purchasePrice: 0.0,
companyId: testCompany.id,
remark: '삭제 테스트용',
isActive: true,
);
final createdLicense = await licenseService.createLicense(newLicense);
print('✅ 삭제할 라이센스 생성: ${createdLicense.licenseKey}');
// 라이센스 삭제
await licenseService.deleteLicense(createdLicense.id!);
print('✅ 라이센스 삭제 성공');
// 삭제 확인
try {
await licenseService.getLicenseById(createdLicense.id!);
fail('삭제된 라이센스가 여전히 조회됩니다');
} catch (e) {
print('✅ 삭제 확인: 라이센스가 정상적으로 삭제되었습니다');
}
});
test('6. 만료 예정 라이센스 조회', () async {
print('\n⏰ 만료 예정 라이센스 조회 테스트...');
// 30일 이내 만료 예정 라이센스 생성
final expiringLicense = License(
licenseKey: 'EXPIRING-${DateTime.now().millisecondsSinceEpoch}',
productName: 'Soon Expiring Product',
vendor: 'Test Vendor',
licenseType: 'subscription',
userCount: 5,
purchaseDate: DateTime.now(),
expiryDate: DateTime.now().add(Duration(days: 15)), // 15일 후 만료
purchasePrice: 10000.0,
companyId: testCompany.id,
remark: '만료 예정 테스트',
isActive: true,
);
await licenseService.createLicense(expiringLicense);
print('✅ 만료 예정 라이센스 생성 (15일 후 만료)');
final expiringLicensesResult = await licenseService.getExpiringLicenses(days: 30);
final expiringLicenses = expiringLicensesResult;
print('✅ 만료 예정 라이센스 ${expiringLicenses.length}개 조회');
expect(expiringLicenses, isA<List<License>>());
});
test('7. 에러 처리 테스트', () async {
print('\n❌ 에러 처리 테스트...');
// 잘못된 ID로 조회
try {
await licenseService.getLicenseById(999999);
fail('존재하지 않는 라이센스 조회가 성공했습니다');
} catch (e) {
print('✅ 잘못된 ID 에러 처리 성공: $e');
}
// 필수 필드 누락
try {
final invalidLicense = License(
licenseKey: '', // 빈 라이센스 키
productName: 'Invalid Product',
companyId: testCompany.id,
);
await licenseService.createLicense(invalidLicense);
fail('유효하지 않은 라이센스 생성이 성공했습니다');
} catch (e) {
print('✅ 유효성 검증 에러 처리 성공: $e');
}
});
test('8. 페이지네이션 테스트', () async {
print('\n📄 페이지네이션 테스트...');
// 첫 페이지
final page1Result = await licenseService.getLicenses(page: 1, perPage: 5);
final page1 = page1Result.items;
print('✅ 1페이지: ${page1.length}개 라이센스');
// 두 번째 페이지
final page2Result = await licenseService.getLicenses(page: 2, perPage: 5);
final page2 = page2Result.items;
print('✅ 2페이지: ${page2.length}개 라이센스');
expect(page1.length, lessThanOrEqualTo(5));
expect(page2.length, lessThanOrEqualTo(5));
});
test('9. 필터링 테스트', () async {
print('\n🔎 필터링 테스트...');
// 활성 라이센스만 조회
final activeLicensesResult = await licenseService.getLicenses(isActive: true);
final activeLicenses = activeLicensesResult.items;
print('✅ 활성 라이센스: ${activeLicenses.length}');
// 특정 회사 라이센스만 조회
final companyLicensesResult = await licenseService.getLicenses(
companyId: testCompany.id,
);
final companyLicenses = companyLicensesResult.items;
print('${testCompany.name} 라이센스: ${companyLicenses.length}');
expect(activeLicenses, isA<List<License>>());
expect(companyLicenses, isA<List<License>>());
});
});
print('\n🎉 모든 라이센스 통합 테스트 완료!');
}

View File

@@ -7,7 +7,7 @@ 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/data/datasources/remote/equipment_remote_datasource.dart';
import 'package:superport/data/datasources/remote/license_remote_datasource.dart';
// import 'package:superport/data/datasources/remote/license_remote_datasource.dart'; // License 시스템 제거
import 'package:superport/data/datasources/remote/warehouse_remote_datasource.dart';
import 'package:superport/data/datasources/remote/dashboard_remote_datasource.dart';
import 'package:superport/data/models/auth/login_request.dart';
@@ -15,7 +15,7 @@ import 'package:superport/services/auth_service.dart';
import 'package:superport/services/company_service.dart';
import 'package:superport/services/user_service.dart';
import 'package:superport/services/equipment_service.dart';
import 'package:superport/services/license_service.dart';
// import 'package:superport/services/license_service.dart'; // License 시스템 제거
import 'package:superport/services/warehouse_service.dart';
import 'package:superport/services/dashboard_service.dart';
import 'package:superport/core/config/environment.dart';
@@ -104,14 +104,14 @@ class RealApiTestHelper {
// RemoteDataSource 등록 (일부 서비스가 GetIt을 통해 가져옴)
final companyRemoteDataSource = CompanyRemoteDataSourceImpl(apiClient);
final licenseRemoteDataSource = LicenseRemoteDataSourceImpl(apiClient: apiClient);
// final licenseRemoteDataSource = LicenseRemoteDataSourceImpl(apiClient: apiClient); // License 시스템 제거
final warehouseRemoteDataSource = WarehouseRemoteDataSourceImpl(apiClient: apiClient);
final equipmentRemoteDataSource = EquipmentRemoteDataSourceImpl();
final userRemoteDataSource = UserRemoteDataSourceImpl(apiClient);
final dashboardRemoteDataSource = DashboardRemoteDataSourceImpl(apiClient);
getIt.registerSingleton<CompanyRemoteDataSource>(companyRemoteDataSource);
getIt.registerSingleton<LicenseRemoteDataSource>(licenseRemoteDataSource);
// getIt.registerSingleton<LicenseRemoteDataSource>(licenseRemoteDataSource); // License 시스템 제거
getIt.registerSingleton<WarehouseRemoteDataSource>(warehouseRemoteDataSource);
getIt.registerSingleton<EquipmentRemoteDataSource>(equipmentRemoteDataSource);
getIt.registerSingleton<UserRemoteDataSource>(userRemoteDataSource);
@@ -121,7 +121,7 @@ class RealApiTestHelper {
getIt.registerSingleton<CompanyService>(CompanyService(companyRemoteDataSource));
getIt.registerSingleton<UserService>(UserService(userRemoteDataSource));
getIt.registerSingleton<EquipmentService>(EquipmentService());
getIt.registerSingleton<LicenseService>(LicenseService(licenseRemoteDataSource));
// getIt.registerSingleton<LicenseService>(LicenseService(licenseRemoteDataSource)); // License 시스템 제거
getIt.registerSingleton<WarehouseService>(WarehouseService());
getIt.registerSingleton<DashboardService>(DashboardServiceImpl(dashboardRemoteDataSource));
}
@@ -133,8 +133,8 @@ class RealApiTestHelper {
}
final loginRequest = LoginRequest(
email: 'admin@superport.kr',
password: 'admin123!',
email: 'admin@example.com',
password: 'password123',
);
final result = await authService.login(loginRequest);
@@ -242,18 +242,19 @@ class TestDataHelper {
};
}
/// 테스트용 라이선스 데이터
static Map<String, dynamic> createTestLicenseData({required int companyId}) {
return {
'name': generateUniqueName('Test License'),
'product_key': 'KEY-${generateUniqueId()}',
'company_id': companyId,
'license_type': 'subscription',
'quantity': 5,
'expiry_date': DateTime.now().add(const Duration(days: 365)).toIso8601String(),
'purchase_date': DateTime.now().toIso8601String(),
};
}
// License 시스템이 제거됨
// /// 테스트용 라이선스 데이터
// static Map<String, dynamic> createTestLicenseData({required int companyId}) {
// return {
// 'name': generateUniqueName('Test License'),
// 'product_key': 'KEY-${generateUniqueId()}',
// 'company_id': companyId,
// 'license_type': 'subscription',
// 'quantity': 5,
// 'expiry_date': DateTime.now().add(const Duration(days: 365)).toIso8601String(),
// 'purchase_date': DateTime.now().toIso8601String(),
// };
// }
/// 테스트용 창고 데이터
static Map<String, dynamic> createTestWarehouseData({required int companyId}) {

View File

@@ -0,0 +1,355 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:superport/core/migrations/license_to_maintenance_migration.dart';
import 'package:superport/core/migrations/maintenance_data_validator.dart';
void main() {
group('License to Maintenance Migration Tests', () {
// 테스트용 License 데이터
final testLicenseData = [
{
'id': 1,
'equipment_id': 101,
'license_type': 'O', // Onsite
'period_months': 12,
'cost': 1000000,
'vendor_name': '삼성전자서비스',
'vendor_contact': '1588-3366',
'start_date': '2024-01-01T00:00:00Z',
'expiry_date': '2024-12-31T23:59:59Z',
'created_at': '2024-01-01T00:00:00Z',
},
{
'id': 2,
'equipment_id': 102,
'license_type': 'R', // Remote
'period_months': 6,
'cost': 500000,
'vendor_name': 'LG전자서비스',
'vendor_contact': '1544-7777',
'start_date': '2024-06-01T00:00:00Z',
'expiry_date': '2024-11-30T23:59:59Z',
'created_at': '2024-06-01T00:00:00Z',
},
{
'id': 3,
'equipment_id': 103,
'license_type': 'O',
'period_months': 24,
'cost': 2000000,
'vendor_name': '델코리아',
'vendor_contact': '1588-1588',
'start_date': '2023-01-01T00:00:00Z',
'expiry_date': '2024-12-31T23:59:59Z', // 곧 만료
'created_at': '2023-01-01T00:00:00Z',
},
];
// 테스트용 Equipment 데이터
final testEquipmentData = [
{'id': 101, 'equipment_number': 'EQ-001', 'name': '서버 #1'},
{'id': 102, 'equipment_number': 'EQ-002', 'name': '서버 #2'},
{'id': 103, 'equipment_number': 'EQ-003', 'name': '서버 #3'},
];
// 테스트용 Equipment History 데이터
final testEquipmentHistoryData = [
{
'id': 201,
'equipments_id': 101,
'transaction_type': 'IN',
'created_at': '2024-01-01T00:00:00Z',
},
{
'id': 202,
'equipments_id': 102,
'transaction_type': 'IN',
'created_at': '2024-06-01T00:00:00Z',
},
{
'id': 203,
'equipments_id': 103,
'transaction_type': 'IN',
'created_at': '2023-01-01T00:00:00Z',
},
];
test('Should successfully migrate license data to maintenance', () async {
// 실행
final result = await LicenseToMaintenanceMigration.migrate(
licenseData: testLicenseData,
equipmentData: testEquipmentData,
equipmentHistoryData: testEquipmentHistoryData,
);
// 검증
expect(result.success, true);
expect(result.maintenanceData, isNotNull);
expect(result.maintenanceData!.length, 3);
expect(result.backup, isNotNull);
expect(result.statistics, isNotNull);
});
test('Should correctly map equipment history IDs', () async {
// 실행
final result = await LicenseToMaintenanceMigration.migrate(
licenseData: testLicenseData,
equipmentData: testEquipmentData,
equipmentHistoryData: testEquipmentHistoryData,
);
// 각 Maintenance가 올바른 equipment_history_id를 가지는지 검증
final maintenance1 = result.maintenanceData!
.firstWhere((m) => m['id'] == 1);
expect(maintenance1['equipment_history_id'], 201);
final maintenance2 = result.maintenanceData!
.firstWhere((m) => m['id'] == 2);
expect(maintenance2['equipment_history_id'], 202);
final maintenance3 = result.maintenanceData!
.firstWhere((m) => m['id'] == 3);
expect(maintenance3['equipment_history_id'], 203);
});
test('Should correctly convert license types to maintenance types', () async {
// 실행
final result = await LicenseToMaintenanceMigration.migrate(
licenseData: testLicenseData,
equipmentData: testEquipmentData,
equipmentHistoryData: testEquipmentHistoryData,
);
// 유형 변환 검증
final maintenance1 = result.maintenanceData!
.firstWhere((m) => m['id'] == 1);
expect(maintenance1['maintenance_type'], 'O'); // Onsite
final maintenance2 = result.maintenanceData!
.firstWhere((m) => m['id'] == 2);
expect(maintenance2['maintenance_type'], 'R'); // Remote
});
test('Should calculate correct maintenance status', () async {
// 실행
final result = await LicenseToMaintenanceMigration.migrate(
licenseData: testLicenseData,
equipmentData: testEquipmentData,
equipmentHistoryData: testEquipmentHistoryData,
);
// 상태 계산 검증
for (final maintenance in result.maintenanceData!) {
final status = maintenance['status'];
expect(
['scheduled', 'upcoming', 'overdue'].contains(status),
true,
reason: 'Status should be one of: scheduled, upcoming, overdue',
);
}
});
test('Should preserve cost and vendor information', () async {
// 실행
final result = await LicenseToMaintenanceMigration.migrate(
licenseData: testLicenseData,
equipmentData: testEquipmentData,
equipmentHistoryData: testEquipmentHistoryData,
);
// 비용 및 업체 정보 보존 검증
final maintenance1 = result.maintenanceData!
.firstWhere((m) => m['id'] == 1);
expect(maintenance1['cost'], 1000000);
expect(maintenance1['vendor_name'], '삼성전자서비스');
expect(maintenance1['vendor_contact'], '1588-3366');
});
test('Should generate correct analysis statistics', () async {
// 실행
final result = await LicenseToMaintenanceMigration.migrate(
licenseData: testLicenseData,
equipmentData: testEquipmentData,
equipmentHistoryData: testEquipmentHistoryData,
);
// 통계 검증
expect(result.statistics, isNotNull);
expect(result.statistics!.totalCount, 3);
expect(result.statistics!.activeCount, greaterThanOrEqualTo(0));
expect(result.statistics!.expiredCount, greaterThanOrEqualTo(0));
expect(result.statistics!.upcomingCount, greaterThanOrEqualTo(0));
// 총합 검증
final total = result.statistics!.activeCount +
result.statistics!.expiredCount +
result.statistics!.upcomingCount;
expect(total, result.statistics!.totalCount);
});
test('Should create valid backup data', () async {
// 실행
final result = await LicenseToMaintenanceMigration.migrate(
licenseData: testLicenseData,
equipmentData: testEquipmentData,
equipmentHistoryData: testEquipmentHistoryData,
);
// 백업 데이터 검증
expect(result.backup, isNotNull);
expect(result.backup!['timestamp'], isNotNull);
expect(result.backup!['version'], '1.0.0');
expect(result.backup!['data'], testLicenseData);
expect(result.backup!['checksum'], isNotNull);
});
test('Should handle missing equipment history gracefully', () async {
// Equipment History가 없는 License 데이터
final incompleteData = [
{
'id': 999,
'equipment_id': 999, // 존재하지 않는 Equipment
'license_type': 'O',
'period_months': 12,
'cost': 1000000,
'start_date': '2024-01-01T00:00:00Z',
'expiry_date': '2024-12-31T23:59:59Z',
},
];
// 실행
final result = await LicenseToMaintenanceMigration.migrate(
licenseData: incompleteData,
equipmentData: testEquipmentData,
equipmentHistoryData: testEquipmentHistoryData,
);
// 검증 - 마이그레이션은 성공하지만 데이터는 변환되지 않음
expect(result.success, true);
expect(result.maintenanceData!.length, 0); // 변환된 데이터 없음
});
test('Should validate migrated data correctly', () async {
// 실행
final result = await LicenseToMaintenanceMigration.migrate(
licenseData: testLicenseData,
equipmentData: testEquipmentData,
equipmentHistoryData: testEquipmentHistoryData,
);
// 데이터 검증
final validationReport = await MaintenanceDataValidator.validate(
maintenanceData: result.maintenanceData!,
equipmentHistoryData: testEquipmentHistoryData,
);
// 검증 결과 확인
expect(validationReport.isValid, true);
expect(validationReport.dataIntegrity, true);
expect(validationReport.businessRulesValid, true);
});
test('Should support rollback functionality', () async {
// 마이그레이션 실행
final result = await LicenseToMaintenanceMigration.migrate(
licenseData: testLicenseData,
equipmentData: testEquipmentData,
equipmentHistoryData: testEquipmentHistoryData,
);
expect(result.success, true);
expect(result.backup, isNotNull);
// 롤백 테스트
final rollbackSuccess = await LicenseToMaintenanceMigration.rollback(
result.backup!,
);
expect(rollbackSuccess, true);
});
});
group('Edge Cases and Error Handling', () {
test('Should handle empty license data', () async {
// 실행
final result = await LicenseToMaintenanceMigration.migrate(
licenseData: [],
equipmentData: [],
equipmentHistoryData: [],
);
// 검증
expect(result.success, true);
expect(result.maintenanceData!.length, 0);
expect(result.statistics!.totalCount, 0);
});
test('Should handle null dates gracefully', () async {
// null 날짜를 가진 License 데이터
final dataWithNullDates = [
{
'id': 1,
'equipment_id': 101,
'license_type': 'O',
'period_months': 12,
'cost': 1000000,
'start_date': null,
'expiry_date': null,
},
];
final equipmentHistory = [
{
'id': 201,
'equipments_id': 101,
'transaction_type': 'IN',
},
];
// 실행
final result = await LicenseToMaintenanceMigration.migrate(
licenseData: dataWithNullDates,
equipmentData: [],
equipmentHistoryData: equipmentHistory,
);
// 검증
expect(result.success, true);
expect(result.maintenanceData!.length, 1);
expect(result.maintenanceData![0]['status'], 'scheduled');
});
test('Should handle duplicate license IDs', () async {
// 중복 ID를 가진 License 데이터
final duplicateData = [
{
'id': 1,
'equipment_id': 101,
'license_type': 'O',
'period_months': 12,
},
{
'id': 1, // 중복 ID
'equipment_id': 102,
'license_type': 'R',
'period_months': 6,
},
];
final equipmentHistory = [
{'id': 201, 'equipments_id': 101},
{'id': 202, 'equipments_id': 102},
];
// 실행
final result = await LicenseToMaintenanceMigration.migrate(
licenseData: duplicateData,
equipmentData: [],
equipmentHistoryData: equipmentHistory,
);
// 검증 - 중복 ID도 처리되어야 함
expect(result.success, true);
expect(result.maintenanceData!.length, 2);
});
});
}

122
test/vendor_api_test.dart Normal file
View File

@@ -0,0 +1,122 @@
import 'package:dio/dio.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:superport/data/datasources/remote/api_client.dart';
import 'package:superport/data/models/vendor_dto.dart';
import 'package:superport/data/repositories/vendor_repository.dart';
void main() {
late Dio dio;
late VendorRepository vendorRepository;
String? authToken;
setUpAll(() async {
// 직접 Dio 인스턴스 생성 (테스트용)
dio = Dio(BaseOptions(
baseUrl: 'http://43.201.34.104:8080/api/v1',
connectTimeout: const Duration(seconds: 30),
receiveTimeout: const Duration(seconds: 30),
));
// 로그인하여 토큰 획득
try {
final loginResponse = await dio.post('/auth/login', data: {
'email': 'admin@example.com',
'password': 'password123',
});
authToken = loginResponse.data['access_token'];
dio.options.headers['Authorization'] = 'Bearer $authToken';
print('✅ 로그인 성공! 토큰 획득됨');
} catch (e) {
print('❌ 로그인 실패: $e');
fail('로그인에 실패했습니다');
}
});
group('Vendor API Tests', () {
test('Vendors 목록 조회 테스트', () async {
try {
// 직접 API 호출 테스트
final response = await dio.get('/vendors', queryParameters: {
'page': 1,
'limit': 5,
});
print('\n========== 원본 API 응답 ==========');
print('Status Code: ${response.statusCode}');
print('응답 데이터: ${response.data}');
expect(response.statusCode, 200);
expect(response.data, isA<Map<String, dynamic>>());
expect(response.data['data'], isA<List>());
expect(response.data['total'], isA<int>());
expect(response.data['page'], isA<int>());
expect(response.data['total_pages'], isA<int>());
print('\n========== JSON 파싱 테스트 ==========');
// VendorListResponse로 파싱 테스트
try {
final vendorListResponse = VendorListResponse.fromJson(response.data);
print('✅ VendorListResponse 파싱 성공');
print('Items 개수: ${vendorListResponse.items.length}');
print('총 개수: ${vendorListResponse.totalCount}');
print('현재 페이지: ${vendorListResponse.currentPage}');
print('총 페이지: ${vendorListResponse.totalPages}');
expect(vendorListResponse.items.length, greaterThan(0));
expect(vendorListResponse.totalCount, greaterThan(0));
// 첫 번째 Vendor 데이터 확인
final firstVendor = vendorListResponse.items.first;
print('\n첫 번째 벤더 정보:');
print('ID: ${firstVendor.id}');
print('이름: ${firstVendor.name}');
print('삭제됨: ${firstVendor.isDeleted}');
print('활성화: ${firstVendor.isActive}');
expect(firstVendor.id, isNotNull);
expect(firstVendor.name.isNotEmpty, true);
} catch (e, stackTrace) {
print('❌ VendorListResponse 파싱 실패: $e');
print('Stack trace: $stackTrace');
fail('JSON 파싱에 실패했습니다: $e');
}
} catch (e, stackTrace) {
print('❌ API 호출 실패: $e');
print('Stack trace: $stackTrace');
fail('API 호출에 실패했습니다: $e');
}
});
test('단일 Vendor 조회 테스트', () async {
try {
// 먼저 목록에서 첫 번째 벤더 ID 가져오기
final listResponse = await dio.get('/vendors', queryParameters: {'limit': 1});
final firstVendorId = listResponse.data['data'][0]['id'];
// 단일 벤더 조회
final response = await dio.get('/vendors/$firstVendorId');
print('\n========== 단일 벤더 조회 ==========');
print('Status Code: ${response.statusCode}');
print('응답 데이터: ${response.data}');
expect(response.statusCode, 200);
expect(response.data, isA<Map<String, dynamic>>());
// VendorDto로 파싱 테스트
final vendor = VendorDto.fromJson(response.data);
print('✅ VendorDto 파싱 성공');
print('벤더 정보: ${vendor.name}');
} catch (e) {
print('❌ 단일 벤더 조회 실패: $e');
fail('단일 벤더 조회에 실패했습니다: $e');
}
});
});
}

View File

@@ -0,0 +1,59 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:superport/utils/constants.dart';
import 'package:superport/data/models/vendor_dto.dart';
import 'package:superport/data/repositories/vendor_repository.dart';
import 'package:superport/domain/usecases/vendor_usecase.dart';
/// Vendor 페이지네이션 파라미터 테스트
void main() {
group('Vendor Pagination 파라미터 테스트', () {
test('PaginationConstants.defaultPageSize가 10인지 확인', () {
expect(PaginationConstants.defaultPageSize, 10);
expect(PaginationConstants.maxPageSize, 100);
expect(PaginationConstants.minPageSize, 5);
});
test('VendorUseCase 기본 limit 파라미터가 10인지 확인', () {
// VendorUseCaseImpl을 직접 테스트하기 어려우므로
// 상수값이 올바른지만 확인
const testLimit = PaginationConstants.defaultPageSize;
expect(testLimit, 10);
});
test('VendorRepository 기본 limit 파라미터가 10인지 확인', () {
// VendorRepositoryImpl을 직접 테스트하기 어려우므로
// 상수값이 올바른지만 확인
const testLimit = PaginationConstants.defaultPageSize;
expect(testLimit, 10);
});
test('페이지 계산이 올바른지 확인', () {
const pageSize = 10;
// 1페이지: 1~10
final page1Start = (1 - 1) * pageSize + 1;
expect(page1Start, 1);
// 2페이지: 11~20
final page2Start = (2 - 1) * pageSize + 1;
expect(page2Start, 11);
// 3페이지: 21~30
final page3Start = (3 - 1) * pageSize + 1;
expect(page3Start, 21);
});
test('API 요청 쿼리 파라미터 시뮬레이션 (page_size 사용)', () {
// 실제 API 요청에서 전송될 파라미터들 시뮬레이션 - Vendors API만 page_size 사용
final queryParams = <String, dynamic>{
'page': 1,
'page_size': PaginationConstants.defaultPageSize,
};
expect(queryParams['page'], 1);
expect(queryParams['page_size'], 10);
print('✅ API 요청 파라미터 (최종): $queryParams');
});
});
}

View File

@@ -0,0 +1,50 @@
import 'package:dio/dio.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
test('Test Zipcode API structure', () async {
final dio = Dio();
dio.options.baseUrl = 'http://43.201.34.104:8080/api/v1';
try {
// 먼저 로그인해서 토큰을 받자
final loginResponse = await dio.post('/auth/login', data: {
'email': 'admin@example.com',
'password': 'password123'
});
final token = loginResponse.data['access_token'];
dio.options.headers['Authorization'] = 'Bearer $token';
// Zipcodes API 테스트 - 검색 매개변수로 테스트
final zipcodesResponse = await dio.get('/zipcodes', queryParameters: {
'search': '서울',
'limit': 5
});
print('=== Zipcodes API 응답 구조 ===');
print('상태 코드: ${zipcodesResponse.statusCode}');
print('응답 데이터 타입: ${zipcodesResponse.data.runtimeType}');
print('응답 내용: ${zipcodesResponse.data}');
if (zipcodesResponse.data is Map) {
final data = zipcodesResponse.data as Map<String, dynamic>;
print('응답 키: ${data.keys.toList()}');
if (data['data'] is List && (data['data'] as List).isNotEmpty) {
final firstItem = (data['data'] as List).first;
print('첫 번째 우편번호 구조: $firstItem');
print('첫 번째 우편번호 키: ${firstItem.keys.toList()}');
}
}
} catch (e) {
if (e is DioException) {
print('API 에러: ${e.response?.statusCode}');
print('에러 메시지: ${e.response?.data}');
} else {
print('예상치 못한 에러: $e');
}
}
});
}