Zap·후원 FPI 귀속 · 이클립스 방어 Shake 전용 · 가입 팬덤만 방어

This commit is contained in:
Sn-Kinos
2026-10-05 21:53:20 +09:00
parent 17c658b272
commit 71ec17dc3c
21 changed files with 196 additions and 134 deletions
+28 -12
View File
@@ -56,7 +56,7 @@ Future<void> _pumpGalaxy(
}
}
/// 흔들어 방어 화면. 센서가 없는 테스트 환경이라 눌러서 참여하는 경로로 본다.
/// 흔들어 방어 화면. 센서 대신 가짜 흔들기 스트림을 넣는다 — 방어는 Shake only(FX §5).
Future<void> _pumpDefend(WidgetTester tester, EclipseRepository repo) async {
tester.view.physicalSize = const Size(1080, 2400);
tester.view.devicePixelRatio = 2;
@@ -64,7 +64,7 @@ Future<void> _pumpDefend(WidgetTester tester, EclipseRepository repo) async {
await tester.pumpWidget(
MaterialApp(
theme: buildAppTheme(),
home: EclipseDefendScreen(repository: repo, fandomId: 'bts'),
home: EclipseDefendScreen(repository: repo, fandomId: 'bts', shakes: () => _shakes.stream),
),
);
await tester.pump();
@@ -77,6 +77,9 @@ Future<void> _settle(WidgetTester tester) async {
}
}
/// 가짜 가속도 센서 — 흔들기 한 번마다 이벤트 하나.
final _shakes = StreamController<DateTime>.broadcast();
void main() {
group('이클립스 경보 배너 (별첨 1 ① 「인앱 워닝 배너 병행」)', () {
testWidgets('활성 이클립스가 없으면 배너가 뜨지 않는다', (tester) async {
@@ -367,14 +370,13 @@ void main() {
expect(find.textContaining('흔들어 방어'), findsWidgets);
});
testWidgets('누르면 흔들기가 묶여 서버로 나간다', (tester) async {
testWidgets('흔들기가 묶여 서버로 나간다', (tester) async {
final repo = FakeEclipseRepository(state: eclipseFixture());
addTearDown(repo.dispose);
await _pumpDefend(tester, repo);
// 센서가 없는 단말용 버튼. 판정은 서버가 하므로 흔들기와 같은 경로다.
for (var i = 0; i < 4; i++) {
await tester.tap(find.text('흔들기 어려우면 눌러서 참여'));
for (var i = 0; i < 4; i++) {
_shakes.add(DateTime.now());
await tester.pump(const Duration(milliseconds: 80));
}
await _settle(tester);
@@ -392,7 +394,7 @@ void main() {
// 다섯 번 참여했는데 서버가 둘만 받아들인 상황.
for (var i = 0; i < 5; i++) {
await tester.tap(find.text('흔들기 어려우면 눌러서 참여'));
_shakes.add(DateTime.now());
await tester.pump(const Duration(milliseconds: 80));
}
await _settle(tester);
@@ -406,15 +408,15 @@ void main() {
addTearDown(repo.dispose);
await _pumpDefend(tester, repo);
expect(find.text('흔들기 어려우면 눌러서 참여'), findsNothing);
expect(find.text('운석 충돌을\n성공적으로 막았어요!'), findsOneWidget);
expect(find.text('이 기기는 흔들기 방어를 지원하지 않아요'), findsNothing);
expect(find.text('이클립스를\n성공적으로 막았어요!'), findsOneWidget);
});
testWidgets('마감은 판정 대기이며 서버 실패·취소만 해당 결과로 표시한다', (tester) async {
final repo = FakeEclipseRepository(state: eclipseFixture());
addTearDown(repo.dispose);
await _pumpDefend(tester, repo);
await tester.tap(find.text('흔들기 어려우면 눌러서 참여'));
_shakes.add(DateTime.now());
repo.push(eclipseFixture(endsAt: DateTime.now().subtract(const Duration(seconds: 1))));
await tester.pump();
await _settle(tester);
@@ -437,7 +439,7 @@ void main() {
addTearDown(repo.dispose);
await _pumpDefend(tester, repo);
for (var i = 0; i < 12; i++) {
await tester.tap(find.text('흔들기 어려우면 눌러서 참여'));
_shakes.add(DateTime.now());
await tester.pump(const Duration(milliseconds: 100));
}
expect(repo.calls, isNotEmpty);
@@ -451,7 +453,7 @@ void main() {
..failWith = const BackendException('unavailable', 'private backend error');
addTearDown(repo.dispose);
await _pumpDefend(tester, repo);
await tester.tap(find.text('흔들기 어려우면 눌러서 참여'));
_shakes.add(DateTime.now());
await _settle(tester);
expect(repo.calls, hasLength(1));
final original = repo.calls.single;
@@ -465,6 +467,20 @@ void main() {
expect(find.text('같은 참여 다시 확인'), findsNothing);
});
testWidgets('센서가 없는 단말은 탭 대체 없이 미지원 안내만 (FX §5 Shake only)', (tester) async {
final repo = FakeEclipseRepository(state: eclipseFixture());
addTearDown(repo.dispose);
await tester.pumpWidget(MaterialApp(
theme: buildAppTheme(),
home: EclipseDefendScreen(repository: repo, fandomId: 'bts',
shakes: () => Stream<DateTime>.error(StateError('no sensor'))),
));
await _settle(tester);
expect(find.text('이 기기는 흔들기 방어를 지원하지 않아요'), findsOneWidget);
expect(find.byType(FilledButton), findsNothing);
expect(repo.calls, isEmpty);
});
testWidgets('진행 중인 이클립스가 없으면 그 사실을 알린다', (tester) async {
final repo = FakeEclipseRepository();
addTearDown(repo.dispose);