앱 단위·화면·통합 테스트
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:fancake/core/data/planet_visual_state.dart';
|
||||
import 'package:fancake/features/galaxy/galaxy_data.dart';
|
||||
import 'package:fancake/features/galaxy/galaxy_motion.dart';
|
||||
import 'package:fancake/features/galaxy/galaxy_screen.dart';
|
||||
import 'package:fancake/features/galaxy/widgets/galaxy_field.dart';
|
||||
import 'package:fancake/features/planet/planet_data.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'eclipse_stubs.dart';
|
||||
|
||||
void main() {
|
||||
test('상태별 표류는 점진적으로 변하고 사용자 드래그는 유지된다', () {
|
||||
final clock = GalaxyClock();
|
||||
addTearDown(clock.dispose);
|
||||
for (final scale in [0.25, 0.5, 1.5, 1.0]) {
|
||||
final before = clock.velocity;
|
||||
clock.idleSpeedScale = scale;
|
||||
clock.advance(1 / 60);
|
||||
final target = GalaxyMotion.idleSpin * scale;
|
||||
expect(
|
||||
clock.velocity,
|
||||
inExclusiveRange(
|
||||
before < target ? before : target,
|
||||
before > target ? before : target,
|
||||
),
|
||||
);
|
||||
for (var i = 0; i < 600; i++) {
|
||||
clock.advance(1 / 60);
|
||||
}
|
||||
expect(clock.velocity, closeTo(target, 1e-6));
|
||||
}
|
||||
clock.idleSpeedScale = 0.25;
|
||||
clock.drag(10);
|
||||
clock.advance(1 / 60);
|
||||
expect(clock.velocity, closeTo(10 * 60 * GalaxyMotion.dragSpinGain, 1e-9));
|
||||
});
|
||||
|
||||
testWidgets('선택 행성의 서버 상태만 주변 궤도에 적용하고 Reduce Motion은 정지한다', (tester) async {
|
||||
final streams = <String, StreamController<PlanetVisualState>>{};
|
||||
Stream<PlanetVisualState> watch(String id) => streams
|
||||
.putIfAbsent(id, () => StreamController<PlanetVisualState>.broadcast())
|
||||
.stream;
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: GalaxyScreen(
|
||||
repository: const SampleGalaxyRepository(),
|
||||
planetRepository: samplePlanetRepository,
|
||||
eclipse: const NoEclipseRepository(),
|
||||
watchPlanet: watch,
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pump();
|
||||
await tester.pump();
|
||||
final clock = tester
|
||||
.widgetList<AnimatedBuilder>(find.byType(AnimatedBuilder))
|
||||
.map((w) => w.listenable)
|
||||
.whereType<GalaxyClock>()
|
||||
.first;
|
||||
GalaxyField field() => tester.widget<GalaxyField>(find.byType(GalaxyField));
|
||||
final mine = field().planets.firstWhere((p) => p.isMine);
|
||||
for (final entry in [
|
||||
(const PlanetVisualState(isHeroTime: true), 1.5),
|
||||
(const PlanetVisualState(isHeroTime: true, isEclipsed: true), 0.5),
|
||||
(const PlanetVisualState(isHeroTime: true, isHibernating: true), 0.25),
|
||||
(const PlanetVisualState(), 1.0),
|
||||
]) {
|
||||
streams[mine.id]!.add(entry.$1);
|
||||
await tester.pump();
|
||||
expect(clock.idleSpeedScale, entry.$2);
|
||||
}
|
||||
final other = field().planets.firstWhere((p) => !p.isMine);
|
||||
field().onSelect(other);
|
||||
await tester.pump();
|
||||
streams[mine.id]!.add(const PlanetVisualState(isHibernating: true));
|
||||
streams[other.id]!.add(const PlanetVisualState(isHeroTime: true));
|
||||
await tester.pump();
|
||||
expect(clock.idleSpeedScale, 1.5);
|
||||
tester.platformDispatcher.accessibilityFeaturesTestValue =
|
||||
const FakeAccessibilityFeatures(disableAnimations: true);
|
||||
addTearDown(tester.platformDispatcher.clearAccessibilityFeaturesTestValue);
|
||||
await tester.pump();
|
||||
final spin = clock.spin;
|
||||
await tester.pump(const Duration(seconds: 1));
|
||||
expect(clock.spin, spin);
|
||||
await tester.pumpWidget(const SizedBox());
|
||||
for (final stream in streams.values) {
|
||||
expect(stream.hasListener, isFalse);
|
||||
await stream.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user