132 lines
3.8 KiB
Dart
132 lines
3.8 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
import 'package:fuel_tax_tracker/widgets/onboarding_tour_overlay.dart';
|
|
|
|
/// Unit-level coverage of the tour's presentational overlay widget,
|
|
/// independent of MainShell's step-sequencing/navigation logic (covered
|
|
/// in main_shell_test.dart's onboarding-tour group instead).
|
|
void main() {
|
|
Widget wrap(Widget child) => MaterialApp(home: Scaffold(body: child));
|
|
|
|
testWidgets('shows the title, description, and step count', (tester) async {
|
|
final targetKey = GlobalKey();
|
|
|
|
await tester.pumpWidget(wrap(
|
|
OnboardingTourOverlay(
|
|
targetKey: targetKey,
|
|
title: 'Example Title',
|
|
description: 'Example description text.',
|
|
stepNumber: 2,
|
|
totalSteps: 4,
|
|
onNext: () {},
|
|
onSkip: () {},
|
|
),
|
|
));
|
|
|
|
expect(find.text('Example Title'), findsOneWidget);
|
|
expect(find.text('Example description text.'), findsOneWidget);
|
|
expect(find.text('Step 2 of 4'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('shows "Next" before the last step and "Got It" on the last step', (tester) async {
|
|
final targetKey = GlobalKey();
|
|
|
|
await tester.pumpWidget(wrap(
|
|
OnboardingTourOverlay(
|
|
targetKey: targetKey,
|
|
title: 'T',
|
|
description: 'D',
|
|
stepNumber: 1,
|
|
totalSteps: 3,
|
|
onNext: () {},
|
|
onSkip: () {},
|
|
),
|
|
));
|
|
expect(find.widgetWithText(FilledButton, 'Next'), findsOneWidget);
|
|
expect(find.widgetWithText(FilledButton, 'Got It'), findsNothing);
|
|
|
|
await tester.pumpWidget(wrap(
|
|
OnboardingTourOverlay(
|
|
targetKey: targetKey,
|
|
title: 'T',
|
|
description: 'D',
|
|
stepNumber: 3,
|
|
totalSteps: 3,
|
|
onNext: () {},
|
|
onSkip: () {},
|
|
),
|
|
));
|
|
expect(find.widgetWithText(FilledButton, 'Got It'), findsOneWidget);
|
|
expect(find.widgetWithText(FilledButton, 'Next'), findsNothing);
|
|
});
|
|
|
|
testWidgets('invokes onNext/onSkip when their buttons are tapped', (tester) async {
|
|
var nextTapped = false;
|
|
var skipTapped = false;
|
|
final targetKey = GlobalKey();
|
|
|
|
await tester.pumpWidget(wrap(
|
|
OnboardingTourOverlay(
|
|
targetKey: targetKey,
|
|
title: 'T',
|
|
description: 'D',
|
|
stepNumber: 1,
|
|
totalSteps: 2,
|
|
onNext: () => nextTapped = true,
|
|
onSkip: () => skipTapped = true,
|
|
),
|
|
));
|
|
|
|
await tester.tap(find.widgetWithText(TextButton, 'Skip Tour'));
|
|
expect(skipTapped, isTrue);
|
|
|
|
await tester.tap(find.widgetWithText(FilledButton, 'Next'));
|
|
expect(nextTapped, isTrue);
|
|
});
|
|
|
|
testWidgets(
|
|
'renders without crashing when the target key has no RenderObject yet — falls back to a '
|
|
'centered card', (tester) async {
|
|
final targetKey = GlobalKey(); // never attached to anything
|
|
|
|
await tester.pumpWidget(wrap(
|
|
OnboardingTourOverlay(
|
|
targetKey: targetKey,
|
|
title: 'T',
|
|
description: 'D',
|
|
stepNumber: 1,
|
|
totalSteps: 1,
|
|
onNext: () {},
|
|
onSkip: () {},
|
|
),
|
|
));
|
|
|
|
expect(find.text('T'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('tapping the dimmed barrier does not invoke onNext or onSkip', (tester) async {
|
|
var nextTapped = false;
|
|
var skipTapped = false;
|
|
final targetKey = GlobalKey();
|
|
|
|
await tester.pumpWidget(wrap(
|
|
OnboardingTourOverlay(
|
|
targetKey: targetKey,
|
|
title: 'T',
|
|
description: 'D',
|
|
stepNumber: 1,
|
|
totalSteps: 1,
|
|
onNext: () => nextTapped = true,
|
|
onSkip: () => skipTapped = true,
|
|
),
|
|
));
|
|
|
|
// Top-left corner — away from the card, which sits mid/lower-screen.
|
|
await tester.tapAt(const Offset(5, 5));
|
|
await tester.pump();
|
|
|
|
expect(nextTapped, isFalse);
|
|
expect(skipTapped, isFalse);
|
|
});
|
|
}
|