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

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
+70
View File
@@ -7,6 +7,7 @@ import 'package:fancake/features/quest/quest_data.dart';
import 'package:fancake/features/quest/quest_detail_screen.dart';
import 'package:fancake/features/quest/quest_list_screen.dart';
import 'package:fancake/features/quest/quest_reward_screen.dart';
import 'package:fancake/features/quest/widgets/paused_quest_capsule.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
@@ -516,6 +517,50 @@ void main() {
});
});
group('일시 정지 · 이어하기 · 목록 보상받기 (원장 C-83 · 명세 518:88405)', () {
testWidgets('목록 「보상받기」는 상세를 거쳐 바로 수령 흐름(보상 안내 모달)을 연다', (tester) async {
await pumpWide(tester, const QuestListScreen(repository: _sample));
await tester.pump();
await tester.tap(
find.descendant(of: find.byType(QuestTabStrip), matching: find.text(QuestTab.inProgress.label)),
);
await tester.pump();
await tester.tap(find.widgetWithText(FilledButton, '보상받기'));
await tester.pumpAndSettle();
expect(find.text('+10 기여 POP'), findsOneWidget);
});
testWidgets('일시 정지 Quest — 상세에 멈춘 진행값 · 「이어하기」, 진행중 탭 카드에 「일시 정지」', (tester) async {
await pumpWide(tester, const QuestDetailScreen(questId: 's1', repository: _PausedRepo()));
await tester.pump();
expect(find.text('일시 정지'), findsOneWidget);
expect(find.text('43 / 60'), findsOneWidget);
expect(find.widgetWithText(FilledButton, '이어하기'), findsOneWidget);
await pumpWide(tester, const QuestListScreen(repository: _PausedRepo()));
await tester.pump();
await tester.tap(
find.descendant(of: find.byType(QuestTabStrip), matching: find.text(QuestTab.inProgress.label)),
);
await tester.pump();
expect(find.text('Music Shake · 일시 정지 · 43/60'), findsOneWidget);
expect(find.widgetWithText(FilledButton, '이어하기'), findsOneWidget);
});
testWidgets('탭 위 캡슐 — 일시 정지 Quest 가 있을 때만 한 줄 · 누르면 그 상세', (tester) async {
await pumpWide(tester, const Scaffold(body: PausedQuestCapsule(repository: _PausedRepo())));
await tester.pump();
expect(find.text('일시 정지 · 응원 흔들기 · 43/60'), findsOneWidget);
await tester.tap(find.byKey(const ValueKey('paused-quest-capsule')));
await tester.pumpAndSettle();
expect(find.byType(QuestDetailScreen), findsOneWidget);
await pumpWide(tester, const Scaffold(body: PausedQuestCapsule(repository: _sample)));
await tester.pump();
expect(find.byKey(const ValueKey('paused-quest-capsule')), findsNothing);
});
});
testWidgets('F4 화면 문구에 내부 경로가 새지 않는다', (tester) async {
for (final screen in <Widget>[
const QuestListScreen(repository: _sample),
@@ -700,3 +745,28 @@ class _ReviewQuests extends SampleQuestRepository {
),
);
}
/// 일시 정지한 Music Shake 1건(43/60)이 있는 표본.
class _PausedRepo extends SampleQuestRepository {
const _PausedRepo();
static const _card = QuestCard(
id: 's1', title: '응원 흔들기', categoryName: 'Music Shake', type: QuestType.musicShake,
author: QuestAuthor.admin, stage: QuestStage.paused, goal: 120, progress: 0,
rewardPop: 3, participants: 0,
session: QuestSession(state: QuestStage.paused, progress: 43, total: 60),
);
@override
Future<List<QuestCard>> load({int limit = 10}) async => const [_card];
@override
Future<List<QuestCard>> more({required int offset, int limit = 10}) async => const [];
@override
Future<QuestDetail> detail(String questId) async =>
const QuestDetail(card: _card, imageLabel: '', description: '');
@override
Future<QuestCard?> pausedQuest() async => _card;
}