feat: refactor API paths for authentication, inventory, and recipes; add contract tests for repositories

This commit is contained in:
Nils-Johan Gynther
2026-04-22 10:21:07 +02:00
parent 655adf66ae
commit c163821bad
8 changed files with 246 additions and 19 deletions
@@ -0,0 +1,102 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:recipe_flutter/core/api/api_client.dart';
import 'package:recipe_flutter/features/inventory/data/inventory_repository.dart';
class FakeInventoryApiClient extends ApiClient {
FakeInventoryApiClient();
String? lastMethod;
String? lastPath;
Object? lastBody;
@override
Future<dynamic> getJson(String path, {String? token}) async {
lastMethod = 'GET';
lastPath = path;
if (path.startsWith('/inventory')) {
return [
{
'id': 43,
'productId': 1,
'quantity': 2,
'unit': 'st',
'opened': false,
'product': {'name': 'Agg'}
}
];
}
return [];
}
@override
Future<dynamic> postJson(String path, {Object? body, String? token}) async {
lastMethod = 'POST';
lastPath = path;
lastBody = body;
return {
'id': 43,
'productId': 1,
'quantity': 1,
'unit': 'st',
'opened': false,
'product': {'name': 'Agg'}
};
}
@override
Future<dynamic> patchJson(String path, {Object? body, String? token}) async {
lastMethod = 'PATCH';
lastPath = path;
lastBody = body;
return {
'id': 43,
'productId': 1,
'quantity': 1,
'unit': 'st',
'opened': false,
'product': {'name': 'Agg'}
};
}
@override
Future<dynamic> deleteJson(String path, {String? token}) async {
lastMethod = 'DELETE';
lastPath = path;
return null;
}
}
void main() {
group('InventoryRepository API contract', () {
test('fetchInventoryItem uses list endpoint, not missing detail endpoint', () async {
final api = FakeInventoryApiClient();
final repository = InventoryRepository(api);
final item = await repository.fetchInventoryItem(43);
expect(item.id, 43);
expect(api.lastMethod, 'GET');
expect(api.lastPath, '/inventory');
});
test('updateInventoryItem uses PATCH /inventory/:id', () async {
final api = FakeInventoryApiClient();
final repository = InventoryRepository(api);
await repository.updateInventoryItem(43, {'unit': 'st'});
expect(api.lastMethod, 'PATCH');
expect(api.lastPath, '/inventory/43');
});
test('consumeInventoryItem uses POST /inventory/:id/consume', () async {
final api = FakeInventoryApiClient();
final repository = InventoryRepository(api);
await repository.consumeInventoryItem(43, amountUsed: 0.5);
expect(api.lastMethod, 'POST');
expect(api.lastPath, '/inventory/43/consume');
});
});
}