feat: manage, account and help pages
- 管理页:单元集 / 计划 / 算法三个维度,卡片带元数据 - 账户页:资料、学习数据、竖直分组的四个功能入口 - 新增设置、文档与帮助(底部可上滑助手)、反馈、关于四个页面 - 抽出 StatBlock 与 GroupedListSection 共用组件 - 关闭 Android 预测式返回,转场改为 M3 水平滑入
This commit is contained in:
1 parent
2a307b2f48
commit
22715f7247
15 files changed
+1789
-72
No files matched your search
+114
-4
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'package:mobile/main.dart';
|
||||
import 'package:mobile/widgets/grouped_list_section.dart';
|
||||
|
||||
/// 在导航栏内按标签定位,避免和页面标题的相同文字混淆。
|
||||
Finder navLabel(String label) {
|
||||
@@ -11,9 +12,22 @@ Finder navLabel(String label) {
|
||||
);
|
||||
}
|
||||
|
||||
/// 手机尺寸(400 × 800 dp),避免默认 800×600 掩盖溢出问题。
|
||||
void usePhoneSurface(WidgetTester tester) {
|
||||
tester.view.physicalSize = const Size(400, 800);
|
||||
tester.view.devicePixelRatio = 1.0;
|
||||
addTearDown(tester.view.reset);
|
||||
}
|
||||
|
||||
Future<void> pumpApp(WidgetTester tester) async {
|
||||
usePhoneSurface(tester);
|
||||
await tester.pumpWidget(const KiriMemoApp());
|
||||
await tester.pumpAndSettle();
|
||||
}
|
||||
|
||||
void main() {
|
||||
testWidgets('底部导航提供学习 / 管理 / 统计 / 账户四个入口', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(const KiriMemoApp());
|
||||
await pumpApp(tester);
|
||||
|
||||
expect(find.byType(NavigationBar), findsOneWidget);
|
||||
expect(find.byType(NavigationDestination), findsNWidgets(4));
|
||||
@@ -23,8 +37,19 @@ void main() {
|
||||
}
|
||||
});
|
||||
|
||||
testWidgets('Android 端使用水平滑入转场,而非预测式返回', (WidgetTester tester) async {
|
||||
await pumpApp(tester);
|
||||
|
||||
final MaterialApp app = tester.widget<MaterialApp>(find.byType(MaterialApp));
|
||||
final PageTransitionsTheme transitions = app.theme!.pageTransitionsTheme;
|
||||
expect(
|
||||
transitions.builders[TargetPlatform.android],
|
||||
isA<FadeForwardsPageTransitionsBuilder>(),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('默认停留在学习页,点击其它入口会切换', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(const KiriMemoApp());
|
||||
await pumpApp(tester);
|
||||
|
||||
NavigationBar bar = tester.widget<NavigationBar>(find.byType(NavigationBar));
|
||||
expect(bar.selectedIndex, 0);
|
||||
@@ -43,7 +68,7 @@ void main() {
|
||||
});
|
||||
|
||||
testWidgets('学习首页展示今日任务与唯一主行动', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(const KiriMemoApp());
|
||||
await pumpApp(tester);
|
||||
|
||||
expect(find.text('今日计划'), findsOneWidget);
|
||||
expect(find.text('待复习'), findsOneWidget);
|
||||
@@ -62,12 +87,97 @@ void main() {
|
||||
for (final String label in <String>['收藏夹', '自我测试', '附带资料', '计划设置']) {
|
||||
expect(find.text(label), findsOneWidget);
|
||||
}
|
||||
});
|
||||
|
||||
testWidgets('未接入内核的入口点击后给出反馈', (WidgetTester tester) async {
|
||||
await pumpApp(tester);
|
||||
|
||||
// 未接入内核的入口点击后要有反馈,不能静默无响应。
|
||||
await tester.tap(find.text('开始学习'));
|
||||
await tester.pump();
|
||||
await tester.pump(const Duration(milliseconds: 300));
|
||||
|
||||
expect(find.text('学习会话 尚未接入内核'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('管理页有三个维度,各自列出卡片', (WidgetTester tester) async {
|
||||
await pumpApp(tester);
|
||||
await tester.tap(navLabel('管理'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
for (final String label in <String>['单元集', '计划', '算法']) {
|
||||
expect(find.text(label), findsOneWidget);
|
||||
}
|
||||
expect(find.text('高考必背古诗文'), findsOneWidget);
|
||||
expect(find.text('标识 cngk-t'), findsOneWidget);
|
||||
|
||||
await tester.tap(find.text('计划'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('每日计划'), findsOneWidget);
|
||||
expect(find.text('周末冲刺'), findsOneWidget);
|
||||
expect(find.text('新识记'), findsNWidgets(2));
|
||||
|
||||
await tester.tap(find.text('算法'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('NSP-0'), findsOneWidget);
|
||||
expect(find.text('默认'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('账户页展示资料、学习数据与四个功能入口', (WidgetTester tester) async {
|
||||
await pumpApp(tester);
|
||||
await tester.tap(navLabel('账户'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text('zhiyu'), findsOneWidget);
|
||||
expect(find.text('ID KM-1024 · 大一'), findsOneWidget);
|
||||
expect(find.text('累计学习'), findsOneWidget);
|
||||
expect(find.text('坚持'), findsOneWidget);
|
||||
|
||||
// 四个入口是同一张分组卡片里的四行。
|
||||
expect(find.byType(GroupedListSection), findsOneWidget);
|
||||
expect(find.byType(GroupedListTile), findsNWidgets(4));
|
||||
|
||||
for (final String label in <String>[
|
||||
'设置',
|
||||
'文档与帮助',
|
||||
'反馈问题',
|
||||
'关于 KiriMemo',
|
||||
]) {
|
||||
expect(find.text(label), findsOneWidget);
|
||||
}
|
||||
});
|
||||
|
||||
testWidgets('账户页可以进入设置页,设置项按分组排列', (WidgetTester tester) async {
|
||||
await pumpApp(tester);
|
||||
await tester.tap(navLabel('账户'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.tap(find.text('设置'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text('每日新识记上限'), findsOneWidget);
|
||||
expect(find.text('答错后重新排队'), findsOneWidget);
|
||||
|
||||
// 分组在下方,需要滚动到可见。
|
||||
await tester.scrollUntilVisible(find.text('版本'), 200);
|
||||
expect(find.text('版本'), findsOneWidget);
|
||||
expect(find.text('1.0.0'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('文档与帮助页底部有可上滑的助手', (WidgetTester tester) async {
|
||||
await pumpApp(tester);
|
||||
await tester.tap(navLabel('账户'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.tap(find.text('文档与帮助'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text('文档内容将在这里显示'), findsOneWidget);
|
||||
expect(find.text('问问 KiriMemo'), findsOneWidget);
|
||||
|
||||
// 收起时是横栏,点开后出现输入框。
|
||||
expect(find.byType(TextField), findsNothing);
|
||||
await tester.tap(find.text('问问 KiriMemo'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byType(TextField), findsOneWidget);
|
||||
});
|
||||
}
|
||||
Reference in new issue
Block a user