import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:tane/data/export_import/seed_label_codec.dart'; import 'package:tane/data/species_repository.dart'; import 'package:tane/data/variety_repository.dart'; import 'package:tane/db/database.dart'; import 'package:tane/ui/qr_scan.dart'; import '../support/test_support.dart'; /// Hosts a button that feeds [payload] to [handleScannedPayload], standing in /// for the camera — the handler is what carries the flow's logic. class _ScanHost extends StatelessWidget { const _ScanHost({ required this.repository, required this.species, required this.payload, required this.opened, }); final VarietyRepository repository; final SpeciesRepository species; final String payload; final List opened; @override Widget build(BuildContext context) { return Scaffold( body: Center( child: ElevatedButton( key: const Key('scanHost.fire'), onPressed: () => handleScannedPayload( context, repository: repository, species: species, payload: payload, openVariety: opened.add, ), child: const Text('scan'), ), ), ); } } void main() { late AppDatabase db; late VarietyRepository repo; late SpeciesRepository species; setUp(() { db = newTestDatabase(); repo = newTestRepository(db); species = newTestSpeciesRepository(db); }); tearDown(() => db.close()); Future> pumpAndFire(WidgetTester tester, String payload) async { final opened = []; await tester.pumpWidget( wrapScreen( repository: repo, child: _ScanHost( repository: repo, species: species, payload: payload, opened: opened, ), ), ); await tester.tap(find.byKey(const Key('scanHost.fire'))); await tester.pumpAndSettle(); return opened; } testWidgets('a known label opens its record straight away', (tester) async { final id = await repo.addQuickVariety(label: 'Tomate Rosa'); final payload = SeedLabelCodec.encode( const SeedLabelData(varietyLabel: 'tomate rosa'), ); final opened = await pumpAndFire(tester, payload); expect(opened, [id]); expect(find.byKey(const Key('scan.addPrompt')), findsNothing); await disposeTree(tester); }); testWidgets('an unknown label asks first, then adds and opens it', ( tester, ) async { final payload = SeedLabelCodec.encode( const SeedLabelData( varietyLabel: 'Acelga de Perales', year: 2024, origin: 'María', ), ); final opened = await pumpAndFire(tester, payload); expect(find.byKey(const Key('scan.addPrompt')), findsOneWidget); expect(opened, isEmpty); // nothing created before the person says so expect(await db.select(db.varieties).get(), isEmpty); await tester.tap(find.byKey(const Key('scan.add'))); await tester.pumpAndSettle(); final varieties = await db.select(db.varieties).get(); expect(varieties.single.label, 'Acelga de Perales'); final lots = await db.select(db.lots).get(); expect(lots.single.harvestYear, 2024); expect(lots.single.originName, 'María'); expect(opened, [varieties.single.id]); await disposeTree(tester); }); testWidgets('declining the prompt adds nothing', (tester) async { final payload = SeedLabelCodec.encode( const SeedLabelData(varietyLabel: 'Acelga de Perales'), ); final opened = await pumpAndFire(tester, payload); await tester.tap(find.byKey(const Key('scan.cancel'))); await tester.pumpAndSettle(); expect(await db.select(db.varieties).get(), isEmpty); expect(opened, isEmpty); await disposeTree(tester); }); testWidgets('a non-label QR just says so', (tester) async { final opened = await pumpAndFire(tester, 'https://example.org/whatever'); expect(find.text('That code is not a seed label'), findsOneWidget); expect(opened, isEmpty); await disposeTree(tester); }); }