yumi-flutter/test/room_rocket_status_test.dart
2026-05-15 23:35:35 +08:00

360 lines
11 KiB
Dart

import 'package:flutter_test/flutter_test.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';
void main() {
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(
'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('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 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');
});
}