Files
fanuzu/app/test/galaxy_environment_test.dart

96 lines
3.5 KiB
Dart

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();
}
});
}