115 lines
3.9 KiB
Dart
115 lines
3.9 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:provider/provider.dart';
|
|
|
|
import 'package:fuel_tax_tracker/models/fuel_entry.dart';
|
|
import 'package:fuel_tax_tracker/models/vehicle.dart';
|
|
import 'package:fuel_tax_tracker/screens/edit_fuel_entry_screen.dart';
|
|
import 'package:fuel_tax_tracker/screens/receipt_detail_screen.dart';
|
|
import 'package:fuel_tax_tracker/screens/receipt_image_screen.dart';
|
|
import 'package:fuel_tax_tracker/services/app_state.dart';
|
|
|
|
/// Covers [ReceiptDetailScreen] itself — the single place to view a
|
|
/// receipt's photo and logged data together, with edit/delete for the
|
|
/// entry. Deliberately never taps through to an actual delete: that would
|
|
/// call [AppState.deleteFuelEntry], which needs an initialized database not
|
|
/// set up here (see settings_purge_test.dart for the same convention).
|
|
void main() {
|
|
final vehicle = Vehicle(id: 'v1', vin: '1FMPU18L1TLB51349', nickname: 'Red Truck', updatedAt: DateTime.utc(2026, 1, 1));
|
|
final entry = FuelEntry(
|
|
id: 'e1',
|
|
vehicleId: 'v1',
|
|
date: DateTime(2026, 5, 14, 9, 30),
|
|
gallons: 10.523,
|
|
pricePerGallon: 3.499,
|
|
totalCost: 36.81,
|
|
updatedAt: DateTime.utc(2026, 5, 14),
|
|
receiptDriveFileId: 'remote-1',
|
|
);
|
|
|
|
Future<void> pumpDetail(WidgetTester tester, AppState appState) async {
|
|
await tester.pumpWidget(
|
|
ChangeNotifierProvider.value(
|
|
value: appState,
|
|
child: MaterialApp(home: ReceiptDetailScreen(entryId: 'e1')),
|
|
),
|
|
);
|
|
}
|
|
|
|
testWidgets('shows the vehicle, date, gallons, price, and total', (tester) async {
|
|
final appState = AppState()
|
|
..isLoading = false
|
|
..vehicles = [vehicle]
|
|
..fuelEntries = [entry];
|
|
|
|
await pumpDetail(tester, appState);
|
|
|
|
expect(find.text('Red Truck'), findsOneWidget);
|
|
expect(find.text('VIN: 1FMPU18L1TLB51349'), findsOneWidget);
|
|
expect(find.text('10.523 gal'), findsOneWidget);
|
|
expect(find.text('\$3.50'), findsOneWidget, reason: 'price per gallon');
|
|
expect(find.text('\$36.81'), findsOneWidget, reason: 'total cost');
|
|
});
|
|
|
|
testWidgets('shows a fallback instead of crashing when the entry no longer exists',
|
|
(tester) async {
|
|
final appState = AppState()
|
|
..isLoading = false
|
|
..vehicles = [vehicle]
|
|
..fuelEntries = [];
|
|
|
|
await pumpDetail(tester, appState);
|
|
|
|
expect(find.text('Receipt not found'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('the edit icon opens EditFuelEntryScreen pre-filled', (tester) async {
|
|
final appState = AppState()
|
|
..isLoading = false
|
|
..vehicles = [vehicle]
|
|
..fuelEntries = [entry];
|
|
|
|
await pumpDetail(tester, appState);
|
|
|
|
await tester.tap(find.byTooltip('Edit fuel entry'));
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.byType(EditFuelEntryScreen), findsOneWidget);
|
|
expect(find.widgetWithText(TextFormField, '10.523'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('the delete icon shows a warning dialog; Cancel dismisses it without deleting',
|
|
(tester) async {
|
|
final appState = AppState()
|
|
..isLoading = false
|
|
..vehicles = [vehicle]
|
|
..fuelEntries = [entry];
|
|
|
|
await pumpDetail(tester, appState);
|
|
|
|
await tester.tap(find.byTooltip('Delete fuel entry'));
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.text('Delete fuel entry?'), findsOneWidget);
|
|
|
|
await tester.tap(find.text('Cancel'));
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.text('Delete fuel entry?'), findsNothing);
|
|
expect(appState.fuelEntries, hasLength(1), reason: 'not deleted');
|
|
});
|
|
|
|
testWidgets('tapping the photo opens the full-screen viewer', (tester) async {
|
|
final appState = AppState()
|
|
..isLoading = false
|
|
..vehicles = [vehicle]
|
|
..fuelEntries = [entry];
|
|
|
|
await pumpDetail(tester, appState);
|
|
|
|
await tester.tap(find.byType(GestureDetector).first);
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.byType(ReceiptImageScreen), findsOneWidget);
|
|
});
|
|
}
|