퀘스트 일시 정지 · 이어하기 · 진행 상태 서버 저장 · 목록 보상받기

This commit is contained in:
Sn-Kinos
2026-10-06 03:20:46 +09:00
parent ecf5998725
commit abe5f1ae50
28 changed files with 1023 additions and 118 deletions
+47
View File
@@ -124,4 +124,51 @@ void main() {
expect(shared!.text, contains('PERFECT 5 · GOOD 2 · MISS 1 · MAX COMBO 4'));
expect(shared!.text, contains('#FANUZU'));
});
testWidgets('중간에 나가면 null · 넘긴 판정표에 판정과 영상 시각이 남고, 이어하면 그 판정을 잇는다(C-83)', (tester) async {
final shakes = StreamController<DateTime>();
addTearDown(shakes.close);
late ValueChanged<ShakePlayerEvent> player;
// 이어하기 — 박 0 은 멈추기 전에 perfect 였다.
final judge = ShakeJudge(bpm: 60, segments: 3, hits: const [0, -1, -1], position: const Duration(seconds: 1));
Object? result = 'unset';
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,
judge: judge,
player: (onEvent) {
player = onEvent;
return const SizedBox();
},
),
),
),
child: const Text('go'),
),
),
),
);
await tester.tap(find.text('go'));
await tester.pumpAndSettle();
player((playing: true, position: const Duration(milliseconds: 1000), ended: false));
shakes.add(DateTime.now());
await tester.pump(const Duration(milliseconds: 60));
player((playing: true, position: const Duration(milliseconds: 1600), ended: false));
await tester.pump(const Duration(milliseconds: 60));
expect(find.text('2 COMBO'), findsOneWidget);
await tester.pageBack();
await tester.pumpAndSettle();
expect(result, isNull);
expect(judge.position, const Duration(milliseconds: 1600));
expect(judge.hits.take(2).every((h) => h >= 0), isTrue);
expect(judge.live(judge.position).judged, 2);
});
}