merge: integrate feature/reminder-overlay into dev

This commit is contained in:
qzl
2026-03-20 18:59:19 +08:00
24 changed files with 229 additions and 1974 deletions
@@ -1,94 +0,0 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:social_app/core/notifications/local_notification_service.dart';
import 'package:social_app/core/startup/auth_session_bootstrapper.dart';
import 'package:social_app/features/auth/presentation/bloc/auth_state.dart';
import 'package:social_app/features/calendar/data/services/calendar_service.dart';
import 'package:social_app/features/calendar/reminders/reminder_action_executor.dart';
class MockCalendarService extends Mock implements CalendarService {}
class MockLocalNotificationService extends Mock
implements LocalNotificationService {}
class MockReminderActionExecutor extends Mock
implements ReminderActionExecutor {}
void main() {
late MockCalendarService calendarService;
late MockLocalNotificationService notificationService;
late MockReminderActionExecutor reminderActionExecutor;
late AuthSessionBootstrapper bootstrapper;
setUp(() {
calendarService = MockCalendarService();
notificationService = MockLocalNotificationService();
reminderActionExecutor = MockReminderActionExecutor();
bootstrapper = AuthSessionBootstrapper(
calendarService: calendarService,
notificationService: notificationService,
reminderActionExecutor: reminderActionExecutor,
);
});
test('does not fetch calendar events for unauthenticated state', () async {
await bootstrapper.syncForAuthState(AuthUnauthenticated());
verifyNever(() => calendarService.getEventsForRange(any(), any()));
verifyNever(() => notificationService.rebuildUpcomingReminders(any()));
verifyNever(() => reminderActionExecutor.replayPendingActions());
});
test('fetches upcoming events after authenticated state', () async {
when(
() => calendarService.getEventsForRange(any(), any()),
).thenAnswer((_) async => []);
when(
() => notificationService.rebuildUpcomingReminders(any()),
).thenAnswer((_) async {});
when(
() => reminderActionExecutor.replayPendingActions(),
).thenAnswer((_) async {});
await bootstrapper.syncForAuthState(
const AuthAuthenticated(
user: AuthUser(id: 'u1', phone: 'a@test.com'),
),
);
verify(() => calendarService.getEventsForRange(any(), any())).called(1);
verify(() => notificationService.rebuildUpcomingReminders(any())).called(1);
verify(() => reminderActionExecutor.replayPendingActions()).called(1);
});
test('retries sync when previous bootstrap failed', () async {
when(
() => reminderActionExecutor.replayPendingActions(),
).thenThrow(Exception('offline'));
await bootstrapper.syncForAuthState(
const AuthAuthenticated(
user: AuthUser(id: 'u1', phone: 'a@test.com'),
),
);
when(
() => reminderActionExecutor.replayPendingActions(),
).thenAnswer((_) async {});
when(
() => calendarService.getEventsForRange(any(), any()),
).thenAnswer((_) async => []);
when(
() => notificationService.rebuildUpcomingReminders(any()),
).thenAnswer((_) async {});
await bootstrapper.syncForAuthState(
const AuthAuthenticated(
user: AuthUser(id: 'u1', phone: 'a@test.com'),
),
);
verify(() => reminderActionExecutor.replayPendingActions()).called(2);
verify(() => calendarService.getEventsForRange(any(), any())).called(1);
});
}