177 lines
6.7 KiB
Dart
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));
|
|
});
|
|
}
|