main
1import 'package:blood_pressure_app/features/statistics/value_graph.dart';
2import 'package:blood_pressure_app/model/horizontal_graph_line.dart';
3import 'package:blood_pressure_app/model/storage/storage.dart';
4import 'package:collection/collection.dart';
5import 'package:flutter/material.dart';
6import 'package:blood_pressure_app/l10n/app_localizations.dart';
7import 'package:flutter_test/flutter_test.dart';
8import 'package:health_data_store/health_data_store.dart';
9import 'package:provider/provider.dart';
10
11import '../../model/analyzer_test.dart';
12import '../../util.dart';
13import '../measurement_list/measurement_list_entry_test.dart';
14
15void main() {
16 test('Creates correct sys series', () {
17 final records = [
18 mockRecord(time: DateTime(2000), sys: 123),
19 mockRecord(time: DateTime(2001), sys: 120),
20 // ignore: avoid_redundant_argument_values
21 mockRecord(time: DateTime(2002), sys: null),
22 mockRecord(time: DateTime(2003), sys: 123),
23 mockRecord(time: DateTime(2004), sys: 200),
24 ];
25 assert(records.isSorted((a, b) => a.time.compareTo(b.time)));
26
27 final graph = records.sysGraph();
28 expect(graph, hasLength(4));
29 expect(graph.isSorted((a, b) => a.$1.compareTo(b.$1)), isTrue);
30 expect(graph.elementAt(0).$2, 123);
31 expect(graph.elementAt(1).$2, 120);
32 expect(graph.elementAt(2).$2, 123);
33 expect(graph.elementAt(3).$2, 200);
34 });
35 test('Creates correct dia series', () {
36 final records = [
37 mockRecord(time: DateTime(2000), dia: 123),
38 mockRecord(time: DateTime(2001), dia: 120),
39 // ignore: avoid_redundant_argument_values
40 mockRecord(time: DateTime(2002), dia: null),
41 mockRecord(time: DateTime(2003), dia: 123),
42 mockRecord(time: DateTime(2004), dia: 200),
43 ];
44 assert(records.isSorted((a, b) => a.time.compareTo(b.time)));
45
46 final graph = records.diaGraph();
47 expect(graph, hasLength(4));
48 expect(graph.isSorted((a, b) => a.$1.compareTo(b.$1)), isTrue);
49 expect(graph.elementAt(0).$2, 123);
50 expect(graph.elementAt(1).$2, 120);
51 expect(graph.elementAt(2).$2, 123);
52 expect(graph.elementAt(3).$2, 200);
53 });
54 test('Creates correct pul series', () {
55 final records = [
56 mockRecord(time: DateTime(2000), pul: 123),
57 mockRecord(time: DateTime(2001), pul: 120),
58 // ignore: avoid_redundant_argument_values
59 mockRecord(time: DateTime(2002), pul: null),
60 mockRecord(time: DateTime(2003), pul: 123),
61 mockRecord(time: DateTime(2004), pul: 200),
62 ];
63 assert(records.isSorted((a, b) => a.time.compareTo(b.time)));
64
65 final graph = records.pulGraph();
66 expect(graph, hasLength(4));
67 expect(graph.isSorted((a, b) => a.$1.compareTo(b.$1)), isTrue);
68 expect(graph.elementAt(0).$2, 123.0);
69 expect(graph.elementAt(1).$2, 120.0);
70 expect(graph.elementAt(2).$2, 123.0);
71 expect(graph.elementAt(3).$2, 200.0);
72 });
73 testWidgets('BloodPressureValueGraph shows when there are not enough values', (tester) async {
74 await tester.pumpWidget(_buildGraph([], [], []));
75 final localizations = await AppLocalizations.delegate.load(const Locale('en'));
76 expect(find.text(localizations.errNotEnoughDataToGraph), findsOneWidget);
77 });
78 testWidgets('[gold] graph with all extras is rendered correctly', (tester) async {
79 await tester.pumpWidget(_buildGraph([
80 mockRecord(time: DateTime(2005), sys: 123, dia: 80, pul: 50),
81 mockRecord(time: DateTime(2003), sys: 110, dia: 73, pul: 130),
82 mockRecord(time: DateTime(2003, 5), sys: 140, dia: 74, pul: 64),
83 mockRecord(time: DateTime(2007), sys: 132, dia: 100, pul: 75),
84 ], [
85 (DateTime(2005), Colors.purple),
86 (DateTime(2005, 3), Colors.tealAccent),
87 (DateTime(2007), Colors.yellow),
88 ], [
89 mockIntake(mockMedicine(color: Colors.blueGrey), time: DateTime(2005).millisecondsSinceEpoch),
90 mockIntake(mockMedicine(color: Colors.indigoAccent), time: DateTime(2004).millisecondsSinceEpoch),
91 ],
92 settings: Settings(
93 drawRegressionLines: true,
94 graphLineThickness: 3.2,
95 diaWarn: 75,
96 needlePinBarWidth: 7.0,
97 horizontalGraphLines: [
98 HorizontalGraphLine(Colors.lightBlue, 113),
99 HorizontalGraphLine(Colors.amber, 45),
100 ]
101 )));
102 await tester.pumpAndSettle();
103 final localizations = await AppLocalizations.delegate.load(const Locale('en'));
104 expect(find.text(localizations.errNotEnoughDataToGraph), findsNothing);
105
106 await expectLater(find.byType(BloodPressureValueGraph), myMatchesGoldenFile('full_graph-years.png'));
107 }, tags: 'gold');
108
109 testWidgets('BloodPressureValueGraph is fine with enough values in sys category', (tester) async {
110 await tester.pumpWidget(_buildGraph([
111 mockRecord(time: DateTime(2005), sys: 123),
112 mockRecord(time: DateTime(2003), sys: 110),
113 ], [], []));
114 final localizations = await AppLocalizations.delegate.load(const Locale('en'));
115 expect(find.text(localizations.errNotEnoughDataToGraph), findsNothing);
116 });
117 testWidgets('BloodPressureValueGraph is fine with enough values in dia category', (tester) async {
118 await tester.pumpWidget(_buildGraph([
119 mockRecord(time: DateTime(2005), dia: 123),
120 mockRecord(time: DateTime(2003), dia: 110),
121 ], [], []));
122 final localizations = await AppLocalizations.delegate.load(const Locale('en'));
123 expect(find.text(localizations.errNotEnoughDataToGraph), findsNothing);
124 });
125 testWidgets('BloodPressureValueGraph is fine with enough values in pul category', (tester) async {
126 await tester.pumpWidget(_buildGraph([
127 mockRecord(time: DateTime(2005), pul: 123),
128 mockRecord(time: DateTime(2003), pul: 110),
129 ], [], []));
130 final localizations = await AppLocalizations.delegate.load(const Locale('en'));
131 expect(find.text(localizations.errNotEnoughDataToGraph), findsNothing);
132 });
133
134 testWidgets('[gold] graph renders area at start correctly', (tester) async {
135 await tester.pumpWidget(_buildGraph([
136 mockRecord(time: DateTime(2003), sys: 170, dia: 100, pul: 50),
137 mockRecord(time: DateTime(2005), sys: 110, dia: 70, pul: 50),
138 ], [], [],
139 settings: Settings(
140 diaWarn: 75,
141 sysWarn: 120,
142 ),
143 ));
144 await tester.pumpAndSettle();
145 final localizations = await AppLocalizations.delegate.load(const Locale('en'));
146 expect(find.text(localizations.errNotEnoughDataToGraph), findsNothing);
147
148 await expectLater(find.byType(BloodPressureValueGraph), myMatchesGoldenFile('value-graph-start-warn.png'));
149 }, tags: 'gold');
150 testWidgets('[gold] graph renders area at end correctly', (tester) async {
151 await tester.pumpWidget(_buildGraph([
152 mockRecord(time: DateTime(2005), sys: 170, dia: 100, pul: 50),
153 mockRecord(time: DateTime(2003), sys: 110, dia: 70, pul: 50),
154 ], [], [],
155 settings: Settings(
156 diaWarn: 75,
157 sysWarn: 120,
158 ),
159 ));
160 await tester.pumpAndSettle();
161 final localizations = await AppLocalizations.delegate.load(const Locale('en'));
162 expect(find.text(localizations.errNotEnoughDataToGraph), findsNothing);
163
164 await expectLater(find.byType(BloodPressureValueGraph), myMatchesGoldenFile('value-graph-end-warn.png'));
165 }, tags: 'gold');
166 testWidgets('[gold] warn area not drawn above graph', (tester) async {
167 await tester.pumpWidget(_buildGraph([
168 mockRecord(time: DateTime(2005), sys: 103, dia: null, pul: null),
169 mockRecord(time: DateTime(2003), sys: 89, dia: null, pul: null),
170 ], [], [],
171 settings: Settings(sysWarn: 120),
172 ));
173 await tester.pumpAndSettle();
174 final localizations = await AppLocalizations.delegate.load(const Locale('en'));
175 expect(find.text(localizations.errNotEnoughDataToGraph), findsNothing);
176
177 await expectLater(find.byType(BloodPressureValueGraph), myMatchesGoldenFile('value-graph-warn-not-above.png'));
178 }, tags: 'gold');
179}
180
181Widget _buildGraph(
182 List<BloodPressureRecord> data,
183 List<(DateTime, Color)> colors,
184 List<MedicineIntake> intakes, {
185 Settings? settings,
186}) => materialApp(ChangeNotifierProvider<Settings>.value(
187 value: settings ?? Settings(),
188 child: SizedBox(
189 width: 500,
190 height: 300,
191 child: BloodPressureValueGraph(
192 records: data,
193 colors: colors.map((e) => Note(time: e.$1, color: e.$2.toARGB32())).toList(),
194 intakes: intakes,
195 ),
196 ),
197));