mirror of
https://github.com/kuhyx/wake-alarm.git
synced 2026-11-10 18:07:05 +01:00
On 2026-09-19 the phone was powered off after the bathroom tag and nothing on the PC noticed: every finished session was published and nothing read it. Now wake-alarm distils the phone's morning into an HMAC-signed ~/.local/state/wake_alarm/morning_session.json (wake-alarm-session.timer, 07:00-11:00 every 2 min) that screen-locker and leetcode-guard read to defer their locks -- provisionally until min(start + 90 min, 09:30) while the session is live, until 11:00 once it completed inside that cutoff, and not at all for a session finished later (the phone switched on at noon completes the legs then; that must un-lock nothing). The phone publishes the session at start as well as at finish (current_session, cleared with the finish stamp), so the PC can tell "started, not finished" from "never started". A required 1-5 energy tap joins the weigh-in and ships as latest_energy with a PC reader mirroring _weight (the shared half is _field_reader). Also fixes the vmbox harness, red since the 2026-09-11 home-tidy: the guest tree lives at ~/wake-alarm, and the INSTALL-OK grep matched vm's echo of the command line. Takes Flutter 3.47.5. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Tp54ewdXRLaimUuT8LgYyn
88 lines
2.7 KiB
Dart
88 lines
2.7 KiB
Dart
import 'package:flutter/material.dart';
|
||
import 'package:flutter_test/flutter_test.dart';
|
||
import 'package:shared_preferences/shared_preferences.dart';
|
||
import 'package:wake_alarm_sync/screens/home_history_card.dart';
|
||
import 'package:wake_alarm_sync/services/morning_session.dart';
|
||
import 'package:wake_alarm_sync/services/session_rules.dart';
|
||
import 'package:wake_alarm_sync/services/session_store.dart';
|
||
import 'package:wake_alarm_sync/services/session_tag_settings.dart';
|
||
|
||
MorningSession _session(
|
||
DateTime at, {
|
||
double? kg,
|
||
int reRings = 0,
|
||
SessionOutcome outcome = SessionOutcome.completed,
|
||
}) =>
|
||
SessionRules.start(
|
||
now: at,
|
||
tags: const SessionTagSettings(),
|
||
nfcAvailable: false,
|
||
)
|
||
..weightKg = kg
|
||
..reRings = reRings
|
||
..outcome = outcome;
|
||
|
||
void main() {
|
||
setUp(() => SharedPreferences.setMockInitialValues(<String, Object>{}));
|
||
|
||
test('describes a morning in one line', () {
|
||
expect(
|
||
describeMorning(
|
||
_session(DateTime(2026, 9, 17, 8), kg: 72.4, reRings: 1),
|
||
previousWeight: 72.7,
|
||
),
|
||
'09-17 ✓ 1 re-ring · 72.4 kg (−0.3)',
|
||
);
|
||
expect(
|
||
describeMorning(
|
||
_session(
|
||
DateTime(2026, 9, 16, 8),
|
||
kg: 73,
|
||
outcome: SessionOutcome.failed,
|
||
),
|
||
previousWeight: 72,
|
||
),
|
||
'09-16 ✗ 0 re-rings · 73.0 kg (+1.0)',
|
||
);
|
||
expect(
|
||
describeMorning(
|
||
_session(DateTime(2026, 9, 15, 8), kg: 72),
|
||
previousWeight: 72,
|
||
),
|
||
'09-15 ✓ 0 re-rings · 72.0 kg (±0.0)',
|
||
);
|
||
expect(
|
||
describeMorning(
|
||
_session(DateTime(2026, 9, 14, 8), outcome: SessionOutcome.active),
|
||
),
|
||
'09-14 … 0 re-rings',
|
||
);
|
||
expect(
|
||
describeMorning(_session(DateTime(2026, 9, 13, 8), kg: 72)..energy = 4),
|
||
'09-13 ✓ 0 re-rings · 72.0 kg · energy 4/5',
|
||
);
|
||
});
|
||
|
||
testWidgets('is absent until a morning has finished', (tester) async {
|
||
await tester.pumpWidget(const MaterialApp(home: HomeHistoryCard()));
|
||
await tester.pump();
|
||
expect(find.text('Last mornings'), findsNothing);
|
||
});
|
||
|
||
testWidgets('lists the last seven with weight deltas', (tester) async {
|
||
final store = SessionStore();
|
||
for (var day = 1; day <= 9; day++) {
|
||
await store.archive(_session(DateTime(2026, 9, day, 8), kg: 70.0 + day));
|
||
}
|
||
await tester.pumpWidget(const MaterialApp(home: HomeHistoryCard()));
|
||
await tester.pump();
|
||
expect(find.text('Last mornings'), findsOneWidget);
|
||
expect(
|
||
find.textContaining('09-09 ✓ 0 re-rings · 79.0 kg (+1.0)'),
|
||
findsOne,
|
||
);
|
||
expect(find.textContaining('09-03'), findsOneWidget);
|
||
expect(find.textContaining('09-02'), findsNothing);
|
||
});
|
||
}
|