test: espandi copertura a 110 test e organizza in gruppi

- Aggiunto converter_provider_test.dart (nuovo): stato iniziale, select,
  setGrams, result, swapDirection, reset, search
- Aggiunto qr_test.dart (nuovo): buildQrPayload e parseMealPlanFromQr
  con round-trip e casi di errore
- meal_planner_provider_test: group(), importPlan(), fallback JSON corrotto
- shopping_list_provider_test: group(), addAll con aggregazione quantity,
  fallback JSON corrotto
- shopping_item_test: campi quantity (default, copyWith, JSON round-trip)
- shopping_item_tile_test: group(), visualizzazione (xN)
- conversion_entry_test: caso limite yieldFactor=0
- meal_card_test: group()
- Rimosso widget_test.dart (boilerplate obsoleto)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-17 23:27:19 +02:00
parent 9fcaae9687
commit 65214ac34e
8 changed files with 703 additions and 259 deletions
@@ -7,103 +7,151 @@ void main() {
SharedPreferences.setMockInitialValues({});
});
test('inizia vuota', () async {
final provider = ShoppingListProvider();
await provider.load();
expect(provider.items, isEmpty);
});
group('ShoppingListProvider', () {
test('inizia vuota', () async {
final provider = ShoppingListProvider();
await provider.load();
expect(provider.items, isEmpty);
});
test('add() aggiunge un elemento', () async {
final provider = ShoppingListProvider();
await provider.load();
provider.add('Pollo');
expect(provider.items.length, 1);
expect(provider.items.first.name, 'Pollo');
expect(provider.items.first.checked, false);
});
group('add()', () {
test('aggiunge un elemento', () async {
final provider = ShoppingListProvider();
await provider.load();
provider.add('Pollo');
expect(provider.items.length, 1);
expect(provider.items.first.name, 'Pollo');
expect(provider.items.first.checked, false);
});
test('add() ignora stringa vuota o solo spazi', () async {
final provider = ShoppingListProvider();
await provider.load();
provider.add(' ');
provider.add('');
expect(provider.items, isEmpty);
});
test('ignora stringa vuota o solo spazi', () async {
final provider = ShoppingListProvider();
await provider.load();
provider.add(' ');
provider.add('');
expect(provider.items, isEmpty);
});
test('add() esegue trim del testo', () async {
final provider = ShoppingListProvider();
await provider.load();
provider.add(' Riso ');
expect(provider.items.first.name, 'Riso');
});
test('esegue trim del testo', () async {
final provider = ShoppingListProvider();
await provider.load();
provider.add(' Riso ');
expect(provider.items.first.name, 'Riso');
});
});
test('toggle() inverte lo stato checked', () async {
final provider = ShoppingListProvider();
await provider.load();
provider.add('Riso');
final id = provider.items.first.id;
provider.toggle(id);
expect(provider.items.first.checked, true);
provider.toggle(id);
expect(provider.items.first.checked, false);
});
group('toggle()', () {
test('inverte lo stato checked', () async {
final provider = ShoppingListProvider();
await provider.load();
provider.add('Riso');
final id = provider.items.first.id;
provider.toggle(id);
expect(provider.items.first.checked, true);
provider.toggle(id);
expect(provider.items.first.checked, false);
});
});
test('pendingItems e checkedItems separano correttamente', () async {
final provider = ShoppingListProvider();
await provider.load();
provider.add('Riso');
provider.add('Pasta');
provider.add('Pollo');
provider.toggle(provider.items[0].id);
provider.toggle(provider.items[2].id);
expect(provider.pendingItems.length, 1);
expect(provider.checkedItems.length, 2);
});
group('pendingItems / checkedItems', () {
test('separano correttamente', () async {
final provider = ShoppingListProvider();
await provider.load();
provider.add('Riso');
provider.add('Pasta');
provider.add('Pollo');
provider.toggle(provider.items[0].id);
provider.toggle(provider.items[2].id);
expect(provider.pendingItems.length, 1);
expect(provider.checkedItems.length, 2);
});
});
test('remove() elimina per id', () async {
final provider = ShoppingListProvider();
await provider.load();
provider.add('Pollo');
provider.add('Riso');
final id = provider.items.first.id;
provider.remove(id);
expect(provider.items.length, 1);
expect(provider.items.first.name, 'Riso');
});
group('remove()', () {
test('elimina per id', () async {
final provider = ShoppingListProvider();
await provider.load();
provider.add('Pollo');
provider.add('Riso');
final id = provider.items.first.id;
provider.remove(id);
expect(provider.items.length, 1);
expect(provider.items.first.name, 'Riso');
});
});
test('addAll() non aggiunge duplicati (case-insensitive)', () async {
final provider = ShoppingListProvider();
await provider.load();
provider.add('Pollo');
provider.addAll(['pollo', 'Riso', 'RISO', 'Pasta']);
expect(provider.items.length, 3); // Pollo, Riso, Pasta
});
group('addAll()', () {
test('non aggiunge duplicati (case-insensitive)', () async {
final provider = ShoppingListProvider();
await provider.load();
provider.add('Pollo');
provider.addAll(['pollo', 'Riso', 'RISO', 'Pasta']);
expect(provider.items.length, 3); // Pollo, Riso, Pasta
});
test('addAll() ignora elementi già presenti', () async {
final provider = ShoppingListProvider();
await provider.load();
provider.add('Riso');
provider.addAll(['Riso', 'Pasta']);
expect(provider.items.length, 2);
});
test('ignora elementi già presenti', () async {
final provider = ShoppingListProvider();
await provider.load();
provider.add('Riso');
provider.addAll(['Riso', 'Pasta']);
expect(provider.items.length, 2);
});
test('clearAll() svuota la lista', () async {
final provider = ShoppingListProvider();
await provider.load();
provider.add('Pollo');
provider.add('Riso');
provider.clearAll();
expect(provider.items, isEmpty);
});
test('aggrega duplicati con quantity', () async {
final provider = ShoppingListProvider();
await provider.load();
provider.addAll(['Zucchine', 'Pollo', 'Zucchine', 'Pollo', 'Pollo']);
final zucchine = provider.items.firstWhere((i) => i.name.toLowerCase() == 'zucchine');
final pollo = provider.items.firstWhere((i) => i.name.toLowerCase() == 'pollo');
expect(zucchine.quantity, 2);
expect(pollo.quantity, 3);
});
test('persiste e ricarica i dati', () async {
final provider1 = ShoppingListProvider();
await provider1.load();
provider1.add('Merluzzo');
await Future.delayed(const Duration(milliseconds: 50));
test('imposta quantity=1 per elementi non duplicati', () async {
final provider = ShoppingListProvider();
await provider.load();
provider.addAll(['Pasta', 'Riso']);
for (final item in provider.items) {
expect(item.quantity, 1);
}
});
final provider2 = ShoppingListProvider();
await provider2.load();
expect(provider2.items.first.name, 'Merluzzo');
test('non aggiunge se tutti già presenti', () async {
final provider = ShoppingListProvider();
await provider.load();
provider.add('Riso');
provider.addAll(['riso']);
expect(provider.items.length, 1);
});
});
group('clearAll()', () {
test('svuota la lista', () async {
final provider = ShoppingListProvider();
await provider.load();
provider.add('Pollo');
provider.add('Riso');
provider.clearAll();
expect(provider.items, isEmpty);
});
});
test('persiste e ricarica i dati', () async {
final provider1 = ShoppingListProvider();
await provider1.load();
provider1.add('Merluzzo');
await Future.delayed(const Duration(milliseconds: 50));
final provider2 = ShoppingListProvider();
await provider2.load();
expect(provider2.items.first.name, 'Merluzzo');
});
test('load gestisce JSON corrotto con lista vuota', () async {
SharedPreferences.setMockInitialValues({'shopping_list': 'json non valido {'});
final provider = ShoppingListProvider();
await provider.load();
expect(provider.items, isEmpty);
});
});
}