178 lines
6.1 KiB
Dart
178 lines
6.1 KiB
Dart
import 'package:drift/native.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:focus_seed/src/application/focus_seed_controller.dart';
|
|
import 'package:focus_seed/src/core/date_keys.dart';
|
|
import 'package:focus_seed/src/data/focus_seed_store.dart';
|
|
import 'package:focus_seed/src/data/local/focus_seed_database.dart';
|
|
import 'package:focus_seed/src/models/app_state.dart';
|
|
import 'package:focus_seed/src/models/focus_session.dart';
|
|
import 'package:focus_seed/src/models/habit.dart';
|
|
import 'package:focus_seed/src/models/mood.dart';
|
|
import 'package:focus_seed/src/models/reflection_entry.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
void main() {
|
|
TestWidgetsFlutterBinding.ensureInitialized();
|
|
|
|
setUp(() {
|
|
SharedPreferences.setMockInitialValues({});
|
|
});
|
|
|
|
test('clearToday removes only current-day progress', () async {
|
|
final database = FocusSeedDatabase(NativeDatabase.memory());
|
|
addTearDown(database.close);
|
|
final store = FocusSeedStore(database: database);
|
|
final today = todayKey();
|
|
final yesterday = dateKey(DateTime.now().subtract(const Duration(days: 1)));
|
|
final habit = Habit(
|
|
id: 'habit-1',
|
|
title: 'Keep scope clear',
|
|
createdAt: DateTime.now().subtract(const Duration(days: 2)),
|
|
completedDates: {today, yesterday},
|
|
);
|
|
await store.save(
|
|
AppState(
|
|
anchor: 'Finish the cleanup',
|
|
anchorDateKey: today,
|
|
habits: [habit],
|
|
sessions: [
|
|
FocusSession(
|
|
id: 'session-today',
|
|
minutes: 25,
|
|
completedAt: DateTime.now(),
|
|
),
|
|
FocusSession(
|
|
id: 'session-yesterday',
|
|
minutes: 15,
|
|
completedAt: DateTime.now().subtract(const Duration(days: 1)),
|
|
),
|
|
],
|
|
reflections: [
|
|
ReflectionEntry(
|
|
id: 'reflection-today',
|
|
dateKey: today,
|
|
note: 'Today note',
|
|
mood: Mood.clear,
|
|
createdAt: DateTime.now(),
|
|
),
|
|
ReflectionEntry(
|
|
id: 'reflection-yesterday',
|
|
dateKey: yesterday,
|
|
note: 'Yesterday note',
|
|
mood: Mood.calm,
|
|
createdAt: DateTime.now().subtract(const Duration(days: 1)),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
final controller = FocusSeedController(store: store);
|
|
await controller.load();
|
|
|
|
final cleared = await controller.clearToday();
|
|
final state = controller.state!;
|
|
|
|
expect(cleared, isTrue);
|
|
expect(state.activeAnchor(today), isEmpty);
|
|
expect(state.habits.single.completedDates, {yesterday});
|
|
expect(state.sessions.map((session) => session.id), ['session-yesterday']);
|
|
expect(state.reflections.map((reflection) => reflection.id), [
|
|
'reflection-yesterday',
|
|
]);
|
|
});
|
|
|
|
test('default focus duration persists and survives record cleanup', () async {
|
|
final database = FocusSeedDatabase(NativeDatabase.memory());
|
|
addTearDown(database.close);
|
|
final store = FocusSeedStore(database: database);
|
|
final controller = FocusSeedController(store: store);
|
|
await controller.load();
|
|
|
|
final changed = await controller.setDefaultFocusMinutes(45);
|
|
expect(changed, isTrue);
|
|
expect(controller.state!.defaultFocusMinutes, 45);
|
|
|
|
final reloaded = FocusSeedController(store: store);
|
|
await reloaded.load();
|
|
expect(reloaded.state!.defaultFocusMinutes, 45);
|
|
|
|
final cleared = await reloaded.clearData();
|
|
expect(cleared, isTrue);
|
|
expect(reloaded.state!.defaultFocusMinutes, 45);
|
|
});
|
|
|
|
test('completed focus sessions snapshot the active daily focus', () async {
|
|
final database = FocusSeedDatabase(NativeDatabase.memory());
|
|
addTearDown(database.close);
|
|
final store = FocusSeedStore(database: database);
|
|
final controller = FocusSeedController(store: store);
|
|
await controller.load();
|
|
|
|
final savedFocus = await controller.setTodayAnchor('Review launch notes');
|
|
final savedSession = await controller.completeFocusSession(
|
|
10,
|
|
actualSeconds: 60,
|
|
);
|
|
|
|
expect(savedFocus, isTrue);
|
|
expect(savedSession, isTrue);
|
|
expect(controller.state!.sessions.single.intention, 'Review launch notes');
|
|
|
|
final reloaded = FocusSeedController(store: store);
|
|
await reloaded.load();
|
|
expect(reloaded.state!.sessions.single.intention, 'Review launch notes');
|
|
});
|
|
|
|
test('progress notes can be backfilled for a past record date', () async {
|
|
final database = FocusSeedDatabase(NativeDatabase.memory());
|
|
addTearDown(database.close);
|
|
final store = FocusSeedStore(database: database);
|
|
final controller = FocusSeedController(store: store);
|
|
await controller.load();
|
|
|
|
const pastDate = '2026-06-12';
|
|
final saved = await controller.saveReflectionForDate(
|
|
pastDate,
|
|
'Recovered the next step.',
|
|
Mood.clear,
|
|
);
|
|
|
|
expect(saved, isTrue);
|
|
expect(controller.state!.reflections.single.dateKey, pastDate);
|
|
expect(
|
|
controller.state!.reflections.single.note,
|
|
'Recovered the next step.',
|
|
);
|
|
});
|
|
|
|
test('today anchor does not create a daily action object', () async {
|
|
final database = FocusSeedDatabase(NativeDatabase.memory());
|
|
addTearDown(database.close);
|
|
final store = FocusSeedStore(database: database);
|
|
final controller = FocusSeedController(store: store);
|
|
await controller.load();
|
|
|
|
final savedToday = await controller.setTodayAnchor('Review launch notes');
|
|
|
|
expect(savedToday, isTrue);
|
|
expect(controller.state!.activeAnchor(todayKey()), 'Review launch notes');
|
|
expect(controller.state!.actions, isEmpty);
|
|
});
|
|
|
|
test('focus can complete without a today anchor', () async {
|
|
final database = FocusSeedDatabase(NativeDatabase.memory());
|
|
addTearDown(database.close);
|
|
final store = FocusSeedStore(database: database);
|
|
final controller = FocusSeedController(store: store);
|
|
await controller.load();
|
|
|
|
final savedSession = await controller.completeFocusSession(
|
|
10,
|
|
actualSeconds: 120,
|
|
);
|
|
|
|
expect(savedSession, isTrue);
|
|
expect(controller.state!.sessions.single.intention, isEmpty);
|
|
expect(controller.state!.actions, isEmpty);
|
|
});
|
|
}
|