import 'package:flutter_test/flutter_test.dart'; import 'package:miler/views/Dashboard/home/trip.dart'; import 'package:miler/data/service_profile.dart'; /// ───────────────────────────────────────────────────────────────────────── /// THE BRIEF DESCRIBES WHAT IS LEFT /// /// Home's brief card carries four figures — duration, distance, parcels, /// payment — under a headline that counts down (`20 stops left`). /// /// The headline moved as the rider worked. The figures did not. They were /// counted once over every stop the slot ever held, so a rider with five /// collections to go read `≈4h 15m · 29.0 km · 25 parcels`: the morning he /// started with, including the twenty already in his box and gone to /// Deliveries. The one question the card exists to answer — *what is in front /// of me* — was the one thing on it that was stale. /// /// [Trip.outstanding] is the recount. The line it draws is /// `WorkBoundary.pickupComplete`, the same boundary Home and Deliveries split /// on, so a stop cannot be counted here and owned there. /// ───────────────────────────────────────────────────────────────────────── void main() { tearDown(() => ServiceProfile.setActive(ServiceProfile.parcel)); Map stop( String id, { String status = 'accepted', int parcels = 1, double lat = 11.0, double lng = 76.95, double cash = 0, }) => { 'orderid': id, 'pickupid': id, 'orderstatus': status, 'pickupquantity': parcels, 'pickuplat': lat, 'pickuplon': lng, 'collectionamt': cash, }; group('what the figures count', () { test('a collected stop drops out of every figure', () { final trip = Trip.fromStops( id: 't1', stops: [ stop('A', status: 'picked', lat: 11.00, lng: 76.90), stop('B', lat: 11.05, lng: 76.95), stop('C', lat: 11.10, lng: 77.00), ], hubLat: 11.0, hubLng: 76.95, ); final left = trip.outstanding(originLat: 11.0, originLng: 76.95); expect(trip.stopCount, 3, reason: 'the trip itself is untouched'); expect(left.stopCount, 2); expect(left.totalParcels, lessThan(trip.totalParcels)); expect(left.totalDuration, lessThan(trip.totalDuration)); expect(left.routeMeters, lessThan(trip.routeMeters)); }); test('the local collected record counts, not just the status', () { // The queue is a poll behind, so a stop the rider has just handed over // still reports its old status. `collectedIds` is what closes that // window — the same set Home writes after pickup-complete returns. final trip = Trip.fromStops( id: 't1', stops: [stop('A'), stop('B')], ); expect(trip.outstanding().stopCount, 2, reason: 'nothing collected yet'); expect(trip.outstanding(collectedIds: const {'A'}).stopCount, 1); }); test('nothing collected returns the very same object', () { // The common case — a rider who has not started — must not pay for a // rebuild of the whole trip on every frame of the brief. final trip = Trip.fromStops(id: 't1', stops: [stop('A'), stop('B')]); expect(identical(trip.outstanding(), trip), isTrue); }); test('skipped and cancelled work is not still-to-do', () { final trip = Trip.fromStops( id: 't1', stops: [ stop('A', status: 'skipped'), stop('B', status: 'cancelled'), stop('C'), ], ); expect( trip.outstanding().stopCount, 1, reason: 'a written-off stop is a record, not a stop to plan around', ); }); test('a run with everything collected leaves nothing to describe', () { final trip = Trip.fromStops( id: 't1', stops: [ stop('A', status: 'picked'), stop('B', status: 'picked'), ], ); final left = trip.outstanding(); expect(left.stopCount, 0); expect(left.totalParcels, 0); expect( left.totalDuration, Duration.zero, reason: 'the four cells fall back to the em dash, not to a stale figure', ); }); }); group('payment on a meal run', () { test('is nothing to collect, whatever the payload says', () { ServiceProfile.setActive(ServiceProfile.milkMan); final trip = Trip.fromStops( id: 't1', stops: [stop('A', cash: 250), stop('B', cash: 130)], ); // The cell prints the em dash when this is zero — the rider on a meal // run is never asked for money, so a figure here would be a prompt to // collect one. expect(trip.outstanding().cashToCollect, 0); }); test('but a parcel route still counts the cash it is owed', () { ServiceProfile.setActive(ServiceProfile.parcel); final trip = Trip.fromStops( id: 't1', stops: [ stop('A', status: 'picked', cash: 250), stop('B', cash: 130), ], ); expect( trip.outstanding().cashToCollect, 130, reason: 'the collected stop\'s cash is no longer waiting to be taken', ); }); }); }