682 lines
21 KiB
Dart
682 lines
21 KiB
Dart
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:yumi/app/constants/sc_global_config.dart';
|
|
import 'package:yumi/shared/business_logic/models/res/sc_room_rocket_api_res.dart';
|
|
import 'package:yumi/shared/business_logic/models/res/sc_room_rocket_config_res.dart';
|
|
import 'package:yumi/shared/business_logic/models/res/sc_room_rocket_status_res.dart';
|
|
import 'package:yumi/ui_kit/widgets/room/rocket/room_rocket_api_mapper.dart';
|
|
import 'package:yumi/ui_kit/widgets/room/rocket/room_rocket_note_dialog.dart';
|
|
|
|
void main() {
|
|
test('maps localized rocket rule html from go rule response', () {
|
|
final previousLang = SCGlobalConfig.lang;
|
|
SCGlobalConfig.lang = 'zh';
|
|
try {
|
|
final sections = RoomRocketApiMapper.noteSectionsFromRule({
|
|
'zh-CN': '<p>火箭规则说明</p>',
|
|
'en': '<p>Rocket rules</p>',
|
|
});
|
|
|
|
expect(sections, isNotNull);
|
|
expect(sections?.single.body, '<p>火箭规则说明</p>');
|
|
expect(sections?.single.isHtml, isTrue);
|
|
} finally {
|
|
SCGlobalConfig.lang = previousLang;
|
|
}
|
|
});
|
|
|
|
test('maps rocket rule html from config ruleText fallback', () {
|
|
final previousLang = SCGlobalConfig.lang;
|
|
SCGlobalConfig.lang = 'ar';
|
|
try {
|
|
final sections = RoomRocketApiMapper.noteSectionsFromRule({
|
|
'ruleText': {
|
|
'zh-CN': '<p>火箭规则说明</p>',
|
|
'en': '<p><strong>Rocket</strong> rules</p>',
|
|
},
|
|
});
|
|
|
|
expect(sections?.single.body, '<p><strong>Rocket</strong> rules</p>');
|
|
expect(sections?.single.isHtml, isTrue);
|
|
} finally {
|
|
SCGlobalConfig.lang = previousLang;
|
|
}
|
|
});
|
|
|
|
test('normalizes escaped newline sequences from rocket rule response', () {
|
|
final previousLang = SCGlobalConfig.lang;
|
|
SCGlobalConfig.lang = 'en';
|
|
try {
|
|
final sections = RoomRocketApiMapper.noteSectionsFromRule({
|
|
'en': '<p>Line 1\\nLine 2</p>',
|
|
});
|
|
|
|
expect(sections?.single.body, '<p>Line 1\nLine 2</p>');
|
|
expect(sections?.single.isHtml, isTrue);
|
|
} finally {
|
|
SCGlobalConfig.lang = previousLang;
|
|
}
|
|
});
|
|
|
|
test('formats rocket rule html lists without detached markers', () {
|
|
final text = debugRoomRocketRuleHtmlPlainText(
|
|
'<h2>How to Launch a Rocket</h2>'
|
|
'<ol>'
|
|
'<li><p>Sending gifts in the room will add fuel.</p></li>'
|
|
'<li><p>Once the rocket fuel is full, it will launch.</p></li>'
|
|
'</ol>',
|
|
);
|
|
|
|
expect(text, contains('How to Launch a Rocket\n1. Sending gifts'));
|
|
expect(text, contains('\n2. Once the rocket fuel is full'));
|
|
expect(text, isNot(contains('1. \n')));
|
|
expect(text, isNot(contains('2. \n')));
|
|
});
|
|
|
|
test('preserves newline characters inside rocket rule html text', () {
|
|
final text = debugRoomRocketRuleHtmlPlainText(
|
|
'<p>1. Sending gifts in the room will add fuel.\n'
|
|
'2. Once the rocket fuel is full, it will launch.</p>',
|
|
);
|
|
|
|
expect(
|
|
text,
|
|
'1. Sending gifts in the room will add fuel.\n'
|
|
'2. Once the rocket fuel is full, it will launch.',
|
|
);
|
|
});
|
|
|
|
test('keeps manually numbered rocket rule html from duplicating markers', () {
|
|
final text = debugRoomRocketRuleHtmlPlainText(
|
|
'<h2>How to Launch a Rocket</h2>'
|
|
'<ol>'
|
|
'<li><p>1. Sending gifts in the room will add fuel.</p></li>'
|
|
'<li><p>2. Once the rocket fuel is full, it will launch.</p></li>'
|
|
'<li><p>3. The higher the rocket level, the more rewards.</p></li>'
|
|
'<li><p><strong>Leaderboard and Rewards</strong></p></li>'
|
|
'</ol>'
|
|
'<ol>'
|
|
'<li><p>1. The Top 1 user will receive an exclusive reward.</p></li>'
|
|
'</ol>',
|
|
);
|
|
|
|
expect(text, contains('How to Launch a Rocket\n1. Sending gifts'));
|
|
expect(text, contains('\nLeaderboard and Rewards\n1. The Top 1 user'));
|
|
expect(text, isNot(contains('1. \n1.')));
|
|
expect(text, isNot(contains('4. \nLeaderboard')));
|
|
expect(text, isNot(contains('4. Leaderboard')));
|
|
});
|
|
|
|
test('groups unread reward popups by launch number', () {
|
|
final groups = RoomRocketApiMapper.rewardPopupRecordGroups([
|
|
_rewardRecord(id: 'r1', launchNo: 'launch-a'),
|
|
_rewardRecord(id: 'r2', launchNo: 'launch-a'),
|
|
_rewardRecord(id: 'r3', launchNo: 'launch-b'),
|
|
_rewardRecord(id: 'r4', launchNo: ''),
|
|
_rewardRecord(id: '', launchNo: ''),
|
|
]);
|
|
|
|
expect(groups.map((group) => group.length), [2, 1, 1, 1]);
|
|
expect(groups.first.map((record) => record.id), ['r1', 'r2']);
|
|
expect(groups[1].single.launchNo, 'launch-b');
|
|
});
|
|
|
|
test('matches room winner records to the current popup batch', () {
|
|
final roomRecords = [
|
|
_rewardRecord(id: 'room-a', launchNo: 'launch-a'),
|
|
_rewardRecord(id: 'room-b', launchNo: 'launch-b'),
|
|
];
|
|
final matched = RoomRocketApiMapper.rewardRoomRecordsForPopupGroup(
|
|
roomRecords,
|
|
[_rewardRecord(id: 'popup-b', launchNo: 'launch-b')],
|
|
);
|
|
|
|
expect(matched, hasLength(1));
|
|
expect(matched.single.id, 'room-b');
|
|
});
|
|
|
|
test(
|
|
'parses level-specific reward previews and rocket kings from levels',
|
|
() {
|
|
final status = SCRoomRocketStatusRes.fromJson({
|
|
'currentLevel': 1,
|
|
'levels': [
|
|
{
|
|
'level': 1,
|
|
'rewardPreview': {
|
|
'top1': [
|
|
{
|
|
'rewardScene': 'TOP1',
|
|
'rewardType': 'GOLD',
|
|
'rewardAmount': 100,
|
|
},
|
|
],
|
|
},
|
|
'rocketKings': [
|
|
{'rank': 1, 'userId': 'u1', 'userAvatar': 'avatar-1'},
|
|
],
|
|
},
|
|
{
|
|
'level': 2,
|
|
'rewardPreview': {
|
|
'ignite': [
|
|
{
|
|
'rewardScene': 'IGNITE',
|
|
'rewardType': 'GOLD',
|
|
'rewardAmount': 200,
|
|
},
|
|
],
|
|
},
|
|
'rocketKings': [
|
|
{'rank': 1, 'userId': 'u2', 'userAvatar': 'avatar-2'},
|
|
{'rank': 2, 'userId': 'u3', 'userAvatar': 'avatar-3'},
|
|
{'rank': 3, 'userId': 'u4', 'userAvatar': 'avatar-4'},
|
|
],
|
|
},
|
|
],
|
|
});
|
|
|
|
expect(status.rewardPreviewForLevel(1)?.top1.single.rewardAmount, 100);
|
|
expect(status.rewardPreviewForLevel(2)?.ignite.single.rewardAmount, 200);
|
|
expect(status.rocketKingsForLevel(1).single.userAvatar, 'avatar-1');
|
|
expect(status.rocketKingsForLevel(2), hasLength(3));
|
|
},
|
|
);
|
|
|
|
test('parses level-specific reward previews and rocket kings from maps', () {
|
|
final status = SCRoomRocketStatusRes.fromJson({
|
|
'currentLevel': 1,
|
|
'rewardPreview': {
|
|
'1': {
|
|
'top1': [
|
|
{'rewardScene': 'TOP1', 'rewardType': 'GOLD', 'rewardAmount': 100},
|
|
],
|
|
},
|
|
'2': {
|
|
'inRoom': [
|
|
{
|
|
'rewardScene': 'IN_ROOM',
|
|
'rewardType': 'GOLD',
|
|
'rewardAmount': 300,
|
|
},
|
|
],
|
|
},
|
|
},
|
|
'rocketKings': {
|
|
'1': [
|
|
{'rank': 1, 'userId': 'u1', 'userAvatar': 'avatar-1'},
|
|
],
|
|
'2': [
|
|
{'rank': 1, 'userId': 'u2', 'userAvatar': 'avatar-2'},
|
|
{'rank': 2, 'userId': 'u3', 'userAvatar': 'avatar-3'},
|
|
{'rank': 3, 'userId': 'u4', 'userAvatar': 'avatar-4'},
|
|
],
|
|
},
|
|
});
|
|
|
|
expect(status.rewardPreviewForLevel(1)?.top1.single.rewardAmount, 100);
|
|
expect(status.rewardPreviewForLevel(2)?.inRoom.single.rewardAmount, 300);
|
|
expect(status.rocketKingsForLevel(1).single.userAvatar, 'avatar-1');
|
|
expect(status.rocketKingsForLevel(2), hasLength(3));
|
|
});
|
|
|
|
test('parses refreshed rocket status from snake case payloads', () {
|
|
final status = SCRoomRocketStatusRes.fromJson({
|
|
'room_id': 'room-1',
|
|
'current_level': 2,
|
|
'display_percent': 0,
|
|
'current_energy': 0,
|
|
'need_energy': 200,
|
|
'round_no': 4,
|
|
'levels': [
|
|
{
|
|
'level': 1,
|
|
'rocket_icon_url': 'icon-1',
|
|
'progress_bar_url': 'progress-1',
|
|
},
|
|
{
|
|
'level': 2,
|
|
'rocket_icon_url': 'icon-2',
|
|
'progress_bar_url': 'progress-2',
|
|
},
|
|
],
|
|
});
|
|
final levels = RoomRocketApiMapper.levelsFromStatus(status);
|
|
|
|
expect(status.roomId, 'room-1');
|
|
expect(status.currentLevel, 2);
|
|
expect(status.displayPercent, 0);
|
|
expect(status.needEnergy, 200);
|
|
expect(status.roundNo, 4);
|
|
expect(levels?.last.imageUrl, 'icon-2');
|
|
expect(levels?.last.progressImageUrl, 'progress-2');
|
|
});
|
|
|
|
test('parses realtime level advancement payloads', () {
|
|
final status = SCRoomRocketStatusRes.fromJson({
|
|
'room_id': 'room-1',
|
|
'from_level': 1,
|
|
'to_level': 2,
|
|
'display_percent': 0,
|
|
});
|
|
|
|
expect(status.currentLevel, 2);
|
|
expect(status.level, 2);
|
|
expect(status.displayPercent, 0);
|
|
});
|
|
|
|
test('parses realtime current rocket level aliases', () {
|
|
final status = SCRoomRocketStatusRes.fromJson({
|
|
'room_id': 'room-1',
|
|
'current_rocket_level': 2,
|
|
'display_percent': 0,
|
|
});
|
|
|
|
expect(status.currentLevel, 2);
|
|
expect(status.level, 2);
|
|
});
|
|
|
|
test('merges realtime rocket status without dropping level assets', () {
|
|
final current = SCRoomRocketStatusRes.fromJson({
|
|
'room_id': 'room-1',
|
|
'current_level': 1,
|
|
'display_percent': 98,
|
|
'levels': [
|
|
{
|
|
'level': 1,
|
|
'rocket_icon_url': 'icon-1',
|
|
'progress_bar_url': 'progress-1',
|
|
},
|
|
{
|
|
'level': 2,
|
|
'rocket_icon_url': 'icon-2',
|
|
'progress_bar_url': 'progress-2',
|
|
},
|
|
],
|
|
});
|
|
final realtimeUpdate = SCRoomRocketStatusRes.fromJson({
|
|
'room_id': 'room-1',
|
|
'to_level': 2,
|
|
'display_percent': 0,
|
|
});
|
|
|
|
final merged = current.mergeRealtimeUpdate(realtimeUpdate);
|
|
final levels = RoomRocketApiMapper.levelsFromStatus(merged);
|
|
|
|
expect(merged.currentLevel, 2);
|
|
expect(merged.displayPercent, 0);
|
|
expect(levels?.last.imageUrl, 'icon-2');
|
|
expect(levels?.last.progressImageUrl, 'progress-2');
|
|
});
|
|
|
|
test('parses disabled rocket status from go api', () {
|
|
final status = SCRoomRocketStatusRes.fromJson({
|
|
'configured': true,
|
|
'enabled': false,
|
|
'status': 'DISABLED',
|
|
'roomId': 'room-1',
|
|
'levels': [],
|
|
});
|
|
|
|
expect(status.configured, isTrue);
|
|
expect(status.enabled, isFalse);
|
|
expect(status.isEnabled, isFalse);
|
|
expect(status.status, 'DISABLED');
|
|
expect(RoomRocketApiMapper.levelsFromStatus(status), isNull);
|
|
});
|
|
|
|
test('treats unconfigured or disabled-status rocket as unavailable', () {
|
|
final unconfigured = SCRoomRocketStatusRes.fromJson({
|
|
'configured': false,
|
|
'enabled': true,
|
|
'status': 'ENABLED',
|
|
});
|
|
final disabledStatus = SCRoomRocketStatusRes.fromJson({
|
|
'configured': true,
|
|
'status': 'DISABLED',
|
|
});
|
|
|
|
expect(unconfigured.isEnabled, isFalse);
|
|
expect(disabledStatus.isEnabled, isFalse);
|
|
});
|
|
|
|
test(
|
|
'uses top-level reward preview for the response level instead of current level',
|
|
() {
|
|
final status = SCRoomRocketStatusRes.fromJson({
|
|
'currentLevel': 1,
|
|
'level': 2,
|
|
'rewardPreview': {
|
|
'top1': [
|
|
{'rewardScene': 'TOP1', 'rewardType': 'GOLD', 'rewardAmount': 200},
|
|
],
|
|
},
|
|
});
|
|
|
|
expect(status.rewardPreviewForLevel(1), isNull);
|
|
expect(status.rewardPreviewForLevel(2)?.top1.single.rewardAmount, 200);
|
|
},
|
|
);
|
|
|
|
test('maps enabled rocket configs into level-specific reward groups', () {
|
|
final groups = RoomRocketApiMapper.rewardGroupsByLevelFromConfigs([
|
|
SCRoomRocketConfigRes.fromJson({
|
|
'level': 1,
|
|
'rewardConfig': [
|
|
{'type': 'GOLD', 'detailType': 'GOLD', 'amount': 100, 'sort': 1},
|
|
],
|
|
}),
|
|
SCRoomRocketConfigRes.fromJson({
|
|
'level': 2,
|
|
'rewardConfig': [
|
|
{'type': 'GOLD', 'detailType': 'GOLD', 'amount': 200, 'sort': 1},
|
|
],
|
|
'normalRewardConfig': [
|
|
{
|
|
'type': 'PROPS',
|
|
'detailType': 'AVATAR_FRAME',
|
|
'cover': 'cover-2',
|
|
'quantity': 7,
|
|
'sort': 2,
|
|
},
|
|
],
|
|
}),
|
|
]);
|
|
|
|
expect(groups[1]?.top1.single.amount, '100');
|
|
expect(groups[2]?.top1.single.amount, '200');
|
|
expect(groups[2]?.inRoom.single.imageUrl, 'cover-2');
|
|
expect(groups[2]?.inRoom.single.expireDays, 7);
|
|
});
|
|
|
|
test('normalizes non-gold rocket reward days display text', () {
|
|
final rewards = [
|
|
SCRoomRocketRewardRes.fromJson({
|
|
'rewardType': 'PROPS',
|
|
'rewardAmount': '7d',
|
|
}),
|
|
SCRoomRocketRewardRes.fromJson({
|
|
'rewardType': 'PROPS',
|
|
'rewardAmount': 1,
|
|
}),
|
|
SCRoomRocketRewardRes.fromJson({
|
|
'rewardType': 'PROPS',
|
|
'rewardAmount': 1,
|
|
'expireDays': '30D',
|
|
}),
|
|
SCRoomRocketRewardRes.fromJson({
|
|
'rewardType': 'GOLD',
|
|
'rewardAmount': 100,
|
|
}),
|
|
].map(RoomRocketApiMapper.rewardItemFromPreview).toList(growable: false);
|
|
|
|
expect(rewards[0].displayText, '7d');
|
|
expect(rewards[1].displayText, '1d');
|
|
expect(rewards[2].displayText, '30d');
|
|
expect(rewards[3].displayText, '100');
|
|
|
|
final recordRewards = RoomRocketApiMapper.rewardItemsFromRecords([
|
|
SCRoomRocketRewardRecordRes.fromJson({
|
|
'rewardType': 'PROPS',
|
|
'rewardAmount': '7d',
|
|
}),
|
|
]);
|
|
|
|
expect(recordRewards.single.displayText, '7d');
|
|
});
|
|
|
|
test('parses rocket reward winner avatars from nested resource payloads', () {
|
|
final winners = RoomRocketApiMapper.winnersFromRecords([
|
|
SCRoomRocketRewardRecordRes.fromJson({
|
|
'id': 'r1',
|
|
'userId': 'u1',
|
|
'userInfo': {
|
|
'nickname': 'winner',
|
|
'avatar': {'sourceUrl': 'https://example.com/avatar.png'},
|
|
},
|
|
'rewardType': 'GOLD',
|
|
'rewardAmount': 100,
|
|
}),
|
|
]);
|
|
|
|
expect(winners.single.nickname, 'winner');
|
|
expect(winners.single.avatarUrl, 'https://example.com/avatar.png');
|
|
});
|
|
|
|
test('parses rocket reward winner profile from receiver aliases', () {
|
|
final record = SCRoomRocketRewardRecordRes.fromJson({
|
|
'id': 'r1',
|
|
'acceptUserId': 'u1',
|
|
'acceptNickname': 'winner',
|
|
'acceptUserAvatar': {'cdn_url': 'https://example.com/avatar.png'},
|
|
'rewardType': 'GOLD',
|
|
'rewardAmount': 100,
|
|
});
|
|
final winners = RoomRocketApiMapper.winnersFromRecords([record]);
|
|
|
|
expect(record.userId, 'u1');
|
|
expect(record.displayName, 'winner');
|
|
expect(winners.single.nickname, 'winner');
|
|
expect(winners.single.avatarUrl, 'https://example.com/avatar.png');
|
|
});
|
|
|
|
test('hydrates rocket reward winners from room user profiles', () {
|
|
final records = [
|
|
SCRoomRocketRewardRecordRes.fromJson({
|
|
'id': 'r1',
|
|
'userId': '2042274349',
|
|
'rewardType': 'GOLD',
|
|
'rewardAmount': 100,
|
|
}),
|
|
];
|
|
final winners = RoomRocketApiMapper.winnersFromRecords(
|
|
records,
|
|
userProfileResolver:
|
|
(_) => const RoomRocketRewardUserProfile(
|
|
userId: 'u1',
|
|
account: '2042274349',
|
|
nickname: 'winner',
|
|
avatarUrl: 'https://example.com/avatar.png',
|
|
),
|
|
);
|
|
|
|
expect(records.single.displayName, 'User');
|
|
expect(winners.single.nickname, 'winner');
|
|
expect(winners.single.avatarUrl, 'https://example.com/avatar.png');
|
|
});
|
|
|
|
test('marks rocket reward winners by reward scene', () {
|
|
final winners = RoomRocketApiMapper.winnersFromRecords([
|
|
SCRoomRocketRewardRecordRes.fromJson({
|
|
'id': 'r1',
|
|
'userId': 'top-user',
|
|
'userNickname': 'top winner',
|
|
'rewardScene': 'TOP1',
|
|
'rewardType': 'GOLD',
|
|
'rewardAmount': 100,
|
|
}),
|
|
SCRoomRocketRewardRecordRes.fromJson({
|
|
'id': 'r2',
|
|
'userId': 'ignite-user',
|
|
'userNickname': 'igniter',
|
|
'rewardScene': 'SET_OFF',
|
|
'rewardType': 'PROPS',
|
|
'rewardAmount': 1,
|
|
}),
|
|
]);
|
|
|
|
expect(winners.first.isTop1, isTrue);
|
|
expect(winners.first.isIgniter, isFalse);
|
|
expect(winners.last.isTop1, isFalse);
|
|
expect(winners.last.isIgniter, isTrue);
|
|
});
|
|
|
|
test('keeps nested rocket reward users separated by profile id', () {
|
|
final winners = RoomRocketApiMapper.winnersFromRecords([
|
|
SCRoomRocketRewardRecordRes.fromJson({
|
|
'id': 'r1',
|
|
'launchNo': 'launch-1',
|
|
'userInfo': {'id': 'u1', 'nickname': 'winner 1'},
|
|
'rewardType': 'GOLD',
|
|
'rewardAmount': 100,
|
|
}),
|
|
SCRoomRocketRewardRecordRes.fromJson({
|
|
'id': 'r2',
|
|
'launchNo': 'launch-1',
|
|
'userInfo': {'id': 'u2', 'nickname': 'winner 2'},
|
|
'rewardType': 'GOLD',
|
|
'rewardAmount': 100,
|
|
}),
|
|
]);
|
|
|
|
expect(winners, hasLength(2));
|
|
expect(winners.map((item) => item.nickname), ['winner 1', 'winner 2']);
|
|
});
|
|
|
|
test('parses room reward records from alternate response keys', () {
|
|
final records =
|
|
SCRoomRocketRewardRecordsRes.fromJson({
|
|
'room_reward_records': [
|
|
{
|
|
'id': 'r1',
|
|
'launch_no': 'launch-1',
|
|
'room_id': 'room-1',
|
|
'user_info': {'id': 'u1', 'user_nickname': 'winner 1'},
|
|
'reward_type': 'GOLD',
|
|
'reward_amount': 100,
|
|
},
|
|
{
|
|
'id': 'r2',
|
|
'launch_no': 'launch-1',
|
|
'room_id': 'room-1',
|
|
'user_info': {'id': 'u2', 'user_nickname': 'winner 2'},
|
|
'reward_type': 'GOLD',
|
|
'reward_amount': 200,
|
|
},
|
|
],
|
|
}).records;
|
|
final winners = RoomRocketApiMapper.winnersFromRecords(records);
|
|
|
|
expect(records.map((item) => item.userId), ['u1', 'u2']);
|
|
expect(winners, hasLength(2));
|
|
expect(winners.last.rewards.single.amount, '200');
|
|
});
|
|
|
|
test('parses nested rocket reward record resource payloads', () {
|
|
final record = SCRoomRocketRewardRecordRes.fromJson({
|
|
'id': 'r1',
|
|
'launchNo': 'launch-1',
|
|
'roomId': 'room-1',
|
|
'userInfo': {'id': 'u1', 'nickname': 'winner'},
|
|
'reward': {
|
|
'detailType': 'AVATAR_FRAME',
|
|
'amount': '1969014438069481474',
|
|
'quantity': 7,
|
|
'name': 'yumi-KingTOP1 frame',
|
|
'cover': {'sourceUrl': 'https://example.com/frame.png'},
|
|
},
|
|
});
|
|
final reward = RoomRocketApiMapper.rewardItemsFromRecords([record]).single;
|
|
|
|
expect(record.rewardType, 'AVATAR_FRAME');
|
|
expect(record.rewardItemId, isNotEmpty);
|
|
expect(record.rewardName, 'yumi-KingTOP1 frame');
|
|
expect(record.rewardCover, 'https://example.com/frame.png');
|
|
expect(record.expireDays, 7);
|
|
expect(reward.displayText, '7d');
|
|
});
|
|
|
|
test('parses rocket level contents response from go api', () {
|
|
final contents = SCRoomRocketLevelContentsRes.fromJson({
|
|
'configured': true,
|
|
'sysOrigin': 'LIKEI',
|
|
'enabled': true,
|
|
'timezone': 'Asia/Riyadh',
|
|
'maxLevel': 6,
|
|
'levels': [
|
|
{
|
|
'level': 1,
|
|
'needEnergy': 100,
|
|
'rocketIconUrl': 'icon-1',
|
|
'previewRocketUrl': 'preview-1',
|
|
'rocketAnimationUrl': 'animation-1',
|
|
'rewardPreview': {
|
|
'top1': [
|
|
{
|
|
'rewardScene': 'TOP1',
|
|
'rewardType': 'GOLD',
|
|
'rewardAmount': 100,
|
|
'rewardName': 'Lv1 top1',
|
|
},
|
|
],
|
|
},
|
|
},
|
|
{
|
|
'level': 2,
|
|
'needEnergy': 200,
|
|
'rocketIconUrl': 'icon-2',
|
|
'previewRocketUrl': 'preview-2',
|
|
'rocketAnimationUrl': 'animation-2',
|
|
'rewards': [
|
|
{
|
|
'rewardScene': 'IGNITE',
|
|
'rewardType': 'GOLD',
|
|
'rewardAmount': 200,
|
|
'rewardName': 'Lv2 ignite',
|
|
},
|
|
{
|
|
'rewardScene': 'IN_ROOM',
|
|
'rewardType': 'NONE',
|
|
'rewardName': '轮空',
|
|
},
|
|
],
|
|
},
|
|
],
|
|
});
|
|
|
|
expect(contents.enabled, isTrue);
|
|
expect(contents.levels, hasLength(2));
|
|
expect(contents.levelFor(1)?.rocketIconUrl, 'icon-1');
|
|
expect(contents.rewardPreviewForLevel(1)?.top1.single.rewardAmount, 100);
|
|
expect(contents.rewardPreviewForLevel(2)?.ignite.single.rewardAmount, 200);
|
|
expect(contents.rewardPreviewForLevel(2)?.inRoom, isEmpty);
|
|
expect(contents.levelFor(2)?.rewards, hasLength(2));
|
|
|
|
final levels = RoomRocketApiMapper.levelsFromLevelContents(contents);
|
|
final allGroups = RoomRocketApiMapper.rewardGroupsByLevelFromLevelContents(
|
|
contents,
|
|
);
|
|
final groups = RoomRocketApiMapper.rewardGroupsFromLevelContents(
|
|
contents,
|
|
level: 2,
|
|
);
|
|
|
|
expect(levels?.first.imageUrl, 'icon-1');
|
|
expect(allGroups[1]?.top1.single.amount, '100');
|
|
expect(allGroups[2]?.setOff.single.amount, '200');
|
|
expect(groups?.setOff.single.amount, '200');
|
|
});
|
|
}
|
|
|
|
SCRoomRocketRewardRecordRes _rewardRecord({
|
|
required String id,
|
|
required String launchNo,
|
|
}) {
|
|
return SCRoomRocketRewardRecordRes.fromJson({
|
|
'id': id,
|
|
'launchNo': launchNo,
|
|
'roomId': 'room-1',
|
|
'dayKey': '2026-05-15',
|
|
'roundNo': 1,
|
|
'level': 3,
|
|
'userId': 'user-1',
|
|
'userNickname': 'User 1',
|
|
'rewardScene': 'IN_ROOM',
|
|
'rewardType': 'GOLD',
|
|
'rewardItemId': 'gold',
|
|
'rewardName': 'Yumi',
|
|
'rewardAmount': 100,
|
|
'grantStatus': 'SUCCESS',
|
|
'popupStatus': 'UNREAD',
|
|
});
|
|
}
|