160 lines
6.3 KiB
Dart
160 lines
6.3 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
import 'package:miler/views/Dashboard/home/homepage_banner.dart';
|
|
import 'package:miler/widget/Bottom_page.dart';
|
|
|
|
/// The live strip at the foot of Home and Bookings.
|
|
///
|
|
/// ── The bug being pinned ──
|
|
///
|
|
/// Both pages pinned it to `bottom: 0`, and the nav bar covered it. The bar
|
|
/// *floats* — a `Positioned` pill inside the shell's `Stack` rather than a
|
|
/// `bottomNavigationBar` — so the Scaffold reserves no room for it and
|
|
/// `SafeArea` cannot see it. Nothing in the type system says "you are about to
|
|
/// draw underneath the navigation", which is why it survived on two screens at
|
|
/// once, so it is measured here instead.
|
|
void main() {
|
|
const safeBottom = 34.0; // a home-indicator phone, where it is worst
|
|
|
|
Future<void> pump(
|
|
WidgetTester tester, {
|
|
double width = 390,
|
|
double textScale = 1.0,
|
|
int count = 1,
|
|
String address = '19, Thadagam Road, Venkitapuram, Coimbatore 641025',
|
|
}) async {
|
|
tester.view.physicalSize = Size(width * 3, 844 * 3);
|
|
tester.view.devicePixelRatio = 3.0;
|
|
addTearDown(tester.view.resetPhysicalSize);
|
|
addTearDown(tester.view.resetDevicePixelRatio);
|
|
|
|
await tester.pumpWidget(
|
|
ScreenUtilInit(
|
|
designSize: const Size(390, 844),
|
|
builder: (_, _) => MaterialApp(
|
|
builder: (context, child) => MediaQuery(
|
|
data: MediaQuery.of(context).copyWith(
|
|
padding: const EdgeInsets.only(bottom: safeBottom),
|
|
textScaler: TextScaler.linear(textScale),
|
|
),
|
|
child: child!,
|
|
),
|
|
home: Scaffold(
|
|
body: Stack(
|
|
children: [
|
|
const Positioned.fill(child: ColoredBox(color: Colors.white)),
|
|
// Exactly how both pages mount it.
|
|
Positioned(
|
|
left: 0,
|
|
right: 0,
|
|
bottom: 0,
|
|
child: ActivePickupBanner(
|
|
activePickups: [
|
|
for (var i = 0; i < count; i++)
|
|
{
|
|
'orderid': 'ORD${1000 + i}',
|
|
'pickupaddress': address,
|
|
'orderstatus': 'arrived',
|
|
},
|
|
],
|
|
onTap: (_) {},
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
// Not `pumpAndSettle`: the LIVE dot pulses forever by design, so nothing on
|
|
// this widget ever settles. Two pumps past the longest transition is enough.
|
|
await tester.pump();
|
|
await tester.pump(const Duration(milliseconds: 400));
|
|
}
|
|
|
|
/// Gap between the bottom of the visible card and the bottom of the screen.
|
|
double gapBelowCard(WidgetTester tester) {
|
|
final screen = tester.view.physicalSize.height / tester.view.devicePixelRatio;
|
|
return screen - tester.getRect(find.byType(Material).last).bottom;
|
|
}
|
|
|
|
testWidgets('clears the floating nav bar while the bar is showing',
|
|
(tester) async {
|
|
await pump(tester);
|
|
|
|
final context = tester.element(find.byType(ActivePickupBanner));
|
|
final required = BottomPage.bottomInset(context);
|
|
|
|
expect(gapBelowCard(tester), greaterThanOrEqualTo(required),
|
|
reason: 'the card must sit above the nav bar, which claims '
|
|
'${required.toStringAsFixed(1)}pt at the foot of the page. It was '
|
|
'pinned to bottom: 0 and the bar covered it.');
|
|
});
|
|
|
|
testWidgets('sits at one height rather than chasing the bar', (tester) async {
|
|
// The banner used to follow a `navVisible` notifier down when the bar slid
|
|
// off on scroll and back up when it returned. The bar compacts now instead
|
|
// of leaving, so there is no state in which that room is free — and a
|
|
// banner that re-laid itself out on every change of scroll direction was
|
|
// moving for a 20pt gap the rider would never have noticed.
|
|
await pump(tester);
|
|
final resting = gapBelowCard(tester);
|
|
|
|
await tester.pump(const Duration(milliseconds: 400));
|
|
expect(gapBelowCard(tester), closeTo(resting, 0.5));
|
|
|
|
final context = tester.element(find.byType(ActivePickupBanner));
|
|
expect(resting, greaterThanOrEqualTo(BottomPage.bottomInset(context)),
|
|
reason: 'it must clear the bar at its resting height, which is the '
|
|
'height the bar returns to the moment he scrolls back up');
|
|
});
|
|
|
|
testWidgets('lines up with the nav bar rather than running full width',
|
|
(tester) async {
|
|
await pump(tester);
|
|
final card = tester.getRect(find.byType(Material).last);
|
|
// The nav bar sits on a 16 gutter; the banner stacks directly under it.
|
|
expect(card.left, closeTo(16.w, 1));
|
|
expect(390 - card.right, closeTo(16.w, 1));
|
|
});
|
|
|
|
group('lays out without overflowing', () {
|
|
for (final width in [320.0, 360.0, 390.0, 430.0]) {
|
|
for (final scale in [1.0, 1.3, 1.5, 2.0]) {
|
|
testWidgets('at ${width.toInt()}pt / ${scale}x', (tester) async {
|
|
// A long address plus a plural title is the widest this row ever gets,
|
|
// and the title used to sit unflexed beside a fixed-width LIVE chip.
|
|
await pump(
|
|
tester,
|
|
width: width,
|
|
textScale: scale,
|
|
count: 3,
|
|
address: '19/4B, Thadagam Main Road, Venkitapuram, Coimbatore, '
|
|
'Tamil Nadu 641025',
|
|
);
|
|
expect(tester.takeException(), isNull,
|
|
reason: 'the banner overflowed at ${width.toInt()}pt / ${scale}x');
|
|
});
|
|
}
|
|
}
|
|
});
|
|
|
|
testWidgets('says nothing when there is nothing running', (tester) async {
|
|
await pump(tester, count: 0);
|
|
expect(find.text('Active Pickup'), findsNothing);
|
|
expect(find.text('LIVE'), findsNothing);
|
|
});
|
|
|
|
testWidgets('names the count and the stop status', (tester) async {
|
|
await pump(tester, count: 3);
|
|
expect(find.text('3 Active Pickups'), findsOneWidget);
|
|
expect(find.textContaining('At the stop'), findsOneWidget,
|
|
reason: 'the rider should see how far into the stop he already is. The '
|
|
'wording comes from StopStatusX.label, the one place the app names '
|
|
'its statuses — and it is "At the stop" rather than the banner\'s '
|
|
'old private "At pickup", which was wrong on a delivery');
|
|
});
|
|
}
|