194 lines
5.7 KiB
Dart
194 lines
5.7 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:fruitshorts/l10n/app_localizations.dart';
|
|
import 'package:fruitshorts/pages/discover/widgets/cover_carousel.dart';
|
|
|
|
void main() {
|
|
TestWidgetsFlutterBinding.ensureInitialized();
|
|
|
|
List<CoverItem> items(int count) => [
|
|
for (var index = 0; index < count; index++)
|
|
CoverItem(
|
|
title: 'Banner $index',
|
|
subtitle: 'Subtitle $index',
|
|
image: '/files/banner-$index.png',
|
|
onOpen: _noop,
|
|
),
|
|
];
|
|
|
|
testWidgets('should_turn_cube_and_keep_title_on_poster_when_carousel_pages', (
|
|
tester,
|
|
) async {
|
|
await tester.pumpWidget(
|
|
_localizedApp(
|
|
CoverCarousel(
|
|
items: [
|
|
for (final title in ['The Signal', 'City Lights', 'Vengeance'])
|
|
CoverItem(
|
|
title: title,
|
|
subtitle: 'Mock',
|
|
image: '/files/poster.png',
|
|
onOpen: _noop,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
await tester.pump();
|
|
|
|
expect(find.text('The Signal'), findsOneWidget);
|
|
expect(find.text('Mock'), findsOneWidget);
|
|
|
|
final box = tester.getRect(find.byType(CoverCarousel));
|
|
final gesture = await tester.startGesture(
|
|
Offset(box.right - 40, box.center.dy),
|
|
);
|
|
await gesture.moveBy(const Offset(-500, 0));
|
|
await tester.pump();
|
|
|
|
final turned = tester
|
|
.widgetList<Transform>(find.byType(Transform))
|
|
.any((transform) => (transform.transform.entry(0, 0) - 1).abs() > 0.15);
|
|
expect(turned, isTrue);
|
|
|
|
await gesture.moveBy(const Offset(-200, 0));
|
|
await gesture.up();
|
|
await tester.pump();
|
|
await tester.pump(const Duration(milliseconds: 450));
|
|
|
|
expect(find.text('City Lights'), findsOneWidget);
|
|
expect(tester.takeException(), isNull);
|
|
});
|
|
|
|
testWidgets('should_auto_advance_and_show_dots_when_multiple_items_exist', (
|
|
tester,
|
|
) async {
|
|
await tester.pumpWidget(_localizedApp(CoverCarousel(items: items(3))));
|
|
await tester.pump();
|
|
|
|
expect(find.text('Banner 0'), findsOneWidget);
|
|
expect(find.byKey(const Key('carousel-dot-0')), findsOneWidget);
|
|
expect(find.byKey(const Key('carousel-dot-1')), findsOneWidget);
|
|
expect(find.byKey(const Key('carousel-dot-2')), findsOneWidget);
|
|
|
|
await tester.pump(const Duration(milliseconds: 4500));
|
|
await tester.pump(const Duration(milliseconds: 500));
|
|
|
|
expect(find.text('Banner 1'), findsOneWidget);
|
|
await tester.pumpWidget(const SizedBox.shrink());
|
|
});
|
|
|
|
testWidgets('should_not_schedule_auto_advance_when_only_one_item_exists', (
|
|
tester,
|
|
) async {
|
|
await tester.pumpWidget(_localizedApp(CoverCarousel(items: items(1))));
|
|
await tester.pump(const Duration(seconds: 12));
|
|
|
|
expect(find.text('Banner 0'), findsOneWidget);
|
|
expect(find.byKey(const Key('carousel-dot-0')), findsOneWidget);
|
|
expect(find.byKey(const Key('carousel-dot-1')), findsNothing);
|
|
});
|
|
|
|
testWidgets('should_pause_auto_advance_while_pointer_is_down', (
|
|
tester,
|
|
) async {
|
|
await tester.pumpWidget(_localizedApp(CoverCarousel(items: items(3))));
|
|
await tester.pump();
|
|
final box = tester.getRect(find.byType(CoverCarousel));
|
|
final gesture = await tester.startGesture(box.center);
|
|
await tester.pump(const Duration(seconds: 6));
|
|
|
|
expect(find.text('Banner 0'), findsOneWidget);
|
|
|
|
await gesture.up();
|
|
await tester.pump();
|
|
await tester.pump(const Duration(milliseconds: 4500));
|
|
await tester.pump(const Duration(milliseconds: 500));
|
|
|
|
expect(find.text('Banner 1'), findsOneWidget);
|
|
await tester.pumpWidget(const SizedBox.shrink());
|
|
});
|
|
|
|
testWidgets('should_pause_when_inactive_and_resume_when_active_again', (
|
|
tester,
|
|
) async {
|
|
final active = ValueNotifier(false);
|
|
await tester.pumpWidget(
|
|
_localizedApp(
|
|
ValueListenableBuilder<bool>(
|
|
valueListenable: active,
|
|
builder: (context, enabled, _) =>
|
|
CoverCarousel(items: items(2), active: enabled),
|
|
),
|
|
),
|
|
);
|
|
await tester.pump(const Duration(seconds: 6));
|
|
expect(find.text('Banner 0'), findsOneWidget);
|
|
|
|
active.value = true;
|
|
await tester.pump();
|
|
await tester.pump(const Duration(milliseconds: 4500));
|
|
await tester.pump(const Duration(milliseconds: 500));
|
|
expect(find.text('Banner 1'), findsOneWidget);
|
|
await tester.pumpWidget(const SizedBox.shrink());
|
|
});
|
|
|
|
testWidgets('should_show_icon_fallback_when_banner_image_is_empty', (
|
|
tester,
|
|
) async {
|
|
await tester.pumpWidget(
|
|
_localizedApp(
|
|
CoverCarousel(
|
|
items: const [
|
|
CoverItem(
|
|
title: 'Broken image',
|
|
subtitle: '',
|
|
image: '',
|
|
onOpen: _noop,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
await tester.pump();
|
|
|
|
expect(find.byKey(const Key('carousel-image-fallback')), findsOneWidget);
|
|
});
|
|
|
|
testWidgets(
|
|
'should_keep_existing_open_callback_when_active_poster_is_tapped',
|
|
(tester) async {
|
|
var opened = 0;
|
|
await tester.pumpWidget(
|
|
_localizedApp(
|
|
CoverCarousel(
|
|
items: [
|
|
CoverItem(
|
|
title: 'Tap me',
|
|
subtitle: '',
|
|
image: '/files/banner.png',
|
|
onOpen: () => opened++,
|
|
),
|
|
...items(1),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
await tester.pump();
|
|
|
|
await tester.tap(find.text('Tap me'));
|
|
expect(opened, 1);
|
|
await tester.pumpWidget(const SizedBox.shrink());
|
|
},
|
|
);
|
|
}
|
|
|
|
void _noop() {}
|
|
|
|
Widget _localizedApp(Widget child) => MaterialApp(
|
|
locale: const Locale('en'),
|
|
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
|
supportedLocales: AppLocalizations.supportedLocales,
|
|
home: Scaffold(body: child),
|
|
);
|