Files
doormile_milderapp/test/stop_verify_chrome_test.dart
2026-08-11 13:16:33 +05:30

177 lines
6.7 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/pickups/stop_verify.dart';
import 'package:miler/views/helpers/constants/Colorconstants.dart';
import 'package:miler/views/helpers/widgets/app_widgets.dart';
/// ── The form is the screen; the boxes were not ──
///
/// Every group on a verification leg used to be a filled, rounded, 16pt-padded
/// panel — the stop summary, the parcel checklist, the recipient picker, the
/// OTP, the photo — four to six of them stacked, each holding white controls.
/// That put a *container* rank and a *control* rank on the page at the same
/// weight, when only one of the two is something the rider touches at a door.
///
/// They are named and ruled off instead. These tests pin the parts of that
/// which a later change could quietly undo.
void main() {
Future<void> pump(
WidgetTester tester,
Map<String, dynamic> stop, {
double width = 390,
}) async {
tester.view.physicalSize = Size(width * 3, 844 * 3);
tester.view.devicePixelRatio = 3.0;
addTearDown(tester.view.reset);
await tester.pumpWidget(
ScreenUtilInit(
designSize: const Size(390, 844),
builder: (_, _) =>
MaterialApp(home: StopVerificationPage(pickup: stop)),
),
);
await tester.pumpAndSettle();
}
Map<String, dynamic> stopOf({
required String type,
int deliveryQty = 0,
int pickupQty = 0,
}) => <String, dynamic>{
'orderid': 'T-1',
'type': type,
'pickupcustomer': 'Priya Sharma',
'pickupaddress': '45, Lake View Apartments, Race Course, Coimbatore',
if (deliveryQty > 0) 'deliveryqty': '$deliveryQty',
if (pickupQty > 0) 'pickupqty': '$pickupQty',
'Quantity': '${pickupQty > 0 ? pickupQty : deliveryQty}',
};
/// The width of a chip, measured on the box that actually draws it.
double chipWidth(WidgetTester tester, String label) => tester
.getSize(
find
.ancestor(
of: find.text(label),
matching: find.byType(AnimatedContainer),
)
.first,
)
.width;
testWidgets('a leg step draws no filled panels', (tester) async {
await pump(tester, stopOf(type: 'combined', deliveryQty: 1, pickupQty: 2));
// `cardSurface` is the panel fill. It is still right for the review step —
// one grey block per leg, on the screen the rider signs — but on a step he
// is filling in, every one of them was a box around work rather than the
// work itself.
final fills = tester
.widgetList<Container>(
find.descendant(
of: find.byType(SingleChildScrollView),
matching: find.byType(Container),
),
)
.map((c) => c.decoration)
.whereType<BoxDecoration>()
.map((d) => d.color);
expect(fills, isNot(contains(ColorConstants.cardSurface)));
});
testWidgets('section names are quiet labels, not headings', (tester) async {
await pump(tester, stopOf(type: 'delivery', deliveryQty: 1));
// Small, letterspaced and grey — the group is named without competing with
// the controls inside it.
final label = tester.widget<Text>(find.text('WHO RECEIVED IT?'));
expect(label.style!.color, ColorConstants.secondaryText);
expect(label.style!.letterSpacing, greaterThan(0.8));
// Quieter than the stop it belongs to, which is itself only context.
final name = tester.widget<Text>(find.text('Priya Sharma'));
expect(label.style!.fontSize, lessThan(name.style!.fontSize!));
});
testWidgets('the pickers are an even grid, with no half-width orphan', (
tester,
) async {
await pump(tester, stopOf(type: 'delivery', deliveryQty: 1));
// Four recipients: two rows of two, all the same width. Natural-width chips
// packed themselves three-then-one, which reads as a list that ran out
// rather than as a set of four equal choices.
final customer = chipWidth(tester, 'Customer');
for (final other in const ['Family', 'Security', 'Neighbour']) {
expect(chipWidth(tester, other), closeTo(customer, 0.5));
}
});
testWidgets('an odd picker gives its last option the full row', (
tester,
) async {
await pump(tester, stopOf(type: 'pickup', pickupQty: 2));
// Three conditions. The third at half width on a line of its own is an
// orphan; at full width it is a second row.
expect(
chipWidth(tester, 'Damaged'),
greaterThan(chipWidth(tester, 'Sealed & intact') * 1.8),
);
});
testWidgets('a blocked step gets a neutral bar, not a faded coloured one', (
tester,
) async {
await pump(tester, stopOf(type: 'combined', deliveryQty: 1, pickupQty: 2));
// Nothing has been filled in, so the step is blocked.
expect(find.text('1 parcel still to hand over'), findsOneWidget);
// No accent button at all — a saturated pill at 45% still reads as a
// button, so the rider taps it and nothing happens.
expect(find.byType(MilerButton), findsNothing);
expect(find.byIcon(Icons.lock_outline_rounded), findsOneWidget);
// And the label stays readable: grey type on a neutral fill, not white
// dropped to 45% over a wash of itself.
// Named for where it goes, not for which step it is: the rider is on the
// hand-over leg, so the button announces the collection that follows it.
final label = tester.widget<Text>(find.text('Continue to collect'));
expect(label.style!.color, ColorConstants.secondaryText);
});
testWidgets('completing the step turns the bar a solid accent', (
tester,
) async {
await pump(tester, stopOf(type: 'delivery', deliveryQty: 1));
await tester.tap(find.text('Parcel 1 of 1'));
await tester.pumpAndSettle();
await tester.enterText(find.byType(TextField).first, '482916');
await tester.pumpAndSettle();
// Photo is the last gate and the camera cannot be reached here, so the bar
// is still blocked — but on the name of what is missing, not the parcels.
expect(find.text('Take a proof photo'), findsOneWidget);
// The parcel row and the OTP now report themselves done, which is the
// section-scoped tick: it speaks for its own step, never for the screen.
expect(find.text('Handed over'), findsOneWidget);
});
testWidgets('the app bar clears the status bar', (tester) async {
await pump(tester, stopOf(type: 'delivery', deliveryQty: 1));
// The title used to sit hard against the clock, which is where a system
// default puts it and nowhere near where the rest of the app puts a
// heading. `toolbarHeight` alone only moves it half as far as it adds.
final title = tester.getRect(find.text('Verify delivery'));
expect(title.top, greaterThan(24.0));
});
}