102 lines
3.3 KiB
Dart
102 lines
3.3 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:motorcycle_dash/features/entitlements/widgets/pro_lock_badge.dart';
|
|
import 'package:motorcycle_dash/features/rides/ride_state_machine.dart';
|
|
import 'package:motorcycle_dash/services/entitlements/feature_access_service.dart';
|
|
|
|
/// Regression for Issue #52 / BUG-005 follow-up: the "Forensic CSV & PDF Export" Pro
|
|
/// upsell sheet showed "BOTTOM OVERFLOWED BY 90 PIXELS" in landscape on a Pixel 8a
|
|
/// (~914x411 dp) because showProUpgradeSheet built a non-scrolling Column inside a default
|
|
/// modal bottom sheet, which Flutter caps at 9/16 of the screen height.
|
|
class _FakeRideStateMachine extends StateNotifier<RideSession>
|
|
implements RideStateMachine {
|
|
_FakeRideStateMachine(super.initialState);
|
|
|
|
@override
|
|
dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
|
|
}
|
|
|
|
Future<void> _pumpHost(
|
|
WidgetTester tester, {
|
|
required Size viewport,
|
|
double textScale = 1.0,
|
|
}) async {
|
|
await tester.binding.setSurfaceSize(viewport);
|
|
addTearDown(() => tester.binding.setSurfaceSize(null));
|
|
|
|
await tester.pumpWidget(
|
|
ProviderScope(
|
|
overrides: [
|
|
rideStateMachineProvider.overrideWith(
|
|
(ref) => _FakeRideStateMachine(RideSession(state: RideState.idle)),
|
|
),
|
|
],
|
|
child: MediaQuery(
|
|
data: MediaQueryData(
|
|
size: viewport,
|
|
textScaler: TextScaler.linear(textScale),
|
|
),
|
|
child: MaterialApp(
|
|
home: Scaffold(
|
|
body: Consumer(
|
|
builder: (context, ref, _) => ElevatedButton(
|
|
onPressed: () => showProUpgradeSheet(
|
|
context,
|
|
ref,
|
|
feature: MotorSignalFeature.csvExport,
|
|
),
|
|
child: const Text('Open upsell'),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
void main() {
|
|
TestWidgetsFlutterBinding.ensureInitialized();
|
|
|
|
for (final viewport in const [
|
|
Size(914, 411), // Pixel 8a landscape
|
|
Size(800, 360),
|
|
Size(780, 360),
|
|
]) {
|
|
for (final scale in const [1.0, 1.3]) {
|
|
testWidgets(
|
|
'Pro upgrade sheet has no bottom overflow in landscape '
|
|
'${viewport.width.toInt()}x${viewport.height.toInt()} (text scale $scale)',
|
|
(tester) async {
|
|
await _pumpHost(tester, viewport: viewport, textScale: scale);
|
|
|
|
await tester.tap(find.text('Open upsell'));
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.text('Forensic CSV & PDF Export'), findsOneWidget);
|
|
expect(find.text('VIEW MOTORSIGNAL PRO'), findsOneWidget);
|
|
expect(find.text('NOT NOW'), findsOneWidget);
|
|
// No RenderFlex overflow exception.
|
|
expect(tester.takeException(), isNull);
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
testWidgets('NOT NOW is reachable and dismisses the sheet in landscape', (
|
|
tester,
|
|
) async {
|
|
await _pumpHost(tester, viewport: const Size(800, 360), textScale: 1.3);
|
|
|
|
await tester.tap(find.text('Open upsell'));
|
|
await tester.pumpAndSettle();
|
|
await tester.ensureVisible(find.text('NOT NOW'));
|
|
await tester.tap(find.text('NOT NOW'));
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.text('VIEW MOTORSIGNAL PRO'), findsNothing);
|
|
expect(tester.takeException(), isNull);
|
|
});
|
|
}
|