production

This commit is contained in:
2026-08-28 11:13:15 +05:30
parent d7348e253f
commit 5723d373b2
162 changed files with 17924 additions and 7026 deletions

View File

@@ -7,6 +7,7 @@ import 'package:miler/data/order_events.dart';
import 'package:miler/data/service_profile.dart';
import 'package:miler/views/Dashboard/activity/delivery_details_page.dart';
import 'package:miler/views/helpers/constants/Colorconstants.dart';
import 'package:miler/views/helpers/constants/narrative.dart';
/// ─────────────────────────────────────────────────────────────────────────
/// DELIVERY DETAILS — one stop, the whole story
@@ -111,6 +112,20 @@ void main() {
}
}
/// Opens the full journey log.
///
/// The rungs are behind **View full log** now: the panel leads with a
/// one-line strip of the same ladder, and the detailed version — clocks,
/// places, addresses, the gaps between them — is one tap under it. Every
/// assertion about *which* rungs exist and in what order is unchanged; what
/// changed is that reading them costs a tap, so the tests take it.
Future<void> openLog(WidgetTester tester) async {
final link = find.text('View full log');
if (link.evaluate().isEmpty) return;
await tester.tap(link);
await tester.pumpAndSettle();
}
tearDown(() => ServiceProfile.setActive(ServiceProfile.parcel));
group('the summary', () {
@@ -124,7 +139,11 @@ void main() {
// stop cannot be called one thing on the list and another on the page
// that list opens. It appears twice: the summary and the timeline's head
// rung, which is the newest event.
expect(find.text('Delivered'), findsNWidgets(2));
// Once, not twice. The timeline's own copy of the word is behind
// **View full log** now — the strip above it carries `DELIVERED`, and
// the card under it says where — so the only `Delivered` on a closed
// record page is the verdict itself.
expect(find.text('Delivered'), findsOneWidget);
final headline = tester.widget<Text>(find.text('Delivered').first);
expect(headline.style!.color, ColorConstants.acceptGreen);
@@ -175,12 +194,15 @@ void main() {
testWidgets('runs oldest first, named for the leg', (tester) async {
ServiceProfile.setActive(ServiceProfile.milkMan);
await pump(tester, record());
await openLog(tester);
// The door arrival is not a rung: it folds into the outcome as a
// duration, because "he got there 5m before he handed it over" is a
// subtraction, not an event worth its own line.
expect(find.text('Arrived at customer'), findsNothing);
expect(find.text('5m at the door'), findsOneWidget);
// Twice with the log open: on the rung, and on the card under the strip
// that restates how the last leg went.
expect(find.text('5m at the door'), findsNWidgets(2));
expect(find.text('Out for delivery'), findsOneWidget);
// ── Downwards, like every order-tracking screen ──
@@ -199,6 +221,7 @@ void main() {
testWidgets('a collection is named for its own leg', (tester) async {
await pump(tester, record(type: 'pickup', status: 'picked'));
await openLog(tester);
expect(find.text('Picked up'), findsWidgets);
// On a collection `arrivedat` IS the counter, so it fills the same rung
@@ -224,6 +247,7 @@ void main() {
arrived: false,
),
);
await openLog(tester);
expect(find.text('Set off'), findsNothing);
expect(find.text('Arrived'), findsNothing);
@@ -250,6 +274,7 @@ void main() {
tester,
record(type: 'pickup', status: 'picked', arrived: false),
);
await openLog(tester);
expect(find.text('Set off'), findsOneWidget);
expect(find.text('Arrived'), findsNothing);
});
@@ -280,6 +305,7 @@ void main() {
.add(const Duration(minutes: 65))
.toIso8601String(),
});
await openLog(tester);
for (final rung in const [
'Assigned',
@@ -335,13 +361,15 @@ void main() {
// existed. It must degrade to what it has, not to a page of placeholders.
ServiceProfile.setActive(ServiceProfile.milkMan);
await pump(tester, record());
await openLog(tester);
expect(find.text('Delivered'), findsNWidgets(2));
// The door arrival is not a rung: it folds into the outcome as a
// duration, because "he got there 5m before he handed it over" is a
// subtraction, not an event worth its own line.
expect(find.text('Arrived at customer'), findsNothing);
expect(find.text('5m at the door'), findsOneWidget);
// The rung, and the card under the strip.
expect(find.text('5m at the door'), findsNWidgets(2));
expect(find.text('Out for delivery'), findsOneWidget);
for (final absent in const [
'Order placed',
@@ -363,18 +391,22 @@ void main() {
tester,
record(status: 'skipped', skipReason: 'Customer unreachable'),
);
await openLog(tester);
// The one rung on this page allowed to exist without a timestamp: a
// skipped stop has a delivery in its story that did not occur, and saying
// so is the point of the record. It is an open ring, not a filled disc,
// so it cannot read as a step that is merely pending.
expect(find.text('Delivered'), findsOneWidget);
expect(find.text('Not completed — return visit owed'), findsOneWidget);
// The unreached rung, and the card under the strip that names where the
// story stopped.
expect(find.text('Delivered'), findsNWidgets(2));
expect(find.text('Not completed — return visit owed'), findsNWidgets(2));
});
testWidgets('a completed stop has nothing left unreached', (tester) async {
ServiceProfile.setActive(ServiceProfile.milkMan);
await pump(tester, record());
await openLog(tester);
// Twice — the summary and the timeline's last rung — and never a third
// time as a step still to come.
@@ -388,12 +420,13 @@ void main() {
testWidgets('a round draws both ends; a parcel draws one', (tester) async {
ServiceProfile.setActive(ServiceProfile.milkMan);
await pump(tester, record());
await openLog(tester);
// ── ROUTE is gone; its two addresses moved onto the journey ──
//
// Tracking said *when*, Route said *where*, and the rider joined them
// himself. Each place is now written onto the rung that happened there.
expect(find.text('ROUTE'), findsNothing);
expect(find.text('JOURNEY'), findsOneWidget);
expect(find.text('Journey'), findsOneWidget);
// Once now, not twice. The hero's quiet `from → to` line names both
// ends; the journey names the place on the rung that happened there,
@@ -402,11 +435,14 @@ void main() {
expect(find.text('Vidhya Kitchen'), findsOneWidget);
expect(
find.text('78, Cross Cut Road, Gandhipuram'),
findsOneWidget,
findsNWidgets(2),
reason:
'the address hangs on the rung that happened at it. With no '
'drop address on the booking the one address it has belongs to '
'the door — the fallback ROUTE encoded and this inherited.',
'the door — the fallback ROUTE encoded and this inherited. '
'Twice with the log open: the rung, and the card under the strip '
'that restates where it ended, which is the one line the strip '
'itself has no room for.',
);
// A parcel booking is a first-mile collection *from* the customer, and
@@ -415,7 +451,7 @@ void main() {
ServiceProfile.setActive(ServiceProfile.parcel);
await pump(tester, record(type: 'pickup', status: 'picked'));
expect(find.text('ROUTE'), findsNothing);
expect(find.text('JOURNEY'), findsOneWidget);
expect(find.text('Journey'), findsOneWidget);
});
});
@@ -431,23 +467,31 @@ void main() {
);
await unfold(tester);
// ── The labelled stats strip is gone ──
// ── The stats strip is back, as the app's own fact strip ──
//
// DISTANCE / TOTAL TIME / ORDERS was three captioned cells in a tinted
// box — a dashboard widget, and a dashboard is for comparing many things
// across records. There is one stop on this page and it is finished. The
// figures still earn a place; they earn a line.
expect(find.text('DISTANCE'), findsNothing);
expect(find.text('TOTAL TIME'), findsNothing);
// It was removed once, as DISTANCE / TOTAL TIME / ORDERS in a tinted box,
// on the argument that a dashboard is for comparing many things and there
// is one stop on this page. That argument was about the *panel*; what
// replaced it — one grey centred sentence — went too far the other way,
// and the page it left behind read as unfinished.
//
// What is here now is the tonal fact strip Account and the stop sheet
// already use, inside the panel that owns the figures. So the assertion
// flips: the cells exist, and what is still forbidden is a cell for
// something nobody measured (below).
expect(find.text('DISTANCE'), findsOneWidget);
// The distance now reads once in that line, and once in the folded row
// that names it.
expect(find.text('4.6 km'), findsOneWidget);
// Twice, and both are honest: the strip's value, and the folded row that
// names it against the planned figure.
expect(find.text('4.6 km'), findsNWidgets(2));
expect(find.textContaining('4.6 km'), findsWidgets);
expect(find.text('4.1 km'), findsOneWidget);
// The brief's emerald, which is what "delivered / met / yes" is set in
// on the rebuilt screens. Same meaning, one hue deeper than the old
// `acceptGreen`.
final verdict = tester.widget<Text>(find.text('Yes'));
expect(verdict.style!.color, ColorConstants.acceptGreen);
expect(verdict.style!.color, Narrative.emerald);
// A record that invents a plausible number cannot be caught.
for (final invented in const ['0 km', '0.0 km', '0m', '₹0']) {
@@ -474,7 +518,9 @@ void main() {
testWidgets('the reference is there and copyable', (tester) async {
await pump(tester, record(type: 'pickup', status: 'picked'));
await unfold(tester);
expect(find.text('#DM101'), findsOneWidget);
// Twice: the app bar's quiet identifier and the folded row that owns
// it. Only one of them is copyable, which is the point of the row.
expect(find.text('#DM101'), findsNWidgets(2));
expect(find.byIcon(LucideIcons.copy), findsOneWidget);
});
@@ -518,9 +564,10 @@ void main() {
await unfold(tester);
expect(find.text('Payment'), findsWidgets);
// Due, collected, and again under EARNINGS — the cash that changed hands
// is the one earnings figure this stop really has.
expect(find.text('₹340'), findsNWidgets(3));
// Four: the fact strip at the top of the page, then due, collected, and
// again under EARNINGS — the cash that changed hands is the one earnings
// figure this stop really has.
expect(find.text('₹340'), findsNWidgets(4));
// Earnings folded into Payment — one group about money, not two.
expect(find.text('Payment'), findsWidgets);
expect(find.text('Cash collected'), findsOneWidget);
@@ -576,11 +623,14 @@ void main() {
// Both addresses now sit on the journey, each on the rung that happened
// at it — the counter on the collection, the door on the outcome — so
// this reads the ladder rather than a separate ROUTE section.
await openLog(tester);
final kitchen = tester.getRect(
find.text('4 Cross, RS Puram, Coimbatore 641002'),
);
// `.first`: the door's address is on its rung and again on the card
// under the strip, and the rung is the one this ordering is about.
final door = tester.getRect(
find.text('12, SNS Colony, Peelamedu, Coimbatore 641004'),
find.text('12, SNS Colony, Peelamedu, Coimbatore 641004').first,
);
expect(
@@ -600,16 +650,22 @@ void main() {
// hanging its one address exactly where it always hung.
ServiceProfile.setActive(ServiceProfile.milkMan);
await pump(tester, record());
await openLog(tester);
await unfold(tester);
expect(find.text('78, Cross Cut Road, Gandhipuram'), findsOneWidget);
// The rung, and the outcome card that restates the last one.
expect(find.text('78, Cross Cut Road, Gandhipuram'), findsNWidgets(2));
});
testWidgets('the same street is never printed twice', (tester) async {
ServiceProfile.setActive(ServiceProfile.milkMan);
await pump(tester, record());
await openLog(tester);
await unfold(tester);
expect(find.text('78, Cross Cut Road, Gandhipuram'), findsOneWidget);
// Once on the rung and once on the outcome card, and never a third time
// — the duplication this test was written against was a whole ROUTE
// section repeating the journey.
expect(find.text('78, Cross Cut Road, Gandhipuram'), findsNWidgets(2));
});
});
}