Make compact Dock persistent and support week swipes

This commit is contained in:
Codex
2026-10-14 09:49:53 +08:00
parent fe23c65fd9
commit caf7abe0c0
11 changed files with 474 additions and 363 deletions
+101
View File
@@ -0,0 +1,101 @@
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:timezone/data/latest.dart' as tzdata;
import 'package:hepan_everyday/app/app_controller.dart';
import 'package:hepan_everyday/domain/app_snapshot.dart';
import 'package:hepan_everyday/domain/app_settings.dart';
import 'package:hepan_everyday/domain/schedule_engine.dart';
import 'package:hepan_everyday/features/timetable/timetable_page.dart';
import '../support/fakes.dart';
AppController _controller({bool hasSemester = true}) {
Course lesson(int week) => Course(
id: 'week-$week',
name: '第$week周课程',
teacher: '测试教师',
room: 'A101',
weekday: 3,
startPeriod: 1,
endPeriod: 2,
weeks: {week},
source: CourseSource.file,
);
return AppController(
MemoryStore(
AppSnapshot(
courses: [lesson(1), lesson(2), lesson(3)],
settings: AppSettings(
semester: hasSemester
? Semester(startDate: DateTime(2026, 10, 12), totalWeeks: 3)
: null,
),
),
),
FakeNotifications(),
FakeCalendar(),
() => DateTime.utc(2026, 10, 14),
);
}
Future<void> _open(WidgetTester tester, AppController controller) async {
await controller.initialize();
addTearDown(controller.dispose);
await tester.pumpWidget(
MaterialApp(
home: Scaffold(body: TimetablePage(controller: controller)),
),
);
await tester.pumpAndSettle();
}
void main() {
setUpAll(tzdata.initializeTimeZones);
testWidgets(
'horizontal course swipe changes week and course taps still open',
(tester) async {
await _open(tester, _controller());
expect(find.text('第 1 周'), findsOneWidget);
expect(find.text('第1周课程'), findsOneWidget);
await tester.drag(find.text('第1周课程'), const Offset(-180, 0));
await tester.pumpAndSettle();
expect(find.text('第 2 周'), findsOneWidget);
expect(find.text('第1周课程'), findsNothing);
expect(find.text('第2周课程'), findsOneWidget);
await tester.tap(find.text('第2周课程'));
await tester.pumpAndSettle();
expect(find.text('知道了'), findsOneWidget);
await tester.tap(find.text('知道了'));
await tester.pumpAndSettle();
await tester.drag(find.text('周三'), const Offset(180, 0));
await tester.pumpAndSettle();
expect(find.text('第 1 周'), findsOneWidget);
},
);
testWidgets('one swipe advances one week and stops at semester boundaries', (
tester,
) async {
await _open(tester, _controller());
await tester.drag(find.text('周三'), const Offset(300, 0));
await tester.pumpAndSettle();
expect(find.text('第 1 周'), findsOneWidget);
for (final week in [2, 3, 3]) {
await tester.drag(find.text('周三'), const Offset(-300, 0));
await tester.pumpAndSettle();
expect(find.text('第 $week 周'), findsOneWidget);
}
await tester.tap(find.text('本周'));
await tester.pumpAndSettle();
expect(find.text('第 1 周'), findsOneWidget);
});
testWidgets('swiping an imported timetable without a semester keeps prompt', (
tester,
) async {
await _open(tester, _controller(hasSemester: false));
await tester.drag(find.byType(TimetablePage), const Offset(-180, 0));
await tester.pumpAndSettle();
expect(find.text('课表已导入,请设置学期开始日'), findsOneWidget);
expect(find.text('第 2 周'), findsNothing);
expect(tester.takeException(), isNull);
});
}