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:
@@ -8,6 +8,11 @@ void main() {
|
||||
expect(item.checked, false);
|
||||
});
|
||||
|
||||
test('quantity è 1 di default', () {
|
||||
final item = ShoppingItem(id: '1', name: 'Pollo');
|
||||
expect(item.quantity, 1);
|
||||
});
|
||||
|
||||
test('copyWith() aggiorna solo il campo specificato', () {
|
||||
final item = ShoppingItem(id: '1', name: 'Pollo');
|
||||
final checked = item.copyWith(checked: true);
|
||||
@@ -16,18 +21,26 @@ void main() {
|
||||
expect(checked.id, '1');
|
||||
});
|
||||
|
||||
test('copyWith() aggiorna quantity', () {
|
||||
final item = ShoppingItem(id: '1', name: 'Zucchine');
|
||||
final updated = item.copyWith(quantity: 3);
|
||||
expect(updated.quantity, 3);
|
||||
expect(updated.name, 'Zucchine');
|
||||
});
|
||||
|
||||
test('copyWith() non modifica lorigine', () {
|
||||
final item = ShoppingItem(id: '1', name: 'Pollo');
|
||||
item.copyWith(checked: true);
|
||||
expect(item.checked, false);
|
||||
});
|
||||
|
||||
test('JSON round-trip preserva tutti i campi', () {
|
||||
const item = ShoppingItem(id: '42', name: 'Riso', checked: true);
|
||||
test('JSON round-trip preserva tutti i campi incluso quantity', () {
|
||||
const item = ShoppingItem(id: '42', name: 'Riso', checked: true, quantity: 3);
|
||||
final restored = ShoppingItem.fromJson(item.toJson());
|
||||
expect(restored.id, '42');
|
||||
expect(restored.name, 'Riso');
|
||||
expect(restored.checked, true);
|
||||
expect(restored.quantity, 3);
|
||||
});
|
||||
|
||||
test('fromJson gestisce campo checked assente (default false)', () {
|
||||
@@ -35,12 +48,18 @@ void main() {
|
||||
expect(item.checked, false);
|
||||
});
|
||||
|
||||
test('toJson produce la mappa corretta', () {
|
||||
const item = ShoppingItem(id: '5', name: 'Zucchine', checked: false);
|
||||
test('fromJson gestisce campo quantity assente (default 1)', () {
|
||||
final item = ShoppingItem.fromJson({'id': '1', 'name': 'Pasta', 'checked': false});
|
||||
expect(item.quantity, 1);
|
||||
});
|
||||
|
||||
test('toJson produce la mappa corretta con quantity', () {
|
||||
const item = ShoppingItem(id: '5', name: 'Zucchine', checked: false, quantity: 2);
|
||||
final json = item.toJson();
|
||||
expect(json['id'], '5');
|
||||
expect(json['name'], 'Zucchine');
|
||||
expect(json['checked'], false);
|
||||
expect(json['quantity'], 2);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -18,48 +18,67 @@ Widget _tile({
|
||||
);
|
||||
|
||||
void main() {
|
||||
testWidgets('mostra il nome dell\'elemento', (tester) async {
|
||||
await tester.pumpApp(_tile(item: const ShoppingItem(id: '1', name: 'Pollo')));
|
||||
expect(find.text('Pollo'), findsOneWidget);
|
||||
});
|
||||
group('ShoppingItemTile', () {
|
||||
testWidgets('mostra il nome dell\'elemento', (tester) async {
|
||||
await tester.pumpApp(_tile(item: const ShoppingItem(id: '1', name: 'Pollo')));
|
||||
expect(find.text('Pollo'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('checkbox non spuntato quando checked è false', (tester) async {
|
||||
await tester.pumpApp(_tile(item: const ShoppingItem(id: '1', name: 'Riso')));
|
||||
final checkbox = tester.widget<Checkbox>(find.byType(Checkbox));
|
||||
expect(checkbox.value, false);
|
||||
});
|
||||
testWidgets('checkbox non spuntato quando checked è false', (tester) async {
|
||||
await tester.pumpApp(_tile(item: const ShoppingItem(id: '1', name: 'Riso')));
|
||||
final checkbox = tester.widget<Checkbox>(find.byType(Checkbox));
|
||||
expect(checkbox.value, false);
|
||||
});
|
||||
|
||||
testWidgets('checkbox spuntato quando checked è true', (tester) async {
|
||||
await tester.pumpApp(
|
||||
_tile(item: const ShoppingItem(id: '1', name: 'Riso', checked: true)));
|
||||
final checkbox = tester.widget<Checkbox>(find.byType(Checkbox));
|
||||
expect(checkbox.value, true);
|
||||
});
|
||||
testWidgets('checkbox spuntato quando checked è true', (tester) async {
|
||||
await tester.pumpApp(
|
||||
_tile(item: const ShoppingItem(id: '1', name: 'Riso', checked: true)));
|
||||
final checkbox = tester.widget<Checkbox>(find.byType(Checkbox));
|
||||
expect(checkbox.value, true);
|
||||
});
|
||||
|
||||
testWidgets('chiama onToggle al tap sul checkbox', (tester) async {
|
||||
var toggled = false;
|
||||
await tester.pumpApp(_tile(
|
||||
item: const ShoppingItem(id: '1', name: 'Pollo'),
|
||||
onToggle: () => toggled = true,
|
||||
));
|
||||
await tester.tap(find.byType(Checkbox));
|
||||
expect(toggled, true);
|
||||
});
|
||||
testWidgets('chiama onToggle al tap sul checkbox', (tester) async {
|
||||
var toggled = false;
|
||||
await tester.pumpApp(_tile(
|
||||
item: const ShoppingItem(id: '1', name: 'Pollo'),
|
||||
onToggle: () => toggled = true,
|
||||
));
|
||||
await tester.tap(find.byType(Checkbox));
|
||||
expect(toggled, true);
|
||||
});
|
||||
|
||||
testWidgets('chiama onRemove al tap sul pulsante chiudi', (tester) async {
|
||||
var removed = false;
|
||||
await tester.pumpApp(_tile(
|
||||
item: const ShoppingItem(id: '1', name: 'Pasta'),
|
||||
onRemove: () => removed = true,
|
||||
));
|
||||
await tester.tap(find.byIcon(Icons.close));
|
||||
expect(removed, true);
|
||||
});
|
||||
testWidgets('chiama onRemove al tap sul pulsante chiudi', (tester) async {
|
||||
var removed = false;
|
||||
await tester.pumpApp(_tile(
|
||||
item: const ShoppingItem(id: '1', name: 'Pasta'),
|
||||
onRemove: () => removed = true,
|
||||
));
|
||||
await tester.tap(find.byIcon(Icons.close));
|
||||
expect(removed, true);
|
||||
});
|
||||
|
||||
testWidgets('testo barrato quando elemento è completato', (tester) async {
|
||||
await tester.pumpApp(
|
||||
_tile(item: const ShoppingItem(id: '1', name: 'Tonno', checked: true)));
|
||||
final textWidget = tester.widget<Text>(find.text('Tonno'));
|
||||
expect(textWidget.style?.decoration, TextDecoration.lineThrough);
|
||||
testWidgets('testo barrato quando elemento è completato', (tester) async {
|
||||
await tester.pumpApp(
|
||||
_tile(item: const ShoppingItem(id: '1', name: 'Tonno', checked: true)));
|
||||
final textWidget = tester.widget<Text>(find.text('Tonno'));
|
||||
expect(textWidget.style?.decoration, TextDecoration.lineThrough);
|
||||
});
|
||||
|
||||
testWidgets('non mostra indicatore quantità quando quantity è 1', (tester) async {
|
||||
await tester.pumpApp(_tile(item: const ShoppingItem(id: '1', name: 'Riso')));
|
||||
expect(find.text('(x1)'), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('mostra (x2) quando quantity è 2', (tester) async {
|
||||
await tester.pumpApp(
|
||||
_tile(item: const ShoppingItem(id: '1', name: 'Zucchine', quantity: 2)));
|
||||
expect(find.text('(x2)'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('mostra (xN) per quantità maggiori', (tester) async {
|
||||
await tester.pumpApp(
|
||||
_tile(item: const ShoppingItem(id: '1', name: 'Pollo', quantity: 5)));
|
||||
expect(find.text('(x5)'), findsOneWidget);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user