Pretty much finished the MeasurementProvider

-- MesurementProvider --
(Added)
- editCategory
- editEntry

-- MeasurementEntry --
(Added)
- copyWith

-- MeasurementCategory --
(Added)
- copyWith
This commit is contained in:
ton-An
2021-08-25 16:24:29 +02:00
parent 23a8226e72
commit 755cdd5fae
8 changed files with 204 additions and 7 deletions

View File

@@ -29,6 +29,15 @@ class MeasurementEntry extends Equatable {
required this.notes,
});
MeasurementEntry copyWith({int? id, int? category, DateTime? date, num? value, String? notes}) =>
MeasurementEntry(
id: id ?? this.id,
category: category ?? this.category,
date: date ?? this.date,
value: value ?? this.value,
notes: notes ?? this.notes,
);
// Boilerplate
factory MeasurementEntry.fromJson(Map<String, dynamic> json) => _$MeasurementEntryFromJson(json);

View File

@@ -87,7 +87,7 @@ class MeasurementProvider with ChangeNotifier {
notifyListeners();
}
/// Adds a measurement category to the remote db
/// Adds a measurement category
Future<void> addCategory(MeasurementCategory category) async {
Uri postUri = baseProvider.makeUrl(_categoryUrl);
final Map<String, dynamic> newCategoryMap = await baseProvider.post(category.toJson(), postUri);
@@ -97,7 +97,7 @@ class MeasurementProvider with ChangeNotifier {
notifyListeners();
}
/// Deletes a measurement category from the remote db
/// Deletes a measurement category
Future<void> deleteCategory(int id) async {
MeasurementCategory category = _categories.firstWhere((element) => element.id == id,
orElse: () => throw NoSuchEntryException());
@@ -110,11 +110,27 @@ class MeasurementProvider with ChangeNotifier {
if (response.statusCode >= 400) {
_categories.insert(categoryIndex, category);
notifyListeners();
throw WgerHttpException(response.body);
}
}
/// Adds a measurement entry to the remote db
/// Edits a measurement category
/// Currently there isn't any fallback if the call to the api is unsuccessful, as WgerBaseProvider.patch only returns the response body and not the whole response
Future<void> editCategory(int id, String? newName, String? newUnit) async {
final MeasurementCategory oldCategory = _categories.firstWhere((category) => category.id == id,
orElse: () => throw NoSuchEntryException());
int categoryIndex = _categories.indexOf(oldCategory);
_categories.removeAt(categoryIndex);
final MeasurementCategory tempNewCategory = oldCategory.copyWith(name: newName, unit: newUnit);
final Map<String, dynamic> response =
await baseProvider.patch(tempNewCategory.toJson(), baseProvider.makeUrl(_categoryUrl));
final MeasurementCategory newCategory =
(MeasurementCategory.fromJson(response)).copyWith(entries: oldCategory.entries);
_categories.insert(categoryIndex, newCategory);
notifyListeners();
}
/// Adds a measurement entry
Future<void> addEntry(MeasurementEntry entry) async {
Uri postUri = baseProvider.makeUrl(_entryUrl);
@@ -132,7 +148,7 @@ class MeasurementProvider with ChangeNotifier {
}, orElse: () => throw NoSuchEntryException());
}
/// Deletes a measurement entry from the remote db
/// Deletes a measurement entry
Future<void> deleteEntry(int id, int categoryId) async {
final int categoryIndex = _categories.indexWhere((category) => category.id == categoryId);
if (categoryIndex == -1) throw NoSuchEntryException();
@@ -150,7 +166,26 @@ class MeasurementProvider with ChangeNotifier {
if (response.statusCode >= 400) {
_categories[categoryIndex].entries.insert(entryIndex, entry);
notifyListeners();
throw WgerHttpException(response.body);
}
}
/// Edits a measurement entry
/// Currently there isn't any fallback if the call to the api is unsuccessful, as WgerBaseProvider.patch only returns the response body and not the whole response
Future<void> editEntry(int id, int categroyId, num? newValue, String? newNotes) async {
final MeasurementCategory category = _categories.firstWhere(
(category) => category.id == categroyId,
orElse: () => throw NoSuchEntryException());
final MeasurementEntry oldEntry = category.entries
.firstWhere((entry) => entry.id == id, orElse: () => throw NoSuchEntryException());
final int entryIndex = category.entries.indexOf(oldEntry);
category.entries.removeAt(entryIndex);
final MeasurementEntry tempNewEntry = oldEntry.copyWith(value: newValue, notes: newNotes);
final Map<String, dynamic> response =
await baseProvider.patch(tempNewEntry.toJson(), baseProvider.makeUrl(_entryUrl));
final MeasurementEntry newEntry = MeasurementEntry.fromJson(response);
category.entries.insert(entryIndex, newEntry);
notifyListeners();
}
}

View File

@@ -0,0 +1,5 @@
{
"id": 1,
"name": "Triceps",
"unit": "m"
}

View File

@@ -0,0 +1,6 @@
{
"id": 1,
"name": "Triceps",
"unit": "m",
"entries": null
}

View File

@@ -0,0 +1,7 @@
{
"id": 1,
"category": 1,
"date": "2021-07-21",
"value": 23,
"notes": "I just wanted to edit this to see what happens"
}

View File

@@ -33,4 +33,23 @@ void main() {
// assert
expect(result, tMeasurementEntryMap);
});
test('should copyWith objects of this class', () {
// arrange
MeasurementEntry tMeasurementEntryCopied = MeasurementEntry(
id: 83,
category: 17,
date: DateTime(1960),
value: 93,
notes: 'Interesting',
);
// act
final result = tMeasurementEntry.copyWith(
id: 83, category: 17, date: DateTime(1960), value: 93, notes: 'Interesting');
// assert
expect(result, tMeasurementEntryCopied);
});
}

