149 lines
4.2 KiB
Dart
149 lines
4.2 KiB
Dart
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:yumi/shared/business_logic/models/res/sc_first_recharge_reward_res.dart';
|
|
|
|
void main() {
|
|
group('SCFirstRechargeRewardItem display mapping', () {
|
|
test('maps known non-coin detail types', () {
|
|
final cases = <String, String>{
|
|
'NOBLE_VIP': 'VIP',
|
|
'RIDE': 'Vehicles',
|
|
'AVATAR_FRAME': 'Frames',
|
|
'CHAT_BUBBLE': 'Chat Bubble',
|
|
'DATA_CARD': 'Data Card',
|
|
'GIFT': 'Gift',
|
|
'BADGE': 'Badge',
|
|
};
|
|
|
|
cases.forEach((detailType, expectedTitle) {
|
|
final item = SCFirstRechargeRewardItem.fromJson({
|
|
'id': detailType,
|
|
'type': 'PROPS',
|
|
'detailType': detailType,
|
|
'name': 'Concrete material name',
|
|
'quantity': 7,
|
|
'cover': 'https://example.com/$detailType.png',
|
|
});
|
|
|
|
expect(item.displayTitle, expectedTitle);
|
|
});
|
|
});
|
|
|
|
test('uses quantity as days for duration based props', () {
|
|
for (final detailType in const [
|
|
'NOBLE_VIP',
|
|
'RIDE',
|
|
'AVATAR_FRAME',
|
|
'CHAT_BUBBLE',
|
|
'DATA_CARD',
|
|
]) {
|
|
final item = SCFirstRechargeRewardItem.fromJson({
|
|
'id': detailType,
|
|
'type': 'PROPS',
|
|
'detailType': detailType,
|
|
'quantity': 9,
|
|
});
|
|
|
|
expect(item.displayBadgeText, '9d');
|
|
}
|
|
});
|
|
|
|
test('treats vip aliases as duration rewards', () {
|
|
final item = SCFirstRechargeRewardItem.fromJson({
|
|
'id': 11,
|
|
'type': 'PROPS',
|
|
'typeName': 'VIP',
|
|
'quantity': 5,
|
|
'shortBadgeCoverUrl': 'https://example.com/vip-short.png',
|
|
});
|
|
|
|
expect(item.displayTitle, 'VIP');
|
|
expect(item.displayBadgeText, '5d');
|
|
});
|
|
|
|
test('uses detailType before material name for vehicle rewards', () {
|
|
final item = SCFirstRechargeRewardItem.fromJson({
|
|
'id': 1,
|
|
'type': 'PROPS',
|
|
'detailType': 'RIDE',
|
|
'name': 'Meteor Trail',
|
|
'content': '1962463978629165057',
|
|
'quantity': 7,
|
|
'cover': 'https://example.com/material.png',
|
|
});
|
|
|
|
expect(item.displayTitle, 'Vehicles');
|
|
expect(item.displayBadgeText, '7d');
|
|
});
|
|
|
|
test('uses quantity badge for gift rewards', () {
|
|
final item = SCFirstRechargeRewardItem.fromJson({
|
|
'id': 2,
|
|
'type': 'PROPS',
|
|
'detailType': 'GIFT',
|
|
'name': 'Rose',
|
|
'content': '1001',
|
|
'quantity': 3,
|
|
'cover': 'https://example.com/rose.png',
|
|
});
|
|
|
|
expect(item.displayTitle, 'Gift');
|
|
expect(item.displayBadgeText, 'x3');
|
|
});
|
|
|
|
test('does not invent a duration badge for badge rewards', () {
|
|
final item = SCFirstRechargeRewardItem.fromJson({
|
|
'id': 22,
|
|
'type': 'PROPS',
|
|
'detailType': 'BADGE',
|
|
'name': 'VIP Medal',
|
|
'quantity': 7,
|
|
'cover': 'https://example.com/badge.png',
|
|
});
|
|
|
|
expect(item.displayTitle, 'Badge');
|
|
expect(item.displayBadgeText, '');
|
|
});
|
|
|
|
test('keeps explicit corner text from the API', () {
|
|
final item = SCFirstRechargeRewardItem.fromJson({
|
|
'id': 3,
|
|
'type': 'PROPS',
|
|
'detailType': 'GIFT',
|
|
'name': 'Rose',
|
|
'quantity': 3,
|
|
'cornerText': 'x8',
|
|
});
|
|
|
|
expect(item.displayBadgeText, 'x8');
|
|
});
|
|
|
|
test('reads nested resource type when direct detailType is missing', () {
|
|
final item = SCFirstRechargeRewardItem.fromJson({
|
|
'id': 4,
|
|
'type': 'PROPS',
|
|
'name': 'Meteor Trail',
|
|
'quantity': 3,
|
|
'propsResources': {'type': 'RIDE'},
|
|
});
|
|
|
|
expect(item.displayTitle, 'Vehicles');
|
|
expect(item.displayBadgeText, '3d');
|
|
});
|
|
|
|
test('uses vip short badge cover before generic cover', () {
|
|
final item = SCFirstRechargeRewardItem.fromJson({
|
|
'id': 5,
|
|
'type': 'PROPS',
|
|
'detailType': 'NOBLE_VIP',
|
|
'quantity': 7,
|
|
'cover': 'https://example.com/long-badge.png',
|
|
'shortBadge': {'coverUrl': 'https://example.com/short-badge.png'},
|
|
});
|
|
|
|
expect(item.displayTitle, 'VIP');
|
|
expect(item.cover, 'https://example.com/short-badge.png');
|
|
expect(item.displayBadgeText, '7d');
|
|
});
|
|
});
|
|
}
|