Files
SpotiFLAC-Mobile/test/mornye_playback_button_test.dart

153 lines
5.1 KiB
Dart

import 'package:flutter/cupertino.dart' show CupertinoIcons;
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:spotiflac_android/widgets/mornye_playback_button.dart';
void main() {
Future<void> pumpButton(
WidgetTester tester, {
required VoidCallback onPressed,
IconData icon = CupertinoIcons.play_fill,
bool reduceMotion = false,
}) => tester.pumpWidget(
MaterialApp(
home: MediaQuery(
data: MediaQueryData(disableAnimations: reduceMotion),
child: Scaffold(
body: Center(
child: MornyePlaybackButton(
icon: icon,
tooltip: 'Playback action',
color: Colors.white,
onPressed: onPressed,
),
),
),
),
),
);
double feedbackOpacity(WidgetTester tester) {
final feedback = tester.widget<DecoratedBox>(
find
.ancestor(
of: find.byType(IconButton),
matching: find.byType(DecoratedBox),
)
.first,
);
return (feedback.decoration as BoxDecoration).color!.a;
}
testWidgets('press feedback keeps the tap target fixed and cancels safely', (
tester,
) async {
var calls = 0;
await pumpButton(tester, onPressed: () => calls++);
final button = find.byType(IconButton);
final icon = find.byIcon(CupertinoIcons.play_fill);
final bounds = tester.getRect(button);
final iconBounds = tester.getRect(icon);
expect(feedbackOpacity(tester), 0);
final press = await tester.startGesture(bounds.center);
await tester.pump(const Duration(milliseconds: 100));
await tester.pump(const Duration(milliseconds: 200));
expect(tester.getRect(icon).width, lessThan(iconBounds.width));
expect(tester.getRect(button), bounds);
expect(feedbackOpacity(tester), closeTo(0.14, 0.001));
await press.up();
await tester.pumpAndSettle();
expect(calls, 1);
expect(tester.getRect(icon), iconBounds);
expect(feedbackOpacity(tester), 0);
final cancelled = await tester.startGesture(bounds.center);
await tester.pump(const Duration(milliseconds: 100));
await cancelled.cancel();
await tester.pumpAndSettle();
expect(calls, 1);
expect(tester.getRect(icon), iconBounds);
expect(feedbackOpacity(tester), 0);
});
for (final icon in [
CupertinoIcons.play_fill,
CupertinoIcons.pause_fill,
CupertinoIcons.forward_fill,
CupertinoIcons.backward_fill,
]) {
testWidgets('quick tap on $icon fades a circular highlight in and out', (
tester,
) async {
var calls = 0;
await pumpButton(tester, icon: icon, onPressed: () => calls++);
final button = find.byType(IconButton);
final bounds = tester.getRect(button);
await tester.tap(button);
expect(calls, 1);
await tester.pump();
await tester.pump(const Duration(milliseconds: 50));
final entering = feedbackOpacity(tester);
expect(entering, greaterThan(0));
await tester.pump(const Duration(milliseconds: 60));
final peak = feedbackOpacity(tester);
expect(peak, greaterThan(entering));
await tester.pump(const Duration(milliseconds: 220));
expect(feedbackOpacity(tester), lessThan(peak));
expect(tester.getRect(button), bounds);
await tester.pumpAndSettle();
expect(feedbackOpacity(tester), 0);
expect(calls, 1);
});
}
for (final icon in [
CupertinoIcons.forward_fill,
CupertinoIcons.backward_fill,
]) {
testWidgets(
'skip $icon animates without delaying repeated playback actions',
(tester) async {
var calls = 0;
await pumpButton(tester, icon: icon, onPressed: () => calls++);
final button = find.byType(IconButton);
final bounds = tester.getRect(button);
for (var index = 0; index < 3; index++) {
await tester.tap(button);
await tester.pump(const Duration(milliseconds: 60));
expect(calls, index + 1);
expect(find.byIcon(CupertinoIcons.play_fill), findsNWidgets(3));
expect(tester.getRect(button), bounds);
}
await tester.pumpAndSettle();
expect(find.byIcon(icon), findsOneWidget);
expect(find.byIcon(CupertinoIcons.play_fill), findsNothing);
expect(tester.takeException(), isNull);
},
);
}
testWidgets('Reduce Motion keeps skip glyphs stationary and actions usable', (
tester,
) async {
var calls = 0;
await pumpButton(
tester,
icon: CupertinoIcons.forward_fill,
reduceMotion: true,
onPressed: () => calls++,
);
final icon = find.byIcon(CupertinoIcons.forward_fill);
final bounds = tester.getRect(icon);
final press = await tester.startGesture(tester.getCenter(icon));
await tester.pump(const Duration(milliseconds: 200));
expect(tester.getRect(icon), bounds);
await press.up();
await tester.pump(const Duration(milliseconds: 60));
expect(calls, 1);
expect(find.byIcon(CupertinoIcons.play_fill), findsNothing);
expect(tester.getRect(icon), bounds);
await tester.pumpAndSettle();
});
}