View File

@@ -176,7 +176,7 @@ main() {
MeasurementCategory(id: null, name: 'Strength', unit: 'kN');
Map<String, dynamic> tMeasurementCategoryMap = jsonDecode(fixture('measurement_category.json'));
Map<String, dynamic> tMeasurementCategoryMapWithoutId =
jsonDecode(fixture('measurement_category_toJson_without_id.json'));
jsonDecode(fixture('measurement_category_without_id_to_json.json'));
List<MeasurementCategory> tMeasurementCategoriesAdded = [
MeasurementCategory(id: 2, name: 'Biceps', unit: 'cm'),
MeasurementCategory(id: 1, name: 'Strength', unit: 'kN'),
@@ -253,6 +253,49 @@ main() {
});
});
group('editCategory()', () {
String tCategoryEditedName = 'Triceps';
String tCategoryEditedUnit = 'm';
Map<String, dynamic> tCategoryMapEditedToJson =
jsonDecode(fixture('measurement_category_edited_to_json.json'));
Map<String, dynamic> tCategoryMapEdited =
jsonDecode(fixture('measurement_category_edited.json'));
setUp(() async {
when(mockWgerBaseProvider.patch(any, any))
.thenAnswer((realInvocation) => Future.value(tCategoryMapEdited));
await measurementProvider.fetchAndSetCategories();
});
test('should add the new MeasurementCategory and remove the old one', () async {
// arrange
List<MeasurementCategory> tMeasurementCategoriesEdited = [
MeasurementCategory(id: 1, name: 'Triceps', unit: 'm'),
MeasurementCategory(id: 2, name: 'Biceps', unit: 'cm'),
];
// act
await measurementProvider.editCategory(tCategoryId, tCategoryEditedName, tCategoryEditedUnit);
// assert
expect(measurementProvider.categories, tMeasurementCategoriesEdited);
});
test('should throw a NoSuchEntryException if category doesn\'t exist', () {
// act & assert
expect(
() async =>
await measurementProvider.editCategory(83, tCategoryEditedName, tCategoryEditedUnit),
throwsA(isA<NoSuchEntryException>()));
});
test('should call api to patch the category', () async {
// act
await measurementProvider.editCategory(tCategoryId, tCategoryEditedName, tCategoryEditedUnit);
// assert
verify(mockWgerBaseProvider.patch(tCategoryMapEditedToJson, tCategoryUri));
});
});
group('addEntry()', () {
MeasurementEntry tMeasurementEntry = MeasurementEntry(
id: 3,
@@ -440,4 +483,77 @@ main() {
expect(measurementProvider.categories, tMeasurementCategories);
});
});
group('editEntry()', () {
// remove the old MeasurementCategory
// should call api to patch the category
// should add the new MeasurementCategory from the api call
// notifyListeners()
// should re-add the old MeasurementCategory and remove the new one if call to api fails
// notifyListeners()
int tEntryId = 1;
num tEntryEditedValue = 23;
String tEntryEditedNote = 'I just wanted to edit this to see what happens';
Map<String, dynamic> tEntryMapEdited = jsonDecode(fixture('measurement_entry_edited.json'));
setUp(() async {
when(mockWgerBaseProvider.patch(any, any))
.thenAnswer((realInvocation) => Future.value(tEntryMapEdited));
await measurementProvider.fetchAndSetCategories();
await measurementProvider.fetchAndSetCategoryEntries(1);
});
test('should add the new MeasurementCategory and remove the old one', () async {
// arrange
List<MeasurementCategory> tMeasurementCategoriesEdited = [
MeasurementCategory(id: 1, name: 'Strength', unit: 'kN', entries: [
MeasurementEntry(
id: 1,
category: 1,
date: DateTime(2021, 7, 21),
value: 23,
notes: 'I just wanted to edit this to see what happens',
),
MeasurementEntry(
id: 2,
category: 1,
date: DateTime(2021, 7, 10),
value: 15.00,
notes: '',
)
]),
MeasurementCategory(id: 2, name: 'Biceps', unit: 'cm')
];
// act
await measurementProvider.editEntry(
tEntryId, tCategoryId, tEntryEditedValue, tEntryEditedNote);
// assert
expect(measurementProvider.categories, tMeasurementCategoriesEdited);
});
test('should throw a NoSuchEntryException if category doesn\'t exist', () {
// act & assert
expect(
() async => await measurementProvider.editEntry(
tEntryId, 83, tEntryEditedValue, tEntryEditedNote),
throwsA(isA<NoSuchEntryException>()));
});
test('should throw a NoSuchEntryException if entry doesn\'t exist', () {
// act & assert
expect(
() async => await measurementProvider.editEntry(
83, tCategoryId, tEntryEditedValue, tEntryEditedNote),
throwsA(isA<NoSuchEntryException>()));
});
test('should call api to patch the category', () async {
// act
await measurementProvider.editEntry(
tEntryId, tCategoryId, tEntryEditedValue, tEntryEditedNote);
// assert
verify(mockWgerBaseProvider.patch(tEntryMapEdited, tCategoryEntriesUri));
});
});
}