fix: preserve queued settings and recover interrupted or corrupt state

This commit is contained in:
Codex
2026-10-13 09:32:50 +08:00
parent 5ceab20b67
commit da5b8076a0
16 changed files with 373 additions and 50 deletions
+52
View File
@@ -9,9 +9,61 @@ import 'package:hepan_everyday/services/calendar_service.dart';
import '../support/fakes.dart';
import 'navigation_test.dart' show uiController;
import '../services/calendar_service_test.dart' show CalendarProvider;
import '../domain/schedule_engine_test.dart' show course;
import 'package:hepan_everyday/services/android_calendar_service.dart';
import 'package:hepan_everyday/domain/app_snapshot.dart';
import 'package:hepan_everyday/domain/app_settings.dart';
import 'package:hepan_everyday/domain/semester.dart';
void main() {
setUpAll(tzdata.initializeTimeZones);
testWidgets(
'partial initial calendar sync exposes working cleanup action while switch is off',
(tester) async {
final provider = CalendarProvider()..failAfterFirst = true;
final controller = AppController(
MemoryStore(
AppSnapshot(
courses: [
course(id: 'a'),
course(id: 'b'),
],
settings: AppSettings(
semester: Semester(
startDate: DateTime(2026, 9, 9),
totalWeeks: 1,
),
),
),
),
FakeNotifications(),
AndroidCalendarService(provider),
DateTime.now,
);
await controller.initialize();
await controller.enableCalendarFromUserAction('local');
expect(controller.snapshot.settings.calendarEnabled, isFalse);
expect(provider.records, hasLength(1));
await tester.pumpWidget(
MaterialApp(home: SettingsPage(controller: controller)),
);
await tester.pumpAndSettle();
await tester.scrollUntilVisible(
find.text('重试清理课程日程'),
250,
scrollable: find.byType(Scrollable).first,
);
await tester.ensureVisible(find.text('重试清理课程日程'));
await tester.pumpAndSettle();
await tester.tap(find.text('重试清理课程日程'));
await tester.pumpAndSettle();
expect(provider.records, isEmpty);
expect(controller.snapshot.calendarCleanupPending, isFalse);
controller.dispose();
},
);
testWidgets('calendar provider failure is explained and keeps switch off', (
tester,
) async {