이클립스 방어 횟수 즉시 표시·진동 · Music Shake 영상 재생 중 흔들기 판정 · 결과 공유
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:share_plus/share_plus.dart';
|
||||
|
||||
import 'package:fancake/core/theme/app_theme.dart';
|
||||
import 'package:fancake/features/quest/music_shake_play_screen.dart';
|
||||
import 'package:fancake/features/quest/quest_data.dart';
|
||||
import 'package:fancake/features/quest/quest_evidence.dart';
|
||||
import 'package:fancake/features/quest/quest_reward_screen.dart';
|
||||
|
||||
/// Music Shake 진행 화면 — 영상 시각으로 판정하고 Perfect · Good · Miss · Combo 를 띄운다(PRD-04).
|
||||
void main() {
|
||||
const setup = MusicShakeSetup(
|
||||
videoId: 'WMweEpGlu_U',
|
||||
title: 'BTS - Butter',
|
||||
bpm: 60,
|
||||
segments: 3,
|
||||
);
|
||||
|
||||
testWidgets('재생 중 흔들기만 영상 시각으로 판정 · 끝나면 판정표를 돌려준다', (tester) async {
|
||||
final shakes = StreamController<DateTime>();
|
||||
addTearDown(shakes.close);
|
||||
late ValueChanged<ShakePlayerEvent> player;
|
||||
ShakeJudge? result;
|
||||
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: buildAppTheme(),
|
||||
home: Builder(
|
||||
builder: (context) => TextButton(
|
||||
onPressed: () async =>
|
||||
result = await Navigator.of(context).push<ShakeJudge>(
|
||||
MaterialPageRoute(
|
||||
builder: (_) => MusicShakePlayScreen(
|
||||
setup: setup,
|
||||
shakes: shakes.stream,
|
||||
player: (onEvent) {
|
||||
player = onEvent;
|
||||
return const SizedBox();
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
child: const Text('go'),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.tap(find.text('go'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('BTS - Butter'), findsOneWidget);
|
||||
|
||||
// 재생 전 흔들기는 세지 않는다.
|
||||
shakes.add(DateTime.now());
|
||||
await tester.pump();
|
||||
Future<void> at(int ms, {bool shake = false, bool playing = true}) async {
|
||||
player((
|
||||
playing: playing,
|
||||
position: Duration(milliseconds: ms),
|
||||
ended: false,
|
||||
));
|
||||
if (shake) shakes.add(DateTime.now());
|
||||
await tester.pump(const Duration(milliseconds: 60));
|
||||
}
|
||||
|
||||
await at(0, shake: true); // 박 0 perfect
|
||||
await at(1000, shake: true); // 박 1 perfect
|
||||
await at(1600);
|
||||
expect(find.text('PERFECT'), findsOneWidget);
|
||||
expect(find.text('2 COMBO'), findsOneWidget);
|
||||
|
||||
await at(3000); // 마지막 박(2) 창이 닫힘 → 종료
|
||||
await tester.pumpAndSettle();
|
||||
expect(result, isNotNull);
|
||||
expect(result!.judgement(), {
|
||||
'perfect': 2,
|
||||
'good': 0,
|
||||
'miss': 1,
|
||||
'maxCombo': 2,
|
||||
});
|
||||
});
|
||||
|
||||
testWidgets('결과 화면 — 판정 합계와 결과 카드 SNS 공유(이미지 + 문구)', (tester) async {
|
||||
ShareParams? shared;
|
||||
const card = QuestCard(
|
||||
id: 'shake',
|
||||
title: '응원 흔들기',
|
||||
categoryName: 'Music Shake',
|
||||
type: QuestType.musicShake,
|
||||
author: QuestAuthor.admin,
|
||||
stage: QuestStage.completed,
|
||||
goal: 120,
|
||||
progress: 0,
|
||||
rewardPop: 3,
|
||||
participants: 0,
|
||||
);
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: buildAppTheme(),
|
||||
home: QuestRewardScreen(
|
||||
detail: const QuestDetail(
|
||||
card: card,
|
||||
imageLabel: 'Music Shake',
|
||||
description: '',
|
||||
),
|
||||
reward: const QuestReward(rewardedPop: 3, balanceAfter: 10),
|
||||
shake: const {'perfect': 5, 'good': 2, 'miss': 1, 'maxCombo': 4},
|
||||
share: (p) async => shared = p,
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pump();
|
||||
expect(find.text('PERFECT'), findsOneWidget);
|
||||
expect(find.text('MAX COMBO'), findsOneWidget);
|
||||
expect(find.text('5'), findsOneWidget);
|
||||
await tester.runAsync(() async {
|
||||
await tester.tap(find.byType(OutlinedButton));
|
||||
await Future<void>.delayed(const Duration(milliseconds: 300));
|
||||
});
|
||||
await tester.pump();
|
||||
expect(shared, isNotNull);
|
||||
expect(shared!.text, contains('PERFECT 5 · GOOD 2 · MISS 1 · MAX COMBO 4'));
|
||||
expect(shared!.text, contains('#FANUZU'));
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user