Commit 26ab28c
Changed files (14)
.github
workflows
app
lib
features
export_import
test
health_data_store
lib
src
types
units
.github/workflows/pr.yml
@@ -100,7 +100,7 @@ jobs:
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
- channel: ${{ matrix.channel }}
+ channel: ${{ matrix.channel }} # FIXME: only use one channel type for this
cache: true
- name: Disable analytics
run:
app/lib/features/export_import/add_export_column_dialoge.dart
@@ -173,7 +173,7 @@ class _AddExportColumnDialogeState extends State<AddExportColumnDialoge>
final formatter = (type == _FormatterType.record)
? ScriptedFormatter(recordPattern ?? '')
: ScriptedTimeFormatter(timePattern ?? '');
- final text = formatter.encode(record, note, []);
+ final text = formatter.encode(record, note, [], null);
final decoded = formatter.decode(text);
return Column(
children: [
app/lib/model/export_import/column.dart
@@ -24,12 +24,13 @@ class NativeColumn extends ExportColumn {
color,
needlePin,
intakes,
+ bodyweight,
];
static final NativeColumn timestampUnixMs = NativeColumn._create(
'timestampUnixMs',
RowDataFieldType.timestamp,
- (record, _, __) => record.time.millisecondsSinceEpoch.toString(),
+ (record, _, __, ___) => record.time.millisecondsSinceEpoch.toString(),
(pattern) {
final value = int.tryParse(pattern);
return (value == null) ? null : DateTime.fromMillisecondsSinceEpoch(value);
@@ -38,31 +39,31 @@ class NativeColumn extends ExportColumn {
static final NativeColumn systolic = NativeColumn._create(
'systolic',
RowDataFieldType.sys,
- (record, _, __) => (record.sys?.mmHg).toString(),
+ (record, _, __, ___) => (record.sys?.mmHg).toString(),
int.tryParse,
);
static final NativeColumn diastolic = NativeColumn._create(
'diastolic',
RowDataFieldType.dia,
- (record, _, __) => (record.dia?.mmHg).toString(),
+ (record, _, __, ___) => (record.dia?.mmHg).toString(),
int.tryParse,
);
static final NativeColumn pulse = NativeColumn._create(
'pulse',
RowDataFieldType.pul,
- (record, _, __) => record.pul.toString(),
+ (record, _, __, ___) => record.pul.toString(),
int.tryParse,
);
static final NativeColumn notes = NativeColumn._create(
'notes',
RowDataFieldType.notes,
- (_, note, __) => note.note ?? '',
+ (_, note, __, ___) => note.note ?? '',
(pattern) => pattern,
);
static final NativeColumn color = NativeColumn._create(
'color',
RowDataFieldType.color,
- (_, note, __) => note.color?.toString() ?? '',
+ (_, note, __, ___) => note.color?.toString() ?? '',
(pattern) {
final value = int.tryParse(pattern);
return value;
@@ -71,7 +72,7 @@ class NativeColumn extends ExportColumn {
static final NativeColumn needlePin = NativeColumn._create(
'needlePin',
RowDataFieldType.color,
- (_, note, __) => '{"color":${note.color}}',
+ (_, note, __, ___) => '{"color":${note.color}}',
(pattern) {
try {
final json = jsonDecode(pattern);
@@ -91,7 +92,7 @@ class NativeColumn extends ExportColumn {
static final NativeColumn intakes = NativeColumn._create(
'intakes',
RowDataFieldType.intakes,
- (_, __, intakes) => intakes
+ (_, __, intakes, ___) => intakes
.map((i) => '${i.medicine.designation}(${i.dosis.mg})')
.join('|'),
(String pattern) {
@@ -107,10 +108,16 @@ class NativeColumn extends ExportColumn {
return intakes;
}
);
+ static final NativeColumn bodyweight = NativeColumn._create(
+ 'bodyweight',
+ RowDataFieldType.weightKg,
+ (_, __, ___, weight) => weight?.kg.toString() ?? '',
+ double.tryParse,
+ );
final String _csvTitle;
final RowDataFieldType _restoreableType;
- final String Function(BloodPressureRecord record, Note note, List<MedicineIntake> intakes) _encode;
+ final String Function(BloodPressureRecord record, Note note, List<MedicineIntake> intakes, Weight? bodyweight) _encode;
/// Function to attempt decoding.
///
/// Must either return null or the type indicated by [_restoreableType].
@@ -127,8 +134,8 @@ class NativeColumn extends ExportColumn {
}
@override
- String encode(BloodPressureRecord record, Note note, List<MedicineIntake> intakes) =>
- _encode(record, note, intakes);
+ String encode(BloodPressureRecord record, Note note, List<MedicineIntake> intakes, Weight? bodyweight) =>
+ _encode(record, note, intakes, bodyweight);
@override
String? get formatPattern => null;
@@ -243,8 +250,8 @@ class BuildInColumn extends ExportColumn {
(RowDataFieldType, dynamic)? decode(String pattern) => _formatter.decode(pattern);
@override
- String encode(BloodPressureRecord record, Note note, List<MedicineIntake> intakes) =>
- _formatter.encode(record, note, intakes);
+ String encode(BloodPressureRecord record, Note note, List<MedicineIntake> intakes, Weight? bodyweight) =>
+ _formatter.encode(record, note, intakes, bodyweight);
@override
String? get formatPattern => _formatter.formatPattern;
@@ -289,8 +296,8 @@ class UserColumn extends ExportColumn {
(RowDataFieldType, dynamic)? decode(String pattern) => formatter.decode(pattern);
@override
- String encode(BloodPressureRecord record, Note note, List<MedicineIntake> intakes) =>
- formatter.encode(record, note, intakes);
+ String encode(BloodPressureRecord record, Note note, List<MedicineIntake> intakes, Weight? bodyweight) =>
+ formatter.encode(record, note, intakes, bodyweight);
@override
String? get formatPattern => formatter.formatPattern;
@@ -328,9 +335,9 @@ class TimeColumn extends ExportColumn {
}
@override
- String encode(BloodPressureRecord record, Note note, List<MedicineIntake> intakes) {
+ String encode(BloodPressureRecord record, Note note, List<MedicineIntake> intakes, Weight? bodyweight) {
_formatter ??= ScriptedTimeFormatter(formatPattern);
- return _formatter!.encode(record, note, intakes);
+ return _formatter!.encode(record, note, intakes, bodyweight);
}
@override
app/lib/model/export_import/csv_converter.dart
@@ -22,11 +22,11 @@ class CsvConverter {
final List<Medicine> availableMedicines;
/// Create the contents of a csv file from passed records.
- String create(List<FullEntry> entries) {
+ String create(List<(DateTime, BloodPressureRecord, Note, List<MedicineIntake>, Weight?)> entries) {
final columns = settings.exportFieldsConfiguration.getActiveColumns(availableColumns);
final table = entries.map(
(entry) => columns.map(
- (column) => column.encode(entry.$1, entry.$2, entry.$3),
+ (column) => column.encode(entry.$2, entry.$3, entry.$4, entry.$5),
).toList(),
).toList();
@@ -116,7 +116,7 @@ class CsvConverter {
final List<(RowDataFieldType, dynamic)> recordPieces = [];
for (int fieldIndex = 0; fieldIndex < parsers.length; fieldIndex++) {
final parser = parsers[fieldIndex];
- (RowDataFieldType, dynamic)? piece = parser?.decode(currentLine[fieldIndex]);
+ final (RowDataFieldType, dynamic)? piece = parser?.decode(currentLine[fieldIndex]);
// Validate that the column parsed the expected type.
// Null can be the result of empty fields.
if (piece?.$1 != parser?.restoreAbleType
@@ -172,7 +172,7 @@ class CsvConverter {
if (med == null) return null;
return MedicineIntake(time: timestamp, medicine: med, dosis: Weight.mg(s.$2));
})
- .whereNotNull()
+ .nonNulls
.toList();
entries.add((record, note, intakes ?? []));
currentLineNumber++;
app/lib/model/export_import/export_configuration.dart
@@ -94,6 +94,7 @@ class ActiveExportColumnConfiguration extends ChangeNotifier {
NativeColumn.notes,
NativeColumn.color,
NativeColumn.intakes,
+ NativeColumn.bodyweight,
],
ExportImportPreset.myHeart => [
BuildInColumn.mhDate,
app/lib/model/export_import/import_field_type.dart
@@ -21,7 +21,9 @@ enum RowDataFieldType {
/// Backwards compatability with [MeasurementNeedlePin] json is maintained.
color,
/// Guarantees [List<(String medicineDesignation, double dosisMg)>] is returned.
- intakes;
+ intakes,
+ /// Guarantees a [double] is parsed.
+ weightKg;
/// Select the matching string from [localizations].
String localize(AppLocalizations localizations) => switch(this) {
@@ -32,5 +34,6 @@ enum RowDataFieldType {
notes => localizations.notes,
color => localizations.color,
intakes => localizations.intakes,
+ weightKg => localizations.weight,
};
}
app/lib/model/export_import/pdf_converter.dart
@@ -30,11 +30,11 @@ class PdfConverter {
final ExportColumnsManager availableColumns;
/// Create a pdf from a record list.
- Future<Uint8List> create(List<FullEntry> entries) async {
+ Future<Uint8List> create(List<(DateTime, BloodPressureRecord, Note, List<MedicineIntake>, Weight?)> entries) async {
final pdf = pw.Document(
creator: 'Blood pressure app',
);
- final analyzer = BloodPressureAnalyser(entries.records);
+ final analyzer = BloodPressureAnalyser(entries.map((e) => e.$2).toList());
pdf.addPage(pw.MultiPage(
pageFormat: PdfPageFormat.a4,
@@ -88,12 +88,11 @@ class PdfConverter {
),
);
- pw.Widget _buildPdfTable(Iterable<FullEntry> entries, double availableHeightOnFirstPage) {
+ pw.Widget _buildPdfTable(Iterable<(DateTime, BloodPressureRecord, Note, List<MedicineIntake>, Weight?)> entries, double availableHeightOnFirstPage) {
final columns = pdfSettings.exportFieldsConfiguration.getActiveColumns(availableColumns);
-
final data = entries.map(
(entry) => columns.map(
- (column) => column.encode(entry.$1, entry.$2, entry.$3),
+ (column) => column.encode(entry.$2, entry.$3, entry.$4, entry.$5),
).toList(),
).toList();
@@ -262,5 +261,5 @@ class PdfConverter {
}
extension _PdfCompatability on Color {
- PdfColor toPdfColor() => PdfColor(red / 256, green / 256, blue / 256, opacity);
+ PdfColor toPdfColor() => PdfColor(r / 256, g / 256, b / 256, a);
}
app/lib/model/export_import/record_formatter.dart
@@ -16,7 +16,7 @@ abstract interface class Formatter {
///
/// There is no guarantee that the information in the record can be restored.
/// If not null this must follow [formatPattern].
- String encode(BloodPressureRecord record, Note note, List<MedicineIntake> intakes);
+ String encode(BloodPressureRecord record, Note note, List<MedicineIntake> intakes, Weight? bodyweight);
/// Type of data that can be restored from a string obtained by [encode].
RowDataFieldType? get restoreAbleType;
@@ -57,13 +57,14 @@ class ScriptedFormatter implements Formatter {
} on FormatException { return null; } on TypeError { return null; }
}(),
RowDataFieldType.intakes => NativeColumn.intakes.decode(text),
+ RowDataFieldType.weightKg => double.tryParse(text),
};
if (value != null) return (restoreAbleType!, value);
return null;
}
@override
- String encode(BloodPressureRecord record, Note note, List<MedicineIntake> intakes) {
+ String encode(BloodPressureRecord record, Note note, List<MedicineIntake> intakes, Weight? bodyweight) {
var fieldContents = pattern;
// variables
@@ -73,6 +74,7 @@ class ScriptedFormatter implements Formatter {
fieldContents = fieldContents.replaceAll(r'$PUL', record.pul.toString());
fieldContents = fieldContents.replaceAll(r'$NOTE', note.note ?? '');
fieldContents = fieldContents.replaceAll(r'$COLOR', note.color?.toString() ?? '');
+ // TODO: Weight? formatter, use for mhWeight
// math
fieldContents = fieldContents.replaceAllMapped(RegExp(r'\{\{([^}]*)}}'), (m) {
@@ -185,7 +187,7 @@ class ScriptedTimeFormatter implements Formatter {
}
@override
- String encode(BloodPressureRecord record, Note note, List<MedicineIntake> intakes) =>
+ String encode(BloodPressureRecord record, Note note, List<MedicineIntake> intakes, Weight? _) =>
_timeFormatter.format(record.time);
@override
app/test/model/export_import/column_test.dart
@@ -31,7 +31,7 @@ void main() {
// Use BuildInColumn for utility columns
for (final c in NativeColumn.allColumns) {
final r = _filledRecord(true);
- expect(c.encode(r.$1, r.$2, r.$3), isNotEmpty, reason: '${c.internalIdentifier} is NativeColumn');
+ expect(c.encode(r.$1, r.$2, r.$3, Weight.kg(123)), isNotEmpty, reason: '${c.internalIdentifier} is NativeColumn');
}
});
test('should only contain restoreable types', () {
@@ -43,7 +43,7 @@ void main() {
test('should decode correctly', () {
final r = _filledRecord(true);
for (final c in NativeColumn.allColumns) {
- final txt = c.encode(r.$1, r.$2, r.$3);
+ final txt = c.encode(r.$1, r.$2, r.$3, Weight.kg(123));
final decoded = c.decode(txt);
expect(decoded, isNotNull, reason: 'a real value was encoded: ${c.internalIdentifier}: ${r.debugToString()} > $txt');
switch (decoded!.$1) {
@@ -71,6 +71,9 @@ void main() {
.having((p0) => p0.length, 'length', 1,)
.having((p0) => p0[0].$1, 'designation', 'mockMed',)
.having((p0) => p0[0].$2, 'dosis', 123.4,));
+ case RowDataFieldType.weightKg:
+ expect(decoded.$2, isA<double>()
+ .having((p0) => p0, 'weight', 123.0));
}
}
});
@@ -98,13 +101,13 @@ void main() {
test('should encode without problems', () {
for (final c in BuildInColumn.allColumns) {
final r = _filledRecord();
- expect(c.encode(r.$1, r.$2, r.$3), isNotNull);
+ expect(c.encode(r.$1, r.$2, r.$3, null), isNotNull);
}
});
test('should decode correctly', () {
final r = _filledRecord(true);
for (final c in BuildInColumn.allColumns) {
- final txt = c.encode(r.$1, r.$2, r.$3);
+ final txt = c.encode(r.$1, r.$2, r.$3, Weight.kg(123.45));
final decoded = c.decode(txt);
switch (decoded?.$1) {
case RowDataFieldType.timestamp:
@@ -138,8 +141,11 @@ void main() {
.having((p0) => p0.length, 'length', 1,)
.having((p0) => p0[0].$1, 'designation', 'mockMed',)
.having((p0) => p0[0].$2, 'dosis', 123.4,));
+ case RowDataFieldType.weightKg:
+ expect(decoded?.$2, isA<double>()
+ .having((p0) => p0, 'weight', 123.45));
case null:
- // no-op
+ // no-op
}
}
});
@@ -153,24 +159,24 @@ void main() {
test('should encode like ScriptedFormatter', () {
final r = _filledRecord();
expect(
- UserColumn('','', 'TEST').encode(r.$1, r.$2, r.$3),
- ScriptedFormatter('TEST').encode(r.$1, r.$2, r.$3),
+ UserColumn('','', 'TEST').encode(r.$1, r.$2, r.$3, null),
+ ScriptedFormatter('TEST').encode(r.$1, r.$2, r.$3, null),
);
expect(
- UserColumn('','', r'$SYS').encode(r.$1, r.$2, r.$3),
- ScriptedFormatter(r'$SYS').encode(r.$1, r.$2, r.$3),
+ UserColumn('','', r'$SYS').encode(r.$1, r.$2, r.$3, null),
+ ScriptedFormatter(r'$SYS').encode(r.$1, r.$2, r.$3, null),
);
expect(
- UserColumn('','', r'$SYS-$DIA').encode(r.$1, r.$2, r.$3),
- ScriptedFormatter(r'$SYS-$DIA').encode(r.$1, r.$2, r.$3),
+ UserColumn('','', r'$SYS-$DIA').encode(r.$1, r.$2, r.$3, null),
+ ScriptedFormatter(r'$SYS-$DIA').encode(r.$1, r.$2, r.$3, null),
);
expect(
- UserColumn('','', r'$TIMESTAMP').encode(r.$1, r.$2, r.$3),
- ScriptedFormatter(r'$TIMESTAMP').encode(r.$1, r.$2, r.$3),
+ UserColumn('','', r'$TIMESTAMP').encode(r.$1, r.$2, r.$3, null),
+ ScriptedFormatter(r'$TIMESTAMP').encode(r.$1, r.$2, r.$3, null),
);
expect(
- UserColumn('','', '').encode(r.$1, r.$2, r.$3),
- ScriptedFormatter('').encode(r.$1, r.$2, r.$3),
+ UserColumn('','', '').encode(r.$1, r.$2, r.$3, null),
+ ScriptedFormatter('').encode(r.$1, r.$2, r.$3, null),
);
});
test('should decode like ScriptedFormatter', () {
@@ -181,8 +187,8 @@ void main() {
final column = UserColumn('','', pattern);
final formatter = ScriptedFormatter(pattern);
expect(
- column.decode(column.encode(r.$1, r.$2, r.$3)),
- formatter.decode(formatter.encode(r.$1, r.$2, r.$3)),
+ column.decode(column.encode(r.$1, r.$2, r.$3, null)),
+ formatter.decode(formatter.encode(r.$1, r.$2, r.$3, null)),
);
}
});
app/test/model/export_import/csv_converter_test.dart
@@ -40,18 +40,18 @@ void main() {
test('should be able to recreate records from csv in default configuration', () {
final converter = CsvConverter(CsvExportSettings(), ExportColumnsManager(), []);
- final initialRecords = createRecords();
+ final List<(DateTime, BloodPressureRecord, Note, List<MedicineIntake>, Weight?)> initialRecords = createRecords();
final csv = converter.create(initialRecords);
- final parsedRecords = converter.parse(csv).getOr(failParse);
+ final List<FullEntry> parsedRecords = converter.parse(csv).getOr(failParse);
expect(parsedRecords, pairwiseCompare(initialRecords,
- (FullEntry p0, FullEntry p1) =>
- p0.$1.time == p1.$1.time &&
- p0.$1.sys == p1.$1.sys &&
- p0.$1.dia == p1.$1.dia &&
- p0.$1.pul == p1.$1.pul &&
- p0.$2.note == p1.$2.note &&
- p0.$2.color == p1.$2.color,
+ ((DateTime, BloodPressureRecord, Note, List<MedicineIntake>, Weight?) p0, FullEntry p1) =>
+ p0.$2.time == p1.$2.time &&
+ p0.$2.sys == p1.$1.sys &&
+ p0.$2.dia == p1.$1.dia &&
+ p0.$2.pul == p1.$1.pul &&
+ p0.$3.note == p1.$2.note &&
+ p0.$3.color == p1.$2.color,
'equal to',),);
});
test('should allow partial imports', () {
@@ -354,11 +354,12 @@ void main() {
});
}
-List<FullEntry> createRecords([int count = 20]) => [
+List<(DateTime, BloodPressureRecord, Note, List<MedicineIntake>, Null)> createRecords([int count = 20]) => [
for (int i = 0; i<count; i++)
mockEntryPos(DateTime.fromMillisecondsSinceEpoch(123456 + i),
i, 100+i, 200+1, 'note $i', Color(123+i),),
-];
+].map((e) => (e.time, e.recordObj, e.noteObj, e.intakes, null))
+ .toList();
List<FullEntry>? failParse(EntryParsingError error) {
switch (error) {
app/test/model/export_import/pdf_converter_test.dart
@@ -7,21 +7,22 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:health_data_store/health_data_store.dart';
+import 'csv_converter_test.dart';
import 'record_formatter_test.dart';
void main() {
test('should not return empty data', () async {
final localizations = await AppLocalizations.delegate.load(const Locale('en'));
final converter = PdfConverter(PdfExportSettings(), localizations, Settings(), ExportColumnsManager());
- final pdf = await converter.create(_createRecords());
+ final pdf = await converter.create(createRecords());
expect(pdf.length, isNonZero);
});
test('generated data length should be consistent', () async {
final localizations = await AppLocalizations.delegate.load(const Locale('en'));
final converter = PdfConverter(PdfExportSettings(), localizations, Settings(), ExportColumnsManager());
- final pdf = await converter.create(_createRecords());
+ final pdf = await converter.create(createRecords());
final converter2 = PdfConverter(PdfExportSettings(), localizations, Settings(), ExportColumnsManager());
- final pdf2 = await converter2.create(_createRecords());
+ final pdf2 = await converter2.create(createRecords());
expect(pdf.length, pdf2.length);
});
@@ -34,29 +35,24 @@ void main() {
);
final converter = PdfConverter(pdfSettings, localizations, Settings(), ExportColumnsManager());
- final pdf1 = await converter.create(_createRecords());
+ final pdf1 = await converter.create(createRecords());
pdfSettings.exportData = false;
- final pdf2 = await converter.create(_createRecords());
+ final pdf2 = await converter.create(createRecords());
expect(pdf1.length, isNot(pdf2.length));
expect(pdf1.length, greaterThan(pdf2.length));
pdfSettings.exportStatistics = false;
- final pdf3 = await converter.create(_createRecords());
+ final pdf3 = await converter.create(createRecords());
expect(pdf3.length, isNot(pdf2.length));
expect(pdf3.length, isNot(pdf1.length));
expect(pdf2.length, greaterThan(pdf3.length));
pdfSettings.exportTitle = false;
pdfSettings.exportData = true;
- final pdf4 = await converter.create(_createRecords());
+ final pdf4 = await converter.create(createRecords());
expect(pdf4.length, isNot(pdf1.length));
expect(pdf1.length, greaterThan(pdf4.length));
});
}
-List<FullEntry> _createRecords([int count = 20]) => [
- for (int i = 0; i<count; i++)
- mockEntryPos(DateTime.fromMillisecondsSinceEpoch(123456 + i),
- i, 100+i, 200+1, 'note $i', Color(123+i),),
-];
app/test/model/export_import/record_formatter_test.dart
@@ -12,38 +12,38 @@ void main() {
expect(f.formatPattern, r'$SYS');
final r1 = mockEntryPos(DateTime.now(), 123, 456, 789, 'test text');
- f.encode(r1.$1, r1.$2, r1.$3);
+ f.encode(r1.$1, r1.$2, r1.$3, null);
final r2 = mockEntry();
- f.encode(r2.$1, r2.$2, r2.$3);
+ f.encode(r2.$1, r2.$2, r2.$3, null);
f.decode('123');
});
test('should create correct strings', () {
final r = mockEntryPos(DateTime.fromMillisecondsSinceEpoch(31415926), 123, 45, 67, 'Test', Colors.red);
- expect(ScriptedFormatter(r'constant text',).encode(r.$1, r.$2, r.$3), 'constant text');
- expect(ScriptedFormatter(r'$SYS',).encode(r.$1, r.$2, r.$3), r.$1.sys?.mmHg.toString());
- expect(ScriptedFormatter(r'$DIA',).encode(r.$1, r.$2, r.$3), r.$1.dia?.mmHg.toString());
- expect(ScriptedFormatter(r'$PUL',).encode(r.$1, r.$2, r.$3), r.$1.pul.toString());
- expect(ScriptedFormatter(r'$COLOR',).encode(r.$1, r.$2, r.$3), r.$2.color.toString());
- expect(ScriptedFormatter(r'$NOTE',).encode(r.$1, r.$2, r.$3), r.$2.note);
- expect(ScriptedFormatter(r'$TIMESTAMP',).encode(r.$1, r.$2, r.$3), r.$1.time.millisecondsSinceEpoch.toString());
+ expect(ScriptedFormatter(r'constant text',).encode(r.$1, r.$2, r.$3, null), 'constant text');
+ expect(ScriptedFormatter(r'$SYS',).encode(r.$1, r.$2, r.$3, null), r.$1.sys?.mmHg.toString());
+ expect(ScriptedFormatter(r'$DIA',).encode(r.$1, r.$2, r.$3, null), r.$1.dia?.mmHg.toString());
+ expect(ScriptedFormatter(r'$PUL',).encode(r.$1, r.$2, r.$3, null), r.$1.pul.toString());
+ expect(ScriptedFormatter(r'$COLOR',).encode(r.$1, r.$2, r.$3, null), r.$2.color.toString());
+ expect(ScriptedFormatter(r'$NOTE',).encode(r.$1, r.$2, r.$3, null), r.$2.note);
+ expect(ScriptedFormatter(r'$TIMESTAMP',).encode(r.$1, r.$2, r.$3, null), r.$1.time.millisecondsSinceEpoch.toString());
expect(
- ScriptedFormatter(r'$SYS$DIA$PUL',).encode(r.$1, r.$2, r.$3),
+ ScriptedFormatter(r'$SYS$DIA$PUL',).encode(r.$1, r.$2, r.$3, null),
(r.$1.sys!.mmHg.toString() + r.$1.dia!.mmHg.toString() + r.$1.pul.toString()),);
expect(
- ScriptedFormatter(r'$SYS$SYS',).encode(r.$1, r.$2, r.$3),
+ ScriptedFormatter(r'$SYS$SYS',).encode(r.$1, r.$2, r.$3, null),
(r.$1.sys!.mmHg.toString() + r.$1.sys!.mmHg.toString()),);
expect(
- ScriptedFormatter(r'{{$SYS-$DIA}}',).encode(r.$1, r.$2, r.$3),
+ ScriptedFormatter(r'{{$SYS-$DIA}}',).encode(r.$1, r.$2, r.$3, null),
(r.$1.sys!.mmHg - r.$1.dia!.mmHg).toDouble().toString(),);
expect(
- ScriptedFormatter(r'{{$SYS*$DIA-$PUL}}',).encode(r.$1, r.$2, r.$3),
+ ScriptedFormatter(r'{{$SYS*$DIA-$PUL}}',).encode(r.$1, r.$2, r.$3, null),
(r.$1.sys!.mmHg * r.$1.dia!.mmHg - r.$1.pul!).toDouble().toString(),);
expect(
- ScriptedFormatter(r'$SYS-$DIA',).encode(r.$1, r.$2, r.$3), ('${r.$1.sys?.mmHg}-${r.$1.dia?.mmHg}'));
+ ScriptedFormatter(r'$SYS-$DIA',).encode(r.$1, r.$2, r.$3, null), ('${r.$1.sys?.mmHg}-${r.$1.dia?.mmHg}'));
final formatter = DateFormat.yMMMMEEEEd();
- expect(ScriptedFormatter('\$FORMAT{\$TIMESTAMP,${formatter.pattern}}',).encode(r.$1, r.$2, r.$3),
+ expect(ScriptedFormatter('\$FORMAT{\$TIMESTAMP,${formatter.pattern}}',).encode(r.$1, r.$2, r.$3, null),
formatter.format(r.$1.time),);
});
test('should report correct reversibility', () {
@@ -70,7 +70,7 @@ void main() {
expect(ScriptedFormatter(r'$TIMESTAMP',).decode('12345678'), (RowDataFieldType.timestamp, DateTime.fromMillisecondsSinceEpoch(12345678)));
expect(ScriptedFormatter(r'$NOTE',).decode('test note'), (RowDataFieldType.notes, 'test note'));
final r = mockEntryPos(DateTime.now(), null, null, null, '', Colors.purple);
- final encodedPurple = ScriptedFormatter(r'$COLOR',).encode(r.$1, r.$2, r.$3);
+ final encodedPurple = ScriptedFormatter(r'$COLOR',).encode(r.$1, r.$2, r.$3, null);
expect(ScriptedFormatter(r'$COLOR',).decode(encodedPurple)?.$1, RowDataFieldType.color);
expect(ScriptedFormatter(r'$COLOR',).decode(encodedPurple)?.$2, Colors.purple.value);
expect(ScriptedFormatter(r'test$SYS',).decode('test567'), (RowDataFieldType.sys, 567));
@@ -89,10 +89,10 @@ void main() {
test('should when ignore groups in format strings', () {
final r1 = mockEntry(sys: 123);
- expect(ScriptedFormatter(r'($SYS)',).encode(r1.$1, r1.$2, r1.$3), '(123)');
- expect(ScriptedFormatter(r'($SYS',).encode(r1.$1, r1.$2, r1.$3), '(123');
+ expect(ScriptedFormatter(r'($SYS)',).encode(r1.$1, r1.$2, r1.$3, null), '(123)');
+ expect(ScriptedFormatter(r'($SYS',).encode(r1.$1, r1.$2, r1.$3, null), '(123');
final r2 = mockEntry(note: 'test');
- expect(ScriptedFormatter(r'($NOTE',).encode(r2.$1, r2.$2, r2.$3), '(test');
+ expect(ScriptedFormatter(r'($NOTE',).encode(r2.$1, r2.$2, r2.$3, null), '(test');
expect(ScriptedFormatter(r'($SYS)',).restoreAbleType, RowDataFieldType.sys);
expect(ScriptedFormatter(r'($SYS',).restoreAbleType, RowDataFieldType.sys);
@@ -114,14 +114,14 @@ void main() {
group('ScriptedTimeFormatter', () {
test('should create non-empty string', () {
final r1 = mockEntry();
- expect(ScriptedTimeFormatter('dd').encode(r1.$1, r1.$2, r1.$3), isNotNull);
- expect(ScriptedTimeFormatter('dd').encode(r1.$1, r1.$2, r1.$3), isNotEmpty);
+ expect(ScriptedTimeFormatter('dd').encode(r1.$1, r1.$2, r1.$3, null), isNotNull);
+ expect(ScriptedTimeFormatter('dd').encode(r1.$1, r1.$2, r1.$3, null), isNotEmpty);
});
test('should decode rough time', () {
final formatter = ScriptedTimeFormatter('yyyy.MMMM.dd GGG hh:mm.ss aaa');
final r = mockEntry();
- expect(formatter.encode(r.$1, r.$2, r.$3), isNotNull);
- expect(formatter.decode(formatter.encode(r.$1, r.$2, r.$3))?.$2, isA<DateTime>()
+ expect(formatter.encode(r.$1, r.$2, r.$3, null), isNotNull);
+ expect(formatter.decode(formatter.encode(r.$1, r.$2, r.$3, null))?.$2, isA<DateTime>()
.having((p0) => p0.millisecondsSinceEpoch, 'time(up to one second difference)', closeTo(r.$1.time.millisecondsSinceEpoch, 1000)),);
});
});
health_data_store/lib/src/types/units/pressure.dart
@@ -27,7 +27,7 @@ class Pressure {
@override
String toString() {
- assert(false, 'Avoid calling toString on Pressure directly as this may not'
+ assert(true, 'Avoid calling toString on Pressure directly as this may not'
'respect the users preferences.');
return mmHg.toString();
}