feat(home): 顶部导航随翻页联动并把推荐更名为精选
This commit is contained in:
1 parent
2f4593a46e
commit
335e5dc286
27 files changed
+1095
-214
No files matched your search
@@ -0,0 +1,149 @@
|
||||
// Author: fruit.com.cn
|
||||
// 职责:验证三种顶部导航接入稳定文字过渡并保留点击与选中语义。
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:fruitshorts/core/data/models/content_category.dart';
|
||||
import 'package:fruitshorts/core/widgets/animated_nav_label.dart';
|
||||
import 'package:fruitshorts/l10n/app_localizations.dart';
|
||||
import 'package:fruitshorts/pages/home/widgets/home_grid_header.dart';
|
||||
import 'package:fruitshorts/pages/recommend/recommend_types.dart';
|
||||
import 'package:fruitshorts/pages/recommend/widgets/recommend_channel_nav.dart';
|
||||
import 'package:fruitshorts/pages/recommend/widgets/recommend_top_nav.dart';
|
||||
|
||||
const _midpoint = Duration(milliseconds: 90);
|
||||
const _duration = Duration(milliseconds: 180);
|
||||
const _categories = [
|
||||
ContentCategory(id: 'featured', name: '精选'),
|
||||
ContentCategory(id: 'new', name: '新剧'),
|
||||
];
|
||||
const _shortcuts = [
|
||||
HomeGridCategoryShortcut(
|
||||
label: '精选',
|
||||
categoryName: 'featured',
|
||||
categoryId: 'featured',
|
||||
tab: HomePrimaryTab.featured,
|
||||
),
|
||||
HomeGridCategoryShortcut(
|
||||
label: '新剧',
|
||||
categoryName: 'new',
|
||||
categoryId: 'new',
|
||||
tab: HomePrimaryTab.newReleases,
|
||||
),
|
||||
];
|
||||
|
||||
Widget _host(Widget child) => MaterialApp(
|
||||
locale: const Locale('zh'),
|
||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||
supportedLocales: AppLocalizations.supportedLocales,
|
||||
home: Scaffold(body: child),
|
||||
);
|
||||
|
||||
double _scale(WidgetTester tester, Finder label) {
|
||||
return tester
|
||||
.widget<Transform>(
|
||||
find.descendant(of: label, matching: find.byType(Transform)),
|
||||
)
|
||||
.transform
|
||||
.entry(0, 0);
|
||||
}
|
||||
|
||||
Future<void> _verifyTransition(
|
||||
WidgetTester tester,
|
||||
Widget Function(bool) build,
|
||||
) async {
|
||||
await tester.pumpWidget(_host(build(true)));
|
||||
await tester.pumpAndSettle();
|
||||
final labels = find.byType(AnimatedNavLabel);
|
||||
final rects = [tester.getRect(labels.at(0)), tester.getRect(labels.at(1))];
|
||||
await tester.pumpWidget(_host(build(false)));
|
||||
await tester.pump(_midpoint);
|
||||
expect(_scale(tester, labels.at(0)), inExclusiveRange(0.9, 1.0));
|
||||
expect(_scale(tester, labels.at(1)), inExclusiveRange(0.9, 1.0));
|
||||
expect(tester.getRect(labels.at(0)), rects[0]);
|
||||
expect(tester.getRect(labels.at(1)), rects[1]);
|
||||
await tester.pump(_duration);
|
||||
expect(tester.getRect(labels.at(1)), rects[1]);
|
||||
final semantics = tester.widget<Semantics>(
|
||||
find.descendant(of: labels.at(1), matching: find.byType(Semantics)).first,
|
||||
);
|
||||
expect(semantics.properties.selected, isTrue);
|
||||
}
|
||||
|
||||
void main() {
|
||||
testWidgets('should_keep_channel_labels_regular_when_selection_changes', (
|
||||
tester,
|
||||
) async {
|
||||
const categories = [
|
||||
ContentCategory(id: 'featured', name: '精选'),
|
||||
ContentCategory(id: 'weekly', name: '本周必看'),
|
||||
];
|
||||
for (final selected in categories) {
|
||||
await tester.pumpWidget(
|
||||
_host(
|
||||
RecommendChannelNav(
|
||||
categories: categories,
|
||||
selectedId: selected.id,
|
||||
onSelected: (_) {},
|
||||
onSearch: () {},
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
for (final category in categories) {
|
||||
final text = tester.widget<Text>(find.text(category.name));
|
||||
expect(text.style?.fontWeight, FontWeight.w400);
|
||||
expect(text.style?.fontSize, 17);
|
||||
}
|
||||
expect(tester.takeException(), isNull);
|
||||
}
|
||||
});
|
||||
|
||||
testWidgets('should_keep_home_labels_stable_when_category_changes', (
|
||||
tester,
|
||||
) async {
|
||||
int? tapped;
|
||||
HomeGridHeader header(bool first) => HomeGridHeader(
|
||||
callbacks: HomeGridCallbacks(
|
||||
onSearch: () {},
|
||||
onOpenVip: () {},
|
||||
onOpenWallet: () {},
|
||||
onOpenFilter: () {},
|
||||
),
|
||||
categories: _shortcuts,
|
||||
selectedIndex: first ? 0 : 1,
|
||||
onSectionSelected: (index) => tapped = index,
|
||||
);
|
||||
await _verifyTransition(tester, header);
|
||||
await tester.tap(find.byKey(const Key('home-primary-label-new')));
|
||||
expect(tapped, 1);
|
||||
});
|
||||
|
||||
testWidgets('should_keep_inner_nav_labels_stable_when_tab_changes', (
|
||||
tester,
|
||||
) async {
|
||||
RecommendInnerTab? tapped;
|
||||
RecommendTopNav nav(bool first) => RecommendTopNav(
|
||||
selected: first ? RecommendInnerTab.feed : RecommendInnerTab.playlists,
|
||||
onSelected: (tab) => tapped = tab,
|
||||
onSearch: () {},
|
||||
);
|
||||
await _verifyTransition(tester, nav);
|
||||
await tester.tap(find.byKey(const Key('recommend-tab-playlist')));
|
||||
expect(tapped, RecommendInnerTab.playlists);
|
||||
});
|
||||
|
||||
testWidgets('should_keep_channel_labels_stable_when_selection_changes', (
|
||||
tester,
|
||||
) async {
|
||||
String? tapped;
|
||||
RecommendChannelNav nav(bool first) => RecommendChannelNav(
|
||||
categories: _categories,
|
||||
selectedId: first ? 'featured' : 'new',
|
||||
onSelected: (id) => tapped = id,
|
||||
onSearch: () {},
|
||||
);
|
||||
await _verifyTransition(tester, nav);
|
||||
await tester.tap(find.byKey(const Key('recommend-tab-new')));
|
||||
expect(tapped, 'new');
|
||||
});
|
||||
}
|
||||
Reference in new issue
Block a user