Commit c0ced9e
Changed files (5)
lib
components
measurement_list
screens
test
lib/components/measurement_list/measurement_list_entry.dart
@@ -1,5 +1,6 @@
import 'package:blood_pressure_app/model/blood_pressure.dart';
import 'package:blood_pressure_app/model/settings_store.dart';
+import 'package:blood_pressure_app/screens/add_measurement.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:intl/intl.dart';
@@ -27,9 +28,7 @@ class MeasurementListRow extends StatelessWidget {
Text(formatter.format(record.creationTime), textAlign: TextAlign.right,),
const Spacer(),
IconButton(
- onPressed: () {
- // TODO: implement
- },
+ onPressed: () => _editEntry(context),
icon: const Icon(Icons.edit, color: Colors.blue,),
tooltip: localizations.edit,
),
@@ -106,4 +105,8 @@ class MeasurementListRow extends StatelessWidget {
));
}
}
+
+ void _editEntry(BuildContext context) async {
+ Navigator.push(context, MaterialPageRoute(builder: (context) => AddMeasurementPage.edit(record)));
+ }
}
lib/components/measurement_list.dart
@@ -87,18 +87,9 @@ class MeasurementList extends StatelessWidget {
confirmDismiss: (direction) async {
final model = Provider.of<BloodPressureModel>(context, listen: false);
if (direction == DismissDirection.startToEnd) { // edit
- model.delete(data[index].creationTime);
Navigator.push(
context,
- MaterialPageRoute(
- builder: (context) => AddMeasurementPage(
- initTime: data[index].creationTime,
- initSys: data[index].systolic,
- initDia: data[index].diastolic,
- initPul: data[index].pulse,
- initNote: data[index].notes,
- addInitialValuesOnCancel: true,
- )),
+ MaterialPageRoute(builder: (context) => AddMeasurementPage.edit(data[index])),
);
return false;
} else { // delete
lib/model/ram_only_implementations.dart
@@ -11,6 +11,14 @@ import 'horizontal_graph_line.dart';
class RamBloodPressureModel extends ChangeNotifier implements BloodPressureModel {
final List<BloodPressureRecord> _records = [];
+
+ static RamBloodPressureModel fromEntries(List<BloodPressureRecord> records) {
+ final m = RamBloodPressureModel();
+ for (var e in records) {
+ m.add(e);
+ }
+ return m;
+ }
@override
Future<void> add(BloodPressureRecord measurement) async {
lib/screens/add_measurement.dart
@@ -15,7 +15,7 @@ class AddMeasurementPage extends StatefulWidget {
final int? initDia;
final int? initPul;
final String? initNote;
- final bool addInitialValuesOnCancel;
+ final bool isEdit;
const AddMeasurementPage(
{super.key,
@@ -24,7 +24,18 @@ class AddMeasurementPage extends StatefulWidget {
this.initDia,
this.initPul,
this.initNote,
- this.addInitialValuesOnCancel = false});
+ this.isEdit = false});
+
+ static AddMeasurementPage edit(BloodPressureRecord record) {
+ return AddMeasurementPage(
+ initTime: record.creationTime,
+ initSys: record.systolic,
+ initDia: record.diastolic,
+ initPul: record.pulse,
+ initNote: record.notes,
+ isEdit: true,
+ );
+ }
@override
State<AddMeasurementPage> createState() => _AddMeasurementPageState();
@@ -146,6 +157,7 @@ class _AddMeasurementPageState extends State<AddMeasurementPage> {
}
),
TextFormField(
+ key: const Key('txtNote'),
initialValue: (_note ?? '').toString(),
minLines: 1,
maxLines: 4,
@@ -163,15 +175,6 @@ class _AddMeasurementPageState extends State<AddMeasurementPage> {
TextButton(
key: const Key('btnCancel'),
onPressed: () {
- if (widget.addInitialValuesOnCancel) {
- assert(widget.initTime != null);
- Provider.of<BloodPressureModel>(context, listen: false).add(BloodPressureRecord(
- widget.initTime ?? DateTime.now(),
- widget.initSys,
- widget.initDia,
- widget.initPul,
- widget.initNote ?? ''));
- }
Navigator.of(context).pop();
},
@@ -189,6 +192,12 @@ class _AddMeasurementPageState extends State<AddMeasurementPage> {
final model = Provider.of<BloodPressureModel>(context, listen: false);
final navigator = Navigator.of(context);
+ if (widget.isEdit) {
+ assert(widget.initTime != null);
+ if (widget.initTime != null) {
+ await model.delete(widget.initTime!);
+ }
+ }
await model.add(BloodPressureRecord(_time, _systolic, _diastolic, _pulse, _note ?? ''));
if (settings.exportAfterEveryEntry && context.mounted) {
final exporter = Exporter(settings, model, ScaffoldMessenger.of(context),
test/ui/add_measurement.dart
@@ -0,0 +1,112 @@
+import 'package:blood_pressure_app/model/blood_pressure.dart';
+import 'package:blood_pressure_app/model/ram_only_implementations.dart';
+import 'package:blood_pressure_app/model/settings_store.dart';
+import 'package:blood_pressure_app/screens/add_measurement.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_gen/gen_l10n/app_localizations.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:provider/provider.dart';
+
+void main() {
+ group("Add measurements page", () {
+ group('normal mode', () {
+ testWidgets('smoke test', (tester) async {
+ await _initPage(tester, const AddMeasurementPage());
+ expect(find.text('Systolic'), findsOneWidget);
+ expect(find.text('SAVE'), findsOneWidget);
+ });
+ testWidgets('should start empty', (tester) async {
+ await _initPage(tester, const AddMeasurementPage());
+ final sysInput = tester.widget<TextFormField>(
+ find.descendant(of: find.byKey(const Key('txtSys')), matching: find.byType(TextFormField)));
+ expect(sysInput.initialValue, '');
+ final diaInput = tester.widget<TextFormField>(
+ find.descendant(of: find.byKey(const Key('txtDia')), matching: find.byType(TextFormField)));
+ expect(diaInput.initialValue, '');
+ final pulInput = tester.widget<TextFormField>(
+ find.descendant(of: find.byKey(const Key('txtPul')), matching: find.byType(TextFormField)));
+ expect(pulInput.initialValue, '');
+ final noteInput = tester.widget<TextFormField>(find.byKey(const Key('txtNote')));
+ expect(noteInput.initialValue, '');
+ });
+ });
+ group('edit mode', () {
+ testWidgets('smoke test', (tester) async {
+ final record = BloodPressureRecord(DateTime.now(), 123, 89, 56, 'simple test note');
+ await _initPage(tester, AddMeasurementPage.edit(record),
+ model: RamBloodPressureModel.fromEntries([record])
+ );
+ expect(find.text('Systolic'), findsOneWidget);
+ expect(find.text('SAVE'), findsOneWidget);
+ });
+ testWidgets('should prefill', (tester) async {
+ final record = BloodPressureRecord(DateTime.now(), 123, 89, 56, 'simple test note');
+ await _initPage(tester, AddMeasurementPage.edit(record),
+ model: RamBloodPressureModel.fromEntries([record])
+ );
+
+ final sysInput = tester.widget<TextFormField>(
+ find.descendant(of: find.byKey(const Key('txtSys')), matching: find.byType(TextFormField)));
+ expect(sysInput.initialValue, record.systolic.toString());
+ final diaInput = tester.widget<TextFormField>(
+ find.descendant(of: find.byKey(const Key('txtDia')), matching: find.byType(TextFormField)));
+ expect(diaInput.initialValue, record.diastolic.toString());
+ final pulInput = tester.widget<TextFormField>(
+ find.descendant(of: find.byKey(const Key('txtPul')), matching: find.byType(TextFormField)));
+ expect(pulInput.initialValue, record.pulse.toString());
+ final noteInput = tester.widget<TextFormField>(find.byKey(const Key('txtNote')));
+ expect(noteInput.initialValue, record.notes);
+ });
+ testWidgets('should not delete on cancel', (tester) async {
+ final record = BloodPressureRecord(DateTime.now(), 123, 89, 56, 'simple test note');
+ final model = RamBloodPressureModel.fromEntries([record]);
+ await _initPage(tester, AddMeasurementPage.edit(record), model: model);
+ expect((await model.all).first, record);
+
+ expect(find.byKey(const Key ('txtNote')), findsOneWidget);
+ await tester.enterText(find.byKey(const Key ('txtNote')), 'edited text');
+
+ expect(find.byKey(const Key('btnCancel')), findsOneWidget);
+ await tester.tap(find.byKey(const Key('btnCancel')));
+ await tester.pumpAndSettle();
+ expect((await model.all).first.notes, 'simple test note');
+ expect((await model.all).first, record);
+ });
+ testWidgets('should save changes', (tester) async {
+ final record = BloodPressureRecord(DateTime.now(), 123, 89, 56, 'simple test note');
+ final model = RamBloodPressureModel.fromEntries([record]);
+ await _initPage(tester, AddMeasurementPage.edit(record), model: model);
+ expect((await model.all).first, record);
+
+ expect(find.byKey(const Key ('txtNote')), findsOneWidget);
+ await tester.enterText(find.byKey(const Key ('txtNote')), 'edited text');
+
+ expect(find.byKey(const Key('btnSave')), findsOneWidget);
+ await tester.tap(find.byKey(const Key('btnSave')));
+ await tester.pumpAndSettle();
+ expect((await model.all).first.notes, 'edited text');
+ });
+ });
+ });
+}
+
+Future<void> _initPage(WidgetTester widgetTester, Widget pageWidget, {Settings? settings, BloodPressureModel? model}) async {
+ await widgetTester.pumpWidget(
+ MaterialApp(
+ home: MultiProvider(
+ providers: [
+ ChangeNotifierProvider<Settings>(create: (_) => settings ?? RamSettings()),
+ ChangeNotifierProvider<BloodPressureModel>(create: (_) => model ?? RamBloodPressureModel()),
+ ],
+ child: Localizations(
+ delegates: AppLocalizations.localizationsDelegates,
+ locale: const Locale('en'),
+ child: pageWidget,
+ )
+ )
+ ),
+ );
+
+ await widgetTester.pumpAndSettle();
+}
+