MO-Fuel-Tax-Back/test/theme_toggle_test.dart

103 lines
3.6 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:fuel_tax_tracker/screens/ui_settings_screen.dart';
import 'package:fuel_tax_tracker/services/app_state.dart';
/// Covers the light/dark/system theme toggle on the Settings > UI screen —
/// defaults to System, selecting a segment updates [AppState.themeMode]
/// and persists it to SharedPreferences (so it survives a cold start).
///
/// Deliberately doesn't round-trip through a second [AppState.init] to
/// verify persistence — that pulls in unrelated subsystems (connectivity
/// listening, cloud-restore) with no test-environment platform mocks,
/// which hangs rather than failing fast. Reading the pref back directly
/// verifies the same thing without that baggage.
void main() {
setUp(() {
SharedPreferences.setMockInitialValues({});
});
testWidgets('defaults to System and switches to Dark/Light on tap', (tester) async {
final appState = AppState()..isLoading = false;
await tester.pumpWidget(
ChangeNotifierProvider.value(
value: appState,
child: const MaterialApp(home: UiSettingsScreen()),
),
);
expect(appState.themeMode, ThemeMode.system);
await tester.tap(find.text('Dark'));
await tester.pumpAndSettle();
expect(appState.themeMode, ThemeMode.dark);
await tester.tap(find.text('Light'));
await tester.pumpAndSettle();
expect(appState.themeMode, ThemeMode.light);
});
testWidgets('persists the choice to SharedPreferences', (tester) async {
final appState = AppState()..isLoading = false;
await tester.pumpWidget(
ChangeNotifierProvider.value(
value: appState,
child: const MaterialApp(home: UiSettingsScreen()),
),
);
await tester.tap(find.text('Dark'));
await tester.pumpAndSettle();
final prefs = await SharedPreferences.getInstance();
// Mirrors the private `_prefsKeyThemeMode` key in app_state.dart —
// a black-box persistence check necessarily has to know the storage
// key, and this doubles as a guardrail against silently breaking
// already-persisted user settings by renaming it there.
expect(prefs.getString('theme_mode'), 'dark');
});
group('Estimated Fuel Refund toggle', () {
testWidgets('off by default, flips on and persists when tapped', (tester) async {
final appState = AppState()..isLoading = false;
await tester.pumpWidget(
ChangeNotifierProvider.value(
value: appState,
child: const MaterialApp(home: UiSettingsScreen()),
),
);
expect(appState.showEstimatedFuelRefund, isFalse);
expect(tester.widget<SwitchListTile>(find.byType(SwitchListTile)).value, isFalse);
await tester.tap(find.text('Estimated Fuel Refund'));
await tester.pumpAndSettle();
expect(appState.showEstimatedFuelRefund, isTrue);
final prefs = await SharedPreferences.getInstance();
expect(prefs.getBool('show_estimated_fuel_refund'), isTrue);
});
testWidgets('explanation mentions the Missouri Highway Fuel Tax Refund and the current rate',
(tester) async {
final appState = AppState()..isLoading = false;
await tester.pumpWidget(
ChangeNotifierProvider.value(
value: appState,
child: const MaterialApp(home: UiSettingsScreen()),
),
);
expect(find.textContaining('Missouri Highway Fuel Tax Refund'), findsOneWidget);
expect(find.textContaining('current rate'), findsOneWidget);
});
});
}