tane/apps/app_seeds/test/ui/handover_sheet_test.dart
vjrj d42ed0df1a test(fix): stop handover widget test hanging on awaited stream .first
The 'giving all with payment and promise' widget test awaited
repo.watchSales().first / watchPlantares().first in its body. A Drift
stream's .first never completes under the widget-test fake-async clock
(pumpAndSettle has already returned, so dart_test.yaml's per-test timeout
can't bound it), so the test hung to the framework's 10-min hard cap.

- Read the recorded sale/plantare with one-shot db.select(...).get()
  queries instead (same filter, resolves fine under fake-async) — the
  suite now passes in ~1s.
- Add a pure-Dart guard test that scans test/ui/ and fails loudly if any
  awaited watchX().first reappears, so this stops being recurrent.
2026-07-12 08:17:12 +02:00

151 lines
5 KiB
Dart

import 'package:commons_core/commons_core.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:tane/db/database.dart';
import 'package:tane/db/enums.dart';
import '../support/test_support.dart';
void main() {
late AppDatabase db;
setUp(() => db = newTestDatabase());
tearDown(() => db.close());
testWidgets('the detail screen offers ONE hand-over door, no separate '
'sale/plantare buttons', (tester) async {
final repo = newTestRepository(db);
final id = await repo.addQuickVariety(label: 'Maize');
await tester.pumpWidget(
wrapDetail(
repository: repo,
varietyId: id,
species: newTestSpeciesRepository(db),
),
);
await tester.pumpAndSettle();
expect(find.byKey(const Key('detail.handover')), findsOneWidget);
expect(find.byKey(const Key('detail.addSale')), findsNothing);
expect(find.byKey(const Key('detail.addPlantare')), findsNothing);
await disposeTree(tester);
});
testWidgets('giving all with payment and promise records the three pieces '
'in one save', (tester) async {
final repo = newTestRepository(db);
final id = await repo.addQuickVariety(label: 'Maize');
final lotId = await repo.addLot(
varietyId: id,
quantity: const Quantity(kind: QuantityKind.grams, count: 40),
offerStatus: OfferStatus.sell,
priceAmount: 3,
priceCurrency: '',
);
await tester.pumpWidget(
wrapDetail(
repository: repo,
varietyId: id,
species: newTestSpeciesRepository(db),
),
);
await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key('detail.handover')));
await tester.pumpAndSettle();
// "All of it" is the default — one tap covers the whole-plant case.
final allChip = tester.widget<ChoiceChip>(
find.byKey(const Key('handover.allOfIt')),
);
expect(allChip.selected, isTrue);
await tester.enterText(
find.byKey(const Key('handover.counterparty')),
'María',
);
await tester.tap(find.byKey(const Key('handover.addPayment')));
await tester.pumpAndSettle();
await tester.enterText(find.byKey(const Key('handover.amount')), '2,5');
await tester.tap(find.byKey(const Key('handover.currencyChip.Ğ1')));
await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key('handover.addPromise')));
await tester.pumpAndSettle();
await tester.enterText(
find.byKey(const Key('handover.owed')),
'un puñado',
);
await tester.ensureVisible(find.byKey(const Key('handover.save')));
await tester.tap(find.byKey(const Key('handover.save')));
await tester.pumpAndSettle();
// One-shot .get() reads (NOT watch().first): a Drift stream's `.first`
// never completes under the widget-test fake-async clock, so awaiting it
// in a testWidgets body hangs the whole test to the 10-min hard cap. A
// plain SELECT resolves fine (same as the movements/lot reads below).
final sales = await (db.select(
db.sales,
)..where((s) => s.isDeleted.equals(false))).get();
expect(sales.single.direction, SaleDirection.iSold);
expect(sales.single.amount, 2.5);
expect(sales.single.currency, 'Ğ1');
expect(sales.single.counterparty, 'María');
final plantares = await (db.select(
db.plantares,
)..where((p) => p.isDeleted.equals(false))).get();
expect(plantares.single.direction, PlantareDirection.owedToMe);
expect(plantares.single.owedDescription, 'un puñado');
final lot = await (db.select(
db.lots,
)..where((l) => l.id.equals(lotId))).getSingle();
expect(lot.quantityPrecise, 0);
expect(lot.offerStatus, OfferStatus.private);
expect(lot.priceAmount, isNull);
final movements = await db.select(db.movements).get();
expect(movements.single.type, MovementType.given);
expect(movements.single.plantareId, plantares.single.id);
await disposeTree(tester);
});
testWidgets('receiving hides the how-much choice and mirrors directions', (
tester,
) async {
final repo = newTestRepository(db);
final id = await repo.addQuickVariety(label: 'Maize');
await repo.addLot(varietyId: id);
await tester.pumpWidget(
wrapDetail(
repository: repo,
varietyId: id,
species: newTestSpeciesRepository(db),
),
);
await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key('detail.handover')));
await tester.pumpAndSettle();
await tester.tap(
find.byKey(const Key('handover.direction.iReceived')),
);
await tester.pumpAndSettle();
expect(find.byKey(const Key('handover.allOfIt')), findsNothing);
await tester.ensureVisible(find.byKey(const Key('handover.save')));
await tester.tap(find.byKey(const Key('handover.save')));
await tester.pumpAndSettle();
final movements = await db.select(db.movements).get();
expect(movements.single.type, MovementType.received);
await disposeTree(tester);
});
}