Ad and purchases enabled (still need actual testing)
This commit is contained in:
parent
2fcc6dcab7
commit
faf319322a
35 changed files with 1676 additions and 34 deletions
121
test/user_agreement_screen_test.dart
Normal file
121
test/user_agreement_screen_test.dart
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.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/main.dart';
|
||||
import 'package:fuel_tax_tracker/screens/main_shell.dart';
|
||||
import 'package:fuel_tax_tracker/screens/user_agreement_screen.dart';
|
||||
import 'package:fuel_tax_tracker/services/app_state.dart';
|
||||
|
||||
/// Covers [UserAgreementScreen] — the liability gate `main.dart`'s
|
||||
/// `AppRoot` shows before [MainShell] until [AppState.hasAcceptedUserAgreement]
|
||||
/// is true, so a fresh install sees it before anything else, including the
|
||||
/// onboarding tour.
|
||||
void main() {
|
||||
setUp(() {
|
||||
SharedPreferences.setMockInitialValues({});
|
||||
});
|
||||
|
||||
Future<AppState> pumpScreen(WidgetTester tester) async {
|
||||
// AppState.hasAcceptedUserAgreement defaults to true precisely so that
|
||||
// ad-hoc AppState() construction in every other screen's tests doesn't
|
||||
// trigger this gate — these tests explicitly flip it to false to
|
||||
// reproduce a real fresh install's state.
|
||||
final appState = AppState()
|
||||
..isLoading = false
|
||||
..hasAcceptedUserAgreement = false;
|
||||
await tester.pumpWidget(
|
||||
ChangeNotifierProvider.value(
|
||||
value: appState,
|
||||
child: const MaterialApp(home: UserAgreementScreen()),
|
||||
),
|
||||
);
|
||||
return appState;
|
||||
}
|
||||
|
||||
testWidgets('shows the data-loss liability section and both actions', (tester) async {
|
||||
await pumpScreen(tester);
|
||||
|
||||
expect(find.text('We Are Not Responsible for Your Data or Any Data Loss'), findsOneWidget);
|
||||
expect(find.textContaining('developer is not responsible for your data'), findsOneWidget);
|
||||
expect(find.widgetWithText(FilledButton, 'I Agree'), findsOneWidget);
|
||||
expect(find.widgetWithText(OutlinedButton, 'Decline'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('I Agree marks the agreement accepted and persists it', (tester) async {
|
||||
final appState = await pumpScreen(tester);
|
||||
|
||||
await tester.tap(find.widgetWithText(FilledButton, 'I Agree'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(appState.hasAcceptedUserAgreement, isTrue);
|
||||
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
expect(prefs.getBool('has_accepted_user_agreement'), isTrue,
|
||||
reason: 'persisted so the agreement never shows again on this device');
|
||||
});
|
||||
|
||||
testWidgets('Decline asks the platform to close the app, without accepting', (tester) async {
|
||||
final appState = await pumpScreen(tester);
|
||||
|
||||
final calls = <MethodCall>[];
|
||||
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
|
||||
.setMockMethodCallHandler(SystemChannels.platform, (call) async {
|
||||
calls.add(call);
|
||||
return null;
|
||||
});
|
||||
addTearDown(() {
|
||||
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
|
||||
.setMockMethodCallHandler(SystemChannels.platform, null);
|
||||
});
|
||||
|
||||
await tester.tap(find.widgetWithText(OutlinedButton, 'Decline'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(calls.map((c) => c.method), contains('SystemNavigator.pop'));
|
||||
expect(appState.hasAcceptedUserAgreement, isFalse);
|
||||
});
|
||||
|
||||
group('AppRoot gating', () {
|
||||
Future<AppState> pumpRoot(WidgetTester tester, {required bool hasAcceptedUserAgreement}) async {
|
||||
final appState = AppState()
|
||||
..isLoading = false
|
||||
..hasAcceptedUserAgreement = hasAcceptedUserAgreement;
|
||||
await tester.pumpWidget(
|
||||
ChangeNotifierProvider.value(
|
||||
value: appState,
|
||||
child: const MaterialApp(home: AppRoot()),
|
||||
),
|
||||
);
|
||||
return appState;
|
||||
}
|
||||
|
||||
testWidgets('shows UserAgreementScreen instead of MainShell before it is accepted',
|
||||
(tester) async {
|
||||
await pumpRoot(tester, hasAcceptedUserAgreement: false);
|
||||
|
||||
expect(find.byType(UserAgreementScreen), findsOneWidget);
|
||||
expect(find.byType(MainShell), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('shows MainShell once the agreement is accepted', (tester) async {
|
||||
final appState = await pumpRoot(tester, hasAcceptedUserAgreement: false);
|
||||
|
||||
await tester.tap(find.widgetWithText(FilledButton, 'I Agree'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(appState.hasAcceptedUserAgreement, isTrue);
|
||||
expect(find.byType(UserAgreementScreen), findsNothing);
|
||||
expect(find.byType(MainShell), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('shows MainShell directly when already accepted (returning user)', (tester) async {
|
||||
await pumpRoot(tester, hasAcceptedUserAgreement: true);
|
||||
|
||||
expect(find.byType(UserAgreementScreen), findsNothing);
|
||||
expect(find.byType(MainShell), findsOneWidget);
|
||||
});
|
||||
});
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue