import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:provider/provider.dart'; import 'package:fuel_tax_tracker/models/vehicle.dart'; import 'package:fuel_tax_tracker/screens/add_edit_vehicle_screen.dart'; import 'package:fuel_tax_tracker/screens/vehicle_detail_screen.dart'; import 'package:fuel_tax_tracker/services/app_state.dart'; /// Covers the "VIN already belongs to another vehicle" dialog on the Add /// Vehicle form — [AddEditVehicleScreen] driven directly against an /// [AppState] whose in-memory `vehicles` list is seeded by hand (no /// database/cloud wiring needed, since the dialog only reads /// [AppState.vehicleByVin]). void main() { final existingVehicle = Vehicle( id: 'existing-id', vin: '1FMPU18L1TLB51349', nickname: 'Red Truck', updatedAt: DateTime.utc(2026, 1, 1), ); Future pumpAddVehicleScreen(WidgetTester tester) async { final appState = AppState() ..isLoading = false ..vehicles = [existingVehicle]; await tester.pumpWidget( ChangeNotifierProvider.value( value: appState, child: const MaterialApp(home: AddEditVehicleScreen()), ), ); return appState; } testWidgets('entering a VIN that already exists shows the dialog', (tester) async { await pumpAddVehicleScreen(tester); await tester.enterText(find.widgetWithText(TextFormField, 'VIN *'), existingVehicle.vin); await tester.pumpAndSettle(); expect(find.text('Vehicle already exists'), findsOneWidget); expect( find.text( 'Vehicle with the VIN ${existingVehicle.vin} already exists, would you like to open that vehicle?', ), findsOneWidget, ); }); testWidgets('tapping No dismisses the dialog and stays on the create screen', (tester) async { await pumpAddVehicleScreen(tester); await tester.enterText(find.widgetWithText(TextFormField, 'VIN *'), existingVehicle.vin); await tester.pumpAndSettle(); await tester.tap(find.widgetWithText(TextButton, 'No')); await tester.pumpAndSettle(); expect(find.text('Vehicle already exists'), findsNothing); expect(find.text('Add Vehicle'), findsWidgets); expect( find.text('A vehicle with VIN "${existingVehicle.vin}" already exists.'), findsOneWidget, reason: 'the field itself should be flagged invalid after declining to open the existing vehicle', ); }); testWidgets('tapping Yes opens the existing vehicle', (tester) async { await pumpAddVehicleScreen(tester); await tester.enterText(find.widgetWithText(TextFormField, 'VIN *'), existingVehicle.vin); await tester.pumpAndSettle(); await tester.tap(find.widgetWithText(TextButton, 'Yes')); await tester.pumpAndSettle(); expect(find.byType(VehicleDetailScreen), findsOneWidget); expect(find.text(existingVehicle.displayLabel), findsOneWidget); expect(find.byType(AddEditVehicleScreen), findsNothing, reason: 'the create screen should be popped, not left underneath'); }); testWidgets('editing a vehicle with its own VIN does not trigger the dialog', (tester) async { final appState = AppState() ..isLoading = false ..vehicles = [existingVehicle]; await tester.pumpWidget( ChangeNotifierProvider.value( value: appState, child: MaterialApp(home: AddEditVehicleScreen(vehicle: existingVehicle)), ), ); // The field already starts pre-filled with its own VIN; nudge it to // fire onChanged the same way a real edit would. await tester.enterText(find.widgetWithText(TextFormField, 'VIN *'), existingVehicle.vin); await tester.pumpAndSettle(); expect(find.text('Vehicle already exists'), findsNothing); }); }