FPI 사용자·국가 랭킹 서버 집계 · YouTube 스밍 · Music Shake 참여
This commit is contained in:
@@ -320,16 +320,67 @@ service cloud.firestore {
|
||||
expect(backend.calls, isEmpty);
|
||||
});
|
||||
|
||||
test('회신 대기 유형은 어느 함수도 부르지 않는다', () async {
|
||||
test('시청 · 스트리밍은 무보상 참여 함수만 부른다(C-04) — 보상은 0', () async {
|
||||
final db = await _seed();
|
||||
final backend = _RecordingBackend(db);
|
||||
final backend = _RecordingBackend(db, reply: const {'rewarded': 0, 'remaining': 0});
|
||||
final repo = FirestoreQuestRepository(backend);
|
||||
final cards = await repo.load();
|
||||
final card = _card(cards, 'stream');
|
||||
final card = _card(await repo.load(), 'stream');
|
||||
|
||||
expect(card.type.verifiable, isFalse);
|
||||
expect(card.type.verifiable, isTrue);
|
||||
// 문서에 rewardPop 10 이 남아 있어도 화면에 보상을 약속하지 않는다.
|
||||
expect(card.rewardPop, 0);
|
||||
final reward = await repo.verify(card);
|
||||
expect(backend.calls.single.name, 'fnQuestStreamParticipate');
|
||||
expect(backend.calls.single.payload, {'questId': 'stream'});
|
||||
expect(reward.rewardedPop, 0);
|
||||
});
|
||||
|
||||
test('Music Shake — 박마다 구간을 세고 판정표 · 곡 ID 를 서버에 보낸다', () async {
|
||||
final db = await _seed();
|
||||
// 600 BPM = 박 100ms · 3 구간. 박 0 과 박 1 근처에서만 흔든다.
|
||||
await db.doc('quests/shake').set({
|
||||
'type': 'musicshake', 'title': '응원 흔들기', 'dailyLimit': 1,
|
||||
'trackIds': ['track-a'], 'totalSegments': 3, 'bpm': 600,
|
||||
});
|
||||
final backend = _RecordingBackend(db);
|
||||
final repo = FirestoreQuestRepository(
|
||||
backend,
|
||||
shakes: () async* {
|
||||
final start = DateTime.now();
|
||||
yield start;
|
||||
await Future<void>.delayed(const Duration(milliseconds: 100));
|
||||
yield start.add(const Duration(milliseconds: 140));
|
||||
},
|
||||
);
|
||||
final card = _card(await repo.load(), 'shake');
|
||||
expect(card.type.verifiable, isTrue);
|
||||
expect(card.goal, 3);
|
||||
expect(card.progress, 0);
|
||||
|
||||
// 판을 끝내기 전에는 서버를 부르지 않는다.
|
||||
await expectLater(repo.verify(card), throwsA(isA<BackendException>()));
|
||||
expect(backend.calls, isEmpty);
|
||||
|
||||
expect(await repo.progressStream(card).toList(), [1, 2, 3]);
|
||||
await repo.verify(card);
|
||||
final call = backend.calls.single;
|
||||
expect(call.name, 'fnQuestVerifyMusicShake');
|
||||
expect(call.payload['questId'], 'shake');
|
||||
expect(call.payload['trackId'], 'track-a');
|
||||
expect(call.payload['totalSegments'], 3);
|
||||
final j = call.payload['judgement'] as Map;
|
||||
expect(j['perfect']! + j['good']! + j['miss']!, 3);
|
||||
expect(j['miss'], 1);
|
||||
});
|
||||
|
||||
test('ShakeJudge — 박과의 거리로 perfect · good · miss 를 가르고 최장 연속을 센다', () {
|
||||
final start = DateTime(2026, 10, 5);
|
||||
final judge = ShakeJudge(bpm: 60, segments: 4, start: start)
|
||||
..add(start.add(const Duration(milliseconds: 100))) // 박 0 · perfect
|
||||
..add(start.add(const Duration(milliseconds: 1400))) // 박 1 · good
|
||||
..add(start.add(const Duration(milliseconds: 3000))); // 박 3 · perfect, 박 2 miss
|
||||
expect(judge.judgement(), {'perfect': 2, 'good': 1, 'miss': 1, 'maxCombo': 2});
|
||||
expect(judge.end, start.add(const Duration(milliseconds: 3500)));
|
||||
});
|
||||
|
||||
test('생성은 fn-quest-create 로 — 종료일은 날짜 + 그 시각의 UTC 오프셋(C-06)', () async {
|
||||
|
||||
Reference in New Issue
Block a user