159 lines
5.7 KiB
Dart
159 lines
5.7 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:timezone/data/latest.dart' as tzdata;
|
|
import 'package:hepan_everyday/widgets/glass_dock.dart';
|
|
import 'package:hepan_everyday/widgets/glass_refraction.dart';
|
|
import 'package:hepan_everyday/app/hepan_app.dart';
|
|
|
|
import 'navigation_test.dart' show uiController;
|
|
|
|
void main() {
|
|
setUpAll(tzdata.initializeTimeZones);
|
|
testWidgets('inactive icon press leaves the cursor at its resting size', (
|
|
tester,
|
|
) async {
|
|
await tester.pumpWidget(_dock());
|
|
await tester.pumpAndSettle();
|
|
final lens = find.byType(GlassRefraction).last;
|
|
final resting = tester.getSize(lens);
|
|
final gesture = await tester.startGesture(
|
|
tester.getCenter(find.byIcon(Icons.assignment_rounded)),
|
|
);
|
|
await tester.pump(const Duration(milliseconds: 110));
|
|
await tester.pump(const Duration(milliseconds: 200));
|
|
expect(tester.getSize(lens), resting);
|
|
await gesture.cancel();
|
|
await tester.pumpAndSettle();
|
|
});
|
|
testWidgets('tap cursor travels monotonically with no size jitter', (
|
|
tester,
|
|
) async {
|
|
await tester.pumpWidget(_dock());
|
|
await tester.pumpAndSettle();
|
|
final lens = find.byType(GlassRefraction).last;
|
|
final resting = tester.getRect(lens);
|
|
final target = tester.getCenter(find.byIcon(Icons.assignment_rounded)).dx;
|
|
await tester.tap(find.byIcon(Icons.assignment_rounded));
|
|
await tester.pump();
|
|
var previous = resting.center.dx;
|
|
for (var frame = 0; frame < 50; frame++) {
|
|
await tester.pump(const Duration(milliseconds: 16));
|
|
final rect = tester.getRect(lens);
|
|
expect(rect.width, closeTo(resting.width, 0.05));
|
|
expect(rect.height, closeTo(resting.height, 0.05));
|
|
expect(rect.center.dx, greaterThanOrEqualTo(previous - 0.05));
|
|
expect(rect.center.dx, lessThanOrEqualTo(target + 0.05));
|
|
previous = rect.center.dx;
|
|
}
|
|
expect(previous, closeTo(target, 0.05));
|
|
});
|
|
testWidgets('base and selected cursor both refract the live backdrop', (
|
|
tester,
|
|
) async {
|
|
await tester.pumpWidget(_dock());
|
|
await tester.pumpAndSettle();
|
|
final glass = find.byType(GlassRefraction);
|
|
expect(glass, findsNWidgets(2));
|
|
expect(tester.getSize(glass.first), const Size(264, 58));
|
|
expect(
|
|
tester.widget<GlassRefraction>(glass.first).strength,
|
|
greaterThan(0),
|
|
);
|
|
});
|
|
testWidgets('reduced motion snaps the cursor without oscillation', (
|
|
tester,
|
|
) async {
|
|
await tester.pumpWidget(_dock(reduceMotion: true));
|
|
await tester.pumpAndSettle();
|
|
final lens = find.byType(GlassRefraction).last;
|
|
final resting = tester.getSize(lens);
|
|
await tester.tap(find.byIcon(Icons.person_rounded));
|
|
await tester.pump();
|
|
final target = tester.getCenter(find.byIcon(Icons.person_rounded)).dx;
|
|
expect(tester.getCenter(lens).dx, closeTo(target, 0.05));
|
|
await tester.pump(const Duration(milliseconds: 200));
|
|
expect(tester.getCenter(lens).dx, closeTo(target, 0.05));
|
|
expect(tester.getSize(lens), resting);
|
|
});
|
|
testWidgets('held cursor enlarges before dragging and returns on release', (
|
|
tester,
|
|
) async {
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
home: Scaffold(
|
|
body: Center(child: GlassDock(selectedIndex: 0, onSelected: (_) {})),
|
|
),
|
|
),
|
|
);
|
|
await tester.pumpAndSettle();
|
|
final lens = find.byType(GlassRefraction).last;
|
|
final resting = tester.getSize(lens);
|
|
final gesture = await tester.startGesture(
|
|
tester.getCenter(find.byKey(const Key('dock-cursor'))),
|
|
);
|
|
await tester.pump(const Duration(milliseconds: 110));
|
|
await tester.pump(const Duration(milliseconds: 200));
|
|
final held = tester.getSize(lens);
|
|
expect(held.width, greaterThan(resting.width * 1.25));
|
|
expect(held.height, greaterThan(resting.height * 1.25));
|
|
await gesture.cancel();
|
|
await tester.pumpAndSettle();
|
|
expect(tester.getSize(lens).width, closeTo(resting.width, 0.5));
|
|
expect(tester.getSize(lens).height, closeTo(resting.height, 0.5));
|
|
});
|
|
testWidgets('Dock stays stationary and tappable while scrolling timetable', (
|
|
tester,
|
|
) async {
|
|
tester.view.physicalSize = const Size(390, 844);
|
|
tester.view.devicePixelRatio = 1;
|
|
addTearDown(tester.view.resetPhysicalSize);
|
|
addTearDown(tester.view.resetDevicePixelRatio);
|
|
final c = uiController();
|
|
await c.initialize();
|
|
await c.showDemo();
|
|
await tester.pumpWidget(HepanApp(controller: c));
|
|
await tester.pumpAndSettle();
|
|
final dock = find.byType(GlassDock);
|
|
final before = tester.getRect(dock);
|
|
final gesture = await tester.startGesture(
|
|
tester.getCenter(find.text('周三')),
|
|
);
|
|
await gesture.moveBy(const Offset(0, -80));
|
|
await tester.pump();
|
|
await tester.pump(const Duration(milliseconds: 120));
|
|
final fading = find.ancestor(
|
|
of: dock,
|
|
matching: find.byType(FadeTransition),
|
|
);
|
|
final opacity = fading.evaluate().isEmpty
|
|
? 1.0
|
|
: tester.widget<FadeTransition>(fading.first).opacity.value;
|
|
expect(opacity, greaterThan(0.95));
|
|
expect(tester.getRect(dock), before);
|
|
expect(tester.getRect(dock).top, lessThan(844));
|
|
await gesture.up();
|
|
await tester.pumpAndSettle();
|
|
expect(dock.hitTestable(), findsOneWidget);
|
|
c.dispose();
|
|
});
|
|
}
|
|
|
|
Widget _dock({bool reduceMotion = false}) {
|
|
var selected = 0;
|
|
return MaterialApp(
|
|
home: MediaQuery(
|
|
data: MediaQueryData(disableAnimations: reduceMotion),
|
|
child: StatefulBuilder(
|
|
builder: (context, setState) => Scaffold(
|
|
body: Center(
|
|
child: GlassDock(
|
|
selectedIndex: selected,
|
|
onSelected: (index) => setState(() => selected = index),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|