feat(train): a chart held shows the value under the finger, following it

WorkoutChart, the line of every chart in Train (a day's heart rate and skin
temperature, a workout's, a route's height): held, a line marks the point
nearest the finger and follows it as it moves, its value beside the title,
with its moment where the chart says how to write it (a day's heart rate:
the time of day). A tap does nothing; lifting the finger clears it (the
developer's review of 3 Nov 2026, as stock charts do).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-11-03 21:40:47 +01:00
commit 984527a632
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64

View file

@ -0,0 +1,62 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:halkyon_train_flutter/src/feature/workout/widget/workout_chart.dart';
import 'package:material_ui/material_ui.dart';
void main() {
/// A heart rate from 60 at second 0 to 120 at second 100, in steps of 10
/// a second.
Future<void> pumpChart(WidgetTester tester) => tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: SizedBox(
width: 400,
child: WorkoutChart(
title: 'Heart rate',
points: [
for (var second = 0; second <= 100; second += 10)
(x: second.toDouble(), value: 60 + second * 0.6),
],
label: (value) => '${value.round()} bpm',
xLabel: (x) => 'at ${x.round()} s',
),
),
),
),
);
testWidgets('held, the value and its moment under the finger show beside '
'the title, following the finger, and go when it lifts', (
tester,
) async {
await pumpChart(tester);
final plot = find.byKey(WorkoutChart.plotKey);
final box = tester.getRect(plot);
expect(find.text('at 0 s'), findsNothing);
// Held at the plot's start: the first point.
final gesture = await tester.startGesture(
box.centerLeft + const Offset(1, 0),
);
await tester.pump(const Duration(milliseconds: 600));
expect(find.text('60 bpm · at 0 s'), findsOneWidget);
// Dragged to the middle: second 50, 90 bpm.
await gesture.moveTo(box.center);
await tester.pump();
expect(find.text('90 bpm · at 50 s'), findsOneWidget);
expect(find.text('60 bpm · at 0 s'), findsNothing);
await gesture.up();
await tester.pump();
expect(find.textContaining(' · at '), findsNothing);
});
testWidgets('a tap shows nothing: only a long press inspects', (
tester,
) async {
await pumpChart(tester);
await tester.tap(find.byKey(WorkoutChart.plotKey));
await tester.pump();
expect(find.textContaining(' · at '), findsNothing);
});
}