mirror of
https://github.com/kuhyx/wake-alarm.git
synced 2026-11-10 18:07:05 +01:00
- Sick days screen (own name, sick icon, cat-2 fill): tap today or a later day to mark it sick, tap again to clear; past days inert. Writes the sickdays wire format (state sick/cleared + actor, one HLC per write) to sickdays-sync/devices via crdt_sync syncLog. - Mutual exclusion in both pickers: each syncs the other pool on open and refuses a date it holds, naming the pool; an unreadable pool refuses all. - Native SickDays cache (fail closed via DayCache); AlarmReceiver skips the ring with reason "sick_day" (no markFired, no ring_started); StickCheck verdict sick_day, streak skips sick days; stakes card says so. - Pre-alarm pool sync: allow-while-idle alarm at 21:00 and A-30 (request code 1006) runs a headless engine (poolSyncMain) that pulls both pools from RTDB and rewrites both native caches, so a PC mark arrives with the app closed. The ring decision stays a cache read. - JVM unit tests (JUnit 4.13.2) for DayCache, RingDecision, PoolSyncSchedule, StickCheck; Dart tests; Dart->Python interop check. pylint hook skipped: verify.py imports sickdays, not in the hook env until the sickdays-v0.1.0 tag exists; run by hand in a sickdays venv (10.00/10). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Xfj1sxKH9VBPqpcAni8Jry
49 lines
1.6 KiB
Dart
49 lines
1.6 KiB
Dart
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:wake_alarm_sync/services/enforcement_state.dart';
|
|
import 'package:wake_alarm_sync/services/today_stakes.dart';
|
|
|
|
import '../fake_enforcement_channel.dart';
|
|
|
|
/// 2026-10-01 is a Thursday: a stick day unless it is sick.
|
|
EnforcementState _state({bool sickToday = false, bool sickTomorrow = false}) =>
|
|
EnforcementState.fromMap({
|
|
...nativeState(),
|
|
'sickToday': sickToday,
|
|
'sickTomorrow': sickTomorrow,
|
|
})!;
|
|
|
|
void main() {
|
|
final thuMorning = DateTime(2026, 10, 1, 6, 50);
|
|
|
|
test('the native sick flags are parsed, defaulting to false', () {
|
|
final state = _state(sickToday: true);
|
|
expect(state.sickToday, isTrue);
|
|
expect(state.sickTomorrow, isFalse);
|
|
expect(EnforcementState.fromMap(nativeState())!.sickToday, isFalse);
|
|
});
|
|
|
|
test('a sick stick day promises no lockdown and no PC ring', () {
|
|
final view = describeStakes(
|
|
now: thuMorning,
|
|
state: _state(sickToday: true),
|
|
);
|
|
expect(view.title, 'Today · Thu 1 Oct — sick day');
|
|
expect(view.stakes, ['Sick day — no alarm, nothing at stake.']);
|
|
});
|
|
|
|
test("tomorrow's sick day is announced after today's alarm", () {
|
|
final evening = DateTime(2026, 10, 1, 20);
|
|
final view = describeStakes(
|
|
now: evening,
|
|
state: _state(sickTomorrow: true),
|
|
);
|
|
expect(view.title, 'Tomorrow · Fri 2 Oct — sick day');
|
|
expect(view.stakes, ['Sick day — no alarm, nothing at stake.']);
|
|
});
|
|
|
|
test('the ring line is silent on a sick day', () {
|
|
expect(ringStakesLine(_state()), isNotNull);
|
|
expect(ringStakesLine(_state(sickToday: true)), isNull);
|
|
});
|
|
}
|