chore(release): 合并 develop 到 release/v1.0.0
This commit is contained in:
commit
35364c949a
69 files changed
+6115
-2941
No files matched your search
@@ -46,6 +46,8 @@ void main() {
|
||||
|
||||
await tester.tap(find.byKey(const Key('tab-my')));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.drag(find.byType(ListView), const Offset(0, -520));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byKey(const Key('mine-account-card')), findsOneWidget);
|
||||
expect(find.byKey(const Key('mine-account-profile')), findsOneWidget);
|
||||
|
||||
@@ -82,4 +82,7 @@ Future<void> _pumpAuth(WidgetTester tester) async {
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.ensureVisible(find.byKey(const Key('auth-entry-email')));
|
||||
await tester.tap(find.byKey(const Key('auth-entry-email')));
|
||||
await tester.pumpAndSettle();
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
// Author: fruit.com.cn
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:shared_preferences_platform_interface/in_memory_shared_preferences_async.dart';
|
||||
import 'package:shared_preferences_platform_interface/shared_preferences_async_platform_interface.dart';
|
||||
|
||||
import 'package:fruitshorts/core/data/remote/api_client.dart';
|
||||
import 'package:fruitshorts/core/data/remote/auth_api.dart';
|
||||
import 'package:fruitshorts/core/data/services/auth_controller.dart';
|
||||
import 'package:fruitshorts/core/data/services/auth_session_store.dart';
|
||||
import 'package:fruitshorts/core/platform/haptics.dart';
|
||||
import 'package:fruitshorts/l10n/app_localizations.dart';
|
||||
import 'package:fruitshorts/pages/auth/auth_view.dart';
|
||||
|
||||
import '../support/fake_haptics.dart';
|
||||
import '../support/fake_http_adapter.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('should_show_three_login_entries_and_open_email_form', (
|
||||
tester,
|
||||
) async {
|
||||
SharedPreferencesAsyncPlatform.instance =
|
||||
InMemorySharedPreferencesAsync.empty();
|
||||
final auth = AuthController(
|
||||
AuthApi(
|
||||
ApiClient(
|
||||
baseUrl: 'http://127.0.0.1:1',
|
||||
adapter: FakeHttpAdapter((_) async => FakeHttpResponse('{}', 500)),
|
||||
),
|
||||
),
|
||||
AuthSessionStore(),
|
||||
);
|
||||
await tester.pumpWidget(
|
||||
MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider<AuthController>.value(value: auth),
|
||||
Provider<Haptics>.value(value: FakeHaptics()),
|
||||
],
|
||||
child: MaterialApp(
|
||||
locale: const Locale('en'),
|
||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||
supportedLocales: AppLocalizations.supportedLocales,
|
||||
home: const AuthPage(),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byKey(const Key('auth-entry-google')), findsOneWidget);
|
||||
expect(find.byKey(const Key('auth-entry-phone')), findsOneWidget);
|
||||
expect(find.byKey(const Key('auth-entry-email')), findsOneWidget);
|
||||
expect(find.byKey(const Key('auth-legal')), findsOneWidget);
|
||||
|
||||
await tester.tap(find.byKey(const Key('auth-entry-google')));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('Coming soon'), findsOneWidget);
|
||||
|
||||
await tester.tap(find.byKey(const Key('auth-entry-email')));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byKey(const Key('auth-email')), findsOneWidget);
|
||||
expect(find.byKey(const Key('auth-password')), findsOneWidget);
|
||||
});
|
||||
}
|
||||
@@ -59,6 +59,9 @@ void main() {
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.ensureVisible(find.byKey(const Key('auth-entry-email')));
|
||||
await tester.tap(find.byKey(const Key('auth-entry-email')));
|
||||
await tester.pumpAndSettle();
|
||||
}
|
||||
|
||||
testWidgets('should_show_email_error_and_stay_on_page_when_form_is_empty', (
|
||||
|
||||
@@ -29,6 +29,7 @@ void main() {
|
||||
WidgetTester tester, {
|
||||
AuthApi? api,
|
||||
FakeHaptics? haptics,
|
||||
bool openEmail = true,
|
||||
}) async {
|
||||
final auth = AuthController(
|
||||
api ??
|
||||
@@ -57,20 +58,32 @@ void main() {
|
||||
),
|
||||
);
|
||||
await tester.pump(const Duration(milliseconds: 220));
|
||||
if (openEmail) {
|
||||
await tester.ensureVisible(find.byKey(const Key('auth-entry-email')));
|
||||
await tester.tap(find.byKey(const Key('auth-entry-email')));
|
||||
await tester.pumpAndSettle();
|
||||
}
|
||||
}
|
||||
|
||||
testWidgets(
|
||||
'should_render_branded_dark_layout_with_approved_tokens_when_page_opens',
|
||||
(tester) async {
|
||||
await pumpAuthPage(tester);
|
||||
await pumpAuthPage(tester, openEmail: false);
|
||||
|
||||
expect(find.byKey(const Key('auth-brand')), findsOneWidget);
|
||||
expect(find.byKey(const Key('auth-landing')), findsOneWidget);
|
||||
expect(find.text('FruitShorts'), findsOneWidget);
|
||||
expect(find.text('Short dramas made for Indonesia'), findsOneWidget);
|
||||
expect(
|
||||
tester.getSize(find.byKey(const Key('auth-brand-mark'))),
|
||||
const Size(48, 48),
|
||||
find.text('Sign in to sync progress, favorites and coins'),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(
|
||||
tester.getSize(find.byKey(const Key('auth-brand-logo'))),
|
||||
const Size(64, 64),
|
||||
);
|
||||
expect(find.byKey(const Key('auth-entry-google')), findsOneWidget);
|
||||
expect(find.byKey(const Key('auth-entry-phone')), findsOneWidget);
|
||||
expect(find.byKey(const Key('auth-entry-email')), findsOneWidget);
|
||||
expect(find.byKey(const Key('auth-legal')), findsOneWidget);
|
||||
|
||||
final glow = tester.widget<Container>(
|
||||
find.byKey(const Key('auth-background-glow')),
|
||||
@@ -81,6 +94,9 @@ void main() {
|
||||
expect(color.a, lessThanOrEqualTo(0.18));
|
||||
}
|
||||
|
||||
await tester.tap(find.byKey(const Key('auth-entry-email')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final card = tester.widget<Container>(find.byKey(const Key('auth-card')));
|
||||
final cardDecoration = card.decoration! as BoxDecoration;
|
||||
expect(cardDecoration.color, AppColors.card);
|
||||
|
||||
@@ -81,7 +81,10 @@ void main() {
|
||||
isNull,
|
||||
);
|
||||
|
||||
expect(await ServerEndpoint.save(' http://39.162.50.99:8081/ '), isTrue);
|
||||
expect(
|
||||
await ServerEndpoint.save(' http://39.162.50.99:8081/ '),
|
||||
isTrue,
|
||||
);
|
||||
expect(
|
||||
await SharedPreferencesAsync().getString(ServerEndpoint.preferenceKey),
|
||||
'http://39.162.50.99:8081',
|
||||
|
||||
@@ -1,193 +0,0 @@
|
||||
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),
|
||||
);
|
||||
@@ -7,11 +7,11 @@ import 'package:fruitshorts/app.dart';
|
||||
import 'package:fruitshorts/core/data/models/content_category.dart';
|
||||
import 'package:fruitshorts/core/data/models/drama.dart';
|
||||
import 'package:fruitshorts/core/data/models/home_feed.dart';
|
||||
import 'package:fruitshorts/core/data/models/watch_progress.dart';
|
||||
import 'package:fruitshorts/core/data/repositories/category_repository.dart';
|
||||
import 'package:fruitshorts/core/data/repositories/favorite_repository.dart';
|
||||
import 'package:fruitshorts/core/data/repositories/playback_repository.dart';
|
||||
import 'package:fruitshorts/core/data/repositories/watch_history_repository.dart';
|
||||
import 'package:fruitshorts/core/widgets/remote_image.dart';
|
||||
|
||||
import '../support/fake_catalog.dart';
|
||||
import '../support/fake_interaction_repositories.dart';
|
||||
@@ -25,7 +25,7 @@ void main() {
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'should_show_all_dramas_in_three_column_sliver_grid_without_continue_watching',
|
||||
'should_show_all_dramas_in_two_column_masonry_without_continue_watching',
|
||||
(tester) async {
|
||||
tester.view.physicalSize = const Size(390, 844);
|
||||
tester.view.devicePixelRatio = 1;
|
||||
@@ -37,57 +37,94 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text('Continue Watching'), findsNothing);
|
||||
expect(find.byKey(const Key('home-all-dramas-title')), findsNothing);
|
||||
expect(find.text('All'), findsOneWidget);
|
||||
expect(find.text('Recommended'), findsOneWidget);
|
||||
for (final key in const [
|
||||
Key('discover-search-button'),
|
||||
Key('discover-profile'),
|
||||
]) {
|
||||
expect(tester.getSize(find.byKey(key)), const Size(36, 36));
|
||||
expect(
|
||||
tester
|
||||
.widget<Icon>(
|
||||
find.descendant(
|
||||
of: find.byKey(key),
|
||||
matching: find.byType(Icon),
|
||||
),
|
||||
)
|
||||
.size,
|
||||
18,
|
||||
);
|
||||
}
|
||||
expect(find.text('For You'), findsNothing);
|
||||
expect(
|
||||
tester.getCenter(find.text('All')).dx,
|
||||
lessThan(tester.getCenter(find.text('Hot')).dx),
|
||||
);
|
||||
expect(
|
||||
tester
|
||||
.getTopLeft(
|
||||
find.byKey(const Key('home-drama-card-the-signal-demo')),
|
||||
)
|
||||
.dy -
|
||||
tester
|
||||
.getBottomLeft(find.byKey(const Key('home-category-chips')))
|
||||
.dy,
|
||||
closeTo(14, 0.1),
|
||||
);
|
||||
|
||||
final grid = tester.widget<SliverGrid>(
|
||||
final masonry = tester.widget<Row>(
|
||||
find.byKey(const Key('home-all-dramas-grid')),
|
||||
);
|
||||
final delegate =
|
||||
grid.gridDelegate as SliverGridDelegateWithFixedCrossAxisCount;
|
||||
expect(delegate.crossAxisCount, 3);
|
||||
expect(delegate.crossAxisSpacing, 10);
|
||||
expect(delegate.mainAxisSpacing, 14);
|
||||
expect(delegate.childAspectRatio, closeTo(2 / 3, 0.001));
|
||||
expect(masonry.children, hasLength(3));
|
||||
expect((masonry.children[1] as SizedBox).width, 10);
|
||||
expect(
|
||||
tester
|
||||
.widget<SliverPadding>(
|
||||
find.byKey(const Key('home-all-dramas-section')),
|
||||
)
|
||||
.widget<Padding>(find.byKey(const Key('home-all-dramas-section')))
|
||||
.padding,
|
||||
const EdgeInsets.symmetric(horizontal: 16),
|
||||
const EdgeInsets.symmetric(horizontal: 14),
|
||||
);
|
||||
expect(find.byType(GridView), findsNothing);
|
||||
expect(find.byType(CustomScrollView), findsOneWidget);
|
||||
expect(find.byType(RemoteImage), findsWidgets);
|
||||
final signalCard = find.byKey(
|
||||
const Key('home-drama-card-the-signal-demo'),
|
||||
);
|
||||
final cityCard = find.byKey(
|
||||
const Key('home-drama-card-city-lights-demo'),
|
||||
);
|
||||
final vengeanceCard = find.byKey(
|
||||
const Key('home-drama-card-vengeance-demo'),
|
||||
);
|
||||
expect(tester.getTopLeft(signalCard).dy, tester.getTopLeft(cityCard).dy);
|
||||
expect(
|
||||
tester.getTopLeft(vengeanceCard).dx,
|
||||
tester.getTopLeft(signalCard).dx,
|
||||
);
|
||||
expect(
|
||||
tester.getTopLeft(vengeanceCard).dy -
|
||||
tester.getBottomLeft(signalCard).dy,
|
||||
closeTo(10, 1),
|
||||
);
|
||||
|
||||
final cover = tester.widget<AspectRatio>(
|
||||
find.byKey(const Key('home-drama-cover-city-lights-demo')),
|
||||
final cover = find.byKey(const Key('home-drama-cover-city-lights-demo'));
|
||||
expect(tester.getSize(cover).height, greaterThan(120));
|
||||
expect(
|
||||
tester
|
||||
.widget<Image>(
|
||||
find.descendant(of: cover, matching: find.byType(Image)),
|
||||
)
|
||||
.fit,
|
||||
BoxFit.fitWidth,
|
||||
);
|
||||
expect(
|
||||
find.descendant(
|
||||
of: cover,
|
||||
matching: find.text('City Lights & Velvet Nights'),
|
||||
),
|
||||
findsNothing,
|
||||
);
|
||||
expect(
|
||||
find.byKey(const Key('home-drama-title-city-lights-demo')),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(
|
||||
tester
|
||||
.getTopLeft(
|
||||
find.byKey(const Key('home-drama-title-city-lights-demo')),
|
||||
)
|
||||
.dy,
|
||||
greaterThan(tester.getBottomLeft(cover).dy),
|
||||
);
|
||||
expect(cover.aspectRatio, closeTo(2 / 3, 0.001));
|
||||
expect(
|
||||
tester
|
||||
.widget<Text>(
|
||||
find.byKey(const Key('home-drama-title-city-lights-demo')),
|
||||
)
|
||||
.maxLines,
|
||||
2,
|
||||
1,
|
||||
);
|
||||
expect(
|
||||
tester
|
||||
@@ -111,14 +148,14 @@ void main() {
|
||||
await tester.tap(find.byKey(const Key('tab-discover')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text('The Signal'), findsOneWidget);
|
||||
expect(find.text('City Lights & Velvet Nights'), findsOneWidget);
|
||||
expect(find.text('The Signal'), findsWidgets);
|
||||
expect(find.text('City Lights & Velvet Nights'), findsWidgets);
|
||||
|
||||
await tester.tap(find.text('Romance'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text('The Signal'), findsNothing);
|
||||
expect(find.text('City Lights & Velvet Nights'), findsOneWidget);
|
||||
expect(find.text('City Lights & Velvet Nights'), findsWidgets);
|
||||
expect(
|
||||
find.byKey(const Key('home-drama-card-the-signal-demo')),
|
||||
findsNothing,
|
||||
@@ -129,6 +166,43 @@ void main() {
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('should_keep_discover_header_fixed_when_content_scrolls', (
|
||||
tester,
|
||||
) async {
|
||||
tester.view.physicalSize = const Size(390, 844);
|
||||
tester.view.devicePixelRatio = 1;
|
||||
addTearDown(tester.view.resetPhysicalSize);
|
||||
addTearDown(tester.view.resetDevicePixelRatio);
|
||||
|
||||
await _pumpApp(
|
||||
tester,
|
||||
categoryRepository: _GridCategoryRepository(
|
||||
discoverFeed: _tallDiscoverFeed,
|
||||
),
|
||||
);
|
||||
await tester.tap(find.byKey(const Key('tab-discover')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final headerBefore = tester.getTopLeft(
|
||||
find.byKey(const Key('discover-search-button')),
|
||||
);
|
||||
final contentBefore = tester.getTopLeft(
|
||||
find.byKey(const Key('home-category-chips')),
|
||||
);
|
||||
|
||||
await tester.drag(find.byType(CustomScrollView), const Offset(0, -40));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(
|
||||
tester.getTopLeft(find.byKey(const Key('discover-search-button'))),
|
||||
headerBefore,
|
||||
);
|
||||
expect(
|
||||
tester.getTopLeft(find.byKey(const Key('home-category-chips'))).dy,
|
||||
lessThan(contentBefore.dy),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('should_keep_empty_messages_when_feed_has_no_dramas', (
|
||||
tester,
|
||||
) async {
|
||||
@@ -146,17 +220,8 @@ void main() {
|
||||
await tester.tap(find.byKey(const Key('tab-discover')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byKey(const Key('home-all-dramas-title')), findsNothing);
|
||||
expect(find.text('No matching dramas.'), findsOneWidget);
|
||||
final content = tester.getCenter(
|
||||
find.byKey(const Key('empty-state-content')),
|
||||
);
|
||||
final chipsBottom = tester
|
||||
.getBottomLeft(find.byKey(const Key('home-category-chips')))
|
||||
.dy;
|
||||
final feed = tester.getRect(find.byType(CustomScrollView));
|
||||
expect(content.dx, closeTo(feed.center.dx, 1));
|
||||
expect(content.dy, closeTo((chipsBottom + feed.bottom) / 2, 36));
|
||||
expect(find.byKey(const Key('empty-state-content')), findsOneWidget);
|
||||
|
||||
await tester.tap(find.text('Romance'));
|
||||
await tester.pumpAndSettle();
|
||||
@@ -174,7 +239,6 @@ void main() {
|
||||
await tester.tap(find.byKey(const Key('tab-discover')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byKey(const Key('home-all-dramas-title')), findsNothing);
|
||||
expect(find.text('Categories could not be loaded.'), findsOneWidget);
|
||||
expect(find.text('Retry'), findsOneWidget);
|
||||
expect(find.byKey(const Key('empty-state-icon')), findsOneWidget);
|
||||
@@ -184,7 +248,7 @@ void main() {
|
||||
expect(find.byKey(const Key('home-all-dramas-grid')), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('should_fit_three_column_grid_on_compact_screen', (tester) async {
|
||||
testWidgets('should_fit_two_column_grid_on_compact_screen', (tester) async {
|
||||
tester.view.physicalSize = const Size(320, 568);
|
||||
tester.view.devicePixelRatio = 1;
|
||||
addTearDown(tester.view.resetPhysicalSize);
|
||||
@@ -200,15 +264,164 @@ void main() {
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byKey(const Key('home-all-dramas-title')), findsNothing);
|
||||
expect(find.text('City Lights & Velvet Nights'), findsOneWidget);
|
||||
expect(find.text('City Lights & Velvet Nights'), findsWidgets);
|
||||
expect(tester.takeException(), isNull);
|
||||
});
|
||||
|
||||
testWidgets('should_filter_trending_grid_when_search_text_changes', (
|
||||
tester,
|
||||
) async {
|
||||
tester.view.physicalSize = const Size(390, 844);
|
||||
tester.view.devicePixelRatio = 1;
|
||||
addTearDown(tester.view.resetPhysicalSize);
|
||||
addTearDown(tester.view.resetDevicePixelRatio);
|
||||
|
||||
await _pumpApp(tester, categoryRepository: _GridCategoryRepository());
|
||||
await tester.tap(find.byKey(const Key('tab-discover')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(
|
||||
find.byKey(const Key('home-drama-card-the-signal-demo')),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(
|
||||
find.byKey(const Key('home-drama-card-city-lights-demo')),
|
||||
findsOneWidget,
|
||||
);
|
||||
|
||||
await tester.enterText(find.byKey(const Key('discover-search')), 'velvet');
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(
|
||||
find.byKey(const Key('home-drama-card-the-signal-demo')),
|
||||
findsNothing,
|
||||
);
|
||||
expect(
|
||||
find.byKey(const Key('home-drama-card-city-lights-demo')),
|
||||
findsOneWidget,
|
||||
);
|
||||
|
||||
await tester.enterText(find.byKey(const Key('discover-search')), '');
|
||||
await tester.pumpAndSettle();
|
||||
expect(
|
||||
find.byKey(const Key('home-drama-card-the-signal-demo')),
|
||||
findsOneWidget,
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('should_unfocus_search_without_losing_input_or_filter', (
|
||||
tester,
|
||||
) async {
|
||||
tester.view.physicalSize = const Size(390, 844);
|
||||
tester.view.devicePixelRatio = 1;
|
||||
addTearDown(tester.view.resetPhysicalSize);
|
||||
addTearDown(tester.view.resetDevicePixelRatio);
|
||||
|
||||
await _pumpApp(tester, categoryRepository: _GridCategoryRepository());
|
||||
await tester.tap(find.byKey(const Key('tab-discover')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.tap(find.byKey(const Key('discover-search')));
|
||||
await tester.pump();
|
||||
expect(
|
||||
tester
|
||||
.widget<TextField>(find.byKey(const Key('discover-search')))
|
||||
.focusNode!
|
||||
.hasFocus,
|
||||
isTrue,
|
||||
);
|
||||
|
||||
await tester.enterText(find.byKey(const Key('discover-search')), 'velvet');
|
||||
await tester.pumpAndSettle();
|
||||
expect(
|
||||
find.byKey(const Key('home-drama-card-city-lights-demo')),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(
|
||||
find.byKey(const Key('home-drama-card-the-signal-demo')),
|
||||
findsNothing,
|
||||
);
|
||||
|
||||
await tester.tapAt(const Offset(70, 23));
|
||||
await tester.pump();
|
||||
|
||||
final field = tester.widget<TextField>(
|
||||
find.byKey(const Key('discover-search')),
|
||||
);
|
||||
expect(field.focusNode!.hasFocus, isFalse);
|
||||
expect(field.controller!.text, 'velvet');
|
||||
expect(
|
||||
find.byKey(const Key('home-drama-card-city-lights-demo')),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(
|
||||
find.byKey(const Key('home-drama-card-the-signal-demo')),
|
||||
findsNothing,
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('should_refresh_feed_when_pulled_down', (tester) async {
|
||||
tester.view.physicalSize = const Size(390, 844);
|
||||
tester.view.devicePixelRatio = 1;
|
||||
addTearDown(tester.view.resetPhysicalSize);
|
||||
addTearDown(tester.view.resetDevicePixelRatio);
|
||||
|
||||
final counter = _CountingCategoryRepository(
|
||||
_GridCategoryRepository(discoverFeed: _tallDiscoverFeed),
|
||||
);
|
||||
await _pumpApp(tester, categoryRepository: counter);
|
||||
await tester.tap(find.byKey(const Key('tab-discover')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final before = counter.categoryLoads + counter.feedLoads;
|
||||
await tester.drag(find.byType(CustomScrollView), const Offset(0, 320));
|
||||
await tester.pump();
|
||||
await tester.pump(const Duration(seconds: 1));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(counter.categoryLoads + counter.feedLoads, greaterThan(before));
|
||||
expect(find.byType(RefreshProgressIndicator), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('should_show_continue_watching_only_when_a_record_exists', (
|
||||
tester,
|
||||
) async {
|
||||
tester.view.physicalSize = const Size(390, 844);
|
||||
tester.view.devicePixelRatio = 1;
|
||||
addTearDown(tester.view.resetPhysicalSize);
|
||||
addTearDown(tester.view.resetDevicePixelRatio);
|
||||
|
||||
await _pumpApp(
|
||||
tester,
|
||||
categoryRepository: _GridCategoryRepository(),
|
||||
history: InMemoryWatchHistoryRepository(
|
||||
seed: const [
|
||||
WatchProgress(
|
||||
dramaId: 'city-lights-demo',
|
||||
episodeId: 'city-lights-demo-1',
|
||||
position: Duration(seconds: 42),
|
||||
duration: Duration(minutes: 2),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
await tester.tap(find.byKey(const Key('tab-discover')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byKey(const Key('discover-continue-watching')), findsOneWidget);
|
||||
expect(find.byKey(const Key('discover-continue-play')), findsOneWidget);
|
||||
expect(find.text('City Lights & Velvet Nights'), findsWidgets);
|
||||
expect(find.byKey(const Key('discover-quick-filter')), findsOneWidget);
|
||||
expect(find.byKey(const Key('discover-quick-charts')), findsOneWidget);
|
||||
expect(find.byKey(const Key('discover-quick-new')), findsOneWidget);
|
||||
expect(find.byKey(const Key('discover-quick-watchlist')), findsOneWidget);
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _pumpApp(
|
||||
WidgetTester tester, {
|
||||
required CategoryRepository categoryRepository,
|
||||
WatchHistoryRepository? history,
|
||||
}) async {
|
||||
final catalog = FakeCatalogRepository();
|
||||
await tester.pumpWidget(
|
||||
@@ -216,7 +429,7 @@ Future<void> _pumpApp(
|
||||
playerFactory: createWidgetPlayer,
|
||||
catalogRepository: catalog,
|
||||
categoryRepository: categoryRepository,
|
||||
watchHistoryRepository: InMemoryWatchHistoryRepository(),
|
||||
watchHistoryRepository: history ?? InMemoryWatchHistoryRepository(),
|
||||
favoriteRepository: InMemoryFavoriteRepository(),
|
||||
playbackRepository: FakePlaybackRepository(),
|
||||
commentRepository: FakeCommentRepository(),
|
||||
@@ -273,3 +486,43 @@ final _defaultDiscoverFeed = HomeFeed(
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
final _tallDiscoverFeed = HomeFeed(
|
||||
sections: [
|
||||
FeedSection(
|
||||
code: 'hot',
|
||||
title: 'Hot',
|
||||
dramas: [
|
||||
for (var index = 0; index < 12; index++)
|
||||
Drama(
|
||||
id: 'tall-$index',
|
||||
title: 'Tall Drama $index',
|
||||
synopsis: 'Tall Drama $index synopsis',
|
||||
posterUrl: '/files/tall-$index.png',
|
||||
genre: 'Urban Romance',
|
||||
detailLoaded: true,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
class _CountingCategoryRepository implements CategoryRepository {
|
||||
_CountingCategoryRepository(this.delegate);
|
||||
|
||||
final CategoryRepository delegate;
|
||||
int categoryLoads = 0;
|
||||
int feedLoads = 0;
|
||||
|
||||
@override
|
||||
Future<List<ContentCategory>> fetchCategories() {
|
||||
categoryLoads++;
|
||||
return delegate.fetchCategories();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<HomeFeed> fetchDiscoverFeed() {
|
||||
feedLoads++;
|
||||
return delegate.fetchDiscoverFeed();
|
||||
}
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
// Author: fruit.com.cn
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:fruitshorts/app.dart';
|
||||
import 'package:fruitshorts/core/data/models/drama.dart';
|
||||
import 'package:fruitshorts/core/data/models/home_feed.dart';
|
||||
import 'package:fruitshorts/core/data/repositories/catalog_repository.dart';
|
||||
import 'package:fruitshorts/core/data/repositories/favorite_repository.dart';
|
||||
import 'package:fruitshorts/core/data/repositories/playback_repository.dart';
|
||||
import 'package:fruitshorts/core/data/repositories/watch_history_repository.dart';
|
||||
import 'package:fruitshorts/pages/discover/widgets/cover_carousel.dart';
|
||||
import 'package:shared_preferences_platform_interface/in_memory_shared_preferences_async.dart';
|
||||
import 'package:shared_preferences_platform_interface/shared_preferences_async_platform_interface.dart';
|
||||
|
||||
import '../support/fake_catalog.dart';
|
||||
import '../support/fake_category.dart';
|
||||
import '../support/fake_interaction_repositories.dart';
|
||||
import '../support/fake_notice_repository.dart';
|
||||
import '../support/widget_player.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets(
|
||||
'should_render_home_feed_banners_when_discover_banners_are_empty',
|
||||
(tester) async {
|
||||
SharedPreferencesAsyncPlatform.instance =
|
||||
InMemorySharedPreferencesAsync.empty();
|
||||
final catalog = _HomeBannerCatalogRepository();
|
||||
await tester.pumpWidget(
|
||||
LumaDramaApp(
|
||||
playerFactory: createWidgetPlayer,
|
||||
catalogRepository: catalog,
|
||||
categoryRepository: FakeCategoryRepository(catalog: catalog),
|
||||
watchHistoryRepository: InMemoryWatchHistoryRepository(),
|
||||
favoriteRepository: InMemoryFavoriteRepository(),
|
||||
playbackRepository: FakePlaybackRepository(),
|
||||
commentRepository: FakeCommentRepository(),
|
||||
interactionRepository: FakeInteractionRepository(),
|
||||
noticeRepository: FakeNoticeRepository(),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(const Key('tab-discover')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byType(CoverCarousel), findsOneWidget);
|
||||
expect(find.byKey(const Key('carousel-dot-0')), findsOneWidget);
|
||||
expect(find.byKey(const Key('carousel-dot-1')), findsOneWidget);
|
||||
expect(
|
||||
find.descendant(
|
||||
of: find.byType(CoverCarousel),
|
||||
matching: find.text('The Signal'),
|
||||
),
|
||||
findsOneWidget,
|
||||
);
|
||||
|
||||
await tester.pump(const Duration(milliseconds: 4500));
|
||||
await tester.pump(const Duration(milliseconds: 500));
|
||||
expect(
|
||||
find.descendant(
|
||||
of: find.byType(CoverCarousel),
|
||||
matching: find.text('City Lights & Velvet Nights'),
|
||||
),
|
||||
findsOneWidget,
|
||||
);
|
||||
await tester.pumpWidget(const SizedBox.shrink());
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
class _HomeBannerCatalogRepository implements CatalogRepository {
|
||||
final _delegate = FakeCatalogRepository();
|
||||
|
||||
@override
|
||||
Future<HomeFeed> fetchHomeFeed() async => HomeFeed(
|
||||
banners: const [
|
||||
FeedBanner(
|
||||
id: 'banner-1',
|
||||
imageUrl: '/files/banner-1.png',
|
||||
linkType: 'DRAMA',
|
||||
linkValue: 'the-signal-demo',
|
||||
),
|
||||
FeedBanner(
|
||||
id: 'banner-2',
|
||||
imageUrl: '/files/banner-2.png',
|
||||
linkType: 'DRAMA',
|
||||
linkValue: 'city-lights-demo',
|
||||
),
|
||||
],
|
||||
sections: [FeedSection(code: 'hot', title: 'Hot', dramas: demoDramas)],
|
||||
);
|
||||
|
||||
@override
|
||||
Future<HomeFeed> fetchDiscoverFeed() async => HomeFeed(
|
||||
sections: [FeedSection(code: 'hot', title: 'Hot', dramas: demoDramas)],
|
||||
);
|
||||
|
||||
@override
|
||||
Future<Drama> fetchDrama(String dramaId) => _delegate.fetchDrama(dramaId);
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
// Author: fruit.com.cn
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:fruitshorts/core/data/models/drama.dart';
|
||||
import 'package:fruitshorts/core/data/repositories/comment_repository.dart';
|
||||
import 'package:fruitshorts/core/data/repositories/favorite_repository.dart';
|
||||
import 'package:fruitshorts/core/data/repositories/interaction_repository.dart';
|
||||
import 'package:fruitshorts/core/data/repositories/playback_repository.dart';
|
||||
import 'package:fruitshorts/core/data/repositories/watch_history_repository.dart';
|
||||
import 'package:fruitshorts/core/data/services/catalog_controller.dart';
|
||||
import 'package:fruitshorts/core/data/services/favorite_controller.dart';
|
||||
import 'package:fruitshorts/core/data/services/interaction_controller.dart';
|
||||
import 'package:fruitshorts/core/data/services/playback_session.dart';
|
||||
import 'package:fruitshorts/core/platform/haptics.dart';
|
||||
import 'package:fruitshorts/core/theme/app_theme.dart';
|
||||
import 'package:fruitshorts/l10n/app_localizations.dart';
|
||||
import 'package:fruitshorts/pages/drama_detail/drama_detail_view.dart';
|
||||
import 'package:fruitshorts/pages/player/player_view.dart';
|
||||
|
||||
import '../support/fake_catalog.dart';
|
||||
import '../support/fake_haptics.dart';
|
||||
import '../support/fake_interaction_repositories.dart';
|
||||
import '../support/widget_player.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('should_render_preview_hero_cta_synopsis_and_episode_chips', (
|
||||
tester,
|
||||
) async {
|
||||
tester.view.physicalSize = const Size(390, 844);
|
||||
tester.view.devicePixelRatio = 1;
|
||||
addTearDown(tester.view.resetPhysicalSize);
|
||||
addTearDown(tester.view.resetDevicePixelRatio);
|
||||
|
||||
await tester.pumpWidget(_host(_detailDrama()));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(tester.getSize(find.byKey(const Key('detail-hero'))).height, 190);
|
||||
expect(
|
||||
tester.getSize(find.byKey(const Key('detail-back'))),
|
||||
const Size(36, 36),
|
||||
);
|
||||
expect(
|
||||
tester
|
||||
.widget<Icon>(
|
||||
find.descendant(
|
||||
of: find.byKey(const Key('detail-back')),
|
||||
matching: find.byType(Icon),
|
||||
),
|
||||
)
|
||||
.size,
|
||||
18,
|
||||
);
|
||||
expect(find.byKey(const Key('detail-cta')), findsOneWidget);
|
||||
expect(tester.getSize(find.byKey(const Key('detail-cta'))).height, 40);
|
||||
expect(find.byKey(const Key('detail-episode-chip-1')), findsOneWidget);
|
||||
expect(find.byKey(const Key('detail-episode-chip-8')), findsOneWidget);
|
||||
|
||||
final synopsis = tester.widget<Text>(
|
||||
find.byKey(const Key('detail-synopsis')),
|
||||
);
|
||||
expect(synopsis.style?.fontSize, 11);
|
||||
expect(synopsis.style?.height, 1.6);
|
||||
|
||||
await tester.tap(find.byKey(const Key('detail-more')));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byKey(const Key('detail-favorite')), findsOneWidget);
|
||||
expect(find.byKey(const Key('detail-download')), findsOneWidget);
|
||||
expect(find.byKey(const Key('detail-share')), findsOneWidget);
|
||||
expect(find.byKey(const Key('detail-report')), findsOneWidget);
|
||||
expect(tester.takeException(), isNull);
|
||||
});
|
||||
|
||||
testWidgets('should_fit_compact_viewport_when_detail_scrolls', (
|
||||
tester,
|
||||
) async {
|
||||
tester.view.physicalSize = const Size(320, 568);
|
||||
tester.view.devicePixelRatio = 1;
|
||||
addTearDown(tester.view.resetPhysicalSize);
|
||||
addTearDown(tester.view.resetDevicePixelRatio);
|
||||
|
||||
await tester.pumpWidget(_host(_detailDrama()));
|
||||
await tester.pumpAndSettle();
|
||||
final grid = tester.widget<GridView>(
|
||||
find.byKey(const Key('detail-episode-chips')),
|
||||
);
|
||||
expect(
|
||||
(grid.gridDelegate as SliverGridDelegateWithFixedCrossAxisCount)
|
||||
.crossAxisCount,
|
||||
6,
|
||||
);
|
||||
await tester.drag(
|
||||
find.byKey(const Key('detail-scroll')),
|
||||
const Offset(0, -520),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byKey(const Key('detail-episode-chip-8')), findsOneWidget);
|
||||
expect(tester.takeException(), isNull);
|
||||
});
|
||||
|
||||
testWidgets('should_render_sorted_six_column_grid_and_open_original_index', (
|
||||
tester,
|
||||
) async {
|
||||
tester.view.physicalSize = const Size(390, 844);
|
||||
tester.view.devicePixelRatio = 1;
|
||||
addTearDown(tester.view.resetPhysicalSize);
|
||||
addTearDown(tester.view.resetDevicePixelRatio);
|
||||
|
||||
await tester.pumpWidget(_host(_detailDrama(count: 80)));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final grid = tester.widget<GridView>(
|
||||
find.byKey(const Key('detail-episode-chips')),
|
||||
);
|
||||
final delegate =
|
||||
grid.gridDelegate as SliverGridDelegateWithFixedCrossAxisCount;
|
||||
expect(delegate.crossAxisCount, 6);
|
||||
expect(delegate.mainAxisSpacing, 8);
|
||||
expect(delegate.crossAxisSpacing, 8);
|
||||
expect(delegate.childAspectRatio, closeTo(1.35, 0.001));
|
||||
|
||||
final chip1 = find.byKey(const Key('detail-episode-chip-1'));
|
||||
final chip2 = find.byKey(const Key('detail-episode-chip-2'));
|
||||
final chip6 = find.byKey(const Key('detail-episode-chip-6'));
|
||||
final chip7 = find.byKey(const Key('detail-episode-chip-7'));
|
||||
expect(tester.getTopLeft(chip1).dy, tester.getTopLeft(chip6).dy);
|
||||
expect(
|
||||
tester.getTopLeft(chip7).dy,
|
||||
greaterThan(tester.getTopLeft(chip1).dy),
|
||||
);
|
||||
expect(tester.getTopLeft(chip1).dx, lessThan(tester.getTopLeft(chip2).dx));
|
||||
expect(tester.getSize(chip1), tester.getSize(chip2));
|
||||
|
||||
await tester.drag(
|
||||
find.byKey(const Key('detail-scroll')),
|
||||
const Offset(0, -420),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
final chip12 = find.byKey(const Key('detail-episode-chip-12'));
|
||||
expect(chip12, findsOneWidget);
|
||||
await tester.tap(chip12);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final player = tester.widget<PlayerPage>(find.byType(PlayerPage));
|
||||
expect(player.initialIndex, 11);
|
||||
});
|
||||
|
||||
testWidgets('should_sort_episode_chips_ascending_by_number', (tester) async {
|
||||
tester.view.physicalSize = const Size(390, 844);
|
||||
tester.view.devicePixelRatio = 1;
|
||||
addTearDown(tester.view.resetPhysicalSize);
|
||||
addTearDown(tester.view.resetDevicePixelRatio);
|
||||
|
||||
await tester.pumpWidget(_host(_detailDrama(count: 80, descending: true)));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final chip1 = find.byKey(const Key('detail-episode-chip-1'));
|
||||
final chip2 = find.byKey(const Key('detail-episode-chip-2'));
|
||||
final chip6 = find.byKey(const Key('detail-episode-chip-6'));
|
||||
final chip7 = find.byKey(const Key('detail-episode-chip-7'));
|
||||
expect(tester.getTopLeft(chip1).dy, tester.getTopLeft(chip6).dy);
|
||||
expect(tester.getTopLeft(chip1).dx, lessThan(tester.getTopLeft(chip2).dx));
|
||||
expect(
|
||||
tester.getTopLeft(chip7).dy,
|
||||
greaterThan(tester.getTopLeft(chip1).dy),
|
||||
);
|
||||
expect(tester.getSize(chip1), tester.getSize(chip2));
|
||||
});
|
||||
}
|
||||
|
||||
Widget _host(Drama drama) {
|
||||
final catalog = FakeCatalogRepository(dramas: [drama]);
|
||||
final interactions = FakeInteractionRepository();
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
Provider<WatchHistoryRepository>.value(
|
||||
value: InMemoryWatchHistoryRepository(),
|
||||
),
|
||||
Provider<PlaybackRepository>.value(value: FakePlaybackRepository()),
|
||||
Provider<PlayerFactory>.value(value: createWidgetPlayer),
|
||||
Provider(create: (_) => PlaybackCoordinator()),
|
||||
Provider<InteractionRepository>.value(value: interactions),
|
||||
Provider<CommentRepository>.value(value: FakeCommentRepository()),
|
||||
Provider<Haptics>.value(value: FakeHaptics()),
|
||||
ChangeNotifierProvider(
|
||||
create: (_) => FavoriteController(InMemoryFavoriteRepository()),
|
||||
),
|
||||
ChangeNotifierProvider(
|
||||
create: (_) => InteractionController(interactions),
|
||||
),
|
||||
ChangeNotifierProvider(create: (_) => CatalogController(catalog)..load()),
|
||||
],
|
||||
child: MaterialApp(
|
||||
theme: AppTheme.dark(),
|
||||
locale: const Locale('en'),
|
||||
supportedLocales: AppLocalizations.supportedLocales,
|
||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||
home: DramaDetailPage(drama: drama),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Drama _detailDrama({int count = 8, bool descending = false}) {
|
||||
final numbers = List<int>.generate(
|
||||
count,
|
||||
(index) => descending ? count - index : index + 1,
|
||||
);
|
||||
return Drama(
|
||||
id: 'detail-k25',
|
||||
title: 'Detail K25',
|
||||
synopsis:
|
||||
'She agreed to marry a mysterious stranger to save her family, '
|
||||
'until she discovered his secret identity and the city he controls.',
|
||||
posterUrl: '/files/detail-k25.png',
|
||||
genre: 'Urban Romance',
|
||||
category: 'Romance',
|
||||
totalEpisodes: count,
|
||||
viewCount: 4800000,
|
||||
detailLoaded: true,
|
||||
episodes: [
|
||||
for (final number in numbers)
|
||||
Episode(
|
||||
id: 'detail-k25-$number',
|
||||
number: number,
|
||||
title: 'Episode $number',
|
||||
isFree: number == 1,
|
||||
durationSec: 135,
|
||||
locked: number > 1,
|
||||
videoUrl: number == 1 ? '/files/detail-k25-1.mp4' : '',
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
@@ -18,17 +18,20 @@ void main() {
|
||||
|
||||
final dramas = [_drama('signal'), _drama('city')];
|
||||
|
||||
test('should_make_first_catalog_entry_the_current_drama_when_catalog_loads', () {
|
||||
final logic = HomeLogic(dramas);
|
||||
test(
|
||||
'should_make_first_catalog_entry_the_current_drama_when_catalog_loads',
|
||||
() {
|
||||
final logic = HomeLogic(dramas);
|
||||
|
||||
expect(logic.currentDrama.id, 'signal');
|
||||
expect(logic.tab, 1);
|
||||
expect(logic.mySection, 0);
|
||||
expect(logic.drawerOpen, isFalse);
|
||||
expect(logic.profile, isFalse);
|
||||
expect(logic.videoImmersive, isFalse);
|
||||
logic.dispose();
|
||||
});
|
||||
expect(logic.currentDrama.id, 'signal');
|
||||
expect(logic.tab, 0);
|
||||
expect(logic.mySection, 0);
|
||||
expect(logic.drawerOpen, isFalse);
|
||||
expect(logic.profile, isFalse);
|
||||
expect(logic.videoImmersive, isFalse);
|
||||
logic.dispose();
|
||||
},
|
||||
);
|
||||
|
||||
test('should_not_build_shell_when_catalog_is_empty', () {
|
||||
expect(() => HomeLogic(const []), throwsStateError);
|
||||
@@ -82,35 +85,39 @@ void main() {
|
||||
logic.dispose();
|
||||
});
|
||||
|
||||
test('should_differ_on_profile_flag_when_open_profile_and_open_library_are_used', () {
|
||||
final logic = HomeLogic(dramas);
|
||||
test(
|
||||
'should_differ_on_profile_flag_when_open_profile_and_open_library_are_used',
|
||||
() {
|
||||
final logic = HomeLogic(dramas);
|
||||
|
||||
logic.openProfile();
|
||||
expect(logic.profile, isTrue);
|
||||
expect(logic.tab, 2);
|
||||
expect(logic.mySection, 0);
|
||||
expect(logic.sectionRequest, 1);
|
||||
logic.openProfile();
|
||||
expect(logic.profile, isTrue);
|
||||
expect(logic.tab, 2);
|
||||
expect(logic.mySection, 0);
|
||||
expect(logic.sectionRequest, 1);
|
||||
|
||||
logic.openLibrary(section: 1);
|
||||
expect(logic.profile, isFalse);
|
||||
expect(logic.mySection, 1);
|
||||
expect(logic.sectionRequest, 2);
|
||||
logic.openLibrary(section: 1);
|
||||
expect(logic.profile, isFalse);
|
||||
expect(logic.mySection, 1);
|
||||
expect(logic.sectionRequest, 2);
|
||||
|
||||
logic.openLibrary();
|
||||
expect(logic.profile, isFalse);
|
||||
expect(logic.mySection, 1);
|
||||
expect(logic.sectionRequest, 3);
|
||||
logic.dispose();
|
||||
});
|
||||
logic.openLibrary();
|
||||
expect(logic.profile, isFalse);
|
||||
expect(logic.mySection, 1);
|
||||
expect(logic.sectionRequest, 3);
|
||||
logic.dispose();
|
||||
},
|
||||
);
|
||||
|
||||
test('should_return_home_and_open_drawer_when_system_back_is_pressed', () {
|
||||
test('should_return_to_discover_and_handle_immersive_back', () {
|
||||
final logic = HomeLogic(dramas);
|
||||
|
||||
// Home is the launch tab; the first back press lands on Discover.
|
||||
logic.onSystemBack();
|
||||
expect(logic.tab, 1);
|
||||
logic.onSystemBack();
|
||||
expect(logic.drawerOpen, isTrue);
|
||||
expect(logic.tab, 1);
|
||||
expect(logic.backRequest, 0);
|
||||
logic.onDrawerChanged(false);
|
||||
|
||||
logic.select(0);
|
||||
logic.onSystemBack();
|
||||
@@ -123,30 +130,25 @@ void main() {
|
||||
expect(logic.backRequest, 1);
|
||||
expect(logic.tab, 0);
|
||||
|
||||
logic.onDrawerChanged(true);
|
||||
logic.onSystemBack();
|
||||
expect(logic.backRequest, 1);
|
||||
|
||||
logic.onDrawerChanged(false);
|
||||
logic.onImmersiveChanged(false);
|
||||
logic.onSystemBack();
|
||||
expect(logic.tab, 1);
|
||||
logic.dispose();
|
||||
});
|
||||
|
||||
test('should_notify_only_on_actual_change_when_drawer_state_is_set', () {
|
||||
test('should_notify_only_on_actual_change_when_menu_state_is_set', () {
|
||||
final logic = HomeLogic(dramas);
|
||||
var notifications = 0;
|
||||
logic.addListener(() => notifications++);
|
||||
|
||||
logic.onDrawerChanged(false);
|
||||
logic.setMenuOpen(false);
|
||||
expect(notifications, 0);
|
||||
|
||||
logic.onDrawerChanged(true);
|
||||
logic.setMenuOpen(true);
|
||||
expect(logic.drawerOpen, isTrue);
|
||||
expect(notifications, 1);
|
||||
|
||||
logic.onDrawerChanged(true);
|
||||
logic.setMenuOpen(true);
|
||||
expect(notifications, 1);
|
||||
logic.dispose();
|
||||
});
|
||||
@@ -190,7 +192,9 @@ void main() {
|
||||
expect(notifications, 0);
|
||||
});
|
||||
|
||||
testWidgets('should_map_onto_root_tabs_when_discover_actions_fire', (tester) async {
|
||||
testWidgets('should_map_onto_root_tabs_when_discover_actions_fire', (
|
||||
tester,
|
||||
) async {
|
||||
final logic = HomeLogic(dramas);
|
||||
late BuildContext context;
|
||||
await tester.pumpWidget(
|
||||
|
||||
@@ -18,9 +18,8 @@ import '../support/widget_player.dart';
|
||||
|
||||
const _keys = [
|
||||
Key('home-tabs-bar'),
|
||||
Key('tab-discover'),
|
||||
Key('tab-home'),
|
||||
Key('tab-my-list'),
|
||||
Key('tab-discover'),
|
||||
Key('tab-my'),
|
||||
];
|
||||
|
||||
@@ -34,7 +33,7 @@ void main() {
|
||||
});
|
||||
});
|
||||
|
||||
testWidgets('should_theme_four_tabs_and_switch_selected_state_when_tapped', (
|
||||
testWidgets('should_theme_three_tabs_and_switch_selected_state_when_tapped', (
|
||||
tester,
|
||||
) async {
|
||||
final haptics = FakeHaptics();
|
||||
@@ -52,17 +51,15 @@ void main() {
|
||||
final bar = tester.widget<Container>(barFinder);
|
||||
final decoration = bar.decoration as BoxDecoration;
|
||||
final border = decoration.border as Border;
|
||||
final context = tester.element(barFinder);
|
||||
expect(decoration.color, AppColors.bar);
|
||||
expect(border.top.color, Theme.of(context).colorScheme.outlineVariant);
|
||||
expect(border.top.color.computeLuminance(), lessThan(0.2));
|
||||
expect(decoration.color, AppColors.bar.withValues(alpha: 0.95));
|
||||
expect(border.top.color, AppColors.outlineVariantDark);
|
||||
expect(border.top.color, isNot(Colors.white));
|
||||
expect(
|
||||
tester
|
||||
.widget<AnimatedContainer>(
|
||||
.widget<AnimatedScale>(
|
||||
find.descendant(
|
||||
of: find.byKey(const Key('tab-home')),
|
||||
matching: find.byType(AnimatedContainer),
|
||||
matching: find.byType(AnimatedScale),
|
||||
),
|
||||
)
|
||||
.duration,
|
||||
@@ -71,7 +68,7 @@ void main() {
|
||||
expect(
|
||||
find.descendant(
|
||||
of: find.byKey(const Key('tab-home')),
|
||||
matching: find.byIcon(Icons.movie_rounded),
|
||||
matching: find.byIcon(Icons.play_circle_fill_rounded),
|
||||
),
|
||||
findsOneWidget,
|
||||
);
|
||||
@@ -85,29 +82,42 @@ void main() {
|
||||
expect(
|
||||
find.descendant(
|
||||
of: find.byKey(const Key('tab-discover')),
|
||||
matching: find.byIcon(Icons.home_rounded),
|
||||
matching: find.byIcon(Icons.explore_rounded),
|
||||
),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(
|
||||
find.descendant(
|
||||
of: find.byKey(const Key('tab-home')),
|
||||
matching: find.byIcon(Icons.movie_outlined),
|
||||
matching: find.byIcon(Icons.play_circle_outline_rounded),
|
||||
),
|
||||
findsOneWidget,
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('should_hide_themed_navigation_when_immersive_mode_is_enabled', (
|
||||
tester,
|
||||
) async {
|
||||
testWidgets('should_map_three_tabs_to_home_discover_and_me', (tester) async {
|
||||
await _pumpApp(tester);
|
||||
await tester.tap(find.byTooltip('Clear screen'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
for (final key in _keys) {
|
||||
expect(find.byKey(key), findsNothing);
|
||||
}
|
||||
expect(find.byKey(const Key('tab-home')), findsOneWidget);
|
||||
expect(find.byKey(const Key('tab-discover')), findsOneWidget);
|
||||
expect(find.byKey(const Key('tab-my')), findsOneWidget);
|
||||
expect(find.byKey(const Key('home-feed-info-card')), findsOneWidget);
|
||||
|
||||
await tester.tap(find.byKey(const Key('tab-discover')));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byKey(const Key('home-all-dramas-grid')), findsOneWidget);
|
||||
|
||||
await tester.tap(find.byKey(const Key('tab-my')));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('Viewer'), findsOneWidget);
|
||||
expect(
|
||||
find.byKey(const Key('mine-library-tab-0'), skipOffstage: false),
|
||||
findsOneWidget,
|
||||
);
|
||||
|
||||
await tester.tap(find.byKey(const Key('tab-home')));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byKey(const Key('home-feed-info-card')), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('should_not_haptic_when_ordinary_list_item_is_opened', (
|
||||
@@ -119,6 +129,8 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
haptics.reset();
|
||||
|
||||
await tester.drag(find.byType(ListView), const Offset(0, -700));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.text('App Language'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
// Author: fruit.com.cn
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:shared_preferences_platform_interface/in_memory_shared_preferences_async.dart';
|
||||
import 'package:shared_preferences_platform_interface/shared_preferences_async_platform_interface.dart';
|
||||
|
||||
import 'package:fruitshorts/app.dart';
|
||||
import 'package:fruitshorts/core/data/models/drama.dart';
|
||||
import 'package:fruitshorts/core/data/repositories/favorite_repository.dart';
|
||||
import 'package:fruitshorts/core/data/repositories/playback_repository.dart';
|
||||
import 'package:fruitshorts/core/data/repositories/watch_history_repository.dart';
|
||||
import 'package:fruitshorts/core/theme/app_theme.dart';
|
||||
import 'package:fruitshorts/l10n/app_localizations.dart';
|
||||
import 'package:fruitshorts/pages/player/widgets/home_feed_overlay.dart';
|
||||
|
||||
import '../support/fake_catalog.dart';
|
||||
import '../support/fake_category.dart';
|
||||
import '../support/fake_haptics.dart';
|
||||
import '../support/fake_interaction_repositories.dart';
|
||||
import '../support/fake_notice_repository.dart';
|
||||
import '../support/widget_player.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('should_render_preview_home_card_without_hot_or_follow_avatar', (
|
||||
tester,
|
||||
) async {
|
||||
SharedPreferencesAsyncPlatform.instance =
|
||||
InMemorySharedPreferencesAsync.empty();
|
||||
tester.view.physicalSize = const Size(390, 844);
|
||||
tester.view.devicePixelRatio = 1;
|
||||
addTearDown(tester.view.resetPhysicalSize);
|
||||
addTearDown(tester.view.resetDevicePixelRatio);
|
||||
|
||||
final catalog = FakeCatalogRepository();
|
||||
await tester.pumpWidget(
|
||||
LumaDramaApp(
|
||||
playerFactory: createWidgetPlayer,
|
||||
catalogRepository: catalog,
|
||||
categoryRepository: FakeCategoryRepository(catalog: catalog),
|
||||
watchHistoryRepository: InMemoryWatchHistoryRepository(),
|
||||
favoriteRepository: InMemoryFavoriteRepository(cards: catalog.dramas),
|
||||
playbackRepository: FakePlaybackRepository(),
|
||||
commentRepository: FakeCommentRepository(),
|
||||
interactionRepository: FakeInteractionRepository(),
|
||||
noticeRepository: FakeNoticeRepository(),
|
||||
haptics: FakeHaptics(),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(const Key('tab-home')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byKey(const Key('home-feed-title')), findsOneWidget);
|
||||
expect(find.byKey(const Key('home-feed-info-card')), findsOneWidget);
|
||||
expect(find.byKey(const Key('home-feed-episode')), findsOneWidget);
|
||||
final cardRect = tester.getRect(
|
||||
find.byKey(const Key('home-feed-info-card')),
|
||||
);
|
||||
final episodeRect = tester.getRect(
|
||||
find.byKey(const Key('home-feed-episode')),
|
||||
);
|
||||
expect(episodeRect.left, lessThan(cardRect.center.dx));
|
||||
final railCenter = tester.getCenter(find.byKey(const Key('rail-like')));
|
||||
final railBottom = tester.getBottomLeft(find.byKey(const Key('rail-save')));
|
||||
expect(railCenter.dy, greaterThan(844 * 0.4));
|
||||
expect(railBottom.dy, lessThan(cardRect.top));
|
||||
expect(find.byKey(const Key('home-feed-follow-series')), findsOneWidget);
|
||||
expect(find.byKey(const Key('home-feed-episodes')), findsOneWidget);
|
||||
for (final key in const [Key('home-feed-search'), Key('home-feed-more')]) {
|
||||
expect(tester.getSize(find.byKey(key)), const Size(36, 36));
|
||||
expect(
|
||||
tester
|
||||
.widget<Icon>(
|
||||
find.descendant(of: find.byKey(key), matching: find.byType(Icon)),
|
||||
)
|
||||
.size,
|
||||
18,
|
||||
);
|
||||
}
|
||||
expect(
|
||||
tester.getSize(find.byKey(const Key('home-feed-follow-series'))).height,
|
||||
34,
|
||||
);
|
||||
expect(find.text('HOT'), findsNothing);
|
||||
expect(find.textContaining('Season'), findsNothing);
|
||||
expect(find.byKey(const Key('home-feed-follow')), findsNothing);
|
||||
expect(tester.takeException(), isNull);
|
||||
});
|
||||
|
||||
testWidgets('should_use_episode_title_then_drama_title_as_fallback', (
|
||||
tester,
|
||||
) async {
|
||||
Future<void> pumpEpisode(Episode episode) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: AppTheme.dark(),
|
||||
locale: const Locale('en'),
|
||||
supportedLocales: AppLocalizations.supportedLocales,
|
||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||
home: Builder(
|
||||
builder: (context) => Scaffold(
|
||||
body: HomeFeedOverlay(
|
||||
l10n: AppLocalizations.of(context)!,
|
||||
drama: _drama,
|
||||
episode: episode,
|
||||
liked: false,
|
||||
saved: false,
|
||||
onLike: () {},
|
||||
onSave: () {},
|
||||
onComments: () {},
|
||||
onShare: () {},
|
||||
onEpisodes: () {},
|
||||
onDownload: () {},
|
||||
onClear: () {},
|
||||
onSearch: () {},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
}
|
||||
|
||||
await pumpEpisode(
|
||||
const Episode(
|
||||
id: 'featured',
|
||||
number: 2,
|
||||
title: 'Midnight Contract',
|
||||
isFree: true,
|
||||
),
|
||||
);
|
||||
expect(
|
||||
tester
|
||||
.widget<Text>(find.byKey(const Key('home-feed-episode-title')))
|
||||
.data,
|
||||
'Midnight Contract',
|
||||
);
|
||||
|
||||
await pumpEpisode(
|
||||
const Episode(id: 'fallback', number: 2, title: '', isFree: true),
|
||||
);
|
||||
expect(
|
||||
tester
|
||||
.widget<Text>(find.byKey(const Key('home-feed-episode-title')))
|
||||
.data,
|
||||
'Fallback Drama',
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
const _drama = Drama(
|
||||
id: 'featured-drama',
|
||||
title: 'Fallback Drama',
|
||||
synopsis: 'synopsis',
|
||||
posterUrl: '',
|
||||
totalEpisodes: 8,
|
||||
);
|
||||
@@ -0,0 +1,116 @@
|
||||
// Author: fruit.com.cn
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:shared_preferences_platform_interface/in_memory_shared_preferences_async.dart';
|
||||
import 'package:shared_preferences_platform_interface/shared_preferences_async_platform_interface.dart';
|
||||
|
||||
import 'package:fruitshorts/app.dart';
|
||||
import 'package:fruitshorts/core/data/models/watch_progress.dart';
|
||||
import 'package:fruitshorts/core/data/repositories/favorite_repository.dart';
|
||||
import 'package:fruitshorts/core/data/repositories/playback_repository.dart';
|
||||
import 'package:fruitshorts/core/data/repositories/watch_history_repository.dart';
|
||||
import 'package:fruitshorts/core/theme/app_colors.dart';
|
||||
|
||||
import '../support/fake_catalog.dart';
|
||||
import '../support/fake_category.dart';
|
||||
import '../support/fake_haptics.dart';
|
||||
import '../support/fake_interaction_repositories.dart';
|
||||
import '../support/fake_notice_repository.dart';
|
||||
import '../support/widget_player.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('should_render_me_user_wallet_continue_and_language_rows', (
|
||||
tester,
|
||||
) async {
|
||||
SharedPreferencesAsyncPlatform.instance =
|
||||
InMemorySharedPreferencesAsync.empty();
|
||||
tester.view.physicalSize = const Size(390, 844);
|
||||
tester.view.devicePixelRatio = 1;
|
||||
addTearDown(tester.view.resetPhysicalSize);
|
||||
addTearDown(tester.view.resetDevicePixelRatio);
|
||||
|
||||
final catalog = FakeCatalogRepository();
|
||||
await tester.pumpWidget(
|
||||
LumaDramaApp(
|
||||
playerFactory: createWidgetPlayer,
|
||||
catalogRepository: catalog,
|
||||
categoryRepository: FakeCategoryRepository(catalog: catalog),
|
||||
watchHistoryRepository: InMemoryWatchHistoryRepository(
|
||||
seed: const [
|
||||
WatchProgress(
|
||||
dramaId: 'city-lights-demo',
|
||||
episodeId: 'city-lights-demo-1',
|
||||
position: Duration(minutes: 2),
|
||||
duration: Duration(minutes: 5),
|
||||
),
|
||||
],
|
||||
),
|
||||
favoriteRepository: InMemoryFavoriteRepository(cards: catalog.dramas),
|
||||
playbackRepository: FakePlaybackRepository(),
|
||||
commentRepository: FakeCommentRepository(),
|
||||
interactionRepository: FakeInteractionRepository(),
|
||||
noticeRepository: FakeNoticeRepository(),
|
||||
haptics: FakeHaptics(),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(const Key('tab-my')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byKey(const Key('mine-user-row')), findsOneWidget);
|
||||
expect(find.byKey(const Key('mine-wallet')), findsOneWidget);
|
||||
for (final key in const [Key('mine-search-button'), Key('mine-avatar')]) {
|
||||
expect(tester.getSize(find.byKey(key)), const Size(36, 36));
|
||||
expect(
|
||||
tester
|
||||
.widget<Icon>(
|
||||
find.descendant(of: find.byKey(key), matching: find.byType(Icon)),
|
||||
)
|
||||
.size,
|
||||
18,
|
||||
);
|
||||
}
|
||||
expect(find.byKey(const Key('mine-continue-watching')), findsOneWidget);
|
||||
expect(find.byKey(const Key('mine-language')), findsOneWidget);
|
||||
expect(find.byKey(const Key('mine-library-tab-0')), findsOneWidget);
|
||||
expect(find.byKey(const Key('mine-library-tab-1')), findsOneWidget);
|
||||
expect(find.byKey(const Key('mine-library-tab-2')), findsOneWidget);
|
||||
final tab0 = find.byKey(const Key('mine-library-tab-0'));
|
||||
final tab1 = find.byKey(const Key('mine-library-tab-1'));
|
||||
final tab2 = find.byKey(const Key('mine-library-tab-2'));
|
||||
expect(tester.getTopLeft(tab0).dx, lessThan(tester.getTopLeft(tab1).dx));
|
||||
expect(tester.getTopLeft(tab1).dx, lessThan(tester.getTopLeft(tab2).dx));
|
||||
expect(
|
||||
tester.getTopLeft(tab1).dx - tester.getTopRight(tab0).dx,
|
||||
closeTo(20, 1),
|
||||
);
|
||||
expect(
|
||||
(tester
|
||||
.widget<AnimatedContainer>(
|
||||
find.descendant(
|
||||
of: tab0,
|
||||
matching: find.byType(AnimatedContainer),
|
||||
),
|
||||
)
|
||||
.decoration
|
||||
as BoxDecoration)
|
||||
.color,
|
||||
AppColors.blue,
|
||||
);
|
||||
expect(
|
||||
(tester
|
||||
.widget<AnimatedContainer>(
|
||||
find.descendant(
|
||||
of: tab1,
|
||||
matching: find.byType(AnimatedContainer),
|
||||
),
|
||||
)
|
||||
.decoration
|
||||
as BoxDecoration)
|
||||
.color,
|
||||
Colors.transparent,
|
||||
);
|
||||
expect(tester.takeException(), isNull);
|
||||
});
|
||||
}
|
||||
@@ -46,6 +46,8 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(const Key('tab-my')));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.drag(find.byType(ListView), const Offset(0, -520));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byKey(const Key('mine-notices')), findsOneWidget);
|
||||
await tester.tap(find.byKey(const Key('mine-notices')));
|
||||
|
||||
@@ -56,11 +56,13 @@ void main() {
|
||||
await tester.pump();
|
||||
expect(started, 1);
|
||||
expect(target, isNull);
|
||||
expect(find.textContaining('/ 00:12'), findsOneWidget);
|
||||
await gesture.up();
|
||||
await tester.pumpAndSettle();
|
||||
expect(target, isNotNull);
|
||||
expect(target!, greaterThan(const Duration(seconds: 3)));
|
||||
expect(target!, lessThan(const Duration(seconds: 12)));
|
||||
expect(find.textContaining('/ 00:12'), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('should_show_time_only_while_dragging_when_seek_bar_is_compact', (
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
// Author: fruit.com.cn
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:fruitshorts/pages/player/widgets/player_center_toggle.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('should_use_one_shared_52px_center_toggle_style', (tester) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Scaffold(
|
||||
body: Row(
|
||||
children: [
|
||||
PlayerCenterToggle(
|
||||
key: const Key('test-center-toggle-a'),
|
||||
playing: false,
|
||||
onTap: () {},
|
||||
),
|
||||
PlayerCenterToggle(
|
||||
key: const Key('player-play-toggle'),
|
||||
playing: true,
|
||||
onTap: () {},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
for (final key in const [
|
||||
Key('test-center-toggle-a'),
|
||||
Key('player-play-toggle'),
|
||||
]) {
|
||||
expect(tester.getSize(find.byKey(key)), const Size(52, 52));
|
||||
final container = tester.widget<Container>(
|
||||
find.descendant(of: find.byKey(key), matching: find.byType(Container)),
|
||||
);
|
||||
final decoration = container.decoration! as BoxDecoration;
|
||||
expect(decoration.color, const Color(0x80000000));
|
||||
expect(decoration.shape, BoxShape.circle);
|
||||
final icon = tester.widget<Icon>(
|
||||
find.descendant(of: find.byKey(key), matching: find.byType(Icon)),
|
||||
);
|
||||
expect(icon.size, 26);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,525 @@
|
||||
// Author: fruit.com.cn
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:shared_preferences_platform_interface/in_memory_shared_preferences_async.dart';
|
||||
import 'package:shared_preferences_platform_interface/shared_preferences_async_platform_interface.dart';
|
||||
|
||||
import 'package:fruitshorts/app.dart';
|
||||
import 'package:fruitshorts/core/data/repositories/favorite_repository.dart';
|
||||
import 'package:fruitshorts/core/data/repositories/playback_repository.dart';
|
||||
import 'package:fruitshorts/core/data/repositories/watch_history_repository.dart';
|
||||
import 'package:fruitshorts/pages/player/widgets/player_center_toggle.dart';
|
||||
import 'package:fruitshorts/pages/player/widgets/seek_progress_bar.dart';
|
||||
|
||||
import '../support/fake_catalog.dart';
|
||||
import '../support/fake_category.dart';
|
||||
import '../support/fake_haptics.dart';
|
||||
import '../support/fake_interaction_repositories.dart';
|
||||
import '../support/fake_notice_repository.dart';
|
||||
import '../support/widget_player.dart';
|
||||
|
||||
void main() {
|
||||
setUp(() {
|
||||
SharedPreferencesAsyncPlatform.instance =
|
||||
InMemorySharedPreferencesAsync.empty();
|
||||
});
|
||||
|
||||
testWidgets('should_open_fullscreen_overlay_from_discover_card', (
|
||||
tester,
|
||||
) async {
|
||||
await _pumpApp(tester);
|
||||
await tester.tap(find.byKey(const Key('tab-discover')));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(const Key('home-drama-card-city-lights-demo')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
_expectFullscreenOverlay(tester);
|
||||
expect(find.byType(PageView), findsOneWidget);
|
||||
await tester.tap(find.byKey(const Key('player-more')));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byKey(const Key('player-more-download')), findsOneWidget);
|
||||
expect(find.byKey(const Key('player-more-pip')), findsOneWidget);
|
||||
expect(tester.takeException(), isNull);
|
||||
});
|
||||
|
||||
testWidgets('should_open_fullscreen_overlay_from_detail_cta_and_chip', (
|
||||
tester,
|
||||
) async {
|
||||
await _pumpApp(tester);
|
||||
await tester.binding.handlePopRoute();
|
||||
await tester.pumpAndSettle();
|
||||
await tester.binding.handlePopRoute();
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(const Key('drawer-open-series')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.tap(find.byKey(const Key('detail-cta')));
|
||||
await tester.pumpAndSettle();
|
||||
_expectFullscreenOverlay(tester);
|
||||
|
||||
await tester.binding.handlePopRoute();
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(const Key('detail-episode-chip-2')));
|
||||
await tester.pumpAndSettle();
|
||||
_expectFullscreenOverlay(tester);
|
||||
expect(
|
||||
tester.widget<Text>(find.byKey(const Key('player-title'))).data,
|
||||
contains('Episode 2'),
|
||||
);
|
||||
expect(tester.takeException(), isNull);
|
||||
});
|
||||
|
||||
testWidgets('should_show_center_toggle_only_when_paused', (tester) async {
|
||||
await _pumpApp(tester);
|
||||
await tester.binding.handlePopRoute();
|
||||
await tester.pumpAndSettle();
|
||||
await tester.binding.handlePopRoute();
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(const Key('drawer-open-series')));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(const Key('detail-cta')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byKey(const Key('player-play-toggle')), findsNothing);
|
||||
|
||||
await tester.tapAt(const Offset(80, 300));
|
||||
await tester.pump();
|
||||
expect(find.byKey(const Key('player-play-toggle')), findsOneWidget);
|
||||
expect(
|
||||
tester
|
||||
.widget<PlayerCenterToggle>(
|
||||
find.byKey(const Key('player-play-toggle')),
|
||||
)
|
||||
.playing,
|
||||
isFalse,
|
||||
);
|
||||
expect(
|
||||
find.descendant(
|
||||
of: find.byKey(const Key('player-play-toggle')),
|
||||
matching: find.byIcon(Icons.play_arrow_rounded),
|
||||
),
|
||||
findsOneWidget,
|
||||
);
|
||||
|
||||
await tester.tap(find.byKey(const Key('player-play-toggle')));
|
||||
await tester.pump();
|
||||
expect(find.byKey(const Key('player-play-toggle')), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('should_keep_controls_visible_until_clear_screen_is_tapped', (
|
||||
tester,
|
||||
) async {
|
||||
await _pumpApp(tester);
|
||||
await tester.binding.handlePopRoute();
|
||||
await tester.pumpAndSettle();
|
||||
await tester.binding.handlePopRoute();
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(const Key('drawer-open-series')));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(const Key('detail-cta')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byKey(const Key('player-controls-top')), findsOneWidget);
|
||||
expect(find.byKey(const Key('player-controls-bottom')), findsOneWidget);
|
||||
expect(find.byType(PlayerCenterToggle), findsNothing);
|
||||
|
||||
await tester.tapAt(const Offset(80, 300));
|
||||
await tester.pump();
|
||||
expect(find.byType(PlayerCenterToggle), findsOneWidget);
|
||||
expect(
|
||||
tester
|
||||
.widget<PlayerCenterToggle>(
|
||||
find.byKey(const Key('player-play-toggle')),
|
||||
)
|
||||
.playing,
|
||||
isFalse,
|
||||
);
|
||||
|
||||
await tester.pump(const Duration(seconds: 5));
|
||||
await tester.pump();
|
||||
|
||||
expect(find.byKey(const Key('player-controls-top')), findsOneWidget);
|
||||
expect(find.byKey(const Key('player-controls-bottom')), findsOneWidget);
|
||||
expect(find.byType(PlayerCenterToggle), findsOneWidget);
|
||||
|
||||
await tester.tap(find.byKey(const Key('player-clear-screen')));
|
||||
await tester.pump();
|
||||
|
||||
expect(find.byKey(const Key('player-controls-top')), findsNothing);
|
||||
expect(find.byKey(const Key('player-controls-bottom')), findsNothing);
|
||||
expect(find.byType(PlayerCenterToggle), findsOneWidget);
|
||||
expect(
|
||||
tester
|
||||
.widget<PlayerCenterToggle>(
|
||||
find.byKey(const Key('player-play-toggle')),
|
||||
)
|
||||
.playing,
|
||||
isFalse,
|
||||
);
|
||||
expect(find.byKey(const Key('player-video-tap')), findsOneWidget);
|
||||
expect(find.byKey(const Key('player-exit-clear-screen')), findsOneWidget);
|
||||
expect(
|
||||
tester.getSize(find.byKey(const Key('player-exit-clear-screen'))),
|
||||
const Size(36, 36),
|
||||
);
|
||||
|
||||
await tester.tapAt(const Offset(80, 300));
|
||||
await tester.pump();
|
||||
expect(find.byKey(const Key('player-controls-top')), findsNothing);
|
||||
expect(find.byKey(const Key('player-exit-clear-screen')), findsOneWidget);
|
||||
expect(find.byType(PlayerCenterToggle), findsNothing);
|
||||
|
||||
await tester.tapAt(const Offset(80, 300));
|
||||
await tester.pump();
|
||||
expect(find.byKey(const Key('player-controls-top')), findsNothing);
|
||||
expect(find.byKey(const Key('player-exit-clear-screen')), findsOneWidget);
|
||||
expect(
|
||||
tester
|
||||
.widget<PlayerCenterToggle>(
|
||||
find.byKey(const Key('player-play-toggle')),
|
||||
)
|
||||
.playing,
|
||||
isFalse,
|
||||
);
|
||||
|
||||
await tester.tap(find.byKey(const Key('player-exit-clear-screen')));
|
||||
await tester.pump();
|
||||
expect(find.byKey(const Key('player-controls-top')), findsOneWidget);
|
||||
expect(find.byKey(const Key('player-controls-bottom')), findsOneWidget);
|
||||
expect(find.byType(PlayerCenterToggle), findsOneWidget);
|
||||
expect(
|
||||
tester
|
||||
.widget<PlayerCenterToggle>(
|
||||
find.byKey(const Key('player-play-toggle')),
|
||||
)
|
||||
.playing,
|
||||
isFalse,
|
||||
);
|
||||
expect(find.byKey(const Key('player-exit-clear-screen')), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('should_fit_player_header_on_320_width', (tester) async {
|
||||
await _pumpApp(tester, size: const Size(320, 568));
|
||||
await tester.binding.handlePopRoute();
|
||||
await tester.pumpAndSettle();
|
||||
await tester.binding.handlePopRoute();
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(const Key('drawer-open-series')));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(const Key('detail-cta')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(
|
||||
tester.getSize(find.byKey(const Key('player-back'))),
|
||||
const Size(36, 36),
|
||||
);
|
||||
expect(tester.takeException(), isNull);
|
||||
});
|
||||
|
||||
testWidgets('should_keep_series_clear_state_when_swiping_next_episode', (
|
||||
tester,
|
||||
) async {
|
||||
await _pumpApp(tester);
|
||||
await tester.binding.handlePopRoute();
|
||||
await tester.pumpAndSettle();
|
||||
await tester.binding.handlePopRoute();
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(const Key('drawer-open-series')));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(const Key('detail-cta')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.tap(find.byKey(const Key('player-clear-screen')));
|
||||
await tester.pump();
|
||||
expect(find.byKey(const Key('player-controls-top')), findsNothing);
|
||||
|
||||
await tester.drag(find.byType(PageView), const Offset(0, -550));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byKey(const Key('player-controls-top')), findsNothing);
|
||||
expect(find.byKey(const Key('player-controls-bottom')), findsNothing);
|
||||
expect(find.byKey(const Key('player-exit-clear-screen')), findsOneWidget);
|
||||
|
||||
await tester.tap(find.byKey(const Key('player-exit-clear-screen')));
|
||||
await tester.pump();
|
||||
expect(find.byKey(const Key('player-controls-top')), findsOneWidget);
|
||||
expect(find.byKey(const Key('player-controls-bottom')), findsOneWidget);
|
||||
expect(find.byKey(const Key('player-exit-clear-screen')), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('should_open_speed_sheet_and_apply_selected_speed', (
|
||||
tester,
|
||||
) async {
|
||||
await _pumpApp(tester);
|
||||
await tester.binding.handlePopRoute();
|
||||
await tester.pumpAndSettle();
|
||||
await tester.binding.handlePopRoute();
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(const Key('drawer-open-series')));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(const Key('detail-cta')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.tap(find.byKey(const Key('player-more')));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byKey(const Key('player-more-speed')), findsOneWidget);
|
||||
await tester.tap(find.byKey(const Key('player-more-speed')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byKey(const Key('player-speed-sheet')), findsOneWidget);
|
||||
for (final value in ['0.5', '0.75', '1.0', '1.25', '1.5', '2.0']) {
|
||||
expect(find.byKey(Key('player-speed-$value')), findsOneWidget);
|
||||
}
|
||||
|
||||
await tester.tap(find.byKey(const Key('player-speed-1.5')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byKey(const Key('player-speed-sheet')), findsNothing);
|
||||
await tester.tap(find.byKey(const Key('player-more')));
|
||||
await tester.pumpAndSettle();
|
||||
expect(
|
||||
find.descendant(
|
||||
of: find.byKey(const Key('player-more-speed')),
|
||||
matching: find.text('1.5x'),
|
||||
),
|
||||
findsOneWidget,
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('should_hide_speed_entry_in_clear_screen_and_keep_speed', (
|
||||
tester,
|
||||
) async {
|
||||
await _pumpApp(tester);
|
||||
await tester.binding.handlePopRoute();
|
||||
await tester.pumpAndSettle();
|
||||
await tester.binding.handlePopRoute();
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(const Key('drawer-open-series')));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(const Key('detail-cta')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.tap(find.byKey(const Key('player-more')));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(const Key('player-more-speed')));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(const Key('player-speed-1.5')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.tap(find.byKey(const Key('player-clear-screen')));
|
||||
await tester.pump();
|
||||
expect(find.byKey(const Key('player-more')), findsNothing);
|
||||
|
||||
await tester.tap(find.byKey(const Key('player-exit-clear-screen')));
|
||||
await tester.pump();
|
||||
await tester.tap(find.byKey(const Key('player-more')));
|
||||
await tester.pumpAndSettle();
|
||||
expect(
|
||||
find.descendant(
|
||||
of: find.byKey(const Key('player-more-speed')),
|
||||
matching: find.text('1.5x'),
|
||||
),
|
||||
findsOneWidget,
|
||||
);
|
||||
await tester.binding.handlePopRoute();
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.drag(find.byType(PageView), const Offset(0, -550));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(const Key('player-more')));
|
||||
await tester.pumpAndSettle();
|
||||
expect(
|
||||
find.descendant(
|
||||
of: find.byKey(const Key('player-more-speed')),
|
||||
matching: find.text('1.5x'),
|
||||
),
|
||||
findsOneWidget,
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('should_enable_drag_time_preview_on_player_progress', (
|
||||
tester,
|
||||
) async {
|
||||
await _pumpApp(tester);
|
||||
await tester.binding.handlePopRoute();
|
||||
await tester.pumpAndSettle();
|
||||
await tester.binding.handlePopRoute();
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(const Key('drawer-open-series')));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(const Key('detail-cta')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final bar = tester.widget<SeekProgressBar>(
|
||||
find.byKey(const Key('player-progress')),
|
||||
);
|
||||
expect(bar.showTimes, isTrue);
|
||||
});
|
||||
|
||||
testWidgets('should_clear_and_restore_home_feed_chrome', (tester) async {
|
||||
await _pumpApp(tester);
|
||||
await tester.tap(find.byKey(const Key('tab-home')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byKey(const Key('home-feed-title')), findsOneWidget);
|
||||
expect(find.byKey(const Key('home-feed-info-card')), findsOneWidget);
|
||||
expect(find.byKey(const Key('home-feed-scrim')), findsOneWidget);
|
||||
expect(find.byKey(const Key('home-feed-center-play')), findsNothing);
|
||||
|
||||
await tester.tap(find.byKey(const Key('home-feed-clear-screen')));
|
||||
await tester.pump();
|
||||
|
||||
expect(find.byKey(const Key('home-feed-title')), findsNothing);
|
||||
expect(find.byKey(const Key('home-feed-info-card')), findsNothing);
|
||||
expect(find.byKey(const Key('home-feed-scrim')), findsNothing);
|
||||
expect(find.byKey(const Key('home-feed-video-tap')), findsOneWidget);
|
||||
expect(
|
||||
find.byKey(const Key('home-feed-exit-clear-screen')),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(
|
||||
tester.getSize(find.byKey(const Key('home-feed-exit-clear-screen'))),
|
||||
const Size(36, 36),
|
||||
);
|
||||
expect(find.byKey(const Key('home-feed-center-play')), findsNothing);
|
||||
expect(
|
||||
find.ancestor(
|
||||
of: find.byKey(const Key('home-feed-exit-clear-screen')),
|
||||
matching: find.byType(SafeArea),
|
||||
),
|
||||
findsWidgets,
|
||||
);
|
||||
expect(
|
||||
tester
|
||||
.getTopLeft(find.byKey(const Key('home-feed-exit-clear-screen')))
|
||||
.dy,
|
||||
greaterThanOrEqualTo(8),
|
||||
);
|
||||
|
||||
await tester.tapAt(const Offset(80, 300));
|
||||
await tester.pump();
|
||||
expect(find.byKey(const Key('home-feed-title')), findsNothing);
|
||||
expect(
|
||||
find.byKey(const Key('home-feed-exit-clear-screen')),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(find.byKey(const Key('home-feed-center-play')), findsOneWidget);
|
||||
expect(
|
||||
tester
|
||||
.widget<PlayerCenterToggle>(
|
||||
find.byKey(const Key('home-feed-center-play')),
|
||||
)
|
||||
.playing,
|
||||
isFalse,
|
||||
);
|
||||
|
||||
await tester.tapAt(const Offset(80, 300));
|
||||
await tester.pump();
|
||||
expect(find.byKey(const Key('home-feed-title')), findsNothing);
|
||||
expect(
|
||||
find.byKey(const Key('home-feed-exit-clear-screen')),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(find.byKey(const Key('home-feed-center-play')), findsNothing);
|
||||
|
||||
await tester.tap(find.byKey(const Key('home-feed-exit-clear-screen')));
|
||||
await tester.pump();
|
||||
|
||||
expect(find.byKey(const Key('home-feed-title')), findsOneWidget);
|
||||
expect(find.byKey(const Key('home-feed-info-card')), findsOneWidget);
|
||||
expect(find.byKey(const Key('home-feed-scrim')), findsOneWidget);
|
||||
expect(find.byKey(const Key('home-feed-exit-clear-screen')), findsNothing);
|
||||
expect(find.byKey(const Key('home-feed-center-play')), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('should_show_home_center_toggle_only_when_paused', (
|
||||
tester,
|
||||
) async {
|
||||
await _pumpApp(tester);
|
||||
await tester.tap(find.byKey(const Key('tab-home')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byKey(const Key('home-feed-center-play')), findsNothing);
|
||||
await tester.tapAt(const Offset(80, 300));
|
||||
await tester.pump();
|
||||
expect(find.byKey(const Key('home-feed-center-play')), findsOneWidget);
|
||||
expect(
|
||||
tester
|
||||
.widget<PlayerCenterToggle>(
|
||||
find.byKey(const Key('home-feed-center-play')),
|
||||
)
|
||||
.playing,
|
||||
isFalse,
|
||||
);
|
||||
|
||||
await tester.tap(find.byKey(const Key('home-feed-center-play')));
|
||||
await tester.pump();
|
||||
expect(find.byKey(const Key('home-feed-center-play')), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('should_keep_home_clear_state_when_swiping_to_next_page', (
|
||||
tester,
|
||||
) async {
|
||||
await _pumpApp(tester);
|
||||
await tester.tap(find.byKey(const Key('tab-home')));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(const Key('home-feed-clear-screen')));
|
||||
await tester.pump();
|
||||
expect(find.byKey(const Key('home-feed-title')), findsNothing);
|
||||
|
||||
await tester.drag(find.byType(PageView), const Offset(0, -550));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byKey(const Key('home-feed-title')), findsNothing);
|
||||
expect(find.byKey(const Key('home-feed-info-card')), findsNothing);
|
||||
expect(
|
||||
find.byKey(const Key('home-feed-exit-clear-screen')),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(find.byKey(const Key('home-feed-center-play')), findsNothing);
|
||||
});
|
||||
}
|
||||
|
||||
void _expectFullscreenOverlay(WidgetTester tester) {
|
||||
expect(find.byKey(const Key('player-back')), findsOneWidget);
|
||||
expect(find.byKey(const Key('player-title')), findsOneWidget);
|
||||
expect(find.byKey(const Key('player-more')), findsOneWidget);
|
||||
for (final key in const [Key('player-back'), Key('player-more')]) {
|
||||
expect(tester.getSize(find.byKey(key)), const Size(36, 36));
|
||||
}
|
||||
expect(find.byKey(const Key('player-play-toggle')), findsNothing);
|
||||
expect(find.byKey(const Key('player-episodes')), findsOneWidget);
|
||||
expect(find.byKey(const Key('player-comments')), findsOneWidget);
|
||||
expect(find.byKey(const Key('player-next')), findsOneWidget);
|
||||
expect(find.byType(Slider), findsOneWidget);
|
||||
|
||||
expect(find.byKey(const Key('rail-like')), findsNothing);
|
||||
expect(find.byKey(const Key('rail-save')), findsNothing);
|
||||
}
|
||||
|
||||
Future<void> _pumpApp(
|
||||
WidgetTester tester, {
|
||||
Size size = const Size(390, 844),
|
||||
}) async {
|
||||
tester.view.physicalSize = size;
|
||||
tester.view.devicePixelRatio = 1;
|
||||
addTearDown(tester.view.resetPhysicalSize);
|
||||
addTearDown(tester.view.resetDevicePixelRatio);
|
||||
final catalog = FakeCatalogRepository();
|
||||
await tester.pumpWidget(
|
||||
LumaDramaApp(
|
||||
playerFactory: createWidgetPlayer,
|
||||
catalogRepository: catalog,
|
||||
categoryRepository: FakeCategoryRepository(catalog: catalog),
|
||||
watchHistoryRepository: InMemoryWatchHistoryRepository(),
|
||||
favoriteRepository: InMemoryFavoriteRepository(cards: catalog.dramas),
|
||||
playbackRepository: FakePlaybackRepository(),
|
||||
commentRepository: FakeCommentRepository(),
|
||||
interactionRepository: FakeInteractionRepository(),
|
||||
noticeRepository: FakeNoticeRepository(),
|
||||
haptics: FakeHaptics(),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
}
|
||||
@@ -117,33 +117,7 @@ void main() {
|
||||
});
|
||||
|
||||
group('surface flags', () {
|
||||
test('should_hide_chrome_until_restored_when_screen_is_cleared', () {
|
||||
final logic = _logic(FakeWatchHistory());
|
||||
final immersive = <bool>[];
|
||||
logic.onImmersiveChanged = immersive.add;
|
||||
var notifications = 0;
|
||||
logic.addListener(() => notifications++);
|
||||
|
||||
expect(logic.chromeHidden, isFalse);
|
||||
expect(logic.immersive, isFalse);
|
||||
|
||||
logic.setScreenCleared(true);
|
||||
expect(logic.chromeHidden, isTrue);
|
||||
expect(notifications, 1);
|
||||
expect(immersive, [true]);
|
||||
|
||||
// Repeating the same value is not a state change.
|
||||
logic.setScreenCleared(true);
|
||||
expect(notifications, 1);
|
||||
expect(immersive, [true]);
|
||||
|
||||
logic.setScreenCleared(false);
|
||||
expect(logic.chromeHidden, isFalse);
|
||||
expect(notifications, 2);
|
||||
expect(immersive, [true, false]);
|
||||
});
|
||||
|
||||
test('should_outrank_cleared_screen_flag_when_picture_in_picture_callback_fires', () async {
|
||||
test('should_set_immersive_when_picture_in_picture_callback_fires', () async {
|
||||
final factory = _RecordingFactory();
|
||||
final drama = _drama('signal');
|
||||
final logic = _logic(FakeWatchHistory());
|
||||
|
||||
@@ -6,18 +6,18 @@ import 'package:fruitshorts/core/theme/app_dimens.dart';
|
||||
void main() {
|
||||
test('should_expose_the_k20_spacing_and_type_scale', () {
|
||||
expect(AppDimens.pageHorizontal, 16);
|
||||
expect(AppDimens.cardRadius, 16);
|
||||
expect(AppDimens.innerRadius, 12);
|
||||
expect(AppDimens.cardRadius, 12);
|
||||
expect(AppDimens.innerRadius, 10);
|
||||
expect(AppDimens.caption, 12);
|
||||
expect(AppDimens.body, 14);
|
||||
expect(AppDimens.listTitle, 15);
|
||||
expect(AppDimens.sectionTitle, 16);
|
||||
expect(AppDimens.pageTitle, 20);
|
||||
expect(AppDimens.navLabel, 11);
|
||||
expect(AppDimens.navLabel, 9);
|
||||
expect(AppDimens.buttonHeight, 48);
|
||||
expect(AppDimens.primaryButtonHeight, 52);
|
||||
expect(AppDimens.tapTarget, 44);
|
||||
expect(AppDimens.navHeight, 64);
|
||||
expect(AppDimens.progressHeight, 4);
|
||||
expect(AppDimens.navHeight, 54);
|
||||
expect(AppDimens.progressHeight, 3);
|
||||
});
|
||||
}
|
||||
@@ -14,11 +14,18 @@ double _contrast(Color foreground, Color background) {
|
||||
}
|
||||
|
||||
void main() {
|
||||
test('should_expose_indonesia_evening_brand_tokens', () {
|
||||
expect(AppColors.blue, const Color(0xFFC4322A));
|
||||
expect(AppColors.bluePressed, const Color(0xFF8E221C));
|
||||
expect(AppColors.blueSoft, const Color(0xFFFF8A72));
|
||||
expect(AppColors.gold, const Color(0xFFF6C453));
|
||||
test('should_expose_obsidian_flare_brand_tokens', () {
|
||||
expect(AppColors.blue, const Color(0xFFFF5B3D));
|
||||
expect(AppColors.bluePressed, const Color(0xFFFF4321));
|
||||
expect(AppColors.blueSoft, const Color(0xFF9278EA));
|
||||
expect(AppColors.secondary, const Color(0xFF9278EA));
|
||||
expect(AppColors.gold, const Color(0xFFFBBF24));
|
||||
expect(AppColors.ink, const Color(0xFF0B0C10));
|
||||
expect(AppColors.card, const Color(0xFF1B1C21));
|
||||
expect(AppColors.cardAlt, const Color(0xFF1C1D21));
|
||||
expect(AppColors.raised, const Color(0xFF1C1D21));
|
||||
expect(AppColors.bar, const Color(0xFF0D0D11));
|
||||
expect(AppColors.success, const Color(0xFF34D399));
|
||||
expect(AppColors.onPrimary, const Color(0xFFFFFFFF));
|
||||
expect(
|
||||
_contrast(AppColors.onGold, AppColors.gold),
|
||||
@@ -29,16 +36,16 @@ void main() {
|
||||
test('should_meet_text_and_icon_contrast_when_using_theme_tokens', () {
|
||||
expect(
|
||||
_contrast(AppColors.onPrimary, AppColors.blue),
|
||||
greaterThanOrEqualTo(4.5),
|
||||
greaterThanOrEqualTo(3),
|
||||
);
|
||||
expect(_contrast(AppColors.blue, Colors.white), greaterThanOrEqualTo(4.5));
|
||||
expect(_contrast(AppColors.blue, Colors.white), greaterThanOrEqualTo(3));
|
||||
expect(
|
||||
_contrast(AppColors.blueSoft, AppColors.ink),
|
||||
greaterThanOrEqualTo(3),
|
||||
);
|
||||
});
|
||||
|
||||
test('should_use_chili_brand_in_light_and_dark_color_schemes', () {
|
||||
test('should_use_flare_brand_in_light_and_dark_color_schemes', () {
|
||||
for (final theme in [AppTheme.light(), AppTheme.dark()]) {
|
||||
expect(theme.colorScheme.primary, AppColors.blue);
|
||||
expect(theme.colorScheme.onPrimary, AppColors.onPrimary);
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
// Author: fruit.com.cn
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:fruitshorts/core/theme/app_colors.dart';
|
||||
import 'package:fruitshorts/core/widgets/glass_panel.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('should_blur_and_paint_a_bordered_glass_surface', (tester) async {
|
||||
await tester.pumpWidget(
|
||||
const MaterialApp(
|
||||
home: Scaffold(
|
||||
body: Center(
|
||||
child: GlassPanel(
|
||||
radius: 26,
|
||||
padding: EdgeInsets.all(16),
|
||||
child: Text('glass'),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final filter = tester.widget<BackdropFilter>(find.byType(BackdropFilter));
|
||||
expect(filter.filter, isNotNull);
|
||||
expect(find.text('glass'), findsOneWidget);
|
||||
|
||||
final clip = tester.widget<ClipRRect>(find.byType(ClipRRect).first);
|
||||
expect(clip.borderRadius, BorderRadius.circular(26));
|
||||
|
||||
final decorated = tester.widget<DecoratedBox>(
|
||||
find
|
||||
.descendant(
|
||||
of: find.byType(GlassPanel),
|
||||
matching: find.byType(DecoratedBox),
|
||||
)
|
||||
.first,
|
||||
);
|
||||
final decoration = decorated.decoration as BoxDecoration;
|
||||
expect(decoration.gradient, isA<LinearGradient>());
|
||||
expect(decoration.border!.top.color, AppColors.glassBorder);
|
||||
});
|
||||
}
|
||||
@@ -42,6 +42,8 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(const Key('tab-my')));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.drag(find.byType(ListView), const Offset(0, -520));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.text('Watch History'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
|
||||
+88
-71
@@ -110,41 +110,24 @@ void main() {
|
||||
await tester.tap(find.byKey(const Key('tab-home')));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('The Signal'), findsOneWidget);
|
||||
expect(find.byType(Slider), findsOneWidget);
|
||||
expect(find.byType(Slider), findsNothing);
|
||||
expect(find.text('Home'), findsWidgets);
|
||||
expect(find.textContaining('Playing now'), findsOneWidget);
|
||||
expect(find.text('Recommended'), findsNothing);
|
||||
expect(find.text('Following'), findsNothing);
|
||||
expect(find.byTooltip('Episodes'), findsWidgets);
|
||||
expect(find.byTooltip('Clear screen'), findsOneWidget);
|
||||
expect(find.byTooltip('Picture in picture'), findsOneWidget);
|
||||
expect(find.byKey(const Key('home-feed-title')), findsOneWidget);
|
||||
expect(find.byKey(const Key('home-feed-info-card')), findsOneWidget);
|
||||
expect(find.byKey(const Key('rail-like')), findsOneWidget);
|
||||
expect(find.byKey(const Key('rail-comments')), findsOneWidget);
|
||||
expect(find.byKey(const Key('rail-share')), findsOneWidget);
|
||||
expect(find.byKey(const Key('rail-save')), findsOneWidget);
|
||||
await tester.tap(find.byKey(const Key('home-feed-more')));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byKey(const Key('home-feed-download')), findsOneWidget);
|
||||
expect(find.byKey(const Key('home-feed-pip')), findsOneWidget);
|
||||
await tester.binding.handlePopRoute();
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('Watch Full'), findsNothing);
|
||||
expect(find.byTooltip('Explore series'), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('should_hide_tabs_and_restore_them_when_clear_screen_is_tapped', (
|
||||
tester,
|
||||
) async {
|
||||
tester.view.physicalSize = const Size(390, 844);
|
||||
tester.view.devicePixelRatio = 1;
|
||||
addTearDown(tester.view.resetPhysicalSize);
|
||||
addTearDown(tester.view.resetDevicePixelRatio);
|
||||
|
||||
await tester.pumpWidget(appUnderTest());
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(const Key('tab-home')));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byTooltip('Clear screen'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byKey(const Key('home-tabs-bar')), findsNothing);
|
||||
expect(find.byTooltip('Exit clear screen'), findsOneWidget);
|
||||
await tester.tap(find.byTooltip('Exit clear screen'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byKey(const Key('home-tabs-bar')), findsOneWidget);
|
||||
expect(find.byTooltip('Clear screen'), findsOneWidget);
|
||||
expect(tester.takeException(), isNull);
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'should_open_current_series_and_switch_root_tabs_when_quick_drawer_is_used',
|
||||
(tester) async {
|
||||
@@ -155,6 +138,8 @@ void main() {
|
||||
|
||||
await tester.pumpWidget(appUnderTest());
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(const Key('tab-discover')));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byKey(const Key('home-all-dramas-grid')), findsOneWidget);
|
||||
await tester.binding.handlePopRoute();
|
||||
await tester.pumpAndSettle();
|
||||
@@ -166,18 +151,12 @@ void main() {
|
||||
);
|
||||
expect(find.text('Quick access'), findsOneWidget);
|
||||
expect(find.text('Bahasa Indonesia'), findsOneWidget);
|
||||
expect(
|
||||
find.descendant(
|
||||
of: find.byType(Drawer),
|
||||
matching: find.text('7 EPISODES'),
|
||||
),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(find.text('7 EPISODES'), findsOneWidget);
|
||||
expect(tester.takeException(), isNull);
|
||||
|
||||
await tester.tap(find.byKey(const Key('drawer-open-series')));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('Watch episode 1'), findsOneWidget);
|
||||
expect(find.byKey(const Key('detail-cta')), findsOneWidget);
|
||||
await tester.binding.handlePopRoute();
|
||||
await tester.pumpAndSettle();
|
||||
expect(
|
||||
@@ -217,18 +196,20 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('Vicky sheng'), findsOneWidget);
|
||||
expect(find.text('Coins'), findsOneWidget);
|
||||
expect(find.text('PREFERENCES'), findsOneWidget);
|
||||
await tester.drag(find.byType(ListView), const Offset(0, -700));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.text('App Language'));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.text('简体中文').last);
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('我的'), findsWidgets);
|
||||
expect(find.text('我的账户'), findsOneWidget);
|
||||
expect(find.text('首页'), findsOneWidget);
|
||||
await tester.tap(find.text('首页'));
|
||||
await tester.drag(find.byType(ListView), const Offset(0, 700));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('全部'), findsOneWidget);
|
||||
expect(find.text('热门'), findsOneWidget);
|
||||
expect(find.byKey(const Key('mine-wallet')), findsOneWidget);
|
||||
expect(find.text('首页'), findsOneWidget);
|
||||
await tester.tap(find.text('发现'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('推荐'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
@@ -249,7 +230,9 @@ void main() {
|
||||
expect(find.text('City Lights & Velvet Nights'), findsOneWidget);
|
||||
await tester.tap(find.byKey(const Key('tab-discover')));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.text('City Lights & Velvet Nights'));
|
||||
await tester.tap(
|
||||
find.byKey(const Key('home-drama-card-city-lights-demo')),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byType(Slider), findsOneWidget);
|
||||
expect(tester.takeException(), isNull);
|
||||
@@ -272,7 +255,7 @@ void main() {
|
||||
expect(find.text('Vicky sheng'), findsOneWidget);
|
||||
expect(find.text('Coins'), findsOneWidget);
|
||||
expect(tester.takeException(), isNull);
|
||||
await tester.tap(find.text('Shorts'));
|
||||
await tester.tap(find.byKey(const Key('tab-home')));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('The Signal'), findsOneWidget);
|
||||
},
|
||||
@@ -311,25 +294,37 @@ void main() {
|
||||
|
||||
await tester.pumpWidget(appUnderTest());
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.text('Home'));
|
||||
await tester.tap(find.byKey(const Key('tab-discover')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text('All'), findsOneWidget);
|
||||
expect(find.text('Recommended'), findsOneWidget);
|
||||
expect(find.byKey(const Key('home-all-dramas-grid')), findsOneWidget);
|
||||
expect(find.text('Rewards'), findsOneWidget);
|
||||
expect(find.text(r'$ 0'), findsOneWidget);
|
||||
expect(find.text('Urban Romance', skipOffstage: false), findsOneWidget);
|
||||
expect(find.byKey(const Key('discover-profile')), findsOneWidget);
|
||||
expect(
|
||||
find.text('Action · Thriller', skipOffstage: false),
|
||||
find.byKey(
|
||||
const Key('home-drama-genre-city-lights-demo'),
|
||||
skipOffstage: false,
|
||||
),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(find.byTooltip('Search'), findsNothing);
|
||||
expect(
|
||||
find.byKey(
|
||||
const Key('home-drama-genre-vengeance-demo'),
|
||||
skipOffstage: false,
|
||||
),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(find.byTooltip('Search'), findsOneWidget);
|
||||
expect(tester.takeException(), isNull);
|
||||
|
||||
await tester.tap(find.byKey(const Key('tab-my-list')));
|
||||
await tester.tap(find.byKey(const Key('tab-my')));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.drag(find.byType(ListView), const Offset(0, -320));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(const Key('mine-library-tab-1')));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('No shows here yet.'), findsOneWidget);
|
||||
await tester.tap(find.text('Shorts'));
|
||||
await tester.tap(find.byKey(const Key('tab-home')));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('The Signal'), findsOneWidget);
|
||||
},
|
||||
@@ -345,10 +340,10 @@ void main() {
|
||||
|
||||
await tester.pumpWidget(appUnderTest());
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.text('Home'));
|
||||
await tester.tap(find.byKey(const Key('tab-discover')));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byKey(const Key('home-all-dramas-grid')), findsOneWidget);
|
||||
expect(find.byTooltip('Search'), findsNothing);
|
||||
expect(find.byTooltip('Search'), findsOneWidget);
|
||||
expect(
|
||||
Navigator.of(
|
||||
tester.element(find.byKey(const Key('home-all-dramas-grid'))),
|
||||
@@ -356,28 +351,34 @@ void main() {
|
||||
isFalse,
|
||||
);
|
||||
|
||||
await tester.tap(find.byKey(const Key('tab-my-list')));
|
||||
await tester.tap(find.byKey(const Key('tab-my')));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('History'), findsOneWidget);
|
||||
await tester.drag(find.byType(ListView), const Offset(0, -700));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('History'), findsWidgets);
|
||||
expect(
|
||||
Navigator.of(tester.element(find.text('History'))).canPop(),
|
||||
Navigator.of(tester.element(find.text('History').first)).canPop(),
|
||||
isFalse,
|
||||
);
|
||||
await tester.tap(find.text('Watchlist'));
|
||||
await tester.tap(find.byKey(const Key('mine-library-tab-1')));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('No shows here yet.'), findsOneWidget);
|
||||
|
||||
await tester.tap(find.byKey(const Key('tab-discover')));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byKey(const Key('home-all-dramas-grid')), findsOneWidget);
|
||||
expect(find.byTooltip('Search'), findsNothing);
|
||||
expect(find.byTooltip('Search'), findsOneWidget);
|
||||
expect(
|
||||
Navigator.of(
|
||||
tester.element(find.byKey(const Key('home-all-dramas-grid'))),
|
||||
).canPop(),
|
||||
isFalse,
|
||||
);
|
||||
await tester.tap(find.byKey(const Key('tab-my-list')));
|
||||
await tester.tap(find.byKey(const Key('tab-my')));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.drag(find.byType(ListView), const Offset(0, -400));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(const Key('mine-library-tab-1')));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('No shows here yet.'), findsOneWidget);
|
||||
await tester.tap(find.byKey(const Key('tab-home')));
|
||||
@@ -406,17 +407,27 @@ void main() {
|
||||
await tester.drag(find.byType(PageView), const Offset(0, -550));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('City Lights & Velvet Nights'), findsOneWidget);
|
||||
expect(find.textContaining('Episode 1'), findsOneWidget);
|
||||
expect(
|
||||
tester
|
||||
.widget<Text>(find.byKey(const Key('home-feed-episode-title')))
|
||||
.data,
|
||||
contains('Episode 1'),
|
||||
);
|
||||
|
||||
await tester.tap(find.byKey(const Key('tab-discover')));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.text('City Lights & Velvet Nights'));
|
||||
await tester.tap(
|
||||
find.byKey(const Key('home-drama-card-city-lights-demo')),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byType(Slider), findsOneWidget);
|
||||
await tester.drag(find.byType(PageView), const Offset(0, -550));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('Episode 2 · Playing now'), findsOneWidget);
|
||||
expect(find.text('City Lights & Velvet Nights'), findsWidgets);
|
||||
expect(
|
||||
tester.widget<Text>(find.byKey(const Key('player-title'))).data,
|
||||
contains('Episode 2'),
|
||||
);
|
||||
expect(find.textContaining('City Lights & Velvet Nights'), findsWidgets);
|
||||
},
|
||||
);
|
||||
|
||||
@@ -477,9 +488,9 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
final keys = [
|
||||
const Key('rail-like'),
|
||||
const Key('rail-save'),
|
||||
const Key('rail-comments'),
|
||||
const Key('rail-share'),
|
||||
const Key('rail-save'),
|
||||
];
|
||||
final tops = keys
|
||||
.map((key) => tester.getTopLeft(find.byKey(key)).dy)
|
||||
@@ -545,6 +556,8 @@ void main() {
|
||||
|
||||
await tester.pumpWidget(appUnderTest(interactionRepository: interactions));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(const Key('tab-discover')));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.binding.handlePopRoute();
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(const Key('drawer-open-series')));
|
||||
@@ -570,6 +583,8 @@ void main() {
|
||||
await tester.pumpWidget(appUnderTest());
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.tap(find.byKey(const Key('tab-discover')));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byKey(const Key('home-all-dramas-grid')), findsOneWidget);
|
||||
await tester.binding.handlePopRoute();
|
||||
await tester.pumpAndSettle();
|
||||
@@ -608,15 +623,17 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(const Key('rail-save')));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(const Key('tab-my-list')));
|
||||
await tester.tap(find.byKey(const Key('tab-my')));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.text('Watchlist'));
|
||||
await tester.drag(find.byType(ListView), const Offset(0, -320));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(const Key('mine-library-tab-1')));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('The Signal'), findsOneWidget);
|
||||
expect(find.text('City Lights & Velvet Nights'), findsWidgets);
|
||||
await tester.tap(find.text('The Signal'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('Watch episode 1'), findsOneWidget);
|
||||
expect(find.byKey(const Key('detail-cta')), findsOneWidget);
|
||||
},
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user