Stage 5: History, the shared daily Streak and Reminders
- Streak computed from all complete Sessions: Grace Hour (00:00-01:00 counts for yesterday unless it is done), a Freeze per 7 Streak Days (max 2) spent automatically on a missed day (ADR 0006) - Top bar flame (grey until today is done) opening a panel with current and longest Streak, Freezes and a month calendar; 'Day N of your streak' on a fresh summary - History per Mode grouped by day, reopening each summary - Two adjustable Reminders (19:00, 22:30) scheduled 14 days ahead with flutter_local_notifications, none on a done day; permission asked after the first complete Session or from Settings - Settings: Reminders, the Player chime, exercise credits Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
971ff64117
commit
1ffe6269ea
31 files changed
+1972
-50
No files matched your search
@@ -0,0 +1,69 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:zenxercise/src/streak/reminders.dart';
|
||||
import 'package:zenxercise/src/streak/streak.dart';
|
||||
|
||||
void main() {
|
||||
const evening = Reminder(enabled: true, minutes: 19 * 60);
|
||||
const late = Reminder(enabled: true, minutes: 22 * 60 + 30);
|
||||
|
||||
Streak streak({bool todayDone = false, required DateTime now}) =>
|
||||
Streak.compute([if (todayDone) now.subtract(const Duration(minutes: 1))], now: now);
|
||||
|
||||
test('both Reminders are planned for each of the next days', () {
|
||||
final now = DateTime(2026, 10, 29, 9);
|
||||
final planned = upcomingReminders(
|
||||
[evening, late],
|
||||
streak: streak(now: now),
|
||||
now: now,
|
||||
days: 2,
|
||||
);
|
||||
|
||||
expect(planned.map((r) => r.at), [
|
||||
DateTime(2026, 10, 29, 19),
|
||||
DateTime(2026, 10, 29, 22, 30),
|
||||
DateTime(2026, 10, 30, 19),
|
||||
DateTime(2026, 10, 30, 22, 30),
|
||||
]);
|
||||
expect(planned.map((r) => r.id).toSet(), hasLength(4));
|
||||
});
|
||||
|
||||
test('a done day gets no Reminders, and times already past are skipped', () {
|
||||
final now = DateTime(2026, 10, 29, 20);
|
||||
final done = upcomingReminders(
|
||||
[evening, late],
|
||||
streak: streak(todayDone: true, now: now),
|
||||
now: now,
|
||||
days: 2,
|
||||
);
|
||||
final open = upcomingReminders(
|
||||
[evening, late],
|
||||
streak: streak(now: now),
|
||||
now: now,
|
||||
days: 1,
|
||||
);
|
||||
|
||||
expect(done.map((r) => r.at), [DateTime(2026, 10, 30, 19), DateTime(2026, 10, 30, 22, 30)]);
|
||||
expect(open.map((r) => r.at), [DateTime(2026, 10, 29, 22, 30)]);
|
||||
});
|
||||
|
||||
test('a switched-off Reminder is never planned', () {
|
||||
final now = DateTime(2026, 10, 29, 9);
|
||||
final planned = upcomingReminders(
|
||||
[evening, const Reminder(enabled: false, minutes: 22 * 60 + 30)],
|
||||
streak: streak(now: now),
|
||||
now: now,
|
||||
days: 2,
|
||||
);
|
||||
|
||||
expect(planned.map((r) => r.at.hour), [19, 19]);
|
||||
});
|
||||
|
||||
test('only today\'s Reminders mention the running Streak; later ones cannot know it', () {
|
||||
final now = DateTime(2026, 10, 29, 9);
|
||||
final s = Streak.compute([DateTime(2026, 10, 27, 18), DateTime(2026, 10, 28, 18)], now: now);
|
||||
|
||||
final planned = upcomingReminders([evening], streak: s, now: now, days: 2);
|
||||
|
||||
expect(planned.map((r) => r.streakDays), [2, null]);
|
||||
});
|
||||
}
|
||||
Reference in new issue
Block a user