Merge branch 'train-days' into integration
# Conflicts: # apps/train/halkyon_train_flutter/lib/src/app/train_paths.dart # docs/adr/0030-halkyon-train.md
This commit is contained in:
commit
81adeb91cc
1 changed files with 25705 additions and 410 deletions
|
|
@ -55,6 +55,8 @@ import 'package:halkyon_train_flutter/src/feature/strength/model/exercise_catalo
|
|||
import 'package:halkyon_train_flutter/src/feature/strength/model/strength_plan.dart';
|
||||
import 'package:halkyon_train_flutter/src/feature/weather/data/weather_gateway.dart';
|
||||
import 'package:halkyon_train_flutter/src/feature/weather/model/workout_weather.dart';
|
||||
import 'package:halkyon_train_flutter/src/feature/weight/data/weight_repository.dart';
|
||||
import 'package:halkyon_train_flutter/src/feature/weight/widget/weight_card.dart';
|
||||
import 'package:halkyon_train_flutter/src/feature/workout/data/workout_repository.dart';
|
||||
import 'package:halkyon_train_flutter/src/feature/workout/model/series_chunk.dart';
|
||||
import 'package:halkyon_train_flutter/src/feature/workout/model/workout.dart';
|
||||
|
|
@ -85,6 +87,7 @@ import '../support/memory_plan_gateway.dart';
|
|||
import '../support/memory_profile_gateway.dart';
|
||||
import '../support/memory_route_gateway.dart';
|
||||
import '../support/memory_strength_plan_gateway.dart';
|
||||
import '../support/memory_weight_gateway.dart';
|
||||
import '../support/memory_workout_gateway.dart';
|
||||
|
||||
void main() {
|
||||
|
|
@ -121,6 +124,7 @@ void main() {
|
|||
PlanRepository? plans,
|
||||
RouteRepository? routes,
|
||||
PlaceRepository? places,
|
||||
WeightRepository? weights,
|
||||
StrengthPlanRepository? strengthPlans,
|
||||
StrengthSessionStore? strengthSession,
|
||||
RoutingGateway? routing,
|
||||
|
|
@ -193,6 +197,10 @@ void main() {
|
|||
opened.add(person);
|
||||
return TrainPerson(
|
||||
person,
|
||||
sync: SyncService(
|
||||
({required onMerge}) async {},
|
||||
debounce: const Duration(days: 1),
|
||||
),
|
||||
workouts:
|
||||
workouts ??
|
||||
WorkoutRepository(
|
||||
|
|
@ -255,6 +263,16 @@ void main() {
|
|||
),
|
||||
),
|
||||
chosenPlace: ChosenPlaceStore(),
|
||||
weights:
|
||||
weights ??
|
||||
WeightRepository(
|
||||
MemoryWeightGateway(),
|
||||
TrainKeys(
|
||||
MemoryContentKeyGateway(),
|
||||
FakeContentCipher(),
|
||||
() async => FakeAccountCrypto().keysNumbered(1),
|
||||
),
|
||||
),
|
||||
strengthPlans:
|
||||
strengthPlans ??
|
||||
StrengthPlanRepository(
|
||||
|
|
@ -505,14 +523,15 @@ void main() {
|
|||
}
|
||||
});
|
||||
|
||||
testWidgets('Settings groups the training first, then the account, About '
|
||||
'Halkyon Train last and the version small at the very foot', (
|
||||
tester,
|
||||
) async {
|
||||
testWidgets('Settings groups where sync stands first, with Sync now, then '
|
||||
'the training, then the account, About Halkyon Train last and the '
|
||||
'version small at the very foot', (tester) async {
|
||||
await start(tester, usedBefore: true);
|
||||
await openSettings(tester);
|
||||
|
||||
expect(find.text('Sync now'), findsOneWidget);
|
||||
final order = [
|
||||
'Sync',
|
||||
'Your body',
|
||||
'Account',
|
||||
'Sign out',
|
||||
|
|
@ -961,6 +980,25 @@ void main() {
|
|||
await tester.pumpAndSettle();
|
||||
}
|
||||
|
||||
testWidgets("the switches' explanations wait behind their question marks "
|
||||
'(D64)', (tester) async {
|
||||
await openMovement(tester);
|
||||
const hint =
|
||||
'When the phone counted hardly a step for a while; never while '
|
||||
'recording or in a car.';
|
||||
expect(find.text(hint), findsNothing);
|
||||
|
||||
await tester.tap(
|
||||
find.descendant(
|
||||
of: find.widgetWithText(SwitchListTile, 'Remind me to move'),
|
||||
matching: find.byType(HelpButton),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text(hint), findsOneWidget);
|
||||
expect(platform.configured, [null], reason: 'nothing switched');
|
||||
});
|
||||
|
||||
testWidgets('reminders turned on ask for the permissions, and the job '
|
||||
'gets the settings and the words, each change again', (tester) async {
|
||||
await openMovement(tester);
|
||||
|
|
@ -1194,6 +1232,57 @@ void main() {
|
|||
expect(find.text('50'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('a weight entered on Progress shows on its card and in Your '
|
||||
'body, and goes again from All (D64)', (tester) async {
|
||||
await start(tester, usedBefore: true, profile: profile);
|
||||
await openProgress(tester);
|
||||
await tester.runAsync(pumpEventQueue);
|
||||
await tester.pump();
|
||||
final card = find.byType(WeightCard);
|
||||
expect(
|
||||
find.descendant(
|
||||
of: card,
|
||||
matching: find.textContaining('Add your weight'),
|
||||
),
|
||||
findsOneWidget,
|
||||
);
|
||||
|
||||
await tester.tap(
|
||||
find.descendant(of: card, matching: find.byTooltip('Add weight')),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.enterText(find.byType(TextField), '1000');
|
||||
await tester.tap(find.text('Save'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('A weight between 20 and 400 kg'), findsOneWidget);
|
||||
|
||||
await tester.enterText(find.byType(TextField), '71,4');
|
||||
await tester.tap(find.text('Save'));
|
||||
await tester.runAsync(pumpEventQueue);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.runAsync(pumpEventQueue);
|
||||
await tester.pumpAndSettle();
|
||||
expect(
|
||||
find.descendant(of: card, matching: find.text('71.4 kg')),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(
|
||||
find.descendant(
|
||||
of: find.byType(BodyCard),
|
||||
matching: find.textContaining('71.4 kg'),
|
||||
),
|
||||
findsOneWidget,
|
||||
reason: "the latest weight is the body's",
|
||||
);
|
||||
|
||||
await tester.tap(find.descendant(of: card, matching: find.text('All')));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byTooltip('Delete'));
|
||||
await tester.runAsync(pumpEventQueue);
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('71.4 kg'), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets("without figures, Profile's card says what they're for", (
|
||||
tester,
|
||||
) async {
|
||||
|
|
@ -2835,6 +2924,8 @@ void main() {
|
|||
'recovery': 4,
|
||||
'rmssd': 48,
|
||||
'baselineRmssd': 45,
|
||||
// Polar's mark for a status it has none of.
|
||||
'ansStatus': -100.0,
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
|
@ -2872,16 +2963,36 @@ void main() {
|
|||
await tester.tap(find.text('Tuesday, October 27'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Inside Profile, the tabs beside it (D60).
|
||||
expect(find.byType(NavigationBar), findsOneWidget);
|
||||
// A screen of its own over the tabs, the way back at its top left
|
||||
// (the developer's review of 3 Nov 2026).
|
||||
expect(find.byType(NavigationBar), findsNothing);
|
||||
expect(find.byType(BackButton), findsOneWidget);
|
||||
expect(find.text('Heart rate'), findsOneWidget);
|
||||
expect(find.text('The night'), findsOneWidget);
|
||||
expect(find.text('You slept well'), findsOneWidget);
|
||||
await tester.scrollUntilVisible(find.text('Nightly Recharge'), 200);
|
||||
expect(
|
||||
find.text('Heart rate variability 48 ms, your usual 45 ms'),
|
||||
findsOneWidget,
|
||||
// The person's figures in rows, each with their usual; Polar's mark
|
||||
// for no value shown nowhere, the explanation behind the question
|
||||
// mark.
|
||||
expect(find.text('Recovery'), findsOneWidget);
|
||||
expect(find.text('4 of 6'), findsOneWidget);
|
||||
expect(find.text('Heart rate variability'), findsOneWidget);
|
||||
expect(find.text('48 ms'), findsOneWidget);
|
||||
expect(find.text('usually 45 ms'), findsOneWidget);
|
||||
expect(find.textContaining('100'), findsNothing);
|
||||
expect(find.text('Autonomic nervous system'), findsNothing);
|
||||
expect(find.textContaining('from −10 to +10'), findsNothing);
|
||||
await tester.tap(
|
||||
find.descendant(
|
||||
of: find.ancestor(
|
||||
of: find.text('Nightly Recharge'),
|
||||
matching: find.byType(Row),
|
||||
),
|
||||
matching: find.byType(HelpButton),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.textContaining('from −10 to +10'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets("Home shows today's figures from the band, even before a "
|
||||
|
|
|
|||
Loading…
Reference in a new issue