import 'package:flutter_test/flutter_test.dart'; import 'package:lanebow/models/subscription_model.dart'; void main() { group('Subscription 모델 테스트', () { test('fromJson 메서드가 JSON 데이터를 올바르게 변환해야 함', () { // given final json = { 'id': 'sub_123', 'userId': 'user_123', 'clubId': 'club_123', 'planType': 'premium', 'status': 'active', 'startDate': '2023-01-01T00:00:00.000Z', 'endDate': '2024-01-01T00:00:00.000Z', 'price': 19900, 'currency': 'KRW', 'autoRenew': true, 'features': {'feature1': true, 'feature2': false}, 'paymentMethod': 'card', 'transactionId': 'tx_123', 'createdAt': '2023-01-01T00:00:00.000Z', 'updatedAt': '2023-01-01T00:00:00.000Z', }; // when final subscription = Subscription.fromJson(json); // then expect(subscription.id, 'sub_123'); expect(subscription.userId, 'user_123'); expect(subscription.clubId, 'club_123'); expect(subscription.planType, SubscriptionPlanType.premium); expect(subscription.status, SubscriptionStatus.active); expect(subscription.startDate, DateTime.parse('2023-01-01T00:00:00.000Z')); expect(subscription.endDate, DateTime.parse('2024-01-01T00:00:00.000Z')); expect(subscription.price, 19900); expect(subscription.currency, 'KRW'); expect(subscription.autoRenew, true); expect(subscription.features, {'feature1': true, 'feature2': false}); expect(subscription.paymentMethod, 'card'); expect(subscription.transactionId, 'tx_123'); expect(subscription.createdAt, DateTime.parse('2023-01-01T00:00:00.000Z')); expect(subscription.updatedAt, DateTime.parse('2023-01-01T00:00:00.000Z')); }); test('fromJson 메서드가 알 수 없는 planType과 status를 기본값으로 처리해야 함', () { // given final json = { 'id': 'sub_123', 'userId': 'user_123', 'planType': 'unknown_plan', 'status': 'unknown_status', 'startDate': '2023-01-01T00:00:00.000Z', 'endDate': '2024-01-01T00:00:00.000Z', 'price': 19900, 'currency': 'KRW', 'autoRenew': true, 'createdAt': '2023-01-01T00:00:00.000Z', 'updatedAt': '2023-01-01T00:00:00.000Z', }; // when final subscription = Subscription.fromJson(json); // then expect(subscription.planType, SubscriptionPlanType.free); // 기본값 expect(subscription.status, SubscriptionStatus.expired); // 기본값 }); test('toJson 메서드가 Subscription 객체를 JSON으로 올바르게 변환해야 함', () { // given final subscription = Subscription( id: 'sub_123', userId: 'user_123', clubId: 'club_123', planType: SubscriptionPlanType.premium, status: SubscriptionStatus.active, startDate: DateTime.parse('2023-01-01T00:00:00.000Z'), endDate: DateTime.parse('2024-01-01T00:00:00.000Z'), price: 19900, currency: 'KRW', autoRenew: true, features: {'feature1': true, 'feature2': false}, paymentMethod: 'card', transactionId: 'tx_123', createdAt: DateTime.parse('2023-01-01T00:00:00.000Z'), updatedAt: DateTime.parse('2023-01-01T00:00:00.000Z'), ); // when final json = subscription.toJson(); // then expect(json['id'], 'sub_123'); expect(json['userId'], 'user_123'); expect(json['clubId'], 'club_123'); expect(json['planType'], 'premium'); expect(json['status'], 'active'); expect(json['startDate'], '2023-01-01T00:00:00.000Z'); expect(json['endDate'], '2024-01-01T00:00:00.000Z'); expect(json['price'], 19900); expect(json['currency'], 'KRW'); expect(json['autoRenew'], true); expect(json['features'], {'feature1': true, 'feature2': false}); expect(json['paymentMethod'], 'card'); expect(json['transactionId'], 'tx_123'); expect(json['createdAt'], '2023-01-01T00:00:00.000Z'); expect(json['updatedAt'], '2023-01-01T00:00:00.000Z'); }); test('isActive getter가 올바르게 동작해야 함', () { // given final activeSubscription = Subscription( id: 'sub_123', userId: 'user_123', planType: SubscriptionPlanType.premium, status: SubscriptionStatus.active, startDate: DateTime.now().subtract(const Duration(days: 10)), endDate: DateTime.now().add(const Duration(days: 10)), price: 19900, currency: 'KRW', autoRenew: true, createdAt: DateTime.now(), updatedAt: DateTime.now(), ); final canceledSubscription = Subscription( id: 'sub_123', userId: 'user_123', planType: SubscriptionPlanType.premium, status: SubscriptionStatus.canceled, startDate: DateTime.now().subtract(const Duration(days: 10)), endDate: DateTime.now().add(const Duration(days: 10)), price: 19900, currency: 'KRW', autoRenew: false, createdAt: DateTime.now(), updatedAt: DateTime.now(), ); // then expect(activeSubscription.isActive, true); expect(canceledSubscription.isActive, false); }); test('isExpired getter가 올바르게 동작해야 함', () { // given final expiredByStatus = Subscription( id: 'sub_123', userId: 'user_123', planType: SubscriptionPlanType.premium, status: SubscriptionStatus.expired, startDate: DateTime.now().subtract(const Duration(days: 20)), endDate: DateTime.now().add(const Duration(days: 10)), // 아직 만료일이 지나지 않았지만 상태가 expired price: 19900, currency: 'KRW', autoRenew: false, createdAt: DateTime.now(), updatedAt: DateTime.now(), ); final expiredByDate = Subscription( id: 'sub_123', userId: 'user_123', planType: SubscriptionPlanType.premium, status: SubscriptionStatus.active, startDate: DateTime.now().subtract(const Duration(days: 20)), endDate: DateTime.now().subtract(const Duration(days: 1)), // 만료일이 지남 price: 19900, currency: 'KRW', autoRenew: true, createdAt: DateTime.now(), updatedAt: DateTime.now(), ); final activeSubscription = Subscription( id: 'sub_123', userId: 'user_123', planType: SubscriptionPlanType.premium, status: SubscriptionStatus.active, startDate: DateTime.now().subtract(const Duration(days: 10)), endDate: DateTime.now().add(const Duration(days: 10)), price: 19900, currency: 'KRW', autoRenew: true, createdAt: DateTime.now(), updatedAt: DateTime.now(), ); // then expect(expiredByStatus.isExpired, true); expect(expiredByDate.isExpired, true); expect(activeSubscription.isExpired, false); }); test('daysLeft getter가 올바르게 동작해야 함', () { // given final expiredSubscription = Subscription( id: 'sub_123', userId: 'user_123', planType: SubscriptionPlanType.premium, status: SubscriptionStatus.expired, startDate: DateTime.now().subtract(const Duration(days: 20)), endDate: DateTime.now().add(const Duration(days: 10)), price: 19900, currency: 'KRW', autoRenew: false, createdAt: DateTime.now(), updatedAt: DateTime.now(), ); final activeSubscription = Subscription( id: 'sub_123', userId: 'user_123', planType: SubscriptionPlanType.premium, status: SubscriptionStatus.active, startDate: DateTime.now().subtract(const Duration(days: 10)), endDate: DateTime.now().add(const Duration(days: 10)), price: 19900, currency: 'KRW', autoRenew: true, createdAt: DateTime.now(), updatedAt: DateTime.now(), ); // then expect(expiredSubscription.daysLeft, 0); // 만료된 구독은 항상 0일 반환 expect(activeSubscription.daysLeft >= 9 && activeSubscription.daysLeft <= 10, true); // 테스트 실행 시점에 따라 9일 또는 10일이 될 수 있음 }); test('planName getter가 올바르게 동작해야 함', () { // given final freeSubscription = Subscription( id: 'sub_123', userId: 'user_123', planType: SubscriptionPlanType.free, status: SubscriptionStatus.active, startDate: DateTime.now(), endDate: DateTime.now().add(const Duration(days: 30)), price: 0, currency: 'KRW', autoRenew: true, createdAt: DateTime.now(), updatedAt: DateTime.now(), ); final basicSubscription = Subscription( id: 'sub_123', userId: 'user_123', planType: SubscriptionPlanType.basic, status: SubscriptionStatus.active, startDate: DateTime.now(), endDate: DateTime.now().add(const Duration(days: 30)), price: 9900, currency: 'KRW', autoRenew: true, createdAt: DateTime.now(), updatedAt: DateTime.now(), ); final premiumSubscription = Subscription( id: 'sub_123', userId: 'user_123', planType: SubscriptionPlanType.premium, status: SubscriptionStatus.active, startDate: DateTime.now(), endDate: DateTime.now().add(const Duration(days: 30)), price: 19900, currency: 'KRW', autoRenew: true, createdAt: DateTime.now(), updatedAt: DateTime.now(), ); final enterpriseSubscription = Subscription( id: 'sub_123', userId: 'user_123', planType: SubscriptionPlanType.enterprise, status: SubscriptionStatus.active, startDate: DateTime.now(), endDate: DateTime.now().add(const Duration(days: 30)), price: 49900, currency: 'KRW', autoRenew: true, createdAt: DateTime.now(), updatedAt: DateTime.now(), ); // then expect(freeSubscription.planName, '무료'); expect(basicSubscription.planName, '기본'); expect(premiumSubscription.planName, '프리미엄'); expect(enterpriseSubscription.planName, '기업용'); }); }); group('SubscriptionPlan 모델 테스트', () { test('fromJson 메서드가 JSON 데이터를 올바르게 변환해야 함', () { // given final json = { 'type': 'premium', 'name': '프리미엄', 'description': '대규모 클럽을 위한 고급 기능', 'monthlyPrice': 19900, 'yearlyPrice': 199000, 'currency': 'KRW', 'features': ['무제한 회원 관리', '고급 통계 및 분석'], 'maxMembers': 100, 'maxEvents': 100, 'hasAdvancedStats': true, 'hasCustomization': true, 'hasPriority': true, }; // when final plan = SubscriptionPlan.fromJson(json); // then expect(plan.type, SubscriptionPlanType.premium); expect(plan.name, '프리미엄'); expect(plan.description, '대규모 클럽을 위한 고급 기능'); expect(plan.monthlyPrice, 19900); expect(plan.yearlyPrice, 199000); expect(plan.currency, 'KRW'); expect(plan.features, ['무제한 회원 관리', '고급 통계 및 분석']); expect(plan.maxMembers, 100); expect(plan.maxEvents, 100); expect(plan.hasAdvancedStats, true); expect(plan.hasCustomization, true); expect(plan.hasPriority, true); }); test('fromJson 메서드가 알 수 없는 type을 기본값으로 처리해야 함', () { // given final json = { 'type': 'unknown_type', 'name': '알 수 없는 플랜', 'description': '설명', 'monthlyPrice': 0, 'yearlyPrice': 0, 'currency': 'KRW', 'features': [], 'maxMembers': 0, 'maxEvents': 0, 'hasAdvancedStats': false, 'hasCustomization': false, 'hasPriority': false, }; // when final plan = SubscriptionPlan.fromJson(json); // then expect(plan.type, SubscriptionPlanType.free); // 기본값 }); test('fromJson 메서드가 부울 필드에 대한 기본값을 설정해야 함', () { // given final json = { 'type': 'basic', 'name': '기본', 'description': '설명', 'monthlyPrice': 9900, 'yearlyPrice': 99000, 'currency': 'KRW', 'features': ['기능1', '기능2'], 'maxMembers': 30, 'maxEvents': 20, // 부울 필드 생략 }; // when final plan = SubscriptionPlan.fromJson(json); // then expect(plan.hasAdvancedStats, false); // 기본값 expect(plan.hasCustomization, false); // 기본값 expect(plan.hasPriority, false); // 기본값 }); test('toJson 메서드가 SubscriptionPlan 객체를 JSON으로 올바르게 변환해야 함', () { // given final plan = SubscriptionPlan( type: SubscriptionPlanType.premium, name: '프리미엄', description: '대규모 클럽을 위한 고급 기능', monthlyPrice: 19900, yearlyPrice: 199000, currency: 'KRW', features: ['무제한 회원 관리', '고급 통계 및 분석'], maxMembers: 100, maxEvents: 100, hasAdvancedStats: true, hasCustomization: true, hasPriority: true, ); // when final json = plan.toJson(); // then expect(json['type'], 'premium'); expect(json['name'], '프리미엄'); expect(json['description'], '대규모 클럽을 위한 고급 기능'); expect(json['monthlyPrice'], 19900); expect(json['yearlyPrice'], 199000); expect(json['currency'], 'KRW'); expect(json['features'], ['무제한 회원 관리', '고급 통계 및 분석']); expect(json['maxMembers'], 100); expect(json['maxEvents'], 100); expect(json['hasAdvancedStats'], true); expect(json['hasCustomization'], true); expect(json['hasPriority'], true); }); test('getDefaultPlans 메서드가 기본 플랜 목록을 반환해야 함', () { // when final plans = SubscriptionPlan.getDefaultPlans(); // then expect(plans.length, 4); // 무료, 기본, 프리미엄, 기업용 4가지 플랜 // 무료 플랜 확인 final freePlan = plans.firstWhere((p) => p.type == SubscriptionPlanType.free); expect(freePlan.name, '무료'); expect(freePlan.monthlyPrice, 0); expect(freePlan.maxMembers, 10); // 기본 플랜 확인 final basicPlan = plans.firstWhere((p) => p.type == SubscriptionPlanType.basic); expect(basicPlan.name, '기본'); expect(basicPlan.monthlyPrice, 9900); expect(basicPlan.maxMembers, 30); // 프리미엄 플랜 확인 final premiumPlan = plans.firstWhere((p) => p.type == SubscriptionPlanType.premium); expect(premiumPlan.name, '프리미엄'); expect(premiumPlan.monthlyPrice, 19900); expect(premiumPlan.maxMembers, 100); // 기업용 플랜 확인 final enterprisePlan = plans.firstWhere((p) => p.type == SubscriptionPlanType.enterprise); expect(enterprisePlan.name, '기업용'); expect(enterprisePlan.monthlyPrice, 49900); expect(enterprisePlan.maxMembers, 1000); }); }); }