69 lines
2.5 KiB
Dart
69 lines
2.5 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:provider/provider.dart';
|
|
|
|
import 'package:fuel_tax_tracker/services/app_state.dart';
|
|
import 'package:fuel_tax_tracker/widgets/ad_free_upsell_dialog.dart';
|
|
|
|
/// Covers the "remove ads for a year" upsell shown right after a user
|
|
/// watches the app's one ad placement — see `AppState.syncNow`'s
|
|
/// `onAdWatched` hook, wired up in main.dart. Tested here as a standalone
|
|
/// dialog function, matching backup_reminder_test.dart's convention.
|
|
void main() {
|
|
Future<void> openDialog(WidgetTester tester, AppState appState) async {
|
|
await tester.pumpWidget(
|
|
ChangeNotifierProvider.value(
|
|
value: appState,
|
|
child: MaterialApp(
|
|
home: Builder(
|
|
builder: (context) => ElevatedButton(
|
|
onPressed: () => showAdFreeUpsellDialog(context),
|
|
child: const Text('open'),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
await tester.tap(find.text('open'));
|
|
await tester.pumpAndSettle();
|
|
}
|
|
|
|
testWidgets('shows the pitch with both actions', (tester) async {
|
|
await openDialog(tester, AppState());
|
|
|
|
expect(find.text('Tired of Ads?'), findsOneWidget);
|
|
expect(find.text('Not Now'), findsOneWidget);
|
|
expect(find.text('Remove Ads'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('falls back to generic copy when no price is loaded yet', (tester) async {
|
|
await openDialog(tester, AppState());
|
|
|
|
expect(find.textContaining('a single one-time purchase'), findsOneWidget);
|
|
expect(find.textContaining('\$'), findsNothing);
|
|
});
|
|
|
|
testWidgets('Not Now closes the dialog without navigating anywhere', (tester) async {
|
|
await openDialog(tester, AppState());
|
|
|
|
await tester.tap(find.text('Not Now'));
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.text('Tired of Ads?'), findsNothing);
|
|
});
|
|
|
|
testWidgets('Remove Ads closes the dialog and starts the purchase flow', (tester) async {
|
|
final appState = AppState();
|
|
await openDialog(tester, appState);
|
|
|
|
await tester.tap(find.text('Remove Ads'));
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.text('Tired of Ads?'), findsNothing, reason: 'dialog closed');
|
|
// buyAdFreeYear() delegates to PurchaseService, which — with no real
|
|
// store connection in tests — surfaces its failure through
|
|
// AppState.purchaseError rather than throwing, so tapping through is
|
|
// enough to confirm the button actually invoked it without crashing.
|
|
expect(appState.purchaseError, isNotNull);
|
|
});
|
|
}
|