Skip to content

Commit d9b4d66

Browse files
committed
Add tests for interpolation logic
1 parent 6cc9631 commit d9b4d66

File tree

4 files changed

+105
-3
lines changed

4 files changed

+105
-3
lines changed

lib/helpers/consts.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,3 +137,7 @@ enum WeightUnitEnum { kg, lb }
137137
const textInputTypeDecimal = TextInputType.numberWithOptions(decimal: true);
138138

139139
const String API_MAX_PAGE_SIZE = '999';
140+
141+
/// Marker used for identifying interpolated values in a list, e.g. for measurements
142+
/// the milliseconds in the entry date are set to this value
143+
const INTERPOLATION_MARKER = 123;

lib/helpers/measurements.dart

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
* along with this program. If not, see <http://www.gnu.org/licenses/>.
1717
*/
1818

19+
import 'package:wger/helpers/consts.dart';
1920
import 'package:wger/helpers/date.dart';
2021
import 'package:wger/widgets/measurements/charts.dart';
2122

@@ -95,8 +96,15 @@ MeasurementChartEntry interpolateBetween(
9596

9697
// Create a special DateTime with milliseconds ending in 123 to mark it as interpolated
9798
// which we leverage in the UI
98-
final markedDate =
99-
DateTime(date.year, date.month, date.day, date.hour, date.minute, date.second, 123);
99+
final markedDate = DateTime(
100+
date.year,
101+
date.month,
102+
date.day,
103+
date.hour,
104+
date.minute,
105+
date.second,
106+
INTERPOLATION_MARKER,
107+
);
100108

101109
return MeasurementChartEntry(
102110
before.value + (after.value - before.value) * (startDuration / totalDuration),

lib/widgets/measurements/charts.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ class _MeasurementChartWidgetFlState extends State<MeasurementChartWidgetFl> {
8888
DateFormat.Md(Localizations.localeOf(context).languageCode).format(date);
8989

9090
// Check if this is an interpolated point (milliseconds ending with 123)
91-
final bool isInterpolated = msSinceEpoch % 1000 == 123;
91+
final bool isInterpolated = msSinceEpoch % 1000 == INTERPOLATION_MARKER;
9292
final String interpolatedMarker = isInterpolated ? ' (interpolated)' : '';
9393

9494
return LineTooltipItem(
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import 'package:flutter_test/flutter_test.dart';
2+
import 'package:wger/helpers/consts.dart';
3+
import 'package:wger/helpers/measurements.dart';
4+
import 'package:wger/widgets/measurements/charts.dart';
5+
6+
void main() {
7+
group('whereDateWithInterpolation', () {
8+
// Helper to create entries
9+
MeasurementChartEntry entry(num value, DateTime date) => MeasurementChartEntry(value, date);
10+
11+
// Test: No interpolation needed, exact start and end dates exist
12+
test('returns entries within range when start and end exist', () {
13+
final entries = [
14+
entry(10, DateTime(2023, 1, 1)),
15+
entry(20, DateTime(2023, 1, 2)),
16+
entry(30, DateTime(2023, 1, 3)),
17+
];
18+
final result = entries.whereDateWithInterpolation(DateTime(2023, 1, 1), DateTime(2023, 1, 3));
19+
20+
// Entries on start and end date should be included if they exist
21+
expect(result.first.value, 10);
22+
expect(result.last.value, 20);
23+
});
24+
25+
// Test: Interpolates start if missing
26+
test('interpolates start if missing', () {
27+
final entries = [
28+
entry(10, DateTime(2023, 1, 1)),
29+
entry(30, DateTime(2023, 1, 3)),
30+
];
31+
final result = entries.whereDateWithInterpolation(DateTime(2023, 1, 2), DateTime(2023, 1, 3));
32+
33+
// Only the interpolated value for 2nd Jan is included
34+
expect(result.length, 1);
35+
expect(result.first.value, closeTo(20, 0.0001));
36+
expect(result.first.date.millisecond, INTERPOLATION_MARKER);
37+
expect(result.first.date.day, 2);
38+
});
39+
40+
// Test: Interpolates end if missing
41+
test('interpolates end if missing', () {
42+
final entries = [
43+
entry(10, DateTime(2023, 1, 1)),
44+
entry(30, DateTime(2023, 1, 3)),
45+
];
46+
final result = entries.whereDateWithInterpolation(DateTime(2023, 1, 1), DateTime(2023, 1, 2));
47+
// Should include the entry for 1st Jan and an interpolated value for 2nd Jan
48+
expect(result.length, 2);
49+
expect(result.first.value, 10);
50+
expect(result.first.date.day, 1);
51+
expect(result.last.value, closeTo(20, 0.0001));
52+
expect(result.last.date.day, 2);
53+
});
54+
55+
// Test: No interpolation if out of bounds
56+
test('returns empty if no data in range', () {
57+
final entries = [
58+
entry(10, DateTime(2023, 1, 1)),
59+
entry(20, DateTime(2023, 1, 2)),
60+
];
61+
final result = entries.whereDateWithInterpolation(DateTime(2023, 2, 1), DateTime(2023, 2, 2));
62+
expect(result, isEmpty);
63+
});
64+
65+
// Test: Only start interpolation if data exists before and after
66+
test('does not interpolate if no data before start', () {
67+
final entries = [
68+
entry(10, DateTime(2023, 1, 2)),
69+
entry(20, DateTime(2023, 1, 3)),
70+
];
71+
final result = entries.whereDateWithInterpolation(DateTime(2023, 1, 1), DateTime(2023, 1, 3));
72+
// No interpolation possible for Jan 1, only entry for Jan 2 is included
73+
expect(result.length, 1);
74+
expect(result.first.date.day, 2);
75+
});
76+
77+
// Test: Only end interpolation if data exists before and after
78+
test('does not interpolate if no data after end', () {
79+
final entries = [
80+
entry(10, DateTime(2023, 1, 1)),
81+
entry(20, DateTime(2023, 1, 2)),
82+
];
83+
final result = entries.whereDateWithInterpolation(DateTime(2023, 1, 1), DateTime(2023, 1, 3));
84+
// No interpolation possible for Jan 3, only entries for Jan 1 and Jan 2 are included
85+
expect(result.length, 2);
86+
expect(result.first.date.day, 1);
87+
expect(result.last.date.day, 2);
88+
});
89+
});
90+
}

0 commit comments

Comments
 (0)