import 'dart:io'; import 'package:flutter_test/flutter_test.dart'; import 'package:hepan_everyday/data/file_snapshot_store.dart'; import 'package:hepan_everyday/domain/app_snapshot.dart'; import 'package:hepan_everyday/domain/app_settings.dart'; import '../domain/schedule_engine_test.dart' show course; void main() { late Directory directory; setUp(() async { directory = await Directory.systemTemp.createTemp('hepan-test-'); }); tearDown(() async { await directory.delete(recursive: true); }); for (final badBackup in [false, true]) { test( 'fresh recovery archives corrupt primary and ${badBackup ? 'corrupt' : 'missing'} backup before saving', () async { await File('${directory.path}/hepan_snapshot.json') .writeAsString('damaged primary'); if (badBackup) { await File('${directory.path}/hepan_snapshot.bak') .writeAsString('damaged backup'); } final store = FileSnapshotStore(directory); await expectLater(store.load(), throwsFormatException); await store.startFresh(); final archives = await directory .list() .where((e) => e.path.contains('.damaged-')) .toList(); expect(archives, hasLength(badBackup ? 2 : 1)); final contents = await Future.wait( archives.map((e) => File(e.path).readAsString()), ); expect(contents, contains('damaged primary')); if (badBackup) { expect(contents, contains('damaged backup')); } expect((await store.load())!.courses, isEmpty); await store.save(AppSnapshot(courses: [course()])); expect((await store.load())!.courses.single.id, 'math'); }, ); } test( 'reopening restores courses, settings and calendar identifiers', () async { final original = AppSnapshot( settings: AppSettings(reminderMinutes: 30), courses: [course()], calendarEventIds: {'math/2026-09-09': '17'}, ); await FileSnapshotStore(directory).save(original); final loaded = await FileSnapshotStore(directory).load(); expect(loaded, isNotNull); expect(loaded!.courses.single.name, '矩阵论'); expect(loaded.settings.reminderMinutes, 30); expect(loaded.calendarEventIds, {'math/2026-09-09': '17'}); }, ); test( 'damaged snapshot reports failure instead of returning empty courses', () async { await File('${directory.path}/hepan_snapshot.json') .writeAsString('damaged'); await expectLater( FileSnapshotStore(directory).load(), throwsFormatException, ); }, ); test('valid previous snapshot is available for explicit recovery', () async { final store = FileSnapshotStore(directory); await store.save(AppSnapshot(settings: AppSettings(reminderMinutes: 15))); await store.save(AppSnapshot(settings: AppSettings(reminderMinutes: 30))); await File('${directory.path}/hepan_snapshot.json') .writeAsString('damaged'); expect((await store.restoreBackup()).settings.reminderMinutes, 15); }); }