mirror of
https://github.com/kuhyx/diet-guard.git
synced 2026-11-11 12:27:42 +01:00
Some checks are pending
dependency freshness / dependencies on newest stable (push) Waiting to run
file-length / file length <= 250 lines (push) Waiting to run
md-naming / markdown naming convention (push) Waiting to run
pre-commit / pre-commit (${{ matrix.group }}) (mypy, mypy, ) (push) Waiting to run
pre-commit / pre-commit (${{ matrix.group }}) (pylint, pylint, ) (push) Waiting to run
pre-commit / pre-commit (${{ matrix.group }}) (rest, , mypy,pylint) (push) Waiting to run
Tests / test (push) Waiting to run
release-apk / release (APK) (push) Waiting to run
repo-contract / repo contract (push) Waiting to run
- lightImpact + 160 ms confirm cue on a validated log (audioplayers, no audio focus); device-local opt-out switch in Settings, on by default - post-log card: confirmation line (slot + the meal's kcal), entrance and kcal/streak count-up on motion tokens transcribed into ui/theme.dart; durations collapse to zero under disableAnimations - test/flutter_test_config.dart mutes the cue suite-wide Todo: 8e66c1b9 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WzxdWVHMLzeojNP4AaPoEj
154 lines
5.1 KiB
Dart
154 lines
5.1 KiB
Dart
import 'package:diet_guard_app/widgets/today_progress_card.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
TodayProgress _progress({
|
|
double consumedKcal = 1450,
|
|
double? previousKcal,
|
|
int adherenceStreak = 3,
|
|
int? previousAdherenceStreak,
|
|
int? loggedSlotMinute,
|
|
double? loggedKcal,
|
|
}) => TodayProgress(
|
|
consumedKcal: consumedKcal,
|
|
budgetKcal: 2200,
|
|
proteinG: 90,
|
|
carbsG: 120,
|
|
fatG: 40,
|
|
adherenceStreak: adherenceStreak,
|
|
previousKcal: previousKcal,
|
|
previousAdherenceStreak: previousAdherenceStreak,
|
|
loggedSlotMinute: loggedSlotMinute,
|
|
loggedKcal: loggedKcal,
|
|
);
|
|
|
|
Future<void> _pump(
|
|
WidgetTester tester,
|
|
TodayProgress progress, {
|
|
bool reduced = false,
|
|
}) => tester.pumpWidget(
|
|
MediaQuery(
|
|
data: MediaQueryData(disableAnimations: reduced),
|
|
child: MaterialApp(
|
|
home: Scaffold(body: TodayProgressCard(progress: progress)),
|
|
),
|
|
),
|
|
);
|
|
|
|
double _entranceOpacity(WidgetTester tester) => tester
|
|
.widget<Opacity>(
|
|
find
|
|
.descendant(
|
|
of: find.byType(TodayProgressCard),
|
|
matching: find.byType(Opacity),
|
|
)
|
|
.first,
|
|
)
|
|
.opacity;
|
|
|
|
void main() {
|
|
group('confirmation line', () {
|
|
testWidgets('prints whole kcal without decimals', (tester) async {
|
|
await _pump(tester, _progress(loggedSlotMinute: 720, loggedKcal: 450));
|
|
expect(find.text('✓ 12:00 · 450 kcal'), findsOneWidget);
|
|
expect(find.textContaining('Logged'), findsNothing);
|
|
});
|
|
|
|
testWidgets('keeps fractional kcal exact', (tester) async {
|
|
await _pump(tester, _progress(loggedSlotMinute: 495, loggedKcal: 450.5));
|
|
expect(find.text('✓ 08:15 · 450.5 kcal'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('is absent when the logged fields are null', (tester) async {
|
|
await _pump(tester, _progress());
|
|
expect(find.textContaining('✓'), findsNothing);
|
|
await _pump(tester, _progress(loggedSlotMinute: 720));
|
|
expect(find.textContaining('✓'), findsNothing);
|
|
await _pump(tester, _progress(loggedKcal: 450));
|
|
expect(find.textContaining('✓'), findsNothing);
|
|
});
|
|
});
|
|
|
|
group('count-up', () {
|
|
testWidgets('runs from previousKcal to consumedKcal', (tester) async {
|
|
await _pump(tester, _progress(previousKcal: 1000));
|
|
expect(find.text('1000 / 2200'), findsOneWidget);
|
|
expect(find.text('1200 left'), findsOneWidget);
|
|
|
|
await tester.pump(const Duration(milliseconds: 160));
|
|
final mid = tester.widget<Text>(find.textContaining(' / 2200')).data!;
|
|
final value = int.parse(mid.split(' / ').first);
|
|
expect(value, greaterThan(1000));
|
|
expect(value, lessThan(1450));
|
|
|
|
await tester.pumpAndSettle();
|
|
expect(find.text('1450 / 2200'), findsOneWidget);
|
|
expect(find.text('750 left'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('is static without previousKcal', (tester) async {
|
|
await _pump(tester, _progress());
|
|
expect(find.text('1450 / 2200'), findsOneWidget);
|
|
await tester.pump(const Duration(milliseconds: 160));
|
|
expect(find.text('1450 / 2200'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('over-budget label and colour follow the animation', (
|
|
tester,
|
|
) async {
|
|
await _pump(tester, _progress(consumedKcal: 2500, previousKcal: 2000));
|
|
expect(find.text('200 left'), findsOneWidget);
|
|
await tester.pumpAndSettle();
|
|
expect(find.text('2500 / 2200'), findsOneWidget);
|
|
expect(find.text('300 over'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('streak counts up when it changed', (tester) async {
|
|
await _pump(tester, _progress(previousAdherenceStreak: 2));
|
|
expect(find.text('Adherence streak: 2 days'), findsOneWidget);
|
|
await tester.pumpAndSettle();
|
|
expect(find.text('Adherence streak: 3 days'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('streak is static when unchanged', (tester) async {
|
|
await _pump(tester, _progress(previousAdherenceStreak: 3));
|
|
expect(find.text('Adherence streak: 3 days'), findsOneWidget);
|
|
await tester.pump(const Duration(milliseconds: 160));
|
|
expect(find.text('Adherence streak: 3 days'), findsOneWidget);
|
|
});
|
|
});
|
|
|
|
group('reduced motion', () {
|
|
testWidgets('first frame shows the final values at full opacity', (
|
|
tester,
|
|
) async {
|
|
await _pump(
|
|
tester,
|
|
_progress(previousKcal: 1000, previousAdherenceStreak: 2),
|
|
reduced: true,
|
|
);
|
|
expect(find.text('1450 / 2200'), findsOneWidget);
|
|
expect(find.text('750 left'), findsOneWidget);
|
|
expect(find.text('Adherence streak: 3 days'), findsOneWidget);
|
|
expect(_entranceOpacity(tester), 1);
|
|
});
|
|
});
|
|
|
|
group('entrance', () {
|
|
testWidgets('starts transparent and ends opaque', (tester) async {
|
|
await _pump(tester, _progress());
|
|
expect(_entranceOpacity(tester), lessThan(1));
|
|
await tester.pumpAndSettle();
|
|
expect(_entranceOpacity(tester), 1);
|
|
});
|
|
|
|
testWidgets('replays for a new TodayProgress instance', (tester) async {
|
|
await _pump(tester, _progress());
|
|
await tester.pumpAndSettle();
|
|
await _pump(tester, _progress());
|
|
expect(_entranceOpacity(tester), lessThan(1));
|
|
await tester.pumpAndSettle();
|
|
});
|
|
});
|
|
}
|