first commit
This commit is contained in:
159
test/active_pickup_banner_test.dart
Normal file
159
test/active_pickup_banner_test.dart
Normal file
@@ -0,0 +1,159 @@
|
||||
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');
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